material_resource.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Copyright (c) 2012-2017 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #include "compile_options.h"
  6. #include "device.h"
  7. #include "dynamic_string.h"
  8. #include "filesystem.h"
  9. #include "json_object.h"
  10. #include "map.h"
  11. #include "material_manager.h"
  12. #include "material_resource.h"
  13. #include "reader_writer.h"
  14. #include "resource_manager.h"
  15. #include "sjson.h"
  16. #include "string_utils.h"
  17. #include "temp_allocator.h"
  18. #include "vector.h"
  19. namespace crown
  20. {
  21. namespace material_resource_internal
  22. {
  23. struct UniformTypeInfo
  24. {
  25. const char* name;
  26. UniformType::Enum type;
  27. u8 size;
  28. };
  29. static const UniformTypeInfo s_uniform_type_info[] =
  30. {
  31. { "float", UniformType::FLOAT, 4 },
  32. { "vector2", UniformType::VECTOR2, 8 },
  33. { "vector3", UniformType::VECTOR3, 12 },
  34. { "vector4", UniformType::VECTOR4, 16 }
  35. };
  36. CE_STATIC_ASSERT(countof(s_uniform_type_info) == UniformType::COUNT);
  37. static UniformType::Enum name_to_uniform_type(const char* name)
  38. {
  39. for (u32 i = 0; i < countof(s_uniform_type_info); ++i)
  40. {
  41. if (strcmp(s_uniform_type_info[i].name, name) == 0)
  42. return s_uniform_type_info[i].type;
  43. }
  44. return UniformType::COUNT;
  45. }
  46. struct Data
  47. {
  48. Array<TextureData> textures;
  49. Array<UniformData> uniforms;
  50. Array<char> dynamic;
  51. Data()
  52. : textures(default_allocator())
  53. , uniforms(default_allocator())
  54. , dynamic(default_allocator())
  55. {}
  56. };
  57. // Returns offset to start of data
  58. template <typename T>
  59. static u32 reserve_dynamic_data(T data, Array<char>& dynamic)
  60. {
  61. u32 offt = array::size(dynamic);
  62. array::push(dynamic, (char*) &data, sizeof(data));
  63. return offt;
  64. }
  65. static void parse_textures(const char* json, Array<TextureData>& textures, Array<char>& names, Array<char>& dynamic, CompileOptions& opts)
  66. {
  67. TempAllocator4096 ta;
  68. JsonObject object(ta);
  69. sjson::parse(json, object);
  70. auto cur = json_object::begin(object);
  71. auto end = json_object::end(object);
  72. for (; cur != end; ++cur)
  73. {
  74. const FixedString key = cur->pair.first;
  75. const char* value = cur->pair.second;
  76. DynamicString texture(ta);
  77. sjson::parse_string(value, texture);
  78. DATA_COMPILER_ASSERT_RESOURCE_EXISTS("texture", texture.c_str(), opts);
  79. TextureHandle th;
  80. th.sampler_handle = 0;
  81. th.texture_handle = 0;
  82. const u32 sampler_name_offset = array::size(names);
  83. array::push(names, key.data(), key.length());
  84. array::push_back(names, '\0');
  85. TextureData td;
  86. td.sampler_name_offset = sampler_name_offset;
  87. td.id = sjson::parse_resource_id(value);
  88. td.data_offset = reserve_dynamic_data(th, dynamic);
  89. array::push_back(textures, td);
  90. }
  91. }
  92. static void parse_uniforms(const char* json, Array<UniformData>& uniforms, Array<char>& names, Array<char>& dynamic, CompileOptions& opts)
  93. {
  94. TempAllocator4096 ta;
  95. JsonObject object(ta);
  96. sjson::parse(json, object);
  97. auto cur = json_object::begin(object);
  98. auto end = json_object::end(object);
  99. for (; cur != end; ++cur)
  100. {
  101. const FixedString key = cur->pair.first;
  102. const char* value = cur->pair.second;
  103. UniformHandle uh;
  104. uh.uniform_handle = 0;
  105. JsonObject uniform(ta);
  106. sjson::parse_object(value, uniform);
  107. DynamicString type(ta);
  108. sjson::parse_string(uniform["type"], type);
  109. const UniformType::Enum ut = name_to_uniform_type(type.c_str());
  110. DATA_COMPILER_ASSERT(ut != UniformType::COUNT
  111. , opts
  112. , "Unknown uniform type: '%s'"
  113. , type.c_str()
  114. );
  115. const u32 name_offset = array::size(names);
  116. array::push(names, key.data(), key.length());
  117. array::push_back(names, '\0');
  118. UniformData ud;
  119. ud.type = ut;
  120. ud.name = StringId32(key.data(), key.length());
  121. ud.name_offset = name_offset;
  122. ud.data_offset = reserve_dynamic_data(uh, dynamic);
  123. switch (ud.type)
  124. {
  125. case UniformType::FLOAT:
  126. reserve_dynamic_data(sjson::parse_float(uniform["value"]), dynamic);
  127. break;
  128. case UniformType::VECTOR2:
  129. reserve_dynamic_data(sjson::parse_vector2(uniform["value"]), dynamic);
  130. break;
  131. case UniformType::VECTOR3:
  132. reserve_dynamic_data(sjson::parse_vector3(uniform["value"]), dynamic);
  133. break;
  134. case UniformType::VECTOR4:
  135. reserve_dynamic_data(sjson::parse_vector4(uniform["value"]), dynamic);
  136. break;
  137. default:
  138. CE_FATAL("Unknown uniform type");
  139. break;
  140. }
  141. array::push_back(uniforms, ud);
  142. }
  143. }
  144. void compile(const char* path, CompileOptions& opts)
  145. {
  146. Buffer buf = opts.read(path);
  147. TempAllocator4096 ta;
  148. JsonObject object(ta);
  149. sjson::parse(buf, object);
  150. Array<TextureData> texdata(default_allocator());
  151. Array<UniformData> unidata(default_allocator());
  152. Array<char> names(default_allocator());
  153. Array<char> dynblob(default_allocator());
  154. DynamicString shader(ta);
  155. sjson::parse_string(object["shader"], shader);
  156. parse_textures(object["textures"], texdata, names, dynblob, opts);
  157. parse_uniforms(object["uniforms"], unidata, names, dynblob, opts);
  158. MaterialResource mr;
  159. mr.version = RESOURCE_VERSION_MATERIAL;
  160. mr.shader = shader.to_string_id();
  161. mr.num_textures = array::size(texdata);
  162. mr.texture_data_offset = sizeof(mr);
  163. mr.num_uniforms = array::size(unidata);
  164. mr.uniform_data_offset = mr.texture_data_offset + sizeof(TextureData)*array::size(texdata);
  165. mr.dynamic_data_size = array::size(dynblob);
  166. mr.dynamic_data_offset = mr.uniform_data_offset + sizeof(UniformData)*array::size(unidata);
  167. // Write
  168. opts.write(mr.version);
  169. opts.write(mr.shader);
  170. opts.write(mr.num_textures);
  171. opts.write(mr.texture_data_offset);
  172. opts.write(mr.num_uniforms);
  173. opts.write(mr.uniform_data_offset);
  174. opts.write(mr.dynamic_data_size);
  175. opts.write(mr.dynamic_data_offset);
  176. for (u32 i = 0; i < array::size(texdata); i++)
  177. {
  178. opts.write(texdata[i].sampler_name_offset);
  179. opts.write(texdata[i]._pad);
  180. opts.write(texdata[i].id);
  181. opts.write(texdata[i].data_offset);
  182. opts.write(texdata[i]._pad1);
  183. }
  184. for (u32 i = 0; i < array::size(unidata); i++)
  185. {
  186. opts.write(unidata[i].type);
  187. opts.write(unidata[i].name);
  188. opts.write(unidata[i].name_offset);
  189. opts.write(unidata[i].data_offset);
  190. }
  191. opts.write(dynblob);
  192. opts.write(names);
  193. }
  194. void* load(File& file, Allocator& a)
  195. {
  196. return device()->_material_manager->load(file, a);
  197. }
  198. void online(StringId64 id, ResourceManager& rm)
  199. {
  200. device()->_material_manager->online(id, rm);
  201. }
  202. void offline(StringId64 id, ResourceManager& rm)
  203. {
  204. device()->_material_manager->offline(id, rm);
  205. }
  206. void unload(Allocator& a, void* res)
  207. {
  208. device()->_material_manager->unload(a, res);
  209. }
  210. } // namespace material_resource_internal
  211. namespace material_resource
  212. {
  213. UniformData* get_uniform_data(const MaterialResource* mr, u32 i)
  214. {
  215. UniformData* base = (UniformData*) ((char*)mr + mr->uniform_data_offset);
  216. return &base[i];
  217. }
  218. UniformData* get_uniform_data_by_name(const MaterialResource* mr, StringId32 name)
  219. {
  220. for (u32 i = 0, n = mr->num_uniforms; i < n; ++i)
  221. {
  222. UniformData* data = get_uniform_data(mr, i);
  223. if (data->name == name)
  224. return data;
  225. }
  226. CE_FATAL("Unknown uniform");
  227. return NULL;
  228. }
  229. const char* get_uniform_name(const MaterialResource* mr, const UniformData* ud)
  230. {
  231. return (const char*)mr + mr->dynamic_data_offset + mr->dynamic_data_size + ud->name_offset;
  232. }
  233. TextureData* get_texture_data(const MaterialResource* mr, u32 i)
  234. {
  235. TextureData* base = (TextureData*) ((char*)mr + mr->texture_data_offset);
  236. return &base[i];
  237. }
  238. const char* get_texture_name(const MaterialResource* mr, const TextureData* td)
  239. {
  240. return (const char*)mr + mr->dynamic_data_offset + mr->dynamic_data_size + td->sampler_name_offset;
  241. }
  242. UniformHandle* get_uniform_handle(const MaterialResource* mr, u32 i, char* dynamic)
  243. {
  244. UniformData* ud = get_uniform_data(mr, i);
  245. return (UniformHandle*) (dynamic + ud->data_offset);
  246. }
  247. UniformHandle* get_uniform_handle_by_name(const MaterialResource* mr, StringId32 name, char* dynamic)
  248. {
  249. UniformData* ud = get_uniform_data_by_name(mr, name);
  250. return (UniformHandle*) (dynamic + ud->data_offset);
  251. }
  252. TextureHandle* get_texture_handle(const MaterialResource* mr, u32 i, char* dynamic)
  253. {
  254. TextureData* td = get_texture_data(mr, i);
  255. return (TextureHandle*) (dynamic + td->data_offset);
  256. }
  257. } // namespace material_resource
  258. } // namespace crown