Shader.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  1. /**
  2. * Copyright (c) 2006-2022 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. // LOVE
  21. #include "Shader.h"
  22. #include "Graphics.h"
  23. #include "math/MathModule.h"
  24. // glslang
  25. #include "libraries/glslang/glslang/Public/ShaderLang.h"
  26. // Needed for reflection information.
  27. #include "libraries/glslang/glslang/Include/Types.h"
  28. #include "libraries/glslang/glslang/MachineIndependent/localintermediate.h"
  29. // C++
  30. #include <string>
  31. #include <regex>
  32. #include <sstream>
  33. namespace love
  34. {
  35. namespace graphics
  36. {
  37. namespace glsl
  38. {
  39. static const char global_syntax[] = R"(
  40. #if !defined(GL_ES) && __VERSION__ < 140
  41. #define lowp
  42. #define mediump
  43. #define highp
  44. #endif
  45. #if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH)
  46. #define LOVE_HIGHP_OR_MEDIUMP highp
  47. #else
  48. #define LOVE_HIGHP_OR_MEDIUMP mediump
  49. #endif
  50. #if __VERSION__ >= 300
  51. #define LOVE_IO_LOCATION(x) layout (location = x)
  52. #else
  53. #define LOVE_IO_LOCATION(x)
  54. #endif
  55. #define number float
  56. #define Image sampler2D
  57. #define ArrayImage sampler2DArray
  58. #define CubeImage samplerCube
  59. #define VolumeImage sampler3D
  60. #if __VERSION__ >= 300 && !defined(LOVE_GLSL1_ON_GLSL3)
  61. #define DepthImage sampler2DShadow
  62. #define DepthArrayImage sampler2DArrayShadow
  63. #define DepthCubeImage samplerCubeShadow
  64. #endif
  65. #define extern uniform
  66. #if defined(GL_EXT_texture_array) && (!defined(GL_ES) || __VERSION__ > 100 || defined(GL_OES_gpu_shader5))
  67. // Only used when !GLSLES1 to work around Ouya driver bug. But we still want it
  68. // enabled for glslang validation when glsl 1-on-3 is used, so also enable it if
  69. // OES_gpu_shader5 exists.
  70. #define LOVE_EXT_TEXTURE_ARRAY_ENABLED
  71. #extension GL_EXT_texture_array : enable
  72. #endif
  73. #ifdef GL_OES_texture_3D
  74. #extension GL_OES_texture_3D : enable
  75. #endif
  76. #ifdef GL_OES_standard_derivatives
  77. #extension GL_OES_standard_derivatives : enable
  78. #endif
  79. #ifdef USE_VULKAN
  80. #define VULKAN_LOCATION(x) layout(location=x)
  81. #define VULKAN_BINDING(x) layout(binding=x)
  82. #else
  83. #define VULKAN_LOCATION(x)
  84. #define VULKAN_BINDING(x)
  85. #endif
  86. )";
  87. static const char render_uniforms[] = R"(
  88. #ifdef USE_VULKAN
  89. VULKAN_BINDING(0) uniform LoveUniformsPerDraw {
  90. vec4 uniformsPerDraw[13];
  91. } udp;
  92. #define love_UniformsPerDraw udp.uniformsPerDraw
  93. #else
  94. // According to the GLSL ES 1.0 spec, uniform precision must match between stages,
  95. // but we can't guarantee that highp is always supported in fragment shaders...
  96. // We *really* don't want to use mediump for these in vertex shaders though.
  97. uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13];
  98. #endif
  99. // These are initialized in love_initializeBuiltinUniforms below. GLSL ES can't
  100. // do it as an initializer.
  101. LOVE_HIGHP_OR_MEDIUMP mat4 TransformMatrix;
  102. LOVE_HIGHP_OR_MEDIUMP mat4 ProjectionMatrix;
  103. LOVE_HIGHP_OR_MEDIUMP mat3 NormalMatrix;
  104. LOVE_HIGHP_OR_MEDIUMP vec4 love_ScreenSize;
  105. LOVE_HIGHP_OR_MEDIUMP vec4 ConstantColor;
  106. LOVE_HIGHP_OR_MEDIUMP float CurrentDPIScale;
  107. LOVE_HIGHP_OR_MEDIUMP float ConstantPointSize;
  108. #define TransformProjectionMatrix (ProjectionMatrix * TransformMatrix)
  109. // Alternate names
  110. #define ViewSpaceFromLocal TransformMatrix
  111. #define ClipSpaceFromView ProjectionMatrix
  112. #define ClipSpaceFromLocal TransformProjectionMatrix
  113. #define ViewNormalFromLocal NormalMatrix
  114. void love_initializeBuiltinUniforms() {
  115. TransformMatrix = mat4(
  116. love_UniformsPerDraw[0],
  117. love_UniformsPerDraw[1],
  118. love_UniformsPerDraw[2],
  119. love_UniformsPerDraw[3]
  120. );
  121. ProjectionMatrix = mat4(
  122. love_UniformsPerDraw[4],
  123. love_UniformsPerDraw[5],
  124. love_UniformsPerDraw[6],
  125. love_UniformsPerDraw[7]
  126. );
  127. NormalMatrix = mat3(
  128. love_UniformsPerDraw[8].xyz,
  129. love_UniformsPerDraw[9].xyz,
  130. love_UniformsPerDraw[10].xyz
  131. );
  132. CurrentDPIScale = love_UniformsPerDraw[8].w;
  133. ConstantPointSize = love_UniformsPerDraw[9].w;
  134. love_ScreenSize = love_UniformsPerDraw[11];
  135. ConstantColor = love_UniformsPerDraw[12];
  136. }
  137. )";
  138. static const char global_functions[] = R"(
  139. #ifdef GL_ES
  140. #if __VERSION__ >= 300 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED)
  141. precision lowp sampler2DArray;
  142. #endif
  143. #if __VERSION__ >= 300 || defined(GL_OES_texture_3D)
  144. precision lowp sampler3D;
  145. #endif
  146. #if __VERSION__ >= 300 && !defined(LOVE_GLSL1_ON_GLSL3)
  147. precision lowp sampler2DShadow;
  148. precision lowp samplerCubeShadow;
  149. precision lowp sampler2DArrayShadow;
  150. #endif
  151. #endif
  152. #if __VERSION__ >= 130 && !defined(LOVE_GLSL1_ON_GLSL3)
  153. #define Texel texture
  154. #else
  155. #if __VERSION__ >= 130
  156. #define texture2D Texel
  157. #define texture3D Texel
  158. #define textureCube Texel
  159. #define texture2DArray Texel
  160. #define love_texture2D texture
  161. #define love_texture3D texture
  162. #define love_textureCube texture
  163. #define love_texture2DArray texture
  164. #else
  165. #define love_texture2D texture2D
  166. #define love_texture3D texture3D
  167. #define love_textureCube textureCube
  168. #define love_texture2DArray texture2DArray
  169. #endif
  170. vec4 Texel(sampler2D s, vec2 c) { return love_texture2D(s, c); }
  171. vec4 Texel(samplerCube s, vec3 c) { return love_textureCube(s, c); }
  172. #if __VERSION__ > 100 || defined(GL_OES_texture_3D)
  173. vec4 Texel(sampler3D s, vec3 c) { return love_texture3D(s, c); }
  174. #endif
  175. #if __VERSION__ >= 130 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED)
  176. vec4 Texel(sampler2DArray s, vec3 c) { return love_texture2DArray(s, c); }
  177. #endif
  178. #ifdef PIXEL
  179. vec4 Texel(sampler2D s, vec2 c, float b) { return love_texture2D(s, c, b); }
  180. vec4 Texel(samplerCube s, vec3 c, float b) { return love_textureCube(s, c, b); }
  181. #if __VERSION__ > 100 || defined(GL_OES_texture_3D)
  182. vec4 Texel(sampler3D s, vec3 c, float b) { return love_texture3D(s, c, b); }
  183. #endif
  184. #if __VERSION__ >= 130 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED)
  185. vec4 Texel(sampler2DArray s, vec3 c, float b) { return love_texture2DArray(s, c, b); }
  186. #endif
  187. #endif
  188. #define texture love_texture
  189. #endif
  190. float gammaToLinearPrecise(float c) {
  191. return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);
  192. }
  193. vec3 gammaToLinearPrecise(vec3 c) {
  194. bvec3 leq = lessThanEqual(c, vec3(0.04045));
  195. c.r = leq.r ? c.r / 12.92 : pow((c.r + 0.055) / 1.055, 2.4);
  196. c.g = leq.g ? c.g / 12.92 : pow((c.g + 0.055) / 1.055, 2.4);
  197. c.b = leq.b ? c.b / 12.92 : pow((c.b + 0.055) / 1.055, 2.4);
  198. return c;
  199. }
  200. vec4 gammaToLinearPrecise(vec4 c) { return vec4(gammaToLinearPrecise(c.rgb), c.a); }
  201. float linearToGammaPrecise(float c) {
  202. return c < 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055;
  203. }
  204. vec3 linearToGammaPrecise(vec3 c) {
  205. bvec3 lt = lessThanEqual(c, vec3(0.0031308));
  206. c.r = lt.r ? c.r * 12.92 : 1.055 * pow(c.r, 1.0 / 2.4) - 0.055;
  207. c.g = lt.g ? c.g * 12.92 : 1.055 * pow(c.g, 1.0 / 2.4) - 0.055;
  208. c.b = lt.b ? c.b * 12.92 : 1.055 * pow(c.b, 1.0 / 2.4) - 0.055;
  209. return c;
  210. }
  211. vec4 linearToGammaPrecise(vec4 c) { return vec4(linearToGammaPrecise(c.rgb), c.a); }
  212. // http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
  213. mediump float gammaToLinearFast(mediump float c) { return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); }
  214. mediump vec3 gammaToLinearFast(mediump vec3 c) { return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); }
  215. mediump vec4 gammaToLinearFast(mediump vec4 c) { return vec4(gammaToLinearFast(c.rgb), c.a); }
  216. mediump float linearToGammaFast(mediump float c) { return max(1.055 * pow(max(c, 0.0), 0.41666666) - 0.055, 0.0); }
  217. mediump vec3 linearToGammaFast(mediump vec3 c) { return max(1.055 * pow(max(c, vec3(0.0)), vec3(0.41666666)) - 0.055, vec3(0.0)); }
  218. mediump vec4 linearToGammaFast(mediump vec4 c) { return vec4(linearToGammaFast(c.rgb), c.a); }
  219. #define gammaToLinear gammaToLinearFast
  220. #define linearToGamma linearToGammaFast
  221. #ifdef LOVE_GAMMA_CORRECT
  222. #define gammaCorrectColor gammaToLinear
  223. #define unGammaCorrectColor linearToGamma
  224. #define gammaCorrectColorPrecise gammaToLinearPrecise
  225. #define unGammaCorrectColorPrecise linearToGammaPrecise
  226. #define gammaCorrectColorFast gammaToLinearFast
  227. #define unGammaCorrectColorFast linearToGammaFast
  228. #else
  229. #define gammaCorrectColor
  230. #define unGammaCorrectColor
  231. #define gammaCorrectColorPrecise
  232. #define unGammaCorrectColorPrecise
  233. #define gammaCorrectColorFast
  234. #define unGammaCorrectColorFast
  235. #endif
  236. )";
  237. static const char vertex_header[] = R"(
  238. #define love_Position gl_Position
  239. #define love_PointSize gl_PointSize
  240. #if __VERSION__ >= 130
  241. #define attribute in
  242. #define varying out
  243. #ifndef LOVE_GLSL1_ON_GLSL3
  244. #define love_VertexID gl_VertexID
  245. #define love_InstanceID gl_InstanceID
  246. #endif
  247. #endif
  248. )";
  249. static const char vertex_functions[] = R"()";
  250. static const char vertex_main[] = R"(
  251. VULKAN_LOCATION(0) attribute vec4 VertexPosition;
  252. VULKAN_LOCATION(1) attribute vec4 VertexTexCoord;
  253. VULKAN_LOCATION(2) attribute vec4 VertexColor;
  254. VULKAN_LOCATION(0) varying vec4 VaryingTexCoord;
  255. VULKAN_LOCATION(1) varying vec4 VaryingColor;
  256. vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition);
  257. void main() {
  258. love_initializeBuiltinUniforms();
  259. VaryingTexCoord = VertexTexCoord;
  260. VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor;
  261. love_Position = position(ClipSpaceFromLocal, VertexPosition);
  262. }
  263. )";
  264. static const char vertex_main_raw[] = R"(
  265. void vertexmain();
  266. void main() {
  267. love_initializeBuiltinUniforms();
  268. vertexmain();
  269. }
  270. )";
  271. static const char pixel_header[] = R"(
  272. #ifdef GL_ES
  273. precision mediump float;
  274. #endif
  275. #define love_MaxRenderTargets gl_MaxDrawBuffers
  276. #if __VERSION__ >= 130
  277. #define varying in
  278. #endif
  279. // Legacy
  280. #define love_MaxCanvases love_MaxRenderTargets
  281. // See Shader::updateScreenParams in Shader.cpp.
  282. #define love_PixelCoord (vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenSize.z) + love_ScreenSize.w))
  283. )";
  284. static const char pixel_functions[] = R"(
  285. VULKAN_BINDING(1) uniform sampler2D love_VideoYChannel;
  286. VULKAN_BINDING(2) uniform sampler2D love_VideoCbChannel;
  287. VULKAN_BINDING(3) uniform sampler2D love_VideoCrChannel;
  288. vec4 VideoTexel(vec2 texcoords) {
  289. vec3 yuv;
  290. yuv[0] = Texel(love_VideoYChannel, texcoords).r;
  291. yuv[1] = Texel(love_VideoCbChannel, texcoords).r;
  292. yuv[2] = Texel(love_VideoCrChannel, texcoords).r;
  293. yuv += vec3(-0.0627451017, -0.501960814, -0.501960814);
  294. vec4 color;
  295. color.r = dot(yuv, vec3(1.164, 0.000, 1.596));
  296. color.g = dot(yuv, vec3(1.164, -0.391, -0.813));
  297. color.b = dot(yuv, vec3(1.164, 2.018, 0.000));
  298. color.a = 1.0;
  299. return gammaCorrectColor(color);
  300. }
  301. )";
  302. static const char pixel_main[] = R"(
  303. #if __VERSION__ >= 130
  304. LOVE_IO_LOCATION(0) out vec4 love_PixelColor;
  305. #else
  306. #define love_PixelColor gl_FragColor
  307. #endif
  308. VULKAN_BINDING(4) uniform sampler2D MainTex;
  309. VULKAN_LOCATION(0) varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
  310. VULKAN_LOCATION(1) varying mediump vec4 VaryingColor;
  311. vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord);
  312. void main() {
  313. love_initializeBuiltinUniforms();
  314. love_PixelColor = effect(VaryingColor, MainTex, VaryingTexCoord.st, love_PixelCoord);
  315. }
  316. )";
  317. static const char pixel_main_custom[] = R"(
  318. #if __VERSION__ >= 130
  319. // Some drivers seem to make the pixel shader do more work when multiple
  320. // pixel shader outputs are defined, even when only one is actually used.
  321. // TODO: We should use reflection or something instead of this, to determine
  322. // how many outputs are actually used in the shader code.
  323. #ifdef LOVE_MULTI_RENDER_TARGETS
  324. LOVE_IO_LOCATION(0) out vec4 love_RenderTargets[love_MaxRenderTargets];
  325. #define love_PixelColor love_RenderTargets[0]
  326. #else
  327. LOVE_IO_LOCATION(0) out vec4 love_PixelColor;
  328. #endif
  329. #else
  330. #ifdef LOVE_MULTI_RENDER_TARGETS
  331. #define love_RenderTargets gl_FragData
  332. #endif
  333. #define love_PixelColor gl_FragColor
  334. #endif
  335. // Legacy
  336. #define love_Canvases love_RenderTargets
  337. #ifdef LOVE_MULTI_RENDER_TARGETS
  338. #define LOVE_MULTI_CANVASES 1
  339. #endif
  340. VULKAN_LOCATION(0) varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
  341. VULKAN_LOCATION(1) varying mediump vec4 VaryingColor;
  342. void effect();
  343. void main() {
  344. love_initializeBuiltinUniforms();
  345. effect();
  346. }
  347. )";
  348. static const char pixel_main_raw[] = R"(
  349. void pixelmain();
  350. void main() {
  351. love_initializeBuiltinUniforms();
  352. pixelmain();
  353. }
  354. )";
  355. static const char compute_header[] = R"(
  356. #define love_ThreadGroupCount gl_NumWorkGroups
  357. #define love_ThreadGroupID gl_WorkGroupID
  358. #define love_LocalThreadID gl_LocalInvocationID
  359. #define love_GlobalThreadID gl_GlobalInvocationID
  360. #define love_LocalThreadIndex gl_LocalInvocationIndex
  361. #define love_ThreadGroupSize gl_WorkGroupSize
  362. )";
  363. static const char compute_uniforms[] = R"(
  364. void love_initializeBuiltinUniforms() {}
  365. )";
  366. static const char compute_functions[] = R"()";
  367. static const char compute_main[] = R"(
  368. void computemain();
  369. void main() {
  370. love_initializeBuiltinUniforms();
  371. computemain();
  372. }
  373. )";
  374. static const char vulkan_vert[] = R"(
  375. #version 450
  376. layout(location = 0) in vec2 inPosition;
  377. layout(location = 0) out vec4 fragColor;
  378. float windowWidth = 800;
  379. float windowHeight = 600;
  380. void main() {
  381. gl_Position = vec4(
  382. 2 * inPosition.x / windowWidth - 1,
  383. 2 * inPosition.y / windowHeight - 1,
  384. 0.0, 1.0);
  385. fragColor = vec4(1, 1, 1, 1);
  386. }
  387. )";
  388. static const char vulkan_pixel[] = R"(
  389. #version 450
  390. layout(location = 0) in vec4 fragColor;
  391. layout(location = 0) out vec4 outColor;
  392. void main() {
  393. outColor = fragColor;
  394. }
  395. )";
  396. struct StageInfo
  397. {
  398. const char *name;
  399. const char *header;
  400. const char *uniforms;
  401. const char *functions;
  402. const char *main;
  403. const char *main_custom;
  404. const char *main_raw;
  405. };
  406. static const StageInfo stageInfo[] =
  407. {
  408. { "VERTEX", vertex_header, render_uniforms, vertex_functions, vertex_main, vertex_main, vertex_main_raw },
  409. { "PIXEL", pixel_header, render_uniforms, pixel_functions, pixel_main, pixel_main_custom, pixel_main_raw },
  410. { "COMPUTE", compute_header, compute_uniforms, compute_functions, compute_main, compute_main, compute_main },
  411. };
  412. static_assert((sizeof(stageInfo) / sizeof(StageInfo)) == SHADERSTAGE_MAX_ENUM, "Stages array size must match ShaderStage enum.");
  413. struct Version
  414. {
  415. std::string glsl;
  416. std::string glsles;
  417. };
  418. // Indexed by Shader::Version
  419. static const Version versions[] =
  420. {
  421. { "#version 120", "#version 100" },
  422. { "#version 330 core", "#version 300 es" },
  423. { "#version 430 core", "#version 320 es" },
  424. };
  425. static Shader::Language getTargetLanguage(const std::string &src)
  426. {
  427. std::regex r("^\\s*#pragma language (\\w+)");
  428. std::smatch m;
  429. std::string langstr = std::regex_search(src, m, r) && m.size() > 1 ? m[1] : std::string("glsl1");
  430. Shader::Language lang = Shader::LANGUAGE_MAX_ENUM;
  431. Shader::getConstant(langstr.c_str(), lang);
  432. return lang;
  433. }
  434. static Shader::EntryPoint getVertexEntryPoint(const std::string &src)
  435. {
  436. std::smatch m;
  437. if (std::regex_search(src, m, std::regex("void\\s+vertexmain\\s*\\(")))
  438. return Shader::ENTRYPOINT_RAW;
  439. if (std::regex_search(src, m, std::regex("vec4\\s+position\\s*\\(")))
  440. return Shader::ENTRYPOINT_HIGHLEVEL;
  441. return Shader::ENTRYPOINT_NONE;
  442. }
  443. static Shader::EntryPoint getPixelEntryPoint(const std::string &src, bool &mrt)
  444. {
  445. mrt = false;
  446. std::smatch m;
  447. if (std::regex_search(src, m, std::regex("void\\s+pixelmain\\s*\\(")))
  448. return Shader::ENTRYPOINT_RAW;
  449. if (std::regex_search(src, m, std::regex("vec4\\s+effect\\s*\\(")))
  450. return Shader::ENTRYPOINT_HIGHLEVEL;
  451. if (std::regex_search(src, m, std::regex("void\\s+effect\\s*\\(")))
  452. {
  453. if (src.find("love_RenderTargets") != std::string::npos || src.find("love_Canvases") != std::string::npos)
  454. mrt = true;
  455. return Shader::ENTRYPOINT_CUSTOM;
  456. }
  457. return Shader::ENTRYPOINT_NONE;
  458. }
  459. static Shader::EntryPoint getComputeEntryPoint(const std::string &src) {
  460. std::smatch m;
  461. if (std::regex_search(src, m, std::regex("void\\s+computemain\\s*\\(")))
  462. return Shader::ENTRYPOINT_RAW;
  463. return Shader::ENTRYPOINT_NONE;
  464. }
  465. } // glsl
  466. static_assert(sizeof(Shader::BuiltinUniformData) == sizeof(float) * 4 * 13, "Update the array in wrap_GraphicsShader.lua if this changes.");
  467. love::Type Shader::type("Shader", &Object::type);
  468. Shader *Shader::current = nullptr;
  469. Shader *Shader::standardShaders[Shader::STANDARD_MAX_ENUM] = {nullptr};
  470. Shader::SourceInfo Shader::getSourceInfo(const std::string &src)
  471. {
  472. SourceInfo info = {};
  473. info.language = glsl::getTargetLanguage(src);
  474. info.stages[SHADERSTAGE_VERTEX] = glsl::getVertexEntryPoint(src);
  475. info.stages[SHADERSTAGE_PIXEL] = glsl::getPixelEntryPoint(src, info.usesMRT);
  476. info.stages[SHADERSTAGE_COMPUTE] = glsl::getComputeEntryPoint(src);
  477. if (info.stages[SHADERSTAGE_COMPUTE])
  478. info.language = LANGUAGE_GLSL4;
  479. return info;
  480. }
  481. std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage, const std::string &code, const Shader::SourceInfo &info, bool gles, bool checksystemfeatures)
  482. {
  483. if (info.language == Shader::LANGUAGE_MAX_ENUM)
  484. throw love::Exception("Invalid shader language");
  485. if (info.stages[stage] == ENTRYPOINT_NONE)
  486. throw love::Exception("Cannot find entry point for shader stage.");
  487. if (info.stages[stage] == ENTRYPOINT_RAW && info.language == LANGUAGE_GLSL1)
  488. throw love::Exception("Shaders using a raw entry point (vertexmain or pixelmain) must use GLSL 3 or greater.");
  489. if (stage == SHADERSTAGE_COMPUTE && info.language != LANGUAGE_GLSL4)
  490. throw love::Exception("Compute shaders must use GLSL 4.");
  491. bool glsl1on3 = info.language == LANGUAGE_GLSL1;
  492. if (checksystemfeatures)
  493. {
  494. const auto &features = gfx->getCapabilities().features;
  495. if (stage == SHADERSTAGE_COMPUTE && !features[Graphics::FEATURE_GLSL4])
  496. throw love::Exception("Compute shaders require GLSL 4 which is not supported on this system.");
  497. if (info.language == LANGUAGE_GLSL3 && !features[Graphics::FEATURE_GLSL3])
  498. throw love::Exception("GLSL 3 shaders are not supported on this system.");
  499. if (info.language == LANGUAGE_GLSL4 && !features[Graphics::FEATURE_GLSL4])
  500. throw love::Exception("GLSL 4 shaders are not supported on this system.");
  501. glsl1on3 = info.language == LANGUAGE_GLSL1 && features[Graphics::FEATURE_GLSL3];
  502. }
  503. Language lang = info.language;
  504. if (glsl1on3)
  505. lang = LANGUAGE_GLSL3;
  506. if (info.vulkan) {
  507. if (stage == SHADERSTAGE_VERTEX) {
  508. return love::graphics::glsl::vulkan_vert;
  509. }
  510. if (stage == SHADERSTAGE_PIXEL) {
  511. return love::graphics::glsl::vulkan_pixel;
  512. }
  513. }
  514. glsl::StageInfo stageinfo = glsl::stageInfo[stage];
  515. std::stringstream ss;
  516. ss << (gles ? glsl::versions[lang].glsles : glsl::versions[lang].glsl) << "\n";
  517. ss << "#define " << stageinfo.name << " " << stageinfo.name << "\n";
  518. if (glsl1on3)
  519. ss << "#define LOVE_GLSL1_ON_GLSL3 1\n";
  520. if (isGammaCorrect())
  521. ss << "#define LOVE_GAMMA_CORRECT 1\n";
  522. if (info.usesMRT)
  523. ss << "#define LOVE_MULTI_RENDER_TARGETS 1\n";
  524. if (info.vulkan)
  525. ss << "#define USE_VULKAN\n";
  526. ss << glsl::global_syntax;
  527. ss << stageinfo.header;
  528. ss << stageinfo.uniforms;
  529. ss << glsl::global_functions;
  530. ss << stageinfo.functions;
  531. if (info.stages[stage] == ENTRYPOINT_HIGHLEVEL)
  532. ss << stageinfo.main;
  533. else if (info.stages[stage] == ENTRYPOINT_CUSTOM)
  534. ss << stageinfo.main_custom;
  535. else if (info.stages[stage] == ENTRYPOINT_RAW)
  536. ss << stageinfo.main_raw;
  537. else
  538. throw love::Exception("Unknown shader entry point %d", info.stages[stage]);
  539. ss << ((!gles && (lang == Shader::LANGUAGE_GLSL1 || glsl1on3)) ? "#line 0\n" : "#line 1\n");
  540. ss << code;
  541. return ss.str();
  542. }
  543. Shader::Shader(StrongRef<ShaderStage> _stages[])
  544. : stages()
  545. {
  546. std::string err;
  547. if (!validateInternal(_stages, err, validationReflection))
  548. throw love::Exception("%s", err.c_str());
  549. for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
  550. stages[i] = _stages[i];
  551. }
  552. Shader::~Shader()
  553. {
  554. for (int i = 0; i < STANDARD_MAX_ENUM; i++)
  555. {
  556. if (this == standardShaders[i])
  557. standardShaders[i] = nullptr;
  558. }
  559. if (current == this)
  560. attachDefault(STANDARD_DEFAULT);
  561. }
  562. bool Shader::hasStage(ShaderStageType stage)
  563. {
  564. return stages[stage] != nullptr;
  565. }
  566. void Shader::attachDefault(StandardShader defaultType)
  567. {
  568. Shader *defaultshader = standardShaders[defaultType];
  569. if (defaultshader == nullptr)
  570. {
  571. current = nullptr;
  572. return;
  573. }
  574. if (current != defaultshader)
  575. defaultshader->attach();
  576. }
  577. bool Shader::isDefaultActive()
  578. {
  579. for (int i = 0; i < STANDARD_MAX_ENUM; i++)
  580. {
  581. if (current == standardShaders[i])
  582. return true;
  583. }
  584. return false;
  585. }
  586. const Shader::UniformInfo *Shader::getMainTextureInfo() const
  587. {
  588. return getUniformInfo(BUILTIN_TEXTURE_MAIN);
  589. }
  590. DataBaseType Shader::getDataBaseType(PixelFormat format)
  591. {
  592. switch (getPixelFormatInfo(format).dataType)
  593. {
  594. case PIXELFORMATTYPE_UNORM:
  595. return DATA_BASETYPE_UNORM;
  596. case PIXELFORMATTYPE_SNORM:
  597. return DATA_BASETYPE_SNORM;
  598. case PIXELFORMATTYPE_UFLOAT:
  599. case PIXELFORMATTYPE_SFLOAT:
  600. return DATA_BASETYPE_FLOAT;
  601. case PIXELFORMATTYPE_SINT:
  602. return DATA_BASETYPE_INT;
  603. case PIXELFORMATTYPE_UINT:
  604. return DATA_BASETYPE_UINT;
  605. default:
  606. return DATA_BASETYPE_FLOAT;
  607. }
  608. }
  609. bool Shader::isResourceBaseTypeCompatible(DataBaseType a, DataBaseType b)
  610. {
  611. if (a == DATA_BASETYPE_FLOAT || a == DATA_BASETYPE_UNORM || a == DATA_BASETYPE_SNORM)
  612. return b == DATA_BASETYPE_FLOAT || b == DATA_BASETYPE_UNORM || b == DATA_BASETYPE_SNORM;
  613. if (a == DATA_BASETYPE_INT && b == DATA_BASETYPE_INT)
  614. return true;
  615. if (a == DATA_BASETYPE_UINT && b == DATA_BASETYPE_UINT)
  616. return true;
  617. return false;
  618. }
  619. void Shader::validateDrawState(PrimitiveType primtype, Texture *maintex) const
  620. {
  621. if ((primtype == PRIMITIVE_POINTS) != validationReflection.usesPointSize)
  622. {
  623. if (validationReflection.usesPointSize)
  624. throw love::Exception("The active shader can only be used to draw points.");
  625. else
  626. throw love::Exception("The gl_PointSize variable must be set in a vertex shader when drawing points.");
  627. }
  628. if (maintex == nullptr)
  629. return;
  630. const UniformInfo *info = getUniformInfo(BUILTIN_TEXTURE_MAIN);
  631. if (info == nullptr)
  632. return;
  633. if (!maintex->isReadable())
  634. throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader.");
  635. auto textype = maintex->getTextureType();
  636. if (info->textureType != TEXTURE_MAX_ENUM && info->textureType != textype)
  637. {
  638. const char *textypestr = "unknown";
  639. const char *shadertextypestr = "unknown";
  640. Texture::getConstant(textype, textypestr);
  641. Texture::getConstant(info->textureType, shadertextypestr);
  642. throw love::Exception("Texture's type (%s) must match the type of the shader's main texture type (%s).", textypestr, shadertextypestr);
  643. }
  644. if (!isResourceBaseTypeCompatible(info->dataBaseType, getDataBaseType(maintex->getPixelFormat())))
  645. throw love::Exception("Texture's data format base type must match the uniform variable declared in the shader (float, int, or uint).");
  646. if (info->isDepthSampler != maintex->getSamplerState().depthSampleMode.hasValue)
  647. {
  648. if (info->isDepthSampler)
  649. throw love::Exception("Depth comparison samplers in shaders can only be used with depth textures which have depth comparison set.");
  650. else
  651. throw love::Exception("Depth textures which have depth comparison set can only be used with depth/shadow samplers in shaders.");
  652. }
  653. }
  654. void Shader::getLocalThreadgroupSize(int *x, int *y, int *z)
  655. {
  656. *x = validationReflection.localThreadgroupSize[0];
  657. *y = validationReflection.localThreadgroupSize[1];
  658. *z = validationReflection.localThreadgroupSize[2];
  659. }
  660. bool Shader::validate(StrongRef<ShaderStage> stages[], std::string& err)
  661. {
  662. ValidationReflection reflection;
  663. return validateInternal(stages, err, reflection);
  664. }
  665. static PixelFormat getPixelFormat(glslang::TLayoutFormat format)
  666. {
  667. using namespace glslang;
  668. switch (format)
  669. {
  670. case ElfNone: return PIXELFORMAT_UNKNOWN;
  671. case ElfRgba32f: return PIXELFORMAT_RGBA32_FLOAT;
  672. case ElfRgba16f: return PIXELFORMAT_RGBA16_FLOAT;
  673. case ElfR32f: return PIXELFORMAT_R32_FLOAT;
  674. case ElfRgba8: return PIXELFORMAT_RGBA8_UNORM;
  675. case ElfRgba8Snorm: return PIXELFORMAT_UNKNOWN; // no snorm yet
  676. case ElfRg32f: return PIXELFORMAT_RG32_FLOAT;
  677. case ElfRg16f: return PIXELFORMAT_RG16_FLOAT;
  678. case ElfR11fG11fB10f: return PIXELFORMAT_RG11B10_FLOAT;
  679. case ElfR16f: return PIXELFORMAT_R16_FLOAT;
  680. case ElfRgba16: return PIXELFORMAT_RGBA16_UNORM;
  681. case ElfRgb10A2: return PIXELFORMAT_RGB10A2_UNORM;
  682. case ElfRg16: return PIXELFORMAT_RG16_UNORM;
  683. case ElfRg8: return PIXELFORMAT_RG8_UNORM;
  684. case ElfR8: return PIXELFORMAT_R8_UNORM;
  685. case ElfRgba16Snorm: return PIXELFORMAT_UNKNOWN;
  686. case ElfRg16Snorm: return PIXELFORMAT_UNKNOWN;
  687. case ElfRg8Snorm: return PIXELFORMAT_UNKNOWN;
  688. case ElfR16Snorm: return PIXELFORMAT_UNKNOWN;
  689. case ElfR8Snorm: return PIXELFORMAT_UNKNOWN;
  690. case ElfRgba32i: return PIXELFORMAT_RGBA32_INT;
  691. case ElfRgba16i: return PIXELFORMAT_RGBA16_INT;
  692. case ElfRgba8i: return PIXELFORMAT_RGBA8_INT;
  693. case ElfR32i: return PIXELFORMAT_R32_INT;
  694. case ElfRg32i: return PIXELFORMAT_RG32_INT;
  695. case ElfRg16i: return PIXELFORMAT_RG16_INT;
  696. case ElfRg8i: return PIXELFORMAT_RG8_INT;
  697. case ElfR16i: return PIXELFORMAT_R16_INT;
  698. case ElfR8i: return PIXELFORMAT_R8_INT;
  699. case ElfRgba32ui: return PIXELFORMAT_RGBA32_UINT;
  700. case ElfRgba16ui: return PIXELFORMAT_RGBA16_UINT;
  701. case ElfRgba8ui: return PIXELFORMAT_RGBA8_UINT;
  702. case ElfR32ui: return PIXELFORMAT_R32_UINT;
  703. case ElfRg32ui: return PIXELFORMAT_RG32_UINT;
  704. case ElfRg16ui: return PIXELFORMAT_RG16_UINT;
  705. case ElfRgb10a2ui: return PIXELFORMAT_UNKNOWN;
  706. case ElfRg8ui: return PIXELFORMAT_RG8_UINT;
  707. case ElfR16ui: return PIXELFORMAT_R16_UINT;
  708. case ElfR8ui: return PIXELFORMAT_R8_UINT;
  709. default: return PIXELFORMAT_UNKNOWN;
  710. }
  711. }
  712. template <typename T>
  713. static T convertData(const glslang::TConstUnion &data)
  714. {
  715. switch (data.getType())
  716. {
  717. case glslang::EbtInt: return (T) data.getIConst();
  718. case glslang::EbtUint: return (T) data.getUConst();
  719. case glslang::EbtDouble: return (T) data.getDConst();
  720. case glslang::EbtInt8: return (T) data.getI8Const();
  721. case glslang::EbtInt16: return (T) data.getI16Const();
  722. case glslang::EbtInt64: return (T) data.getI64Const();
  723. case glslang::EbtUint8: return (T) data.getU8Const();
  724. case glslang::EbtUint16: return (T) data.getU16Const();
  725. case glslang::EbtUint64: return (T) data.getU64Const();
  726. default: return 0;
  727. }
  728. }
  729. bool Shader::validateInternal(StrongRef<ShaderStage> stages[], std::string &err, ValidationReflection &reflection)
  730. {
  731. glslang::TProgram program;
  732. for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
  733. {
  734. if (stages[i] != nullptr)
  735. program.addShader(stages[i]->getGLSLangValidationShader());
  736. }
  737. if (!program.link(EShMsgDefault))
  738. {
  739. err = "Cannot compile shader:\n\n" + std::string(program.getInfoLog()) + "\n" + std::string(program.getInfoDebugLog());
  740. return false;
  741. }
  742. if (!program.buildReflection(EShReflectionSeparateBuffers))
  743. {
  744. err = "Cannot get reflection information for shader.";
  745. return false;
  746. }
  747. const auto *vertintermediate = program.getIntermediate(EShLangVertex);
  748. if (vertintermediate != nullptr)
  749. {
  750. // NOTE: this doesn't check whether the use affects final output...
  751. reflection.usesPointSize = vertintermediate->inIoAccessed("gl_PointSize");
  752. }
  753. if (stages[SHADERSTAGE_COMPUTE] != nullptr)
  754. {
  755. for (int i = 0; i < 3; i++)
  756. {
  757. reflection.localThreadgroupSize[i] = program.getLocalSize(i);
  758. if (reflection.localThreadgroupSize[i] <= 0)
  759. {
  760. err = "Shader validation error:\nNegative local threadgroup size.";
  761. return false;
  762. }
  763. }
  764. }
  765. for (int i = 0; i < program.getNumUniformVariables(); i++)
  766. {
  767. const glslang::TObjectReflection &info = program.getUniform(i);
  768. const glslang::TType *type = info.getType();
  769. if (type == nullptr)
  770. continue;
  771. const glslang::TQualifier &qualifiers = type->getQualifier();
  772. if (type->isImage())
  773. {
  774. if ((info.stages & EShLangComputeMask) == 0)
  775. {
  776. err = "Shader validation error:\nStorage Texture uniform variables (image2D, etc) are only allowed in compute shaders.";
  777. return false;
  778. }
  779. if (!qualifiers.hasFormat())
  780. {
  781. err = "Shader validation error:\nStorage Texture '" + info.name + "' must have an explicit format set in its layout declaration.";
  782. return false;
  783. }
  784. StorageTextureReflection texreflection = {};
  785. texreflection.format = getPixelFormat(qualifiers.getFormat());
  786. if (qualifiers.isReadOnly())
  787. texreflection.access = ACCESS_READ;
  788. else if (qualifiers.isWriteOnly())
  789. texreflection.access = ACCESS_WRITE;
  790. else
  791. texreflection.access = (Access)(ACCESS_READ | ACCESS_WRITE);
  792. reflection.storageTextures[info.name] = texreflection;
  793. }
  794. else if (!type->isOpaque())
  795. {
  796. LocalUniform u = {};
  797. auto &values = u.initializerValues;
  798. // const glslang::TConstUnionArray *constarray = info.getConstArray(); was this function deprecated in a later version?
  799. const glslang::TConstUnionArray* constarray = nullptr;
  800. // Store initializer values for local uniforms. Some love graphics
  801. // backends strip these out of the shader so we need to be able to
  802. // access them (to re-send them) by getting them here.
  803. switch (type->getBasicType())
  804. {
  805. case glslang::EbtFloat:
  806. u.dataType = DATA_BASETYPE_FLOAT;
  807. if (constarray != nullptr)
  808. {
  809. values.resize(constarray->size());
  810. for (int i = 0; i < constarray->size(); i++)
  811. values[i].f = convertData<float>((*constarray)[i]);
  812. }
  813. break;
  814. case glslang::EbtUint:
  815. u.dataType = DATA_BASETYPE_UINT;
  816. if (constarray != nullptr)
  817. {
  818. values.resize(constarray->size());
  819. for (int i = 0; i < constarray->size(); i++)
  820. values[i].u = convertData<uint32>((*constarray)[i]);
  821. }
  822. break;
  823. case glslang::EbtInt:
  824. case glslang::EbtBool:
  825. default:
  826. u.dataType = DATA_BASETYPE_INT;
  827. if (constarray != nullptr)
  828. {
  829. values.resize(constarray->size());
  830. for (int i = 0; i < constarray->size(); i++)
  831. values[i].i = convertData<int32>((*constarray)[i]);
  832. }
  833. break;
  834. }
  835. reflection.localUniforms[info.name] = u;
  836. }
  837. }
  838. for (int i = 0; i < program.getNumBufferBlocks(); i++)
  839. {
  840. const glslang::TObjectReflection &info = program.getBufferBlock(i);
  841. const glslang::TType *type = info.getType();
  842. if (type != nullptr)
  843. {
  844. const glslang::TQualifier &qualifiers = type->getQualifier();
  845. if ((!qualifiers.isReadOnly() || qualifiers.isWriteOnly()) && (info.stages & EShLangComputeMask) == 0)
  846. {
  847. err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must be marked as readonly in vertex and pixel shaders.";
  848. return false;
  849. }
  850. if (qualifiers.layoutPacking != glslang::ElpStd430)
  851. {
  852. err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must use the std430 packing layout.";
  853. return false;
  854. }
  855. const glslang::TTypeList *structure = type->getStruct();
  856. if (structure == nullptr || structure->size() != 1)
  857. {
  858. err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of base types or structs.";
  859. return false;
  860. }
  861. const glslang::TType* elementtype = (*structure)[0].type;
  862. if (elementtype == nullptr || !elementtype->isUnsizedArray())
  863. {
  864. err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must contain a single unsized array of base types or structs.";
  865. return false;
  866. }
  867. BufferReflection bufferReflection = {};
  868. bufferReflection.stride = (size_t) info.size;
  869. bufferReflection.memberCount = (size_t) info.numMembers;
  870. if (qualifiers.isReadOnly())
  871. bufferReflection.access = ACCESS_READ;
  872. else if (qualifiers.isWriteOnly())
  873. bufferReflection.access = ACCESS_WRITE;
  874. else
  875. bufferReflection.access = (Access)(ACCESS_READ | ACCESS_WRITE);
  876. reflection.storageBuffers[info.name] = bufferReflection;
  877. }
  878. else
  879. {
  880. err = "Shader validation error:\nCannot retrieve type information for Storage Buffer Block '" + info.name + "'.";
  881. return false;
  882. }
  883. }
  884. return true;
  885. }
  886. bool Shader::validateTexture(const UniformInfo *info, Texture *tex, bool internalUpdate)
  887. {
  888. const SamplerState &sampler = tex->getSamplerState();
  889. bool isstoragetex = info->baseType == UNIFORM_STORAGETEXTURE;
  890. if (!tex->isReadable())
  891. {
  892. if (internalUpdate)
  893. return false;
  894. else
  895. throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader.");
  896. }
  897. else if (info->isDepthSampler != sampler.depthSampleMode.hasValue)
  898. {
  899. if (internalUpdate)
  900. return false;
  901. else if (info->isDepthSampler)
  902. throw love::Exception("Depth comparison samplers in shaders can only be used with depth textures which have depth comparison set.");
  903. else
  904. throw love::Exception("Depth textures which have depth comparison set can only be used with depth/shadow samplers in shaders.");
  905. }
  906. else if (tex->getTextureType() != info->textureType)
  907. {
  908. if (internalUpdate)
  909. return false;
  910. else
  911. {
  912. const char *textypestr = "unknown";
  913. const char *shadertextypestr = "unknown";
  914. Texture::getConstant(tex->getTextureType(), textypestr);
  915. Texture::getConstant(info->textureType, shadertextypestr);
  916. throw love::Exception("Texture's type (%s) must match the type of %s (%s).", textypestr, info->name.c_str(), shadertextypestr);
  917. }
  918. }
  919. else if (!isResourceBaseTypeCompatible(info->dataBaseType, getDataBaseType(tex->getPixelFormat())))
  920. {
  921. if (internalUpdate)
  922. return false;
  923. else
  924. throw love::Exception("Texture's data format base type must match the uniform variable declared in the shader (float, int, or uint).");
  925. }
  926. else if (isstoragetex && !tex->isComputeWritable())
  927. {
  928. if (internalUpdate)
  929. return false;
  930. else
  931. throw love::Exception("Texture must be created with the computewrite flag set to true in order to be used with a storage texture (image2D etc) shader uniform variable.");
  932. }
  933. else if (isstoragetex && info->storageTextureFormat != getLinearPixelFormat(tex->getPixelFormat()))
  934. {
  935. if (internalUpdate)
  936. return false;
  937. else
  938. {
  939. const char *texpfstr = "unknown";
  940. const char *shaderpfstr = "unknown";
  941. love::getConstant(getLinearPixelFormat(tex->getPixelFormat()), texpfstr);
  942. love::getConstant(info->storageTextureFormat, shaderpfstr);
  943. throw love::Exception("Texture's pixel format (%s) must match the shader uniform variable %s's pixel format (%s)", texpfstr, info->name.c_str(), shaderpfstr);
  944. }
  945. }
  946. return true;
  947. }
  948. bool Shader::validateBuffer(const UniformInfo *info, Buffer *buffer, bool internalUpdate)
  949. {
  950. uint32 requiredtypeflags = 0;
  951. bool texelbinding = info->baseType == UNIFORM_TEXELBUFFER;
  952. bool storagebinding = info->baseType == UNIFORM_STORAGEBUFFER;
  953. if (texelbinding)
  954. requiredtypeflags = BUFFERUSAGEFLAG_TEXEL;
  955. else if (storagebinding)
  956. requiredtypeflags = BUFFERUSAGEFLAG_SHADER_STORAGE;
  957. if ((buffer->getUsageFlags() & requiredtypeflags) == 0)
  958. {
  959. if (internalUpdate)
  960. return false;
  961. else if (texelbinding)
  962. throw love::Exception("Shader uniform '%s' is a texel buffer, but the given Buffer was not created with texel buffer capabilities.", info->name.c_str());
  963. else if (storagebinding)
  964. throw love::Exception("Shader uniform '%s' is a shader storage buffer block, but the given Buffer was not created with shader storage buffer capabilities.", info->name.c_str());
  965. else
  966. throw love::Exception("Shader uniform '%s' does not match the types supported by the given Buffer.", info->name.c_str());
  967. }
  968. if (texelbinding)
  969. {
  970. DataBaseType basetype = buffer->getDataMember(0).info.baseType;
  971. if (!isResourceBaseTypeCompatible(basetype, info->dataBaseType))
  972. {
  973. if (internalUpdate)
  974. return false;
  975. else
  976. throw love::Exception("Texel buffer's data format base type must match the variable declared in the shader.");
  977. }
  978. }
  979. else if (storagebinding)
  980. {
  981. if (info->bufferStride != buffer->getArrayStride())
  982. {
  983. if (internalUpdate)
  984. return false;
  985. else
  986. throw love::Exception("Shader storage block '%s' has an array stride of %d bytes, but the given Buffer has an array stride of %d bytes.",
  987. info->name.c_str(), info->bufferStride, buffer->getArrayStride());
  988. }
  989. else if (info->bufferMemberCount != buffer->getDataMembers().size())
  990. {
  991. if (internalUpdate)
  992. return false;
  993. else
  994. throw love::Exception("Shader storage block '%s' has a struct with %d fields, but the given Buffer has a format with %d members.",
  995. info->name.c_str(), info->bufferMemberCount, buffer->getDataMembers().size());
  996. }
  997. }
  998. return true;
  999. }
  1000. bool Shader::initialize()
  1001. {
  1002. return glslang::InitializeProcess();
  1003. }
  1004. void Shader::deinitialize()
  1005. {
  1006. glslang::FinalizeProcess();
  1007. }
  1008. static const std::string defaultVertex = R"(
  1009. vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition)
  1010. {
  1011. return clipSpaceFromLocal * localPosition;
  1012. }
  1013. )";
  1014. static const std::string defaultPointsVertex = R"(
  1015. vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition)
  1016. {
  1017. love_PointSize = ConstantPointSize * CurrentDPIScale;
  1018. return clipSpaceFromLocal * localPosition;
  1019. }
  1020. )";
  1021. static const std::string defaultStandardPixel = R"(
  1022. vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord)
  1023. {
  1024. return Texel(tex, texcoord) * vcolor;
  1025. }
  1026. )";
  1027. static const std::string defaultVideoPixel = R"(
  1028. void effect()
  1029. {
  1030. love_PixelColor = VideoTexel(VaryingTexCoord.xy) * VaryingColor;
  1031. }
  1032. )";
  1033. static const std::string defaultArrayPixel = R"(
  1034. uniform ArrayImage MainTex;
  1035. void effect()
  1036. {
  1037. love_PixelColor = Texel(MainTex, VaryingTexCoord.xyz) * VaryingColor;
  1038. }
  1039. )";
  1040. const std::string &Shader::getDefaultCode(StandardShader shader, ShaderStageType stage)
  1041. {
  1042. if (stage == SHADERSTAGE_VERTEX)
  1043. {
  1044. if (shader == STANDARD_POINTS)
  1045. return defaultPointsVertex;
  1046. else
  1047. return defaultVertex;
  1048. }
  1049. static std::string nocode = "";
  1050. switch (shader)
  1051. {
  1052. case STANDARD_DEFAULT: return defaultStandardPixel;
  1053. case STANDARD_VIDEO: return defaultVideoPixel;
  1054. case STANDARD_ARRAY: return defaultArrayPixel;
  1055. case STANDARD_POINTS: return defaultStandardPixel;
  1056. case STANDARD_MAX_ENUM: return nocode;
  1057. }
  1058. return nocode;
  1059. }
  1060. static StringMap<Shader::Language, Shader::LANGUAGE_MAX_ENUM>::Entry languageEntries[] =
  1061. {
  1062. { "glsl1", Shader::LANGUAGE_GLSL1 },
  1063. { "glsl3", Shader::LANGUAGE_GLSL3 },
  1064. { "glsl4", Shader::LANGUAGE_GLSL4 },
  1065. };
  1066. static StringMap<Shader::Language, Shader::LANGUAGE_MAX_ENUM> languages(languageEntries, sizeof(languageEntries));
  1067. static StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM>::Entry builtinNameEntries[] =
  1068. {
  1069. { "MainTex", Shader::BUILTIN_TEXTURE_MAIN },
  1070. { "love_VideoYChannel", Shader::BUILTIN_TEXTURE_VIDEO_Y },
  1071. { "love_VideoCbChannel", Shader::BUILTIN_TEXTURE_VIDEO_CB },
  1072. { "love_VideoCrChannel", Shader::BUILTIN_TEXTURE_VIDEO_CR },
  1073. { "love_UniformsPerDraw", Shader::BUILTIN_UNIFORMS_PER_DRAW },
  1074. };
  1075. static StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM> builtinNames(builtinNameEntries, sizeof(builtinNameEntries));
  1076. bool Shader::getConstant(const char *in, Language &out)
  1077. {
  1078. return languages.find(in, out);
  1079. }
  1080. bool Shader::getConstant(Language in, const char *&out)
  1081. {
  1082. return languages.find(in, out);
  1083. }
  1084. bool Shader::getConstant(const char *in, BuiltinUniform &out)
  1085. {
  1086. return builtinNames.find(in, out);
  1087. }
  1088. bool Shader::getConstant(BuiltinUniform in, const char *&out)
  1089. {
  1090. return builtinNames.find(in, out);
  1091. }
  1092. } // graphics
  1093. } // love