mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-18 22:56:29 +02:00
Add support for bindless textures from shader input (vertex buffer) on Vulkan (#6577)
* Add support for bindless textures from shader input (vertex buffer) * Shader cache version bump * Format whitespace * Remove cache entries on pool removal, disable for OpenGL * PR feedback
This commit is contained in:
parent
9b94662b4b
commit
c6f8bfed90
39 changed files with 1091 additions and 311 deletions
|
@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
TextureBindings[i] = stage.Info.Textures.Select(descriptor =>
|
||||
{
|
||||
Target target = ShaderTexture.GetTarget(descriptor.Type);
|
||||
Target target = descriptor.Type != SamplerType.None ? ShaderTexture.GetTarget(descriptor.Type) : default;
|
||||
|
||||
var result = new TextureBindingInfo(
|
||||
target,
|
||||
|
@ -66,7 +66,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
descriptor.ArrayLength,
|
||||
descriptor.CbufSlot,
|
||||
descriptor.HandleIndex,
|
||||
descriptor.Flags);
|
||||
descriptor.Flags,
|
||||
descriptor.Type == SamplerType.None);
|
||||
|
||||
if (descriptor.ArrayLength <= 1)
|
||||
{
|
||||
|
|
|
@ -109,6 +109,13 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
return _oldSpecState.GraphicsState.HasConstantBufferDrawParameters;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <exception cref="DiskCacheLoadException">Pool length is not available on the cache</exception>
|
||||
public int QuerySamplerArrayLengthFromPool()
|
||||
{
|
||||
return QueryArrayLengthFromPool(isSampler: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public SamplerType QuerySamplerType(int handle, int cbufSlot)
|
||||
{
|
||||
|
@ -117,6 +124,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <exception cref="DiskCacheLoadException">Constant buffer derived length is not available on the cache</exception>
|
||||
public int QueryTextureArrayLengthFromBuffer(int slot)
|
||||
{
|
||||
if (!_oldSpecState.TextureArrayFromBufferRegistered(_stageIndex, 0, slot))
|
||||
|
@ -130,6 +138,13 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
return arrayLength;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <exception cref="DiskCacheLoadException">Pool length is not available on the cache</exception>
|
||||
public int QueryTextureArrayLengthFromPool()
|
||||
{
|
||||
return QueryArrayLengthFromPool(isSampler: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TextureFormat QueryTextureFormat(int handle, int cbufSlot)
|
||||
{
|
||||
|
@ -170,6 +185,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <exception cref="DiskCacheLoadException">Texture information is not available on the cache</exception>
|
||||
public void RegisterTexture(int handle, int cbufSlot)
|
||||
{
|
||||
if (!_oldSpecState.TextureRegistered(_stageIndex, handle, cbufSlot))
|
||||
|
@ -182,5 +198,24 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
bool coordNormalized = _oldSpecState.GetCoordNormalized(_stageIndex, handle, cbufSlot);
|
||||
_newSpecState.RegisterTexture(_stageIndex, handle, cbufSlot, format, formatSrgb, target, coordNormalized);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cached texture or sampler pool capacity.
|
||||
/// </summary>
|
||||
/// <param name="isSampler">True to get sampler pool length, false for texture pool length</param>
|
||||
/// <returns>Pool length</returns>
|
||||
/// <exception cref="DiskCacheLoadException">Pool length is not available on the cache</exception>
|
||||
private int QueryArrayLengthFromPool(bool isSampler)
|
||||
{
|
||||
if (!_oldSpecState.TextureArrayFromPoolRegistered(isSampler))
|
||||
{
|
||||
throw new DiskCacheLoadException(DiskCacheLoadResult.MissingTextureArrayLength);
|
||||
}
|
||||
|
||||
int arrayLength = _oldSpecState.GetTextureArrayFromPoolLength(isSampler);
|
||||
_newSpecState.RegisterTextureArrayLengthFromPool(isSampler, arrayLength);
|
||||
|
||||
return arrayLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
private const ushort FileFormatVersionMajor = 1;
|
||||
private const ushort FileFormatVersionMinor = 2;
|
||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||
private const uint CodeGenVersion = 6489;
|
||||
private const uint CodeGenVersion = 6577;
|
||||
|
||||
private const string SharedTocFileName = "shared.toc";
|
||||
private const string SharedDataFileName = "shared.data";
|
||||
|
|
|
@ -120,6 +120,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
return _state.GraphicsState.HasUnalignedStorageBuffer || _state.ComputeState.HasUnalignedStorageBuffer;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int QuerySamplerArrayLengthFromPool()
|
||||
{
|
||||
int length = _state.SamplerPoolMaximumId + 1;
|
||||
_state.SpecializationState?.RegisterTextureArrayLengthFromPool(isSampler: true, length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public SamplerType QuerySamplerType(int handle, int cbufSlot)
|
||||
{
|
||||
|
@ -141,6 +150,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
return arrayLength;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int QueryTextureArrayLengthFromPool()
|
||||
{
|
||||
int length = _state.PoolState.TexturePoolMaximumId + 1;
|
||||
_state.SpecializationState?.RegisterTextureArrayLengthFromPool(isSampler: false, length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
//// <inheritdoc/>
|
||||
public TextureFormat QueryTextureFormat(int handle, int cbufSlot)
|
||||
{
|
||||
|
|
|
@ -213,6 +213,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
public bool QueryHostSupportsScaledVertexFormats() => _context.Capabilities.SupportsScaledVertexFormats;
|
||||
|
||||
public bool QueryHostSupportsSeparateSampler() => _context.Capabilities.SupportsSeparateSampler;
|
||||
|
||||
public bool QueryHostSupportsShaderBallot() => _context.Capabilities.SupportsShaderBallot;
|
||||
|
||||
public bool QueryHostSupportsShaderBarrierDivergence() => _context.Capabilities.SupportsShaderBarrierDivergence;
|
||||
|
|
|
@ -5,6 +5,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// </summary>
|
||||
class GpuAccessorState
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximum ID that a sampler pool entry may have.
|
||||
/// </summary>
|
||||
public readonly int SamplerPoolMaximumId;
|
||||
|
||||
/// <summary>
|
||||
/// GPU texture pool state.
|
||||
/// </summary>
|
||||
|
@ -38,18 +43,21 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <summary>
|
||||
/// Creates a new GPU accessor state.
|
||||
/// </summary>
|
||||
/// <param name="samplerPoolMaximumId">Maximum ID that a sampler pool entry may have</param>
|
||||
/// <param name="poolState">GPU texture pool state</param>
|
||||
/// <param name="computeState">GPU compute state, for compute shaders</param>
|
||||
/// <param name="graphicsState">GPU graphics state, for vertex, tessellation, geometry and fragment shaders</param>
|
||||
/// <param name="specializationState">Shader specialization state (shared by all stages)</param>
|
||||
/// <param name="transformFeedbackDescriptors">Transform feedback information, if the shader uses transform feedback. Otherwise, should be null</param>
|
||||
public GpuAccessorState(
|
||||
int samplerPoolMaximumId,
|
||||
GpuChannelPoolState poolState,
|
||||
GpuChannelComputeState computeState,
|
||||
GpuChannelGraphicsState graphicsState,
|
||||
ShaderSpecializationState specializationState,
|
||||
TransformFeedbackDescriptor[] transformFeedbackDescriptors = null)
|
||||
{
|
||||
SamplerPoolMaximumId = samplerPoolMaximumId;
|
||||
PoolState = poolState;
|
||||
GraphicsState = graphicsState;
|
||||
ComputeState = computeState;
|
||||
|
|
|
@ -2,7 +2,6 @@ using System;
|
|||
|
||||
namespace Ryujinx.Graphics.Gpu.Shader
|
||||
{
|
||||
#pragma warning disable CS0659 // Class overrides Object.Equals(object o) but does not override Object.GetHashCode()
|
||||
/// <summary>
|
||||
/// State used by the <see cref="GpuAccessor"/>.
|
||||
/// </summary>
|
||||
|
@ -52,6 +51,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
{
|
||||
return obj is GpuChannelPoolState state && Equals(state);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(TexturePoolGpuVa, TexturePoolMaximumId, TextureBufferIndex);
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0659
|
||||
}
|
||||
|
|
|
@ -192,12 +192,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// This automatically translates, compiles and adds the code to the cache if not present.
|
||||
/// </remarks>
|
||||
/// <param name="channel">GPU channel</param>
|
||||
/// <param name="samplerPoolMaximumId">Maximum ID that an entry in the sampler pool may have</param>
|
||||
/// <param name="poolState">Texture pool state</param>
|
||||
/// <param name="computeState">Compute engine state</param>
|
||||
/// <param name="gpuVa">GPU virtual address of the binary shader code</param>
|
||||
/// <returns>Compiled compute shader code</returns>
|
||||
public CachedShaderProgram GetComputeShader(
|
||||
GpuChannel channel,
|
||||
int samplerPoolMaximumId,
|
||||
GpuChannelPoolState poolState,
|
||||
GpuChannelComputeState computeState,
|
||||
ulong gpuVa)
|
||||
|
@ -214,7 +216,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
}
|
||||
|
||||
ShaderSpecializationState specState = new(ref computeState);
|
||||
GpuAccessorState gpuAccessorState = new(poolState, computeState, default, specState);
|
||||
GpuAccessorState gpuAccessorState = new(samplerPoolMaximumId, poolState, computeState, default, specState);
|
||||
GpuAccessor gpuAccessor = new(_context, channel, gpuAccessorState);
|
||||
gpuAccessor.InitializeReservedCounts(tfEnabled: false, vertexAsCompute: false);
|
||||
|
||||
|
@ -291,6 +293,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="state">GPU state</param>
|
||||
/// <param name="pipeline">Pipeline state</param>
|
||||
/// <param name="channel">GPU channel</param>
|
||||
/// <param name="samplerPoolMaximumId">Maximum ID that an entry in the sampler pool may have</param>
|
||||
/// <param name="poolState">Texture pool state</param>
|
||||
/// <param name="graphicsState">3D engine state</param>
|
||||
/// <param name="addresses">Addresses of the shaders for each stage</param>
|
||||
|
@ -299,6 +302,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
ref ThreedClassState state,
|
||||
ref ProgramPipelineState pipeline,
|
||||
GpuChannel channel,
|
||||
int samplerPoolMaximumId,
|
||||
ref GpuChannelPoolState poolState,
|
||||
ref GpuChannelGraphicsState graphicsState,
|
||||
ShaderAddresses addresses)
|
||||
|
@ -319,7 +323,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
UpdatePipelineInfo(ref state, ref pipeline, graphicsState, channel);
|
||||
|
||||
ShaderSpecializationState specState = new(ref graphicsState, ref pipeline, transformFeedbackDescriptors);
|
||||
GpuAccessorState gpuAccessorState = new(poolState, default, graphicsState, specState, transformFeedbackDescriptors);
|
||||
GpuAccessorState gpuAccessorState = new(samplerPoolMaximumId, poolState, default, graphicsState, specState, transformFeedbackDescriptors);
|
||||
|
||||
ReadOnlySpan<ulong> addressesSpan = addresses.AsSpan();
|
||||
|
||||
|
|
|
@ -185,11 +185,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
{
|
||||
if (texture.ArrayLength > 1)
|
||||
{
|
||||
bool isBuffer = (texture.Type & SamplerType.Mask) == SamplerType.TextureBuffer;
|
||||
|
||||
ResourceType type = isBuffer
|
||||
? (isImage ? ResourceType.BufferImage : ResourceType.BufferTexture)
|
||||
: (isImage ? ResourceType.Image : ResourceType.TextureAndSampler);
|
||||
ResourceType type = GetTextureResourceType(texture, isImage);
|
||||
|
||||
_resourceDescriptors[setIndex].Add(new ResourceDescriptor(texture.Binding, texture.ArrayLength, type, stages));
|
||||
}
|
||||
|
@ -242,16 +238,38 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
{
|
||||
foreach (TextureDescriptor texture in textures)
|
||||
{
|
||||
bool isBuffer = (texture.Type & SamplerType.Mask) == SamplerType.TextureBuffer;
|
||||
|
||||
ResourceType type = isBuffer
|
||||
? (isImage ? ResourceType.BufferImage : ResourceType.BufferTexture)
|
||||
: (isImage ? ResourceType.Image : ResourceType.TextureAndSampler);
|
||||
ResourceType type = GetTextureResourceType(texture, isImage);
|
||||
|
||||
_resourceUsages[setIndex].Add(new ResourceUsage(texture.Binding, texture.ArrayLength, type, stages));
|
||||
}
|
||||
}
|
||||
|
||||
private static ResourceType GetTextureResourceType(TextureDescriptor texture, bool isImage)
|
||||
{
|
||||
bool isBuffer = (texture.Type & SamplerType.Mask) == SamplerType.TextureBuffer;
|
||||
|
||||
if (isBuffer)
|
||||
{
|
||||
return isImage ? ResourceType.BufferImage : ResourceType.BufferTexture;
|
||||
}
|
||||
else if (isImage)
|
||||
{
|
||||
return ResourceType.Image;
|
||||
}
|
||||
else if (texture.Type == SamplerType.None)
|
||||
{
|
||||
return ResourceType.Sampler;
|
||||
}
|
||||
else if (texture.Separate)
|
||||
{
|
||||
return ResourceType.Texture;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResourceType.TextureAndSampler;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new shader information structure from the added information.
|
||||
/// </summary>
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
PrimitiveTopology = 1 << 1,
|
||||
TransformFeedback = 1 << 3,
|
||||
TextureArrayFromBuffer = 1 << 4,
|
||||
TextureArrayFromPool = 1 << 5,
|
||||
}
|
||||
|
||||
private QueriedStateFlags _queriedState;
|
||||
|
@ -154,7 +155,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
}
|
||||
|
||||
private readonly Dictionary<TextureKey, Box<TextureSpecializationState>> _textureSpecialization;
|
||||
private readonly Dictionary<TextureKey, int> _textureArraySpecialization;
|
||||
private readonly Dictionary<TextureKey, int> _textureArrayFromBufferSpecialization;
|
||||
private readonly Dictionary<bool, int> _textureArrayFromPoolSpecialization;
|
||||
private KeyValuePair<TextureKey, Box<TextureSpecializationState>>[] _allTextures;
|
||||
private Box<TextureSpecializationState>[][] _textureByBinding;
|
||||
private Box<TextureSpecializationState>[][] _imageByBinding;
|
||||
|
@ -165,7 +167,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
private ShaderSpecializationState()
|
||||
{
|
||||
_textureSpecialization = new Dictionary<TextureKey, Box<TextureSpecializationState>>();
|
||||
_textureArraySpecialization = new Dictionary<TextureKey, int>();
|
||||
_textureArrayFromBufferSpecialization = new Dictionary<TextureKey, int>();
|
||||
_textureArrayFromPoolSpecialization = new Dictionary<bool, int>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -327,7 +330,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the coordinate normalization state of a given texture was used during the shader translation process.
|
||||
/// Registers the length of a texture array calculated from a constant buffer size.
|
||||
/// </summary>
|
||||
/// <param name="stageIndex">Shader stage where the texture is used</param>
|
||||
/// <param name="handle">Offset in words of the texture handle on the texture buffer</param>
|
||||
|
@ -335,10 +338,21 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="length">Number of elements in the texture array</param>
|
||||
public void RegisterTextureArrayLengthFromBuffer(int stageIndex, int handle, int cbufSlot, int length)
|
||||
{
|
||||
_textureArraySpecialization[new TextureKey(stageIndex, handle, cbufSlot)] = length;
|
||||
_textureArrayFromBufferSpecialization[new TextureKey(stageIndex, handle, cbufSlot)] = length;
|
||||
_queriedState |= QueriedStateFlags.TextureArrayFromBuffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers the length of a texture array calculated from a texture or sampler pool capacity.
|
||||
/// </summary>
|
||||
/// <param name="isSampler">True for sampler pool, false for texture pool</param>
|
||||
/// <param name="length">Number of elements in the texture array</param>
|
||||
public void RegisterTextureArrayLengthFromPool(bool isSampler, int length)
|
||||
{
|
||||
_textureArrayFromPoolSpecialization[isSampler] = length;
|
||||
_queriedState |= QueriedStateFlags.TextureArrayFromPool;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the format of a given texture was used during the shader translation process.
|
||||
/// </summary>
|
||||
|
@ -385,7 +399,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a given texture was registerd on this specialization state.
|
||||
/// Checks if a given texture was registered on this specialization state.
|
||||
/// </summary>
|
||||
/// <param name="stageIndex">Shader stage where the texture is used</param>
|
||||
/// <param name="handle">Offset in words of the texture handle on the texture buffer</param>
|
||||
|
@ -396,14 +410,25 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a given texture array (from constant buffer) was registerd on this specialization state.
|
||||
/// Checks if a given texture array (from constant buffer) was registered on this specialization state.
|
||||
/// </summary>
|
||||
/// <param name="stageIndex">Shader stage where the texture is used</param>
|
||||
/// <param name="handle">Offset in words of the texture handle on the texture buffer</param>
|
||||
/// <param name="cbufSlot">Slot of the texture buffer constant buffer</param>
|
||||
/// <returns>True if the length for the given buffer and stage exists, false otherwise</returns>
|
||||
public bool TextureArrayFromBufferRegistered(int stageIndex, int handle, int cbufSlot)
|
||||
{
|
||||
return _textureArraySpecialization.ContainsKey(new TextureKey(stageIndex, handle, cbufSlot));
|
||||
return _textureArrayFromBufferSpecialization.ContainsKey(new TextureKey(stageIndex, handle, cbufSlot));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a given texture array (from a sampler pool or texture pool) was registered on this specialization state.
|
||||
/// </summary>
|
||||
/// <param name="isSampler">True for sampler pool, false for texture pool</param>
|
||||
/// <returns>True if the length for the given pool, false otherwise</returns>
|
||||
public bool TextureArrayFromPoolRegistered(bool isSampler)
|
||||
{
|
||||
return _textureArrayFromPoolSpecialization.ContainsKey(isSampler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -412,6 +437,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="stageIndex">Shader stage where the texture is used</param>
|
||||
/// <param name="handle">Offset in words of the texture handle on the texture buffer</param>
|
||||
/// <param name="cbufSlot">Slot of the texture buffer constant buffer</param>
|
||||
/// <returns>Format and sRGB tuple</returns>
|
||||
public (uint, bool) GetFormat(int stageIndex, int handle, int cbufSlot)
|
||||
{
|
||||
TextureSpecializationState state = GetTextureSpecState(stageIndex, handle, cbufSlot).Value;
|
||||
|
@ -424,6 +450,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="stageIndex">Shader stage where the texture is used</param>
|
||||
/// <param name="handle">Offset in words of the texture handle on the texture buffer</param>
|
||||
/// <param name="cbufSlot">Slot of the texture buffer constant buffer</param>
|
||||
/// <returns>Texture target</returns>
|
||||
public TextureTarget GetTextureTarget(int stageIndex, int handle, int cbufSlot)
|
||||
{
|
||||
return GetTextureSpecState(stageIndex, handle, cbufSlot).Value.TextureTarget;
|
||||
|
@ -435,6 +462,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="stageIndex">Shader stage where the texture is used</param>
|
||||
/// <param name="handle">Offset in words of the texture handle on the texture buffer</param>
|
||||
/// <param name="cbufSlot">Slot of the texture buffer constant buffer</param>
|
||||
/// <returns>True if coordinates are normalized, false otherwise</returns>
|
||||
public bool GetCoordNormalized(int stageIndex, int handle, int cbufSlot)
|
||||
{
|
||||
return GetTextureSpecState(stageIndex, handle, cbufSlot).Value.CoordNormalized;
|
||||
|
@ -446,9 +474,20 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="stageIndex">Shader stage where the texture is used</param>
|
||||
/// <param name="handle">Offset in words of the texture handle on the texture buffer</param>
|
||||
/// <param name="cbufSlot">Slot of the texture buffer constant buffer</param>
|
||||
/// <returns>Texture array length</returns>
|
||||
public int GetTextureArrayFromBufferLength(int stageIndex, int handle, int cbufSlot)
|
||||
{
|
||||
return _textureArraySpecialization[new TextureKey(stageIndex, handle, cbufSlot)];
|
||||
return _textureArrayFromBufferSpecialization[new TextureKey(stageIndex, handle, cbufSlot)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the recorded length of a given texture array (from a sampler or texture pool).
|
||||
/// </summary>
|
||||
/// <param name="isSampler">True to get the sampler pool length, false to get the texture pool length</param>
|
||||
/// <returns>Texture array length</returns>
|
||||
public int GetTextureArrayFromPoolLength(bool isSampler)
|
||||
{
|
||||
return _textureArrayFromPoolSpecialization[isSampler];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -894,7 +933,23 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
dataReader.ReadWithMagicAndSize(ref textureKey, TexkMagic);
|
||||
dataReader.Read(ref length);
|
||||
|
||||
specState._textureArraySpecialization[textureKey] = length;
|
||||
specState._textureArrayFromBufferSpecialization[textureKey] = length;
|
||||
}
|
||||
}
|
||||
|
||||
if (specState._queriedState.HasFlag(QueriedStateFlags.TextureArrayFromPool))
|
||||
{
|
||||
dataReader.Read(ref count);
|
||||
|
||||
for (int index = 0; index < count; index++)
|
||||
{
|
||||
bool textureKey = default;
|
||||
int length = 0;
|
||||
|
||||
dataReader.ReadWithMagicAndSize(ref textureKey, TexkMagic);
|
||||
dataReader.Read(ref length);
|
||||
|
||||
specState._textureArrayFromPoolSpecialization[textureKey] = length;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -965,10 +1020,25 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
if (_queriedState.HasFlag(QueriedStateFlags.TextureArrayFromBuffer))
|
||||
{
|
||||
count = (ushort)_textureArraySpecialization.Count;
|
||||
count = (ushort)_textureArrayFromBufferSpecialization.Count;
|
||||
dataWriter.Write(ref count);
|
||||
|
||||
foreach (var kv in _textureArraySpecialization)
|
||||
foreach (var kv in _textureArrayFromBufferSpecialization)
|
||||
{
|
||||
var textureKey = kv.Key;
|
||||
var length = kv.Value;
|
||||
|
||||
dataWriter.WriteWithMagicAndSize(ref textureKey, TexkMagic);
|
||||
dataWriter.Write(ref length);
|
||||
}
|
||||
}
|
||||
|
||||
if (_queriedState.HasFlag(QueriedStateFlags.TextureArrayFromPool))
|
||||
{
|
||||
count = (ushort)_textureArrayFromPoolSpecialization.Count;
|
||||
dataWriter.Write(ref count);
|
||||
|
||||
foreach (var kv in _textureArrayFromPoolSpecialization)
|
||||
{
|
||||
var textureKey = kv.Key;
|
||||
var length = kv.Value;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue