shader.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. #if CROWN_PLATFORM_WINDOWS
  91. "--profile", "vs_3_0",
  92. #endif
  93. NULL
  94. };
  95. int exitcode = os::execute_process(compile_vs);
  96. CE_ASSERT(exitcode == 0, "Failed to compile vertex shader");
  97. const char* compile_fs[] =
  98. {
  99. SHADERC_PATH,
  100. "-f", fs_code_path.c_str(),
  101. "-o", tmpfs_path.c_str(),
  102. "--varyingdef", varying_def_path.c_str(),
  103. "--type", "fragment",
  104. "--platform", _scplatform[opts.platform()],
  105. #if CROWN_PLATFORM_WINDOWS
  106. "--profile", "ps_3_0",
  107. #endif
  108. NULL
  109. };
  110. exitcode = os::execute_process(compile_fs);
  111. if (exitcode)
  112. {
  113. opts.delete_file(tmpvs_path.c_str());
  114. CE_ASSERT(exitcode == 0, "Failed to compile fragment shader");
  115. }
  116. Buffer tmpvs = opts.read(tmpvs_path.c_str());
  117. Buffer tmpfs = opts.read(tmpfs_path.c_str());
  118. opts.write(uint32_t(1)); // version
  119. opts.write(uint32_t(array::size(tmpvs)));
  120. opts.write(array::begin(tmpvs), array::size(tmpvs));
  121. opts.write(uint32_t(array::size(tmpfs)));
  122. opts.write(array::begin(tmpfs), array::size(tmpfs));
  123. opts.delete_file(vs_code_path.c_str());
  124. opts.delete_file(fs_code_path.c_str());
  125. opts.delete_file(varying_def_path.c_str());
  126. opts.delete_file(tmpvs_path.c_str());
  127. opts.delete_file(tmpfs_path.c_str());
  128. }
  129. void* load(File& file, Allocator& a)
  130. {
  131. BinaryReader br(file);
  132. uint32_t version;
  133. br.read(version);
  134. uint32_t vs_code_size;
  135. br.read(vs_code_size);
  136. const bgfx::Memory* vsmem = bgfx::alloc(vs_code_size);
  137. br.read(vsmem->data, vs_code_size);
  138. uint32_t fs_code_size;
  139. br.read(fs_code_size);
  140. const bgfx::Memory* fsmem = bgfx::alloc(fs_code_size);
  141. br.read(fsmem->data, fs_code_size);
  142. Shader* shader = (Shader*) a.allocate(sizeof(Shader));
  143. shader->vs = vsmem;
  144. shader->fs = fsmem;
  145. shader->program.idx = bgfx::invalidHandle;
  146. return shader;
  147. }
  148. void online(StringId64 id, ResourceManager& rm)
  149. {
  150. Shader* shader = (Shader*) rm.get(SHADER_TYPE, id);
  151. bgfx::ShaderHandle vs = bgfx::createShader(shader->vs);
  152. CE_ASSERT(bgfx::isValid(vs), "Failed to create vertex shader");
  153. bgfx::ShaderHandle fs = bgfx::createShader(shader->fs);
  154. CE_ASSERT(bgfx::isValid(fs), "Failed to create fragment shader");
  155. shader->program = bgfx::createProgram(vs, fs, true);
  156. CE_ASSERT(bgfx::isValid(shader->program), "Failed to create GPU program");
  157. }
  158. void offline(StringId64 id, ResourceManager& rm)
  159. {
  160. Shader* shader = (Shader*) rm.get(SHADER_TYPE, id);
  161. bgfx::destroyProgram(shader->program);
  162. }
  163. void unload(Allocator& a, void* res)
  164. {
  165. a.deallocate(res);
  166. }
  167. } // namespace shader_resource
  168. } // namespace crown