Use explicit buffer and texture bindings on shaders (#1666)

* Use explicit buffer and texture bindings on shaders

* More XML docs and other nits
This commit is contained in:
gdkchan 2020-11-08 08:10:00 -03:00 committed by GitHub
parent 5561a3b95e
commit 8d168574eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 496 additions and 551 deletions

View file

@ -218,50 +218,46 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
if (info.UsesCbIndexing)
{
int count = info.CBuffers.Max() + 1;
int[] bindings = new int[count];
for (int i = 0; i < count; i++)
{
bindings[i] = context.Config.Counts.IncrementUniformBuffersCount();
}
foreach (int cbufSlot in info.CBuffers.OrderBy(x => x))
{
context.CBufferDescriptors.Add(new BufferDescriptor(bindings[cbufSlot], cbufSlot));
}
string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
ubName += "_" + DefaultNames.UniformNamePrefix;
string blockName = $"{ubName}_{DefaultNames.BlockSuffix}";
int maxSlot = 0;
foreach (int cbufSlot in info.CBuffers.OrderBy(x => x))
{
context.CBufferDescriptors.Add(new BufferDescriptor($"{blockName}[{cbufSlot}]", cbufSlot));
if (maxSlot < cbufSlot)
{
maxSlot = cbufSlot;
}
}
context.AppendLine("layout (std140) uniform " + blockName);
context.AppendLine($"layout (binding = {bindings[0]}, std140) uniform {blockName}");
context.EnterScope();
context.AppendLine("vec4 " + DefaultNames.DataName + ubSize + ";");
string arraySize = NumberFormatter.FormatInt(maxSlot + 1);
context.LeaveScope($" {ubName}[{arraySize}];");
context.LeaveScope($" {ubName}[{NumberFormatter.FormatInt(count)}];");
}
else
{
foreach (int cbufSlot in info.CBuffers.OrderBy(x => x))
{
int binding = context.Config.Counts.IncrementUniformBuffersCount();
context.CBufferDescriptors.Add(new BufferDescriptor(binding, cbufSlot));
string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
ubName += "_" + DefaultNames.UniformNamePrefix + cbufSlot;
context.CBufferDescriptors.Add(new BufferDescriptor(ubName, cbufSlot));
context.AppendLine("layout (std140) uniform " + ubName);
context.AppendLine($"layout (binding = {binding}, std140) uniform {ubName}");
context.EnterScope();
context.AppendLine("vec4 " + OperandManager.GetUbName(context.Config.Stage, cbufSlot, false) + ubSize + ";");
context.LeaveScope(";");
}
}
@ -275,32 +271,29 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string blockName = $"{sbName}_{DefaultNames.BlockSuffix}";
int maxSlot = 0;
int count = info.SBuffers.Max() + 1;
int[] bindings = new int[count];
for (int i = 0; i < count; i++)
{
bindings[i] = context.Config.Counts.IncrementStorageBuffersCount();
}
foreach (int sbufSlot in info.SBuffers)
{
context.SBufferDescriptors.Add(new BufferDescriptor($"{blockName}[{sbufSlot}]", sbufSlot));
if (maxSlot < sbufSlot)
{
maxSlot = sbufSlot;
}
context.SBufferDescriptors.Add(new BufferDescriptor(bindings[sbufSlot], sbufSlot));
}
context.AppendLine("layout (std430) buffer " + blockName);
context.AppendLine($"layout (binding = {bindings[0]}, std430) buffer {blockName}");
context.EnterScope();
context.AppendLine("uint " + DefaultNames.DataName + "[];");
string arraySize = NumberFormatter.FormatInt(maxSlot + 1);
context.LeaveScope($" {sbName}[{arraySize}];");
context.LeaveScope($" {sbName}[{NumberFormatter.FormatInt(count)}];");
}
private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info)
{
Dictionary<string, AstTextureOperation> samplers = new Dictionary<string, AstTextureOperation>();
HashSet<string> samplers = new HashSet<string>();
// Texture instructions other than TextureSample (like TextureSize)
// may have incomplete sampler type information. In those cases,
@ -312,29 +305,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);
if (!samplers.TryAdd(samplerName, texOp))
if (!samplers.Add(samplerName))
{
continue;
}
string samplerTypeName = texOp.Type.ToGlslSamplerType();
context.AppendLine("uniform " + samplerTypeName + " " + samplerName + ";");
}
foreach (KeyValuePair<string, AstTextureOperation> kv in samplers)
{
string samplerName = kv.Key;
AstTextureOperation texOp = kv.Value;
TextureDescriptor desc;
int firstBinding = -1;
if ((texOp.Flags & TextureFlags.Bindless) != 0)
{
AstOperand operand = texOp.GetSource(0) as AstOperand;
desc = new TextureDescriptor(samplerName, texOp.Type, operand.CbufSlot, operand.CbufOffset);
firstBinding = context.Config.Counts.IncrementTexturesCount();
var desc = new TextureDescriptor(firstBinding, texOp.Type, operand.CbufSlot, operand.CbufOffset);
context.TextureDescriptors.Add(desc);
}
@ -342,27 +326,36 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
for (int index = 0; index < texOp.ArraySize; index++)
{
string indexExpr = NumberFormatter.FormatInt(index);
int binding = context.Config.Counts.IncrementTexturesCount();
string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);
if (firstBinding < 0)
{
firstBinding = binding;
}
desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Format, texOp.Handle + index * 2);
var desc = new TextureDescriptor(binding, texOp.Type, texOp.Format, texOp.Handle + index * 2);
context.TextureDescriptors.Add(desc);
}
}
else
{
desc = new TextureDescriptor(samplerName, texOp.Type, texOp.Format, texOp.Handle);
firstBinding = context.Config.Counts.IncrementTexturesCount();
var desc = new TextureDescriptor(firstBinding, texOp.Type, texOp.Format, texOp.Handle);
context.TextureDescriptors.Add(desc);
}
string samplerTypeName = texOp.Type.ToGlslSamplerType();
context.AppendLine($"layout (binding = {firstBinding}) uniform {samplerTypeName} {samplerName};");
}
}
private static void DeclareImages(CodeGenContext context, StructuredProgramInfo info)
{
Dictionary<string, AstTextureOperation> images = new Dictionary<string, AstTextureOperation>();
HashSet<string> images = new HashSet<string>();
foreach (AstTextureOperation texOp in info.Images.OrderBy(x => x.Handle))
{
@ -370,48 +363,48 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);
if (!images.TryAdd(imageName, texOp))
if (!images.Add(imageName))
{
continue;
}
int firstBinding = -1;
if ((texOp.Type & SamplerType.Indexed) != 0)
{
for (int index = 0; index < texOp.ArraySize; index++)
{
int binding = context.Config.Counts.IncrementImagesCount();
if (firstBinding < 0)
{
firstBinding = binding;
}
var desc = new TextureDescriptor(binding, texOp.Type, texOp.Format, texOp.Handle + index * 2);
context.ImageDescriptors.Add(desc);
}
}
else
{
firstBinding = context.Config.Counts.IncrementImagesCount();
var desc = new TextureDescriptor(firstBinding, texOp.Type, texOp.Format, texOp.Handle);
context.ImageDescriptors.Add(desc);
}
string layout = texOp.Format.ToGlslFormat();
if (!string.IsNullOrEmpty(layout))
{
layout = "layout(" + layout + ") ";
layout = ", " + layout;
}
string imageTypeName = texOp.Type.ToGlslImageType(texOp.Format.GetComponentType());
context.AppendLine("uniform " + layout + imageTypeName + " " + imageName + ";");
}
foreach (KeyValuePair<string, AstTextureOperation> kv in images)
{
string imageName = kv.Key;
AstTextureOperation texOp = kv.Value;
if ((texOp.Type & SamplerType.Indexed) != 0)
{
for (int index = 0; index < texOp.ArraySize; index++)
{
string indexExpr = NumberFormatter.FormatInt(index);
string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);
var desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Format, texOp.Handle + index * 2);
context.TextureDescriptors.Add(desc);
}
}
else
{
var desc = new TextureDescriptor(imageName, texOp.Type, texOp.Format, texOp.Handle);
context.ImageDescriptors.Add(desc);
}
context.AppendLine($"layout (binding = {firstBinding}{layout}) uniform {imageTypeName} {imageName};");
}
}