SPIR-V: Geometry shader passthrough support

This commit is contained in:
gdk 2022-04-07 20:01:13 -03:00 committed by riperiperi
parent cacc9c7da4
commit 3b444f0ea3
4 changed files with 63 additions and 1 deletions

View file

@ -385,6 +385,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var spvType = context.TypePointer(StorageClass.Input, attrType); var spvType = context.TypePointer(StorageClass.Input, attrType);
var spvVar = context.Variable(spvType, StorageClass.Input); var spvVar = context.Variable(spvType, StorageClass.Input);
if (context.Config.PassthroughAttributes != 0)
{
context.Decorate(spvVar, Decoration.PassthroughNV);
}
context.Decorate(spvVar, Decoration.Location, (LiteralInteger)0); context.Decorate(spvVar, Decoration.Location, (LiteralInteger)0);
context.AddGlobalVariable(spvVar); context.AddGlobalVariable(spvVar);
@ -483,10 +488,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input; var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input;
var attrType = context.GetType(attrInfo.Type, attrInfo.Length); var attrType = context.GetType(attrInfo.Type, attrInfo.Length);
bool builtInPassthrough = false;
if (context.Config.Stage == ShaderStage.Geometry && !isOutAttr && (!attrInfo.IsBuiltin || AttributeInfo.IsArrayBuiltIn(attr))) if (context.Config.Stage == ShaderStage.Geometry && !isOutAttr && (!attrInfo.IsBuiltin || AttributeInfo.IsArrayBuiltIn(attr)))
{ {
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)context.InputVertices)); attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)context.InputVertices));
if (context.Config.GpPassthrough)
{
builtInPassthrough = true;
}
} }
var spvType = context.TypePointer(storageClass, attrType); var spvType = context.TypePointer(storageClass, attrType);
@ -497,6 +508,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
context.Decorate(spvVar, Decoration.Patch); context.Decorate(spvVar, Decoration.Patch);
} }
if (builtInPassthrough)
{
context.Decorate(spvVar, Decoration.PassthroughNV);
}
if (attrInfo.IsBuiltin) if (attrInfo.IsBuiltin)
{ {
context.Decorate(spvVar, Decoration.BuiltIn, (LiteralInteger)GetBuiltIn(context, attrInfo.BaseValue)); context.Decorate(spvVar, Decoration.BuiltIn, (LiteralInteger)GetBuiltIn(context, attrInfo.BaseValue));
@ -525,6 +541,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (!isOutAttr) if (!isOutAttr)
{ {
if (!perPatch && (context.Config.PassthroughAttributes & (1 << location)) != 0)
{
context.Decorate(spvVar, Decoration.PassthroughNV);
}
switch (iq) switch (iq)
{ {
case PixelImap.Constant: case PixelImap.Constant:
@ -585,6 +606,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
} }
else else
{ {
if ((context.Config.PassthroughAttributes & (1 << location)) != 0)
{
context.Decorate(spvVar, Decoration.PassthroughNV);
}
switch (iq) switch (iq)
{ {
case PixelImap.Constant: case PixelImap.Constant:

View file

@ -69,6 +69,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
else if (config.Stage == ShaderStage.Geometry) else if (config.Stage == ShaderStage.Geometry)
{ {
context.AddCapability(Capability.Geometry); context.AddCapability(Capability.Geometry);
if (config.GpPassthrough)
{
context.AddExtension("SPV_NV_geometry_shader_passthrough");
context.AddCapability(Capability.GeometryShaderPassthroughNV);
}
} }
else if (config.Stage == ShaderStage.TessellationControl || config.Stage == ShaderStage.TessellationEvaluation) else if (config.Stage == ShaderStage.TessellationControl || config.Stage == ShaderStage.TessellationEvaluation)
{ {

View file

@ -2,6 +2,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper;
@ -35,6 +36,34 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Info = new StructuredProgramInfo(); Info = new StructuredProgramInfo();
Config = config; Config = config;
if (config.GpPassthrough)
{
int passthroughAttributes = config.PassthroughAttributes;
while (passthroughAttributes != 0)
{
int index = BitOperations.TrailingZeroCount(passthroughAttributes);
int attrBase = AttributeConsts.UserAttributeBase + index * 16;
Info.Inputs.Add(attrBase);
Info.Inputs.Add(attrBase + 4);
Info.Inputs.Add(attrBase + 8);
Info.Inputs.Add(attrBase + 12);
passthroughAttributes &= ~(1 << index);
}
Info.Inputs.Add(AttributeConsts.PositionX);
Info.Inputs.Add(AttributeConsts.PositionY);
Info.Inputs.Add(AttributeConsts.PositionZ);
Info.Inputs.Add(AttributeConsts.PositionW);
Info.Inputs.Add(AttributeConsts.PointSize);
for (int i = 0; i < 8; i++)
{
Info.Inputs.Add(AttributeConsts.ClipDistance0 + i * 4);
}
}
} }
public void EnterFunction( public void EnterFunction(

View file

@ -32,7 +32,8 @@ namespace Ryujinx.Graphics.Vulkan
"VK_EXT_fragment_shader_interlock", "VK_EXT_fragment_shader_interlock",
"VK_EXT_index_type_uint8", "VK_EXT_index_type_uint8",
"VK_EXT_robustness2", "VK_EXT_robustness2",
"VK_EXT_shader_subgroup_ballot" "VK_EXT_shader_subgroup_ballot",
"VK_NV_geometry_shader_passthrough"
}; };
private static readonly string[] _excludedMessages = new string[] private static readonly string[] _excludedMessages = new string[]