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:
parent
5561a3b95e
commit
8d168574eb
20 changed files with 496 additions and 551 deletions
|
@ -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};");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue