shader.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #include "shader.h"
  6. #include "config.h"
  7. #include "filesystem.h"
  8. #include "json_parser.h"
  9. #include "os.h"
  10. #include "reader_writer.h"
  11. #include "resource_manager.h"
  12. #include "compile_options.h"
  13. #if CROWN_DEBUG
  14. # define SHADERC_NAME "shaderc-debug-"
  15. #else
  16. # define SHADERC_NAME "shaderc-development-"
  17. #endif // CROWN_DEBUG
  18. #if CROWN_ARCH_32BIT
  19. # define SHADERC_BITS "32"
  20. #elif CROWN_ARCH_64BIT
  21. # define SHADERC_BITS "64"
  22. #endif // CROWN_ARCH_32BIT
  23. #if CROWN_PLATFORM_LINUX
  24. # define SHADERC_PATH SHADERC_NAME""SHADERC_BITS
  25. #elif CROWN_PLATFORM_WINDOWS
  26. # define SHADERC_PATH SHADERC_NAME""SHADERC_BITS".exe"
  27. #endif // CROWN_PLATFORM_WINDOWS
  28. namespace crown
  29. {
  30. namespace shader_resource
  31. {
  32. static const char* _scplatform[Platform::COUNT] =
  33. {
  34. "linux",
  35. "windows",
  36. "android"
  37. };
  38. void compile(const char* path, CompileOptions& opts)
  39. {
  40. Buffer buf = opts.read(path);
  41. JSONParser json(array::begin(buf));
  42. JSONElement root = json.root();
  43. DynamicString vs_code2;
  44. DynamicString fs_code2;
  45. DynamicString varying_def;
  46. DynamicString common_code;
  47. DynamicString vs_in_out;
  48. DynamicString fs_in_out;
  49. root.key("vs_code").to_string(vs_code2);
  50. root.key("fs_code").to_string(fs_code2);
  51. root.key("varying_def").to_string(varying_def);
  52. root.key("common").to_string(common_code);
  53. root.key("vs_in_out").to_string(vs_in_out);
  54. root.key("fs_in_out").to_string(fs_in_out);
  55. DynamicString vs_code;
  56. DynamicString fs_code;
  57. vs_code += vs_in_out;
  58. vs_code += common_code;
  59. vs_code += vs_code2;
  60. fs_code += fs_in_out;
  61. fs_code += common_code;
  62. fs_code += fs_code2;
  63. DynamicString vs_code_path;
  64. DynamicString fs_code_path;
  65. DynamicString varying_def_path;
  66. DynamicString tmpvs_path;
  67. DynamicString tmpfs_path;
  68. opts.get_absolute_path("vs_code.tmp", vs_code_path);
  69. opts.get_absolute_path("fs_code.tmp", fs_code_path);
  70. opts.get_absolute_path("varying.tmp", varying_def_path);
  71. opts.get_absolute_path("tmpvs", tmpvs_path);
  72. opts.get_absolute_path("tmpfs", tmpfs_path);
  73. File* vs_file = opts._fs.open(vs_code_path.c_str(), FOM_WRITE);
  74. vs_file->write(vs_code.c_str(), vs_code.length());
  75. opts._fs.close(vs_file);
  76. File* fs_file = opts._fs.open(fs_code_path.c_str(), FOM_WRITE);
  77. fs_file->write(fs_code.c_str(), fs_code.length());
  78. opts._fs.close(fs_file);
  79. File* varying_file = opts._fs.open(varying_def_path.c_str(), FOM_WRITE);
  80. varying_file->write(varying_def.c_str(), varying_def.length());
  81. opts._fs.close(varying_file);
  82. const char* compile_vs[] =
  83. {
  84. SHADERC_PATH,
  85. "-f", vs_code_path.c_str(),
  86. "-o", tmpvs_path.c_str(),
  87. "--varyingdef", varying_def_path.c_str(),
  88. "--type", "vertex",
  89. "--platform", _scplatform[opts.platform()],
  90. "--profile",
  91. #if CROWN_PLATFORM_LINUX
  92. "120",
  93. #elif CROWN_PLATFORM_WINDOWS
  94. "vs_3_0",
  95. #endif
  96. NULL
  97. };
  98. int exitcode = os::execute_process(compile_vs);
  99. CE_ASSERT(exitcode == 0, "Failed to compile vertex shader");
  100. const char* compile_fs[] =
  101. {
  102. SHADERC_PATH,
  103. "-f", fs_code_path.c_str(),
  104. "-o", tmpfs_path.c_str(),
  105. "--varyingdef", varying_def_path.c_str(),
  106. "--type", "fragment",
  107. "--platform", _scplatform[opts.platform()],
  108. "--profile",
  109. #if CROWN_PLATFORM_LINUX
  110. "120",
  111. #elif CROWN_PLATFORM_WINDOWS
  112. "ps_3_0",
  113. #endif
  114. NULL
  115. };
  116. exitcode = os::execute_process(compile_fs);
  117. if (exitcode)
  118. {
  119. opts.delete_file(tmpvs_path.c_str());
  120. CE_ASSERT(exitcode == 0, "Failed to compile fragment shader");
  121. }
  122. Buffer tmpvs = opts.read(tmpvs_path.c_str());
  123. Buffer tmpfs = opts.read(tmpfs_path.c_str());
  124. opts.write(uint32_t(1)); // version
  125. opts.write(uint32_t(array::size(tmpvs)));
  126. opts.write(array::begin(tmpvs), array::size(tmpvs));
  127. opts.write(uint32_t(array::size(tmpfs)));
  128. opts.write(array::begin(tmpfs), array::size(tmpfs));
  129. opts.delete_file(vs_code_path.c_str());
  130. opts.delete_file(fs_code_path.c_str());
  131. opts.delete_file(varying_def_path.c_str());
  132. opts.delete_file(tmpvs_path.c_str());
  133. opts.delete_file(tmpfs_path.c_str());
  134. }
  135. void* load(File& file, Allocator& a)
  136. {
  137. BinaryReader br(file);
  138. uint32_t version;
  139. br.read(version);
  140. uint32_t vs_code_size;
  141. br.read(vs_code_size);
  142. const bgfx::Memory* vsmem = bgfx::alloc(vs_code_size);
  143. br.read(vsmem->data, vs_code_size);
  144. uint32_t fs_code_size;
  145. br.read(fs_code_size);
  146. const bgfx::Memory* fsmem = bgfx::alloc(fs_code_size);
  147. br.read(fsmem->data, fs_code_size);
  148. Shader* shader = (Shader*) a.allocate(sizeof(Shader));
  149. shader->vs = vsmem;
  150. shader->fs = fsmem;
  151. shader->program.idx = bgfx::invalidHandle;
  152. return shader;
  153. }
  154. void online(StringId64 id, ResourceManager& rm)
  155. {
  156. Shader* shader = (Shader*) rm.get(SHADER_TYPE, id);
  157. bgfx::ShaderHandle vs = bgfx::createShader(shader->vs);
  158. CE_ASSERT(bgfx::isValid(vs), "Failed to create vertex shader");
  159. bgfx::ShaderHandle fs = bgfx::createShader(shader->fs);
  160. CE_ASSERT(bgfx::isValid(fs), "Failed to create fragment shader");
  161. shader->program = bgfx::createProgram(vs, fs, true);
  162. CE_ASSERT(bgfx::isValid(shader->program), "Failed to create GPU program");
  163. }
  164. void offline(StringId64 id, ResourceManager& rm)
  165. {
  166. Shader* shader = (Shader*) rm.get(SHADER_TYPE, id);
  167. bgfx::destroyProgram(shader->program);
  168. }
  169. void unload(Allocator& a, void* res)
  170. {
  171. a.deallocate(res);
  172. }
  173. } // namespace shader_resource
  174. } // namespace crown