ShaderProgramCompiler.cpp 8.8 KB

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