Fix constant buffer array size when indexing is used and other buffer descriptor and resolution scale regressions (#2298)

* Fix constant buffer array size when indexing is used

* Change default QueryConstantBufferUse value

* Fix more regressions

* Ensure proper order
This commit is contained in:
gdkchan 2021-05-20 15:12:15 -03:00 committed by GitHub
parent 7b8ad1c36c
commit b34c0a47b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 23 deletions

View file

@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <summary> /// <summary>
/// Version of the codegen (to be changed when codegen or guest format change). /// Version of the codegen (to be changed when codegen or guest format change).
/// </summary> /// </summary>
private const ulong ShaderCodeGenVersion = 2290; private const ulong ShaderCodeGenVersion = 2298;
// Progress reporting helpers // Progress reporting helpers
private volatile int _shaderCount; private volatile int _shaderCount;

View file

@ -262,10 +262,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string blockName = $"{ubName}_{DefaultNames.BlockSuffix}"; string blockName = $"{ubName}_{DefaultNames.BlockSuffix}";
context.AppendLine($"layout (binding = {descriptors[0].Binding}, std140) uniform {blockName}"); context.AppendLine($"layout (binding = {context.Config.FirstConstantBufferBinding}, std140) uniform {blockName}");
context.EnterScope(); context.EnterScope();
context.AppendLine("vec4 " + DefaultNames.DataName + ubSize + ";"); context.AppendLine("vec4 " + DefaultNames.DataName + ubSize + ";");
context.LeaveScope($" {ubName}[{NumberFormatter.FormatInt(descriptors.Length)}];"); context.LeaveScope($" {ubName}[{NumberFormatter.FormatInt(descriptors.Max(x => x.Slot) + 1)}];");
} }
else else
{ {
@ -291,10 +291,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string blockName = $"{sbName}_{DefaultNames.BlockSuffix}"; string blockName = $"{sbName}_{DefaultNames.BlockSuffix}";
context.AppendLine($"layout (binding = {descriptors[0].Binding}, std430) buffer {blockName}"); context.AppendLine($"layout (binding = {context.Config.FirstStorageBufferBinding}, std430) buffer {blockName}");
context.EnterScope(); context.EnterScope();
context.AppendLine("uint " + DefaultNames.DataName + "[];"); context.AppendLine("uint " + DefaultNames.DataName + "[];");
context.LeaveScope($" {sbName}[{NumberFormatter.FormatInt(descriptors.Length)}];"); context.LeaveScope($" {sbName}[{NumberFormatter.FormatInt(descriptors.Max(x => x.Slot) + 1)}];");
} }
private static void DeclareSamplers(CodeGenContext context, TextureDescriptor[] descriptors) private static void DeclareSamplers(CodeGenContext context, TextureDescriptor[] descriptors)

View file

@ -41,7 +41,7 @@
uint QueryConstantBufferUse() uint QueryConstantBufferUse()
{ {
return 0xffff; return 0;
} }
bool QueryIsTextureBuffer(int handle, int cbufSlot = -1) bool QueryIsTextureBuffer(int handle, int cbufSlot = -1)

View file

@ -293,7 +293,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Instruction.Branch or Instruction.Branch or
Instruction.BranchIfFalse or Instruction.BranchIfFalse or
Instruction.BranchIfTrue => true, Instruction.BranchIfTrue => true,
_ => false, _ => false
}; };
} }

View file

@ -91,6 +91,9 @@ namespace Ryujinx.Graphics.Shader.Translation
private TextureDescriptor[] _cachedTextureDescriptors; private TextureDescriptor[] _cachedTextureDescriptors;
private TextureDescriptor[] _cachedImageDescriptors; private TextureDescriptor[] _cachedImageDescriptors;
public int FirstConstantBufferBinding { get; private set; }
public int FirstStorageBufferBinding { get; private set; }
public ShaderConfig(IGpuAccessor gpuAccessor, TranslationFlags flags, TranslationCounts counts) public ShaderConfig(IGpuAccessor gpuAccessor, TranslationFlags flags, TranslationCounts counts)
{ {
Stage = ShaderStage.Compute; Stage = ShaderStage.Compute;
@ -215,7 +218,7 @@ namespace Ryujinx.Graphics.Shader.Translation
} }
} }
private static void SetUsedTextureOrImage( private void SetUsedTextureOrImage(
Dictionary<TextureInfo, TextureMeta> dict, Dictionary<TextureInfo, TextureMeta> dict,
int cbufSlot, int cbufSlot,
int handle, int handle,
@ -235,7 +238,10 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
usageFlags |= TextureUsageFlags.NeedsScaleValue; usageFlags |= TextureUsageFlags.NeedsScaleValue;
var canScale = (dimensions == 2 && !isArray) || (dimensions == 3 && isArray); var canScale = (Stage == ShaderStage.Fragment || Stage == ShaderStage.Compute) && !isIndexed && !write &&
((dimensions == 2 && !isArray) ||
(dimensions == 3 && isArray));
if (!canScale) if (!canScale)
{ {
// Resolution scaling cannot be applied to this texture right now. // Resolution scaling cannot be applied to this texture right now.
@ -293,34 +299,59 @@ namespace Ryujinx.Graphics.Shader.Translation
if (UsedFeatures.HasFlag(FeatureFlags.CbIndexing)) if (UsedFeatures.HasFlag(FeatureFlags.CbIndexing))
{ {
usedMask = FillMask(usedMask); usedMask |= (int)GpuAccessor.QueryConstantBufferUse();
} }
return _cachedConstantBufferDescriptors = GetBufferDescriptors(usedMask, 0, _counts.IncrementUniformBuffersCount); FirstConstantBufferBinding = _counts.UniformBuffersCount;
return _cachedConstantBufferDescriptors = GetBufferDescriptors(
usedMask,
0,
UsedFeatures.HasFlag(FeatureFlags.CbIndexing),
_counts.IncrementUniformBuffersCount);
} }
public BufferDescriptor[] GetStorageBufferDescriptors() public BufferDescriptor[] GetStorageBufferDescriptors()
{ {
return _cachedStorageBufferDescriptors ??= GetBufferDescriptors(FillMask(_usedStorageBuffers), _usedStorageBuffersWrite, _counts.IncrementStorageBuffersCount); if (_cachedStorageBufferDescriptors != null)
{
return _cachedStorageBufferDescriptors;
}
FirstStorageBufferBinding = _counts.StorageBuffersCount;
return _cachedStorageBufferDescriptors = GetBufferDescriptors(
_usedStorageBuffers,
_usedStorageBuffersWrite,
true,
_counts.IncrementStorageBuffersCount);
} }
private static int FillMask(int mask) private static BufferDescriptor[] GetBufferDescriptors(
{ int usedMask,
// When the storage or uniform buffers are used as array, we must allocate a binding int writtenMask,
// even for the "gaps" that are not used on the shader. bool isArray,
// For this reason, fill up the gaps so that all slots up to the highest one are Func<int> getBindingCallback)
// marked as "used".
return mask != 0 ? (int)(uint.MaxValue >> BitOperations.LeadingZeroCount((uint)mask)) : 0;
}
private static BufferDescriptor[] GetBufferDescriptors(int usedMask, int writtenMask, Func<int> getBindingCallback)
{ {
var descriptors = new BufferDescriptor[BitOperations.PopCount((uint)usedMask)]; var descriptors = new BufferDescriptor[BitOperations.PopCount((uint)usedMask)];
int lastSlot = -1;
for (int i = 0; i < descriptors.Length; i++) for (int i = 0; i < descriptors.Length; i++)
{ {
int slot = BitOperations.TrailingZeroCount(usedMask); int slot = BitOperations.TrailingZeroCount(usedMask);
if (isArray)
{
// The next array entries also consumes bindings, even if they are unused.
for (int j = lastSlot + 1; j < slot; j++)
{
getBindingCallback();
}
}
lastSlot = slot;
descriptors[i] = new BufferDescriptor(getBindingCallback(), slot); descriptors[i] = new BufferDescriptor(getBindingCallback(), slot);
if ((writtenMask & (1 << slot)) != 0) if ((writtenMask & (1 << slot)) != 0)