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($"{layout}patch out vec4 {name};"); }
private static void PrintFunction(CodeGenContext context, StructuredProgramInfo info, StructuredFunction function, string funcName = null) { context.CurrentFunction = function; context.AppendLine(GetFunctionSignature(function, funcName)); context.EnterScope(); Declarations.DeclareLocals(context, function); PrintBlock(context, function.MainBlock); context.LeaveScope(); }
private static void AppendHelperFunction(CodeGenContext context, string filename) { string code = EmbeddedResources.ReadAllText(filename); code = code.Replace("\t", CodeGenContext.Tab); code = code.Replace("$SHARED_MEM$", DefaultNames.SharedMemoryName); code = code.Replace("$STORAGE_MEM$", OperandManager.GetShaderStagePrefix(context.Config.Stage) + "_" + DefaultNames.StorageNamePrefix); if (context.Config.GpuAccessor.QueryHostSupportsShaderBallot()) { code = code.Replace("$SUBGROUP_INVOCATION$", "gl_SubGroupInvocationARB"); code = code.Replace("$SUBGROUP_BROADCAST$", "readInvocationARB"); } else { code = code.Replace("$SUBGROUP_INVOCATION$", "gl_SubgroupInvocationID"); code = code.Replace("$SUBGROUP_BROADCAST$", "subgroupBroadcast"); } context.AppendLine(code); context.AppendLine(); }
private static void DeclareAllOutputAttributes(CodeGenContext context, StructuredProgramInfo info) { for (int attr = 0; attr < MaxAttributes; attr++) { for (int c = 0; c < 4; c++) { char swzMask = "xyzw"[c]; context.AppendLine($"layout (location = {attr}, component = {c}) out float {DefaultNames.OAttributePrefix}{attr}_{swzMask};"); } } foreach (int attr in info.OAttributes.OrderBy(x => x).Where(x => x >= MaxAttributes)) { for (int c = 0; c < 4; c++) { char swzMask = "xyzw"[c]; context.AppendLine($"layout (location = {attr}, component = {c}) out float {DefaultNames.OAttributePrefix}{attr}_{swzMask};"); } } }
private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info) { HashSet <string> samplers = new HashSet <string>(); // Texture instructions other than TextureSample (like TextureSize) // may have incomplete sampler type information. In those cases, // we prefer instead the more accurate information from the // TextureSample instruction, if both are available. foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle * 2 + (x.Inst == Instruction.TextureSample ? 0 : 1))) { string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize); string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr); if ((texOp.Flags & TextureFlags.Bindless) != 0 || !samplers.Add(samplerName)) { continue; } int firstBinding = -1; if ((texOp.Type & SamplerType.Indexed) != 0) { for (int index = 0; index < texOp.ArraySize; index++) { int binding = context.Config.Counts.IncrementTexturesCount(); if (firstBinding < 0) { firstBinding = binding; } var desc = new TextureDescriptor(binding, texOp.Type, texOp.Format, texOp.CbufSlot, texOp.Handle + index * 2); context.TextureDescriptors.Add(desc); } } else { firstBinding = context.Config.Counts.IncrementTexturesCount(); var desc = new TextureDescriptor(firstBinding, texOp.Type, texOp.Format, texOp.CbufSlot, texOp.Handle); context.TextureDescriptors.Add(desc); } string samplerTypeName = texOp.Type.ToGlslSamplerType(); context.AppendLine($"layout (binding = {firstBinding}) uniform {samplerTypeName} {samplerName};"); } }
private static void PrintFunction(CodeGenContext context, StructuredProgramInfo info, StructuredFunction function, string funcName = null) { context.CurrentFunction = function; context.AppendLine(GetFunctionSignature(function, funcName)); context.EnterScope(); Declarations.DeclareLocals(context, function); if (funcName == MainFunctionName) { // Some games will leave some elements of gl_Position uninitialized, // in those cases, the elements will contain undefined values according // to the spec, but on NVIDIA they seems to be always initialized to (0, 0, 0, 1), // so we do explicit initialization to avoid UB on non-NVIDIA gpus. if (context.Config.Stage == ShaderStage.Vertex) { context.AppendLine("gl_Position = vec4(0.0, 0.0, 0.0, 1.0);"); } // Ensure that unused attributes are set, otherwise the downstream // compiler may eliminate them. // (Not needed for fragment shader as it is the last stage). if (context.Config.Stage != ShaderStage.Compute && context.Config.Stage != ShaderStage.Fragment && !context.Config.GpPassthrough) { for (int attr = 0; attr < Declarations.MaxAttributes; attr++) { if (info.OAttributes.Contains(attr)) { continue; } if ((context.Config.Flags & TranslationFlags.Feedback) != 0) { context.AppendLine($"{DefaultNames.OAttributePrefix}{attr}_x = 0.0;"); context.AppendLine($"{DefaultNames.OAttributePrefix}{attr}_y = 0.0;"); context.AppendLine($"{DefaultNames.OAttributePrefix}{attr}_z = 0.0;"); context.AppendLine($"{DefaultNames.OAttributePrefix}{attr}_w = 1.0;"); } else { context.AppendLine($"{DefaultNames.OAttributePrefix}{attr} = vec4(0.0, 0.0, 0.0, 1.0);"); } } } } PrintBlock(context, function.MainBlock); context.LeaveScope(); }
private static void PrintMainBlock(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine("void main()"); context.EnterScope(); Declarations.DeclareLocals(context, info); // Some games will leave some elements of gl_Position uninitialized, // in those cases, the elements will contain undefined values according // to the spec, but on NVIDIA they seems to be always initialized to (0, 0, 0, 1), // so we do explicit initialization to avoid UB on non-NVIDIA gpus. if (context.Config.Stage == ShaderStage.Vertex) { context.AppendLine("gl_Position = vec4(0.0, 0.0, 0.0, 1.0);"); } // Ensure that unused attributes are set, otherwise the downstream // compiler may eliminate them. // (Not needed for fragment shader as it is the last stage). if (context.Config.Stage != ShaderStage.Compute && context.Config.Stage != ShaderStage.Fragment) { for (int attr = 0; attr < Declarations.MaxAttributes; attr++) { if (info.OAttributes.Contains(attr)) { continue; } context.AppendLine($"{DefaultNames.OAttributePrefix}{attr} = vec4(0);"); } } PrintBlock(context, info.MainBlock); context.LeaveScope(); }
private static void DeclareImages(CodeGenContext context, TextureDescriptor[] descriptors) { int arraySize = 0; foreach (var descriptor in descriptors) { if (descriptor.Type.HasFlag(SamplerType.Indexed)) { if (arraySize == 0) { arraySize = ShaderConfig.SamplerArraySize; } else if (--arraySize != 0) { continue; } } string indexExpr = NumberFormatter.FormatInt(arraySize); string imageName = OperandManager.GetImageName( context.Config.Stage, descriptor.CbufSlot, descriptor.HandleIndex, descriptor.Format, descriptor.Type.HasFlag(SamplerType.Indexed), indexExpr); string imageTypeName = descriptor.Type.ToGlslImageType(descriptor.Format.GetComponentType()); if (descriptor.Flags.HasFlag(TextureUsageFlags.ImageCoherent)) { imageTypeName = "coherent " + imageTypeName; } string layout = descriptor.Format.ToGlslFormat(); if (!string.IsNullOrEmpty(layout)) { layout = ", " + layout; } if (context.Config.Options.TargetApi == TargetApi.Vulkan) { layout = $", set = 3{layout}"; } context.AppendLine($"layout (binding = {descriptor.Binding}{layout}) uniform {imageTypeName} {imageName};"); } }
private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info) { string suffix = context.Config.Stage == ShaderStage.Geometry ? "[]" : string.Empty; foreach (int attr in info.IAttributes.OrderBy(x => x)) { string iq = string.Empty; if (context.Config.Stage == ShaderStage.Fragment) { iq = context.Config.ImapTypes[attr].GetFirstUsedType() switch { PixelImap.Constant => "flat ", PixelImap.ScreenLinear => "noperspective ", _ => string.Empty }; } string pass = context.Config.GpPassthrough ? "passthrough, " : string.Empty; string name = $"{DefaultNames.IAttributePrefix}{attr}"; if ((context.Config.Flags & TranslationFlags.Feedback) != 0) { 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};"); } } else { context.AppendLine($"layout ({pass}location = {attr}) {iq}in vec4 {name}{suffix};"); } } }
private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info) { string suffix = context.Config.Stage == ShaderStage.Geometry ? "[]" : string.Empty; foreach (int attr in info.IAttributes.OrderBy(x => x)) { string iq = info.InterpolationQualifiers[attr].ToGlslQualifier(); if (iq != string.Empty) { iq += " "; } context.AppendLine($"layout (location = {attr}) {iq}in vec4 {DefaultNames.IAttributePrefix}{attr}{suffix};"); } }
private static void DeclareImages(CodeGenContext context, StructuredProgramInfo info) { Dictionary <string, AstTextureOperation> images = new Dictionary <string, AstTextureOperation>(); foreach (AstTextureOperation texOp in info.Images.OrderBy(x => x.Handle)) { string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize); string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr); if (!images.TryAdd(imageName, texOp)) { continue; } string imageTypeName = GetImageTypeName(texOp.Type); context.AppendLine("writeonly uniform " + 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.Handle + index * 2); context.TextureDescriptors.Add(desc); } } else { var desc = new TextureDescriptor(imageName, texOp.Type, texOp.Handle); context.ImageDescriptors.Add(desc); } } }
private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info) { if (context.Config.UsedFeatures.HasFlag(FeatureFlags.OaIndexing)) { context.AppendLine($"layout (location = 0) out vec4 {DefaultNames.OAttributePrefix}[{Constants.MaxAttributes}];"); } else { int usedAttributes = context.Config.UsedOutputAttributes; while (usedAttributes != 0) { int index = BitOperations.TrailingZeroCount(usedAttributes); DeclareOutputAttribute(context, index); usedAttributes &= ~(1 << index); } } }
private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info) { if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IaIndexing)) { string suffix = context.Config.Stage == ShaderStage.Geometry ? "[]" : string.Empty; context.AppendLine($"layout (location = 0) in vec4 {DefaultNames.IAttributePrefix}{suffix}[{Constants.MaxAttributes}];"); } else { int usedAttributes = context.Config.UsedInputAttributes | context.Config.PassthroughAttributes; while (usedAttributes != 0) { int index = BitOperations.TrailingZeroCount(usedAttributes); DeclareInputAttribute(context, info, index); usedAttributes &= ~(1 << index); } } }
private static void DeclareSamplers(CodeGenContext context, TextureDescriptor[] descriptors) { int arraySize = 0; foreach (var descriptor in descriptors) { if (descriptor.Type.HasFlag(SamplerType.Indexed)) { if (arraySize == 0) { arraySize = ShaderConfig.SamplerArraySize; } else if (--arraySize != 0) { continue; } } string indexExpr = NumberFormatter.FormatInt(arraySize); string samplerName = OperandManager.GetSamplerName( context.Config.Stage, descriptor.CbufSlot, descriptor.HandleIndex, descriptor.Type.HasFlag(SamplerType.Indexed), indexExpr); string samplerTypeName = descriptor.Type.ToGlslSamplerType(); string layout = string.Empty; if (context.Config.Options.TargetApi == TargetApi.Vulkan) { bool isBuffer = (descriptor.Type & SamplerType.Mask) == SamplerType.TextureBuffer; int setIndex = isBuffer ? 4 : 2; layout = $", set = {setIndex}"; } context.AppendLine($"layout (binding = {descriptor.Binding}{layout}) uniform {samplerTypeName} {samplerName};"); } }
private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info) { string suffix = context.Config.Stage == ShaderStage.Geometry ? "[]" : string.Empty; foreach (int attr in info.IAttributes.OrderBy(x => x)) { string iq = string.Empty; if (context.Config.Stage == ShaderStage.Fragment) { iq = context.Config.ImapTypes[attr].GetFirstUsedType() switch { PixelImap.Constant => "flat ", PixelImap.ScreenLinear => "noperspective ", _ => string.Empty }; } context.AppendLine($"layout (location = {attr}) {iq}in vec4 {DefaultNames.IAttributePrefix}{attr}{suffix};"); } }
private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info) { Dictionary <string, AstTextureOperation> samplers = new Dictionary <string, AstTextureOperation>(); foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle)) { string samplerName = OperandManager.GetSamplerName(context.Config.Type, texOp); if (!samplers.TryAdd(samplerName, texOp)) { continue; } string samplerTypeName = GetSamplerTypeName(texOp.Type); context.AppendLine("uniform " + samplerTypeName + " " + samplerName + ";"); } foreach (KeyValuePair <string, AstTextureOperation> kv in samplers) { string samplerName = kv.Key; AstTextureOperation texOp = kv.Value; TextureDescriptor desc; if ((texOp.Flags & TextureFlags.Bindless) != 0) { AstOperand operand = texOp.GetSource(0) as AstOperand; desc = new TextureDescriptor(samplerName, operand.CbufSlot, operand.CbufOffset); } else { desc = new TextureDescriptor(samplerName, texOp.Handle); } context.TextureDescriptors.Add(desc); } }
private static void PrintBlock(CodeGenContext context, AstBlock block) { AstBlockVisitor visitor = new AstBlockVisitor(block); visitor.BlockEntered += (sender, e) => { switch (e.Block.Type) { case AstBlockType.DoWhile: context.AppendLine("do"); break; case AstBlockType.Else: context.AppendLine("else"); break; case AstBlockType.ElseIf: context.AppendLine($"else if ({GetCondExpr(context, e.Block.Condition)})"); break; case AstBlockType.If: context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})"); break; default: throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\"."); } context.EnterScope(); }; visitor.BlockLeft += (sender, e) => { context.LeaveScope(); if (e.Block.Type == AstBlockType.DoWhile) { context.AppendLine($"while ({GetCondExpr(context, e.Block.Condition)});"); } }; foreach (IAstNode node in visitor.Visit()) { if (node is AstOperation operation) { context.AppendLine(InstGen.GetExpression(context, operation) + ";"); } else if (node is AstAssignment assignment) { VariableType srcType = OperandManager.GetNodeDestType(assignment.Source); VariableType dstType = OperandManager.GetNodeDestType(assignment.Destination); string dest; if (assignment.Destination is AstOperand operand && operand.Type == OperandType.Attribute) { dest = OperandManager.GetOutAttributeName(operand, context.Config); } else { dest = InstGen.GetExpression(context, assignment.Destination); } string src = ReinterpretCast(context, assignment.Source, srcType, dstType); context.AppendLine(dest + " = " + src + ";"); }
public static void Declare(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine("#version 450 core"); context.AppendLine("#extension GL_ARB_gpu_shader_int64 : enable"); context.AppendLine("#extension GL_ARB_shader_ballot : enable"); context.AppendLine("#extension GL_ARB_shader_group_vote : enable"); context.AppendLine("#extension GL_EXT_shader_image_load_formatted : enable"); context.AppendLine("#extension GL_EXT_texture_shadow_lod : enable"); if (context.Config.Stage == ShaderStage.Compute) { context.AppendLine("#extension GL_ARB_compute_shader : enable"); } if (context.Config.GpPassthrough) { context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable"); } context.AppendLine("#pragma optionNV(fastmath off)"); context.AppendLine(); context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;"); context.AppendLine(); if (context.Config.Stage == ShaderStage.Compute) { int localMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeLocalMemorySize(), 4); if (localMemorySize != 0) { string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } int sharedMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeSharedMemorySize(), 4); if (sharedMemorySize != 0) { string sharedMemorySizeStr = NumberFormatter.FormatInt(sharedMemorySize); context.AppendLine($"shared uint {DefaultNames.SharedMemoryName}[{sharedMemorySizeStr}];"); context.AppendLine(); } } else if (context.Config.LocalMemorySize != 0) { int localMemorySize = BitUtils.DivRoundUp(context.Config.LocalMemorySize, 4); string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } var cBufferDescriptors = context.Config.GetConstantBufferDescriptors(); if (cBufferDescriptors.Length != 0) { DeclareUniforms(context, cBufferDescriptors); context.AppendLine(); } var sBufferDescriptors = context.Config.GetStorageBufferDescriptors(); if (sBufferDescriptors.Length != 0) { DeclareStorages(context, sBufferDescriptors); context.AppendLine(); } var textureDescriptors = context.Config.GetTextureDescriptors(); if (textureDescriptors.Length != 0) { DeclareSamplers(context, textureDescriptors); context.AppendLine(); } var imageDescriptors = context.Config.GetImageDescriptors(); if (imageDescriptors.Length != 0) { DeclareImages(context, imageDescriptors); context.AppendLine(); } if (context.Config.Stage != ShaderStage.Compute) { if (context.Config.Stage == ShaderStage.Geometry) { string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString(); context.AppendLine($"layout ({inPrimitive}) in;"); if (context.Config.GpPassthrough) { context.AppendLine($"layout (passthrough) in gl_PerVertex"); context.EnterScope(); context.AppendLine("vec4 gl_Position;"); context.AppendLine("float gl_PointSize;"); context.AppendLine("float gl_ClipDistance[];"); context.LeaveScope(";"); } else { string outPrimitive = context.Config.OutputTopology.ToGlslString(); int maxOutputVertices = context.Config.MaxOutputVertices; context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;"); } context.AppendLine(); } if (info.IAttributes.Count != 0 || context.Config.GpPassthrough) { DeclareInputAttributes(context, info); context.AppendLine(); } if (info.OAttributes.Count != 0 || context.Config.Stage != ShaderStage.Fragment) { DeclareOutputAttributes(context, info); context.AppendLine(); } } else { string localSizeX = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeX()); string localSizeY = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeY()); string localSizeZ = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeZ()); context.AppendLine( "layout (" + $"local_size_x = {localSizeX}, " + $"local_size_y = {localSizeY}, " + $"local_size_z = {localSizeZ}) in;"); context.AppendLine(); } if (context.Config.Stage == ShaderStage.Fragment || context.Config.Stage == ShaderStage.Compute) { if (context.Config.Stage == ShaderStage.Fragment) { if (context.Config.GpuAccessor.QueryEarlyZForce()) { context.AppendLine("layout(early_fragment_tests) in;"); context.AppendLine(); } context.AppendLine($"uniform bool {DefaultNames.IsBgraName}[8];"); context.AppendLine(); } if (DeclareRenderScale(context)) { context.AppendLine(); } } if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Shared) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Shared.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Storage) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Storage.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighU32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighU32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.Shuffle) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleDown) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleUp) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleXor) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.SwizzleAdd) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl"); } }
public static void Declare(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine(context.Config.Options.TargetApi == TargetApi.Vulkan ? "#version 460 core" : "#version 450 core"); context.AppendLine("#extension GL_ARB_gpu_shader_int64 : enable"); context.AppendLine("#extension GL_ARB_shader_ballot : enable"); context.AppendLine("#extension GL_ARB_shader_group_vote : enable"); context.AppendLine("#extension GL_EXT_shader_image_load_formatted : enable"); context.AppendLine("#extension GL_EXT_texture_shadow_lod : enable"); if (context.Config.Stage == ShaderStage.Compute) { context.AppendLine("#extension GL_ARB_compute_shader : enable"); } if (context.Config.GpPassthrough) { context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable"); } context.AppendLine("#pragma optionNV(fastmath off)"); context.AppendLine(); context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;"); context.AppendLine(); if (context.Config.Stage == ShaderStage.Compute) { int localMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeLocalMemorySize(), 4); if (localMemorySize != 0) { string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } int sharedMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeSharedMemorySize(), 4); if (sharedMemorySize != 0) { string sharedMemorySizeStr = NumberFormatter.FormatInt(sharedMemorySize); context.AppendLine($"shared uint {DefaultNames.SharedMemoryName}[{sharedMemorySizeStr}];"); context.AppendLine(); } } else if (context.Config.LocalMemorySize != 0) { int localMemorySize = BitUtils.DivRoundUp(context.Config.LocalMemorySize, 4); string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } var cBufferDescriptors = context.Config.GetConstantBufferDescriptors(); if (cBufferDescriptors.Length != 0) { DeclareUniforms(context, cBufferDescriptors); context.AppendLine(); } var sBufferDescriptors = context.Config.GetStorageBufferDescriptors(); if (sBufferDescriptors.Length != 0) { DeclareStorages(context, sBufferDescriptors); context.AppendLine(); } var textureDescriptors = context.Config.GetTextureDescriptors(); if (textureDescriptors.Length != 0) { DeclareSamplers(context, textureDescriptors); context.AppendLine(); } var imageDescriptors = context.Config.GetImageDescriptors(); if (imageDescriptors.Length != 0) { DeclareImages(context, imageDescriptors); context.AppendLine(); } if (context.Config.Stage != ShaderStage.Compute) { if (context.Config.Stage == ShaderStage.Geometry) { string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString(); context.AppendLine($"layout ({inPrimitive}) in;"); if (context.Config.GpPassthrough) { context.AppendLine($"layout (passthrough) in gl_PerVertex"); context.EnterScope(); context.AppendLine("vec4 gl_Position;"); context.AppendLine("float gl_PointSize;"); context.AppendLine("float gl_ClipDistance[];"); context.LeaveScope(";"); } else { string outPrimitive = context.Config.OutputTopology.ToGlslString(); int maxOutputVertices = context.Config.MaxOutputVertices; context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;"); } context.AppendLine(); } if (context.Config.UsedInputAttributes != 0 || context.Config.GpPassthrough) { DeclareInputAttributes(context, info); context.AppendLine(); } if (context.Config.UsedOutputAttributes != 0 || context.Config.Stage != ShaderStage.Fragment) { DeclareOutputAttributes(context, info); context.AppendLine(); } if (context.Config.Stage != ShaderStage.Compute && context.Config.Stage != ShaderStage.Fragment && (context.Config.Options.Flags & TranslationFlags.Feedback) != 0) { var tfOutput = context.GetTransformFeedbackOutput(AttributeConsts.PositionX); if (tfOutput.Valid) { context.AppendLine($"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) out gl_PerVertex"); context.EnterScope(); context.AppendLine("vec4 gl_Position;"); context.LeaveScope(";"); } } } else { string localSizeX = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeX()); string localSizeY = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeY()); string localSizeZ = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeZ()); context.AppendLine( "layout (" + $"local_size_x = {localSizeX}, " + $"local_size_y = {localSizeY}, " + $"local_size_z = {localSizeZ}) in;"); context.AppendLine(); } bool isFragment = context.Config.Stage == ShaderStage.Fragment; if (isFragment || context.Config.Stage == ShaderStage.Compute) { if (isFragment && context.Config.GpuAccessor.QueryEarlyZForce()) { context.AppendLine("layout(early_fragment_tests) in;"); context.AppendLine(); } if ((context.Config.UsedFeatures & (FeatureFlags.FragCoordXY | FeatureFlags.IntegerSampling)) != 0) { string stage = OperandManager.GetShaderStagePrefix(context.Config.Stage); int scaleElements = context.Config.GetTextureDescriptors().Length + context.Config.GetImageDescriptors().Length; if (isFragment) { scaleElements++; // Also includes render target scale, for gl_FragCoord. } DeclareSupportUniformBlock(context, isFragment, scaleElements); if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling)) { AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl"); context.AppendLine(); } } else if (isFragment) { DeclareSupportUniformBlock(context, true, 0); } } if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Shared) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Shared.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Storage) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Storage.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighU32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighU32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.Shuffle) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleDown) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleUp) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleXor) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.SwizzleAdd) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl"); } }
public static void Declare(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine("#version 420 core"); context.AppendLine(); context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;"); context.AppendLine(); if (context.Config.Type == GalShaderType.Geometry) { context.AppendLine("layout (points) in;"); context.AppendLine("layout (triangle_strip, max_vertices = 4) out;"); context.AppendLine(); } context.AppendLine("layout (std140) uniform Extra"); context.EnterScope(); context.AppendLine("vec2 flip;"); context.AppendLine("int instance;"); context.LeaveScope(";"); context.AppendLine(); if (info.CBuffers.Count != 0) { DeclareUniforms(context, info); context.AppendLine(); } if (info.Samplers.Count != 0) { DeclareSamplers(context, info); context.AppendLine(); } if (info.IAttributes.Count != 0) { DeclareInputAttributes(context, info); context.AppendLine(); } if (info.OAttributes.Count != 0) { DeclareOutputAttributes(context, info); context.AppendLine(); } }
public static void Declare(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine("#version 450 core"); context.AppendLine("#extension GL_ARB_gpu_shader_int64 : enable"); if (context.Config.GpuAccessor.QueryHostSupportsShaderBallot()) { context.AppendLine("#extension GL_ARB_shader_ballot : enable"); } else { context.AppendLine("#extension GL_KHR_shader_subgroup_basic : enable"); context.AppendLine("#extension GL_KHR_shader_subgroup_ballot : enable"); } context.AppendLine("#extension GL_ARB_shader_group_vote : enable"); context.AppendLine("#extension GL_EXT_shader_image_load_formatted : enable"); context.AppendLine("#extension GL_EXT_texture_shadow_lod : enable"); if (context.Config.Stage == ShaderStage.Compute) { context.AppendLine("#extension GL_ARB_compute_shader : enable"); } else if (context.Config.Stage == ShaderStage.Fragment) { if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock()) { context.AppendLine("#extension GL_ARB_fragment_shader_interlock : enable"); } else if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderOrderingIntel()) { context.AppendLine("#extension GL_INTEL_fragment_shader_ordering : enable"); } } if (context.Config.GpPassthrough) { context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable"); } context.AppendLine("#pragma optionNV(fastmath off)"); context.AppendLine(); context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;"); context.AppendLine(); if (context.Config.Stage == ShaderStage.Compute) { int localMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeLocalMemorySize(), 4); if (localMemorySize != 0) { string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } int sharedMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeSharedMemorySize(), 4); if (sharedMemorySize != 0) { string sharedMemorySizeStr = NumberFormatter.FormatInt(sharedMemorySize); context.AppendLine($"shared uint {DefaultNames.SharedMemoryName}[{sharedMemorySizeStr}];"); context.AppendLine(); } } else if (context.Config.LocalMemorySize != 0) { int localMemorySize = BitUtils.DivRoundUp(context.Config.LocalMemorySize, 4); string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } var cBufferDescriptors = context.Config.GetConstantBufferDescriptors(); if (cBufferDescriptors.Length != 0) { DeclareUniforms(context, cBufferDescriptors); context.AppendLine(); } var sBufferDescriptors = context.Config.GetStorageBufferDescriptors(); if (sBufferDescriptors.Length != 0) { DeclareStorages(context, sBufferDescriptors); context.AppendLine(); } var textureDescriptors = context.Config.GetTextureDescriptors(); if (textureDescriptors.Length != 0) { DeclareSamplers(context, textureDescriptors); context.AppendLine(); } var imageDescriptors = context.Config.GetImageDescriptors(); if (imageDescriptors.Length != 0) { DeclareImages(context, imageDescriptors); context.AppendLine(); } if (context.Config.Stage != ShaderStage.Compute) { if (context.Config.Stage == ShaderStage.Geometry) { string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString(); context.AppendLine($"layout ({inPrimitive}) in;"); if (context.Config.GpPassthrough) { context.AppendLine($"layout (passthrough) in gl_PerVertex"); context.EnterScope(); context.AppendLine("vec4 gl_Position;"); context.AppendLine("float gl_PointSize;"); context.AppendLine("float gl_ClipDistance[];"); context.LeaveScope(";"); } else { string outPrimitive = context.Config.OutputTopology.ToGlslString(); int maxOutputVertices = context.Config.MaxOutputVertices; context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;"); } context.AppendLine(); } else if (context.Config.Stage == ShaderStage.TessellationControl) { int threadsPerInputPrimitive = context.Config.ThreadsPerInputPrimitive; context.AppendLine($"layout (vertices = {threadsPerInputPrimitive}) out;"); context.AppendLine(); } else if (context.Config.Stage == ShaderStage.TessellationEvaluation) { string patchType = context.Config.GpuAccessor.QueryTessPatchType().ToGlsl(); string spacing = context.Config.GpuAccessor.QueryTessSpacing().ToGlsl(); string windingOrder = context.Config.GpuAccessor.QueryTessCw() ? "cw" : "ccw"; context.AppendLine($"layout ({patchType}, {spacing}, {windingOrder}) in;"); context.AppendLine(); } if (context.Config.UsedInputAttributes != 0 || context.Config.GpPassthrough) { DeclareInputAttributes(context, info); context.AppendLine(); } if (context.Config.UsedOutputAttributes != 0 || context.Config.Stage != ShaderStage.Fragment) { DeclareOutputAttributes(context, info); context.AppendLine(); } if (context.Config.UsedInputAttributesPerPatch != 0) { DeclareInputAttributesPerPatch(context, context.Config.UsedInputAttributesPerPatch); context.AppendLine(); } if (context.Config.UsedOutputAttributesPerPatch != 0) { DeclareUsedOutputAttributesPerPatch(context, context.Config.UsedOutputAttributesPerPatch); context.AppendLine(); } } else { string localSizeX = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeX()); string localSizeY = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeY()); string localSizeZ = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeZ()); context.AppendLine( "layout (" + $"local_size_x = {localSizeX}, " + $"local_size_y = {localSizeY}, " + $"local_size_z = {localSizeZ}) in;"); context.AppendLine(); } bool isFragment = context.Config.Stage == ShaderStage.Fragment; if (isFragment || context.Config.Stage == ShaderStage.Compute || context.Config.Stage == ShaderStage.Vertex) { if (isFragment && context.Config.GpuAccessor.QueryEarlyZForce()) { context.AppendLine("layout(early_fragment_tests) in;"); context.AppendLine(); } if ((context.Config.UsedFeatures & (FeatureFlags.FragCoordXY | FeatureFlags.IntegerSampling)) != 0) { string stage = OperandManager.GetShaderStagePrefix(context.Config.Stage); int scaleElements = context.Config.GetTextureDescriptors().Length + context.Config.GetImageDescriptors().Length; if (isFragment) { scaleElements++; // Also includes render target scale, for gl_FragCoord. } DeclareSupportUniformBlock(context, context.Config.Stage, scaleElements); if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling)) { AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl"); context.AppendLine(); } } else if (isFragment) { DeclareSupportUniformBlock(context, context.Config.Stage, 0); } } if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Shared) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Shared.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Storage) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Storage.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighU32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighU32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.Shuffle) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleDown) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleUp) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleXor) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.StoreSharedSmallInt) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/StoreSharedSmallInt.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.StoreStorageSmallInt) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/StoreStorageSmallInt.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.SwizzleAdd) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl"); } }
private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info) { Dictionary <string, AstTextureOperation> samplers = new Dictionary <string, AstTextureOperation>(); // Texture instructions other than TextureSample (like TextureSize) // may have incomplete sampler type information. In those cases, // we prefer instead the more accurate information from the // TextureSample instruction, if both are available. foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle * 2 + (x.Inst == Instruction.TextureSample ? 0 : 1))) { string indexExpr = NumberFormatter.FormatInt(texOp.ArraySize); string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr); if (!samplers.TryAdd(samplerName, texOp)) { continue; } string samplerTypeName = GetSamplerTypeName(texOp.Type); context.AppendLine("uniform " + samplerTypeName + " " + samplerName + ";"); } foreach (KeyValuePair <string, AstTextureOperation> kv in samplers) { string samplerName = kv.Key; AstTextureOperation texOp = kv.Value; TextureDescriptor desc; if ((texOp.Flags & TextureFlags.Bindless) != 0) { AstOperand operand = texOp.GetSource(0) as AstOperand; desc = new TextureDescriptor(samplerName, texOp.Type, operand.CbufSlot, operand.CbufOffset); context.TextureDescriptors.Add(desc); } else 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); desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Handle + index * 2); context.TextureDescriptors.Add(desc); } } else { desc = new TextureDescriptor(samplerName, texOp.Type, texOp.Handle); context.TextureDescriptors.Add(desc); } } }
public static void Declare(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine("#version 430 core"); context.AppendLine("#extension GL_ARB_gpu_shader_int64 : enable"); context.AppendLine("#extension GL_ARB_shader_ballot : enable"); context.AppendLine("#extension GL_ARB_shader_group_vote : enable"); context.AppendLine("#extension GL_EXT_shader_image_load_formatted : enable"); if (context.Config.Stage == ShaderStage.Compute) { context.AppendLine("#extension GL_ARB_compute_shader : enable"); } context.AppendLine("#pragma optionNV(fastmath off)"); context.AppendLine(); context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;"); context.AppendLine(); if (context.Config.Stage == ShaderStage.Geometry) { string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString(); context.AppendLine($"layout ({inPrimitive}) in;"); string outPrimitive = context.Config.OutputTopology.ToGlslString(); int maxOutputVertices = context.Config.MaxOutputVertices; context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;"); context.AppendLine(); } if (context.Config.Stage == ShaderStage.Compute) { int localMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeLocalMemorySize(), 4); if (localMemorySize != 0) { string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } int sharedMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeSharedMemorySize(), 4); if (sharedMemorySize != 0) { string sharedMemorySizeStr = NumberFormatter.FormatInt(sharedMemorySize); context.AppendLine($"shared uint {DefaultNames.SharedMemoryName}[{sharedMemorySizeStr}];"); context.AppendLine(); } } else if (context.Config.LocalMemorySize != 0) { int localMemorySize = BitUtils.DivRoundUp(context.Config.LocalMemorySize, 4); string localMemorySizeStr = NumberFormatter.FormatInt(localMemorySize); context.AppendLine($"uint {DefaultNames.LocalMemoryName}[{localMemorySizeStr}];"); context.AppendLine(); } if (info.CBuffers.Count != 0) { DeclareUniforms(context, info); context.AppendLine(); } if (info.SBuffers.Count != 0) { DeclareStorages(context, info); context.AppendLine(); } if (info.Samplers.Count != 0) { DeclareSamplers(context, info); context.AppendLine(); } if (info.Images.Count != 0) { DeclareImages(context, info); context.AppendLine(); } if (context.Config.Stage != ShaderStage.Compute) { if (info.IAttributes.Count != 0) { DeclareInputAttributes(context, info); context.AppendLine(); } if (info.OAttributes.Count != 0 || context.Config.Stage != ShaderStage.Fragment) { DeclareOutputAttributes(context, info); context.AppendLine(); } } else { string localSizeX = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeX()); string localSizeY = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeY()); string localSizeZ = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeZ()); context.AppendLine( "layout (" + $"local_size_x = {localSizeX}, " + $"local_size_y = {localSizeY}, " + $"local_size_z = {localSizeZ}) in;"); context.AppendLine(); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighU32) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighU32.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.Shuffle) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleDown) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleUp) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.ShuffleXor) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl"); } if ((info.HelperFunctionsMask & HelperFunctionsMask.SwizzleAdd) != 0) { AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl"); } }
private static void DeclareOutputAttributePerPatch(CodeGenContext context, int attr) { string name = $"{DefaultNames.PerPatchAttributePrefix}{attr}"; context.AppendLine($"patch out vec4 {name};"); }