shader.cpp 5.1 KB

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