Declarations.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2. using Ryujinx.Graphics.Shader.StructuredIr;
  3. using Ryujinx.Graphics.Shader.Translation;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
  8. {
  9. static class Declarations
  10. {
  11. // At least 16 attributes are guaranteed by the spec.
  12. public const int MaxAttributes = 16;
  13. public static void Declare(CodeGenContext context, StructuredProgramInfo info)
  14. {
  15. context.AppendLine("#version 420 core");
  16. context.AppendLine("#extension GL_ARB_shader_storage_buffer_object : enable");
  17. if (context.Config.Stage == ShaderStage.Compute)
  18. {
  19. context.AppendLine("#extension GL_ARB_compute_shader : enable");
  20. }
  21. context.AppendLine();
  22. context.AppendLine($"const int {DefaultNames.UndefinedName} = 0;");
  23. context.AppendLine();
  24. if (context.Config.Stage == ShaderStage.Geometry)
  25. {
  26. string inPrimitive = "points";
  27. if ((context.Config.Flags & TranslationFlags.Unspecialized) != 0)
  28. {
  29. inPrimitive = DefineNames.InputTopologyName;
  30. }
  31. context.AppendLine($"layout ({inPrimitive}) in;");
  32. string outPrimitive = "triangle_strip";
  33. switch (context.Config.OutputTopology)
  34. {
  35. case OutputTopology.LineStrip: outPrimitive = "line_strip"; break;
  36. case OutputTopology.PointList: outPrimitive = "points"; break;
  37. case OutputTopology.TriangleStrip: outPrimitive = "triangle_strip"; break;
  38. }
  39. int maxOutputVertices = context.Config.MaxOutputVertices;
  40. context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;");
  41. context.AppendLine();
  42. }
  43. context.AppendLine("layout (std140) uniform Extra");
  44. context.EnterScope();
  45. context.AppendLine("vec2 flip;");
  46. context.AppendLine("int instance;");
  47. context.LeaveScope(";");
  48. context.AppendLine();
  49. context.AppendLine($"precise float {DefaultNames.LocalMemoryName}[0x100];");
  50. context.AppendLine();
  51. if (info.CBuffers.Count != 0)
  52. {
  53. DeclareUniforms(context, info);
  54. context.AppendLine();
  55. }
  56. if (info.SBuffers.Count != 0)
  57. {
  58. DeclareStorage(context, info);
  59. context.AppendLine();
  60. }
  61. if (info.Samplers.Count != 0)
  62. {
  63. DeclareSamplers(context, info);
  64. context.AppendLine();
  65. }
  66. if (info.Images.Count != 0)
  67. {
  68. DeclareImages(context, info);
  69. context.AppendLine();
  70. }
  71. if (context.Config.Stage != ShaderStage.Compute)
  72. {
  73. if (info.IAttributes.Count != 0)
  74. {
  75. DeclareInputAttributes(context, info);
  76. context.AppendLine();
  77. }
  78. if (info.OAttributes.Count != 0 || context.Config.Stage != ShaderStage.Fragment)
  79. {
  80. DeclareOutputAttributes(context, info);
  81. context.AppendLine();
  82. }
  83. }
  84. else
  85. {
  86. string localSizeX = "1";
  87. string localSizeY = "1";
  88. string localSizeZ = "1";
  89. if ((context.Config.Flags & TranslationFlags.Unspecialized) != 0)
  90. {
  91. localSizeX = DefineNames.LocalSizeX;
  92. localSizeY = DefineNames.LocalSizeY;
  93. localSizeZ = DefineNames.LocalSizeZ;
  94. }
  95. context.AppendLine(
  96. $"layout (" +
  97. $"local_size_x = {localSizeX}, " +
  98. $"local_size_y = {localSizeY}, " +
  99. $"local_size_z = {localSizeZ}) in;");
  100. context.AppendLine();
  101. }
  102. }
  103. public static void DeclareLocals(CodeGenContext context, StructuredProgramInfo info)
  104. {
  105. foreach (AstOperand decl in info.Locals)
  106. {
  107. string name = context.OperandManager.DeclareLocal(decl);
  108. context.AppendLine(GetVarTypeName(decl.VarType) + " " + name + ";");
  109. }
  110. }
  111. private static string GetVarTypeName(VariableType type)
  112. {
  113. switch (type)
  114. {
  115. case VariableType.Bool: return "bool";
  116. case VariableType.F32: return "precise float";
  117. case VariableType.S32: return "int";
  118. case VariableType.U32: return "uint";
  119. }
  120. throw new ArgumentException($"Invalid variable type \"{type}\".");
  121. }
  122. private static void DeclareUniforms(CodeGenContext context, StructuredProgramInfo info)
  123. {
  124. foreach (int cbufSlot in info.CBuffers.OrderBy(x => x))
  125. {
  126. string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
  127. ubName += "_" + DefaultNames.UniformNamePrefix + cbufSlot;
  128. context.CBufferDescriptors.Add(new BufferDescriptor(ubName, cbufSlot));
  129. context.AppendLine("layout (std140) uniform " + ubName);
  130. context.EnterScope();
  131. string ubSize = "[" + NumberFormatter.FormatInt(context.Config.MaxCBufferSize / 16) + "]";
  132. context.AppendLine("vec4 " + OperandManager.GetUbName(context.Config.Stage, cbufSlot) + ubSize + ";");
  133. context.LeaveScope(";");
  134. }
  135. }
  136. private static void DeclareStorage(CodeGenContext context, StructuredProgramInfo info)
  137. {
  138. foreach (int sbufSlot in info.SBuffers.OrderBy(x => x))
  139. {
  140. string sbName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
  141. sbName += "_" + DefaultNames.StorageNamePrefix + sbufSlot;
  142. context.SBufferDescriptors.Add(new BufferDescriptor(sbName, sbufSlot));
  143. context.AppendLine("layout (std430) buffer " + sbName);
  144. context.EnterScope();
  145. context.AppendLine("precise float " + OperandManager.GetSbName(context.Config.Stage, sbufSlot) + "[];");
  146. context.LeaveScope(";");
  147. }
  148. }
  149. private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info)
  150. {
  151. Dictionary<string, AstTextureOperation> samplers = new Dictionary<string, AstTextureOperation>();
  152. foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle))
  153. {
  154. string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp);
  155. if (!samplers.TryAdd(samplerName, texOp))
  156. {
  157. continue;
  158. }
  159. string samplerTypeName = GetSamplerTypeName(texOp.Type);
  160. context.AppendLine("uniform " + samplerTypeName + " " + samplerName + ";");
  161. }
  162. foreach (KeyValuePair<string, AstTextureOperation> kv in samplers)
  163. {
  164. string samplerName = kv.Key;
  165. AstTextureOperation texOp = kv.Value;
  166. TextureDescriptor desc;
  167. if ((texOp.Flags & TextureFlags.Bindless) != 0)
  168. {
  169. AstOperand operand = texOp.GetSource(0) as AstOperand;
  170. desc = new TextureDescriptor(samplerName, texOp.Type, operand.CbufSlot, operand.CbufOffset);
  171. }
  172. else
  173. {
  174. desc = new TextureDescriptor(samplerName, texOp.Type, texOp.Handle);
  175. }
  176. context.TextureDescriptors.Add(desc);
  177. }
  178. }
  179. private static void DeclareImages(CodeGenContext context, StructuredProgramInfo info)
  180. {
  181. Dictionary<string, AstTextureOperation> images = new Dictionary<string, AstTextureOperation>();
  182. foreach (AstTextureOperation texOp in info.Images.OrderBy(x => x.Handle))
  183. {
  184. string imageName = OperandManager.GetImageName(context.Config.Stage, texOp);
  185. if (!images.TryAdd(imageName, texOp))
  186. {
  187. continue;
  188. }
  189. string imageTypeName = GetImageTypeName(texOp.Type);
  190. context.AppendLine("writeonly uniform " + imageTypeName + " " + imageName + ";");
  191. }
  192. foreach (KeyValuePair<string, AstTextureOperation> kv in images)
  193. {
  194. string imageName = kv.Key;
  195. AstTextureOperation texOp = kv.Value;
  196. TextureDescriptor desc = new TextureDescriptor(imageName, texOp.Type, texOp.Handle);
  197. context.ImageDescriptors.Add(desc);
  198. }
  199. }
  200. private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info)
  201. {
  202. string suffix = context.Config.Stage == ShaderStage.Geometry ? "[]" : string.Empty;
  203. foreach (int attr in info.IAttributes.OrderBy(x => x))
  204. {
  205. string iq = info.InterpolationQualifiers[attr].ToGlslQualifier();
  206. if (iq != string.Empty)
  207. {
  208. iq += " ";
  209. }
  210. context.AppendLine($"layout (location = {attr}) {iq}in vec4 {DefaultNames.IAttributePrefix}{attr}{suffix};");
  211. }
  212. }
  213. private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info)
  214. {
  215. if (context.Config.Stage == ShaderStage.Fragment)
  216. {
  217. DeclareUsedOutputAttributes(context, info);
  218. }
  219. else
  220. {
  221. DeclareAllOutputAttributes(context, info);
  222. }
  223. }
  224. private static void DeclareUsedOutputAttributes(CodeGenContext context, StructuredProgramInfo info)
  225. {
  226. foreach (int attr in info.OAttributes.OrderBy(x => x))
  227. {
  228. context.AppendLine($"layout (location = {attr}) out vec4 {DefaultNames.OAttributePrefix}{attr};");
  229. }
  230. }
  231. private static void DeclareAllOutputAttributes(CodeGenContext context, StructuredProgramInfo info)
  232. {
  233. for (int attr = 0; attr < MaxAttributes; attr++)
  234. {
  235. string iq = $"{DefineNames.OutQualifierPrefixName}{attr} ";
  236. context.AppendLine($"layout (location = {attr}) {iq}out vec4 {DefaultNames.OAttributePrefix}{attr};");
  237. }
  238. foreach (int attr in info.OAttributes.OrderBy(x => x).Where(x => x >= MaxAttributes))
  239. {
  240. context.AppendLine($"layout (location = {attr}) out vec4 {DefaultNames.OAttributePrefix}{attr};");
  241. }
  242. }
  243. private static string GetSamplerTypeName(SamplerType type)
  244. {
  245. string typeName;
  246. switch (type & SamplerType.Mask)
  247. {
  248. case SamplerType.Texture1D: typeName = "sampler1D"; break;
  249. case SamplerType.TextureBuffer: typeName = "samplerBuffer"; break;
  250. case SamplerType.Texture2D: typeName = "sampler2D"; break;
  251. case SamplerType.Texture3D: typeName = "sampler3D"; break;
  252. case SamplerType.TextureCube: typeName = "samplerCube"; break;
  253. default: throw new ArgumentException($"Invalid sampler type \"{type}\".");
  254. }
  255. if ((type & SamplerType.Multisample) != 0)
  256. {
  257. typeName += "MS";
  258. }
  259. if ((type & SamplerType.Array) != 0)
  260. {
  261. typeName += "Array";
  262. }
  263. if ((type & SamplerType.Shadow) != 0)
  264. {
  265. typeName += "Shadow";
  266. }
  267. return typeName;
  268. }
  269. private static string GetImageTypeName(SamplerType type)
  270. {
  271. string typeName;
  272. switch (type & SamplerType.Mask)
  273. {
  274. case SamplerType.Texture1D: typeName = "image1D"; break;
  275. case SamplerType.TextureBuffer: typeName = "imageBuffer"; break;
  276. case SamplerType.Texture2D: typeName = "image2D"; break;
  277. case SamplerType.Texture3D: typeName = "image3D"; break;
  278. case SamplerType.TextureCube: typeName = "imageCube"; break;
  279. default: throw new ArgumentException($"Invalid sampler type \"{type}\".");
  280. }
  281. if ((type & SamplerType.Multisample) != 0)
  282. {
  283. typeName += "MS";
  284. }
  285. if ((type & SamplerType.Array) != 0)
  286. {
  287. typeName += "Array";
  288. }
  289. return typeName;
  290. }
  291. }
  292. }