ShaderProgramCompiler.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <Tests/Framework/Framework.h>
  6. #include <AnKi/ShaderCompiler/ShaderCompiler.h>
  7. #include <AnKi/ShaderCompiler/ShaderDump.h>
  8. #include <AnKi/Util/ThreadHive.h>
  9. ANKI_TEST(ShaderCompiler, ShaderProgramCompilerSimple)
  10. {
  11. const CString sourceCode = R"(
  12. #pragma anki mutator INSTANCE_COUNT 1 2 4
  13. struct Foo
  14. {
  15. Mat4 m_mat;
  16. };
  17. struct Instanced
  18. {
  19. Mat4 m_ankiMvp;
  20. Mat3 m_ankiRotationMat;
  21. Mat4 m_ankiModelViewMat;
  22. Mat4 m_ankiPrevMvp;
  23. Foo m_foo[2];
  24. };
  25. layout(push_constant) uniform ankiMaterial
  26. {
  27. Vec4 u_whatever;
  28. Instanced u_ankiPerInstance[INSTANCE_COUNT];
  29. Vec4 u_color;
  30. };
  31. layout(set = 0, binding = 1) uniform texture2D u_tex2d;
  32. layout(set = 0, binding = 1) uniform texture3D u_tex3d;
  33. layout(set = 0, binding = 2) uniform sampler u_sampler;
  34. layout(set = 0, binding = 3) buffer ssbo
  35. {
  36. Foo u_mats[];
  37. };
  38. #pragma anki start vert
  39. out gl_PerVertex
  40. {
  41. Vec4 gl_Position;
  42. };
  43. void main()
  44. {
  45. gl_Position = u_ankiPerInstance[gl_InstanceIndex].m_ankiMvp * u_mats[gl_InstanceIndex].m_mat * Vec4(gl_VertexID);
  46. }
  47. #pragma anki end vert
  48. #pragma anki start frag
  49. layout(location = 0) out Vec3 out_color;
  50. void main()
  51. {
  52. out_color = Vec3(0);
  53. if(INSTANCE_COUNT == 1)
  54. out_color += textureLod(sampler2D(u_tex2d, u_sampler), Vec2(0), 0.0).rgb;
  55. else if(INSTANCE_COUNT == 2)
  56. out_color += textureLod(sampler3D(u_tex3d, u_sampler), Vec3(0), 0.0).rgb;
  57. else
  58. out_color += textureLod(sampler2D(u_tex2d, u_sampler), Vec2(0), 0.0).rgb
  59. + textureLod(sampler3D(u_tex3d, u_sampler), Vec3(0), 0.0).rgb;
  60. out_color += u_color.xyz;
  61. }
  62. #pragma anki end frag
  63. )";
  64. // Write the file
  65. {
  66. File file;
  67. ANKI_TEST_EXPECT_NO_ERR(file.open("test.glslp", FileOpenFlag::kWrite));
  68. ANKI_TEST_EXPECT_NO_ERR(file.writeText(sourceCode));
  69. }
  70. class Fsystem : public ShaderCompilerFilesystemInterface
  71. {
  72. public:
  73. Error readAllText(CString filename, ShaderCompilerString& txt) final
  74. {
  75. File file;
  76. ANKI_CHECK(file.open(filename, FileOpenFlag::kRead));
  77. ANKI_CHECK(file.readAllText(txt));
  78. return Error::kNone;
  79. }
  80. } fsystem;
  81. HeapMemoryPool pool(allocAligned, nullptr);
  82. const U32 threadCount = 8;
  83. ThreadHive hive(threadCount, &pool);
  84. class TaskManager : public ShaderCompilerAsyncTaskInterface
  85. {
  86. public:
  87. ThreadHive* m_hive = nullptr;
  88. HeapMemoryPool* m_pool;
  89. void enqueueTask(void (*callback)(void* userData), void* userData)
  90. {
  91. struct Ctx
  92. {
  93. void (*m_callback)(void* userData);
  94. void* m_userData;
  95. HeapMemoryPool* m_pool;
  96. };
  97. Ctx* ctx = newInstance<Ctx>(*m_pool);
  98. ctx->m_callback = callback;
  99. ctx->m_userData = userData;
  100. ctx->m_pool = m_pool;
  101. m_hive->submitTask(
  102. [](void* userData, [[maybe_unused]] U32 threadId, [[maybe_unused]] ThreadHive& hive,
  103. [[maybe_unused]] ThreadHiveSemaphore* signalSemaphore) {
  104. Ctx* ctx = static_cast<Ctx*>(userData);
  105. ctx->m_callback(ctx->m_userData);
  106. deleteInstance(*ctx->m_pool, ctx);
  107. },
  108. ctx);
  109. }
  110. Error joinTasks()
  111. {
  112. m_hive->waitAllTasks();
  113. return Error::kNone;
  114. }
  115. } taskManager;
  116. taskManager.m_hive = &hive;
  117. taskManager.m_pool = &pool;
  118. ShaderBinary* binary;
  119. ANKI_TEST_EXPECT_NO_ERR(compileShaderProgram("test.glslp", true, true, ShaderModel::k6_8, fsystem, nullptr, &taskManager, {}, binary));
  120. #if 1
  121. ShaderCompilerString dis;
  122. ShaderDumpOptions options;
  123. dumpShaderBinary(options, *binary, dis);
  124. ANKI_LOGI("Binary disassembly:\n%s\n", dis.cstr());
  125. #endif
  126. }
  127. ANKI_TEST(ShaderCompiler, ShaderProgramCompiler)
  128. {
  129. const CString sourceCode = R"(
  130. #pragma anki mutator INSTANCE_COUNT 1 2 4 8 16 32 64
  131. #pragma anki mutator LOD 0 1 2
  132. #pragma anki mutator PASS 0 1 2 3
  133. #pragma anki mutator DIFFUSE_TEX 0 1
  134. #pragma anki mutator SPECULAR_TEX 0 1
  135. #pragma anki mutator ROUGHNESS_TEX 0 1
  136. #pragma anki mutator METAL_TEX 0 1
  137. #pragma anki mutator NORMAL_TEX 0 1
  138. #pragma anki mutator PARALLAX 0 1
  139. #pragma anki mutator EMISSIVE_TEX 0 1
  140. #pragma anki mutator BONES 0 1
  141. #pragma anki mutator VELOCITY 0 1
  142. #pragma anki rewrite_mutation PASS 1 DIFFUSE_TEX 1 to PASS 1 DIFFUSE_TEX 0
  143. #pragma anki rewrite_mutation PASS 2 DIFFUSE_TEX 1 to PASS 2 DIFFUSE_TEX 0
  144. #pragma anki rewrite_mutation PASS 3 DIFFUSE_TEX 1 to PASS 2 DIFFUSE_TEX 0
  145. #pragma anki rewrite_mutation PASS 1 SPECULAR_TEX 1 to PASS 1 SPECULAR_TEX 0
  146. #pragma anki rewrite_mutation PASS 2 SPECULAR_TEX 1 to PASS 2 SPECULAR_TEX 0
  147. #pragma anki rewrite_mutation PASS 3 SPECULAR_TEX 1 to PASS 2 SPECULAR_TEX 0
  148. #pragma anki rewrite_mutation PASS 1 ROUGHNESS_TEX 1 to PASS 1 ROUGHNESS_TEX 0
  149. #pragma anki rewrite_mutation PASS 2 ROUGHNESS_TEX 1 to PASS 2 ROUGHNESS_TEX 0
  150. #pragma anki rewrite_mutation PASS 3 ROUGHNESS_TEX 1 to PASS 2 ROUGHNESS_TEX 0
  151. #pragma anki rewrite_mutation PASS 1 METAL_TEX 1 to PASS 1 METAL_TEX 0
  152. #pragma anki rewrite_mutation PASS 2 METAL_TEX 1 to PASS 2 METAL_TEX 0
  153. #pragma anki rewrite_mutation PASS 3 METAL_TEX 1 to PASS 2 METAL_TEX 0
  154. #pragma anki rewrite_mutation PASS 1 NORMAL_TEX 1 to PASS 1 NORMAL_TEX 0
  155. #pragma anki rewrite_mutation PASS 2 NORMAL_TEX 1 to PASS 2 NORMAL_TEX 0
  156. #pragma anki rewrite_mutation PASS 3 NORMAL_TEX 1 to PASS 2 NORMAL_TEX 0
  157. #pragma anki rewrite_mutation PASS 1 EMISSIVE_TEX 1 to PASS 1 EMISSIVE_TEX 0
  158. #pragma anki rewrite_mutation PASS 2 EMISSIVE_TEX 1 to PASS 2 EMISSIVE_TEX 0
  159. #pragma anki rewrite_mutation PASS 3 EMISSIVE_TEX 1 to PASS 2 EMISSIVE_TEX 0
  160. #pragma anki rewrite_mutation PASS 1 VELOCITY 1 to PASS 1 VELOCITY 0
  161. #pragma anki rewrite_mutation PASS 2 VELOCITY 1 to PASS 2 VELOCITY 0
  162. #pragma anki rewrite_mutation PASS 3 VELOCITY 1 to PASS 2 VELOCITY 0
  163. layout(set = 0, binding = 0) uniform ankiMaterial
  164. {
  165. Mat4 u_ankiMvp[INSTANCE_COUNT];
  166. #if PASS == 0
  167. Mat3 u_ankiRotationMat[INSTANCE_COUNT];
  168. #endif
  169. #if PASS == 0 && PARALLAX == 1
  170. Mat4 u_ankiModelViewMat[INSTANCE_COUNT];
  171. #endif
  172. #if PASS == 0 && VELOCITY == 1
  173. Mat4 u_ankiPrevMvp[INSTANCE_COUNT];
  174. #endif
  175. };
  176. #if PASS == 0
  177. #if DIFFUSE_TEX == 0
  178. ANKI_SPECIALIZATION_CONSTANT_VEC3(diffColor, 0u);
  179. #else
  180. layout(set = 0, binding = 1) uniform texture2D diffTex;
  181. #endif
  182. #if SPECULAR_TEX == 0
  183. ANKI_SPECIALIZATION_CONSTANT_VEC3(specColor, 3u);
  184. #else
  185. layout(set = 0, binding = 2) uniform texture2D specTex;
  186. #endif
  187. #if ROUGHNESS_TEX == 0
  188. ANKI_SPECIALIZATION_CONSTANT_F32(roughness, 6u);
  189. #else
  190. layout(set = 0, binding = 3) uniform texture2D roughnessTex;
  191. #endif
  192. #if METAL_TEX == 0
  193. ANKI_SPECIALIZATION_CONSTANT_F32(metallic, 7u);
  194. #else
  195. layout(set = 0, binding = 4) uniform texture2D metallicTex;
  196. #endif
  197. #if EMISSIVE_TEX == 0
  198. ANKI_SPECIALIZATION_CONSTANT_VEC3(emission, 8u, Vec3(0.0));
  199. #else
  200. layout(set = 0, binding = 5) uniform texture2D emissiveTex;
  201. #endif
  202. #if PARALLAX == 1 && LOD == 0
  203. ANKI_SPECIALIZATION_CONSTANT_F32(heightMapScale, 11u);
  204. layout(set = 0, binding = 6) uniform texture2D heightTex;
  205. #endif
  206. #endif
  207. #pragma anki start vert
  208. out gl_PerVertex
  209. {
  210. Vec4 gl_Position;
  211. };
  212. void main()
  213. {
  214. gl_Position = Vec4(gl_VertexIndex);
  215. }
  216. #pragma anki end vert
  217. #pragma anki start frag
  218. layout(location = 0) out Vec3 out_color;
  219. void main()
  220. {
  221. out_color = Vec3(0.0);
  222. }
  223. #pragma anki end frag
  224. )";
  225. // Write the file
  226. {
  227. File file;
  228. ANKI_TEST_EXPECT_NO_ERR(file.open("test.glslp", FileOpenFlag::kWrite));
  229. ANKI_TEST_EXPECT_NO_ERR(file.writeText(sourceCode));
  230. }
  231. class Fsystem : public ShaderCompilerFilesystemInterface
  232. {
  233. public:
  234. Error readAllText(CString filename, ShaderCompilerString& txt) final
  235. {
  236. File file;
  237. ANKI_CHECK(file.open(filename, FileOpenFlag::kRead));
  238. ANKI_CHECK(file.readAllText(txt));
  239. return Error::kNone;
  240. }
  241. } fsystem;
  242. HeapMemoryPool pool(allocAligned, nullptr);
  243. const U32 threadCount = 24;
  244. ThreadHive hive(threadCount, &pool);
  245. class TaskManager : public ShaderCompilerAsyncTaskInterface
  246. {
  247. public:
  248. ThreadHive* m_hive = nullptr;
  249. HeapMemoryPool* m_pool = nullptr;
  250. void enqueueTask(void (*callback)(void* userData), void* userData)
  251. {
  252. struct Ctx
  253. {
  254. void (*m_callback)(void* userData);
  255. void* m_userData;
  256. HeapMemoryPool* m_pool;
  257. };
  258. Ctx* ctx = newInstance<Ctx>(*m_pool);
  259. ctx->m_callback = callback;
  260. ctx->m_userData = userData;
  261. ctx->m_pool = m_pool;
  262. m_hive->submitTask(
  263. [](void* userData, [[maybe_unused]] U32 threadId, [[maybe_unused]] ThreadHive& hive,
  264. [[maybe_unused]] ThreadHiveSemaphore* signalSemaphore) {
  265. Ctx* ctx = static_cast<Ctx*>(userData);
  266. ctx->m_callback(ctx->m_userData);
  267. deleteInstance(*ctx->m_pool, ctx);
  268. },
  269. ctx);
  270. }
  271. Error joinTasks()
  272. {
  273. m_hive->waitAllTasks();
  274. return Error::kNone;
  275. }
  276. } taskManager;
  277. taskManager.m_hive = &hive;
  278. taskManager.m_pool = &pool;
  279. ShaderBinary* binary;
  280. ANKI_TEST_EXPECT_NO_ERR(compileShaderProgram("test.glslp", true, true, ShaderModel::k6_8, fsystem, nullptr, &taskManager, {}, binary));
  281. #if 1
  282. ShaderCompilerString dis;
  283. ShaderDumpOptions options;
  284. dumpShaderBinary(options, *binary, dis);
  285. ANKI_LOGI("Binary disassembly:\n%s\n", dis.cstr());
  286. #endif
  287. }