shader.cpp 5.1 KB

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