diff options
Diffstat (limited to 'Ryujinx.Graphics.Shader/CodeGen/Glsl')
6 files changed, 105 insertions, 126 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs index 82534749..418af6cb 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs @@ -70,53 +70,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl AppendLine("}" + suffix); } - public (TextureDescriptor, int) FindTextureDescriptor(AstTextureOperation texOp) - { - TextureDescriptor[] descriptors = Config.GetTextureDescriptors(); - - for (int i = 0; i < descriptors.Length; i++) - { - var descriptor = descriptors[i]; - - if (descriptor.CbufSlot == texOp.CbufSlot && - descriptor.HandleIndex == texOp.Handle && - descriptor.Format == texOp.Format) - { - return (descriptor, i); - } - } - - return (default, -1); - } - - private static int FindDescriptorIndex(TextureDescriptor[] array, AstTextureOperation texOp) - { - for (int i = 0; i < array.Length; i++) - { - var descriptor = array[i]; - - if (descriptor.Type == texOp.Type && - descriptor.CbufSlot == texOp.CbufSlot && - descriptor.HandleIndex == texOp.Handle && - descriptor.Format == texOp.Format) - { - return i; - } - } - - return -1; - } - - public int FindTextureDescriptorIndex(AstTextureOperation texOp) - { - return FindDescriptorIndex(Config.GetTextureDescriptors(), texOp); - } - - public int FindImageDescriptorIndex(AstTextureOperation texOp) - { - return FindDescriptorIndex(Config.GetImageDescriptors(), texOp); - } - public StructuredFunction GetFunction(int id) { return _info.Functions[id]; diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index 54578b79..f9dfb839 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { public static void Declare(CodeGenContext context, StructuredProgramInfo info) { - context.AppendLine("#version 450 core"); + context.AppendLine(context.Config.Options.TargetApi == TargetApi.Vulkan ? "#version 460 core" : "#version 450 core"); context.AppendLine("#extension GL_ARB_gpu_shader_int64 : enable"); if (context.Config.GpuAccessor.QueryHostSupportsShaderBallot()) @@ -43,8 +43,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.AppendLine("#extension GL_INTEL_fragment_shader_ordering : enable"); } } + else + { + context.AppendLine("#extension GL_ARB_shader_viewport_layer_array : enable"); + } - if (context.Config.GpPassthrough) + if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough()) { context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable"); } @@ -123,11 +127,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { if (context.Config.Stage == ShaderStage.Geometry) { - string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString(); + InputTopology inputTopology = context.Config.GpuAccessor.QueryPrimitiveTopology(); + string inPrimitive = inputTopology.ToGlslString(); - context.AppendLine($"layout ({inPrimitive}) in;"); + context.AppendLine($"layout (invocations = {context.Config.ThreadsPerInputPrimitive}, {inPrimitive}) in;"); - if (context.Config.GpPassthrough) + if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough()) { context.AppendLine($"layout (passthrough) in gl_PerVertex"); context.EnterScope(); @@ -140,7 +145,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { string outPrimitive = context.Config.OutputTopology.ToGlslString(); - int maxOutputVertices = context.Config.MaxOutputVertices; + int maxOutputVertices = context.Config.GpPassthrough + ? inputTopology.ToInputVertices() + : context.Config.MaxOutputVertices; context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;"); } @@ -192,9 +199,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.AppendLine(); } - if (context.Config.Stage != ShaderStage.Compute && - context.Config.Stage != ShaderStage.Fragment && - context.Config.TransformFeedbackEnabled) + if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline) { var tfOutput = context.GetTransformFeedbackOutput(AttributeConsts.PositionX); if (tfOutput.Valid) @@ -311,6 +316,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } } + private static string GetTfLayout(TransformFeedbackOutput tfOutput) + { + if (tfOutput.Valid) + { + return $"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) "; + } + + return string.Empty; + } + public static void DeclareLocals(CodeGenContext context, StructuredFunction function) { foreach (AstOperand decl in function.Locals) @@ -326,11 +341,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl switch (type) { case VariableType.Bool: return "bool"; - case VariableType.F32: return "precise float"; - case VariableType.F64: return "double"; + case VariableType.F32: return "precise float"; + case VariableType.F64: return "double"; case VariableType.None: return "void"; - case VariableType.S32: return "int"; - case VariableType.U32: return "uint"; + case VariableType.S32: return "int"; + case VariableType.U32: return "uint"; } throw new ArgumentException($"Invalid variable type \"{type}\"."); @@ -417,10 +432,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl if (context.Config.Options.TargetApi == TargetApi.Vulkan) { - bool isBuffer = (descriptor.Type & SamplerType.Mask) == SamplerType.TextureBuffer; - int setIndex = isBuffer ? 4 : 2; - - layout = $", set = {setIndex}"; + layout = ", set = 2"; } context.AppendLine($"layout (binding = {descriptor.Binding}{layout}) uniform {samplerTypeName} {samplerName};"); @@ -470,10 +482,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl if (context.Config.Options.TargetApi == TargetApi.Vulkan) { - bool isBuffer = (descriptor.Type & SamplerType.Mask) == SamplerType.TextureBuffer; - int setIndex = isBuffer ? 5 : 3; - - layout = $", set = {setIndex}{layout}"; + layout = $", set = 3{layout}"; } context.AppendLine($"layout (binding = {descriptor.Binding}{layout}) uniform {imageTypeName} {imageName};"); @@ -512,7 +521,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl private static void DeclareInputAttribute(CodeGenContext context, StructuredProgramInfo info, int attr) { - string suffix = OperandManager.IsArrayAttribute(context.Config.Stage, isOutAttr: false) ? "[]" : string.Empty; + string suffix = AttributeInfo.IsArrayAttributeGlsl(context.Config.Stage, isOutAttr: false) ? "[]" : string.Empty; string iq = string.Empty; if (context.Config.Stage == ShaderStage.Fragment) @@ -525,29 +534,48 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl }; } - string pass = (context.Config.PassthroughAttributes & (1 << attr)) != 0 ? "passthrough, " : string.Empty; string name = $"{DefaultNames.IAttributePrefix}{attr}"; - if (context.Config.TransformFeedbackEnabled && context.Config.Stage != ShaderStage.Vertex) + if (context.Config.TransformFeedbackEnabled && context.Config.Stage == ShaderStage.Fragment) { for (int c = 0; c < 4; c++) { char swzMask = "xyzw"[c]; - context.AppendLine($"layout ({pass}location = {attr}, component = {c}) {iq}in float {name}_{swzMask}{suffix};"); + context.AppendLine($"layout (location = {attr}, component = {c}) {iq}in float {name}_{swzMask}{suffix};"); } } else { - context.AppendLine($"layout ({pass}location = {attr}) {iq}in vec4 {name}{suffix};"); + bool passthrough = (context.Config.PassthroughAttributes & (1 << attr)) != 0; + string pass = passthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough() ? "passthrough, " : string.Empty; + string type; + + if (context.Config.Stage == ShaderStage.Vertex) + { + type = context.Config.GpuAccessor.QueryAttributeType(attr).GetVec4Type(); + } + else + { + type = AttributeType.Float.GetVec4Type(); + } + + context.AppendLine($"layout ({pass}location = {attr}) {iq}in {type} {name}{suffix};"); } } private static void DeclareInputAttributePerPatch(CodeGenContext context, int attr) { + string layout = string.Empty; + + if (context.Config.Options.TargetApi == TargetApi.Vulkan) + { + layout = $"layout (location = {32 + attr}) "; + } + string name = $"{DefaultNames.PerPatchAttributePrefix}{attr}"; - context.AppendLine($"patch in vec4 {name};"); + context.AppendLine($"{layout}patch in vec4 {name};"); } private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info) @@ -570,10 +598,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl private static void DeclareOutputAttribute(CodeGenContext context, int attr) { - string suffix = OperandManager.IsArrayAttribute(context.Config.Stage, isOutAttr: true) ? "[]" : string.Empty; + string suffix = AttributeInfo.IsArrayAttributeGlsl(context.Config.Stage, isOutAttr: true) ? "[]" : string.Empty; string name = $"{DefaultNames.OAttributePrefix}{attr}{suffix}"; - if (context.Config.TransformFeedbackEnabled && context.Config.Stage != ShaderStage.Fragment) + if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline) { for (int c = 0; c < 4; c++) { @@ -608,9 +636,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl private static void DeclareOutputAttributePerPatch(CodeGenContext context, int attr) { + string layout = string.Empty; + + if (context.Config.Options.TargetApi == TargetApi.Vulkan) + { + layout = $"layout (location = {32 + attr}) "; + } + string name = $"{DefaultNames.PerPatchAttributePrefix}{attr}"; - context.AppendLine($"patch out vec4 {name};"); + context.AppendLine($"{layout}patch out vec4 {name};"); } private static void DeclareSupportUniformBlock(CodeGenContext context, ShaderStage stage, int scaleElements) diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs index 3af120f8..e9dbdd2d 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs @@ -127,7 +127,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl else if (node is AstAssignment assignment) { VariableType srcType = OperandManager.GetNodeDestType(context, assignment.Source); - VariableType dstType = OperandManager.GetNodeDestType(context, assignment.Destination); + VariableType dstType = OperandManager.GetNodeDestType(context, assignment.Destination, isAsgDest: true); string dest; diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs index 69214a35..c40f96f1 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs @@ -7,11 +7,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions { static class InstGenHelper { - private static InstInfo[] _infoTbl; + private static readonly InstInfo[] InfoTable; static InstGenHelper() { - _infoTbl = new InstInfo[(int)Instruction.Count]; + InfoTable = new InstInfo[(int)Instruction.Count]; Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd"); Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd"); @@ -139,12 +139,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions private static void Add(Instruction inst, InstType flags, string opName = null, int precedence = 0) { - _infoTbl[(int)inst] = new InstInfo(flags, opName, precedence); + InfoTable[(int)inst] = new InstInfo(flags, opName, precedence); } public static InstInfo GetInstructionInfo(Instruction inst) { - return _infoTbl[(int)(inst & Instruction.Mask)]; + return InfoTable[(int)(inst & Instruction.Mask)]; } public static string GetSoureExpr(CodeGenContext context, IAstNode node, VariableType dstType) @@ -191,7 +191,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions return false; } - InstInfo info = _infoTbl[(int)(operation.Inst & Instruction.Mask)]; + InstInfo info = InfoTable[(int)(operation.Inst & Instruction.Mask)]; if ((info.Type & (InstType.Call | InstType.Special)) != 0) { diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs index 6805f2fa..09404001 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs @@ -85,13 +85,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions string ApplyScaling(string vector) { - if ((context.Config.Stage.SupportsRenderScale()) && + if (context.Config.Stage.SupportsRenderScale() && texOp.Inst == Instruction.ImageLoad && !isBindless && !isIndexed) { // Image scales start after texture ones. - int scaleIndex = context.Config.GetTextureDescriptors().Length + context.FindImageDescriptorIndex(texOp); + int scaleIndex = context.Config.GetTextureDescriptors().Length + context.Config.FindImageDescriptorIndex(texOp); if (pCount == 3 && isArray) { @@ -621,11 +621,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions { if (intCoords) { - if ((context.Config.Stage.SupportsRenderScale()) && + if (context.Config.Stage.SupportsRenderScale() && !isBindless && !isIndexed) { - int index = context.FindTextureDescriptorIndex(texOp); + int index = context.Config.FindTextureDescriptorIndex(texOp); if (pCount == 3 && isArray) { @@ -762,7 +762,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions } else { - (TextureDescriptor descriptor, int descriptorIndex) = context.FindTextureDescriptor(texOp); + (TextureDescriptor descriptor, int descriptorIndex) = context.Config.FindTextureDescriptor(texOp); bool hasLod = !descriptor.Type.HasFlag(SamplerType.Multisample) && descriptor.Type != SamplerType.TextureBuffer; string texCall; @@ -780,6 +780,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions } if (context.Config.Stage.SupportsRenderScale() && + (texOp.Index < 2 || (texOp.Type & SamplerType.Mask) == SamplerType.Texture3D) && !isBindless && !isIndexed) { diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs index 334c744d..da720f4d 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { class OperandManager { - private static string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" }; + private static readonly string[] StagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" }; private struct BuiltInAttribute { @@ -26,8 +26,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } } - private static Dictionary<int, BuiltInAttribute> _builtInAttributes = - new Dictionary<int, BuiltInAttribute>() + private static Dictionary<int, BuiltInAttribute> _builtInAttributes = new Dictionary<int, BuiltInAttribute>() { { AttributeConsts.TessLevelOuter0, new BuiltInAttribute("gl_TessLevelOuter[0]", VariableType.F32) }, { AttributeConsts.TessLevelOuter1, new BuiltInAttribute("gl_TessLevelOuter[1]", VariableType.F32) }, @@ -197,11 +196,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return name + $"[{(value >> 4)}]." + swzMask; } - else if (config.TransformFeedbackEnabled && (config.Stage != ShaderStage.Vertex || isOutAttr)) + else if (config.TransformFeedbackEnabled && + ((config.LastInVertexPipeline && isOutAttr) || + (config.Stage == ShaderStage.Fragment && !isOutAttr))) { string name = $"{prefix}{(value >> 4)}_{swzMask}"; - if (!perPatch && IsArrayAttribute(config.Stage, isOutAttr)) + if (!perPatch && AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr)) { name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]"; } @@ -212,7 +213,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { string name = $"{prefix}{(value >> 4)}"; - if (!perPatch && IsArrayAttribute(config.Stage, isOutAttr)) + if (!perPatch && AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr)) { name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]"; } @@ -276,7 +277,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl string name = builtInAttr.Name; - if (!perPatch && IsArrayAttribute(config.Stage, isOutAttr) && IsArrayBuiltIn(value)) + if (!perPatch && AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr) && AttributeInfo.IsArrayBuiltIn(value)) { name = isOutAttr ? $"gl_out[gl_InvocationID].{name}" : $"gl_in[{indexExpr}].{name}"; } @@ -304,32 +305,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return $"{name}[{attrExpr} >> 2][{attrExpr} & 3]"; } - public static bool IsArrayAttribute(ShaderStage stage, bool isOutAttr) - { - if (isOutAttr) - { - return stage == ShaderStage.TessellationControl; - } - else - { - return stage == ShaderStage.TessellationControl || - stage == ShaderStage.TessellationEvaluation || - stage == ShaderStage.Geometry; - } - } - - private static bool IsArrayBuiltIn(int attr) - { - if (attr <= AttributeConsts.TessLevelInner1 || - attr == AttributeConsts.TessCoordX || - attr == AttributeConsts.TessCoordY) - { - return false; - } - - return (attr & AttributeConsts.SpecialMask) == 0; - } - public static string GetUbName(ShaderStage stage, int slot, bool cbIndexable) { if (cbIndexable) @@ -391,12 +366,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { int index = (int)stage; - if ((uint)index >= _stagePrefixes.Length) + if ((uint)index >= StagePrefixes.Length) { return "invalid"; } - return _stagePrefixes[index]; + return StagePrefixes[index]; } private static char GetSwizzleMask(int value) @@ -409,7 +384,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return $"{DefaultNames.ArgumentNamePrefix}{argIndex}"; } - public static VariableType GetNodeDestType(CodeGenContext context, IAstNode node) + public static VariableType GetNodeDestType(CodeGenContext context, IAstNode node, bool isAsgDest = false) { if (node is AstOperation operation) { @@ -455,7 +430,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return context.CurrentFunction.GetArgumentType(argIndex); } - return GetOperandVarType(operand); + return GetOperandVarType(context, operand, isAsgDest); } else { @@ -463,7 +438,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } } - private static VariableType GetOperandVarType(AstOperand operand) + private static VariableType GetOperandVarType(CodeGenContext context, AstOperand operand, bool isAsgDest = false) { if (operand.Type == OperandType.Attribute) { @@ -471,6 +446,21 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { return builtInAttr.Type; } + else if (context.Config.Stage == ShaderStage.Vertex && !isAsgDest && + operand.Value >= AttributeConsts.UserAttributeBase && + operand.Value < AttributeConsts.UserAttributeEnd) + { + int location = (operand.Value - AttributeConsts.UserAttributeBase) / 16; + + AttributeType type = context.Config.GpuAccessor.QueryAttributeType(location); + + return type switch + { + AttributeType.Sint => VariableType.S32, + AttributeType.Uint => VariableType.U32, + _ => VariableType.F32 + }; + } } return OperandInfo.GetVarType(operand); |