Renderer.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /*
  2. Copyright (c) 2013 Daniele Bartolini, Michele Rossi
  3. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  4. Permission is hereby granted, free of charge, to any person
  5. obtaining a copy of this software and associated documentation
  6. files (the "Software"), to deal in the Software without
  7. restriction, including without limitation the rights to use,
  8. copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the
  10. Software is furnished to do so, subject to the following
  11. conditions:
  12. The above copyright notice and this permission notice shall be
  13. included in all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  19. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #pragma once
  24. #include "Config.h"
  25. #include "Types.h"
  26. #include "PixelFormat.h"
  27. #include "VertexFormat.h"
  28. #include "StringUtils.h"
  29. #include "RenderContext.h"
  30. #include "OsThread.h"
  31. #include "OS.h"
  32. namespace crown
  33. {
  34. extern ShaderUniform name_to_stock_uniform(const char* uniform);
  35. class RendererImplementation;
  36. class Renderer
  37. {
  38. public:
  39. Renderer(Allocator& a);
  40. ~Renderer();
  41. void init_impl();
  42. void shutdown_impl();
  43. void render_impl();
  44. void create_vertex_buffer_impl(VertexBufferId id, size_t count, VertexFormat format, const void* vertices);
  45. void create_dynamic_vertex_buffer_impl(VertexBufferId id, size_t count, VertexFormat format);
  46. void update_vertex_buffer_impl(VertexBufferId id, size_t offset, size_t count, const void* vertices);
  47. void destroy_vertex_buffer_impl(VertexBufferId id);
  48. void create_index_buffer_impl(IndexBufferId id, size_t count, const void* indices);
  49. void create_dynamic_index_buffer_impl(IndexBufferId id, size_t count);
  50. void update_index_buffer_impl(IndexBufferId id, size_t offset, size_t count, const void* indices);
  51. void destroy_index_buffer_impl(IndexBufferId id);
  52. void create_texture_impl(TextureId id, uint32_t width, uint32_t height, PixelFormat format, const void* data);
  53. void update_texture_impl(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data);
  54. void destroy_texture_impl(TextureId id);
  55. void create_shader_impl(ShaderId id, ShaderType type, const char* text);
  56. void destroy_shader_impl(ShaderId id);
  57. void create_gpu_program_impl(GPUProgramId id, ShaderId vertex, ShaderId pixel);
  58. void destroy_gpu_program_impl(GPUProgramId id);
  59. void create_uniform_impl(UniformId id, const char* name, UniformType type, uint8_t num);
  60. void update_uniform_impl(UniformId id, size_t size, const void* data);
  61. void destroy_uniform_impl(UniformId id);
  62. void create_render_target_impl(RenderTargetId id, uint16_t width, uint16_t height, RenderTargetFormat format);
  63. void destroy_render_target_impl(RenderTargetId id);
  64. inline void init()
  65. {
  66. m_should_run = true;
  67. m_thread.start(render_thread, this);
  68. m_submit->m_commands.write(COMMAND_INIT_RENDERER);
  69. frame();
  70. }
  71. inline void shutdown()
  72. {
  73. if (m_should_run)
  74. {
  75. m_submit->m_commands.write(COMMAND_SHUTDOWN_RENDERER);
  76. frame();
  77. m_should_run = false;
  78. m_thread.stop();
  79. }
  80. }
  81. /// Creates a new vertex buffer optimized for rendering static vertex data.
  82. /// @a vertices is the array containig @a count vertex data elements of the given @a format.
  83. inline VertexBufferId create_vertex_buffer(size_t count, VertexFormat format, const void* vertices)
  84. {
  85. const VertexBufferId id = m_vertex_buffers.create();
  86. m_submit->m_commands.write(COMMAND_CREATE_VERTEX_BUFFER);
  87. m_submit->m_commands.write(id);
  88. m_submit->m_commands.write(count);
  89. m_submit->m_commands.write(format);
  90. m_submit->m_commands.write(vertices);
  91. return id;
  92. }
  93. inline VertexBufferId create_dynamic_vertex_buffer(size_t count, VertexFormat format)
  94. {
  95. const VertexBufferId id = m_vertex_buffers.create();
  96. m_submit->m_commands.write(COMMAND_CREATE_DYNAMIC_VERTEX_BUFFER);
  97. m_submit->m_commands.write(id);
  98. m_submit->m_commands.write(count);
  99. m_submit->m_commands.write(format);
  100. return id;
  101. }
  102. /// Updates the data associated with the given vertex buffer @a id.
  103. /// @a vertices is the array containig @a count vertex data elements of the format
  104. /// specified at the creation of the buffer.
  105. /// @note
  106. /// @a count and @a offset together do not have to exceed the number of elements specified
  107. /// at the creation of the buffer.
  108. inline void update_vertex_buffer(VertexBufferId id, size_t offset, size_t count, const void* vertices)
  109. {
  110. m_submit->m_commands.write(COMMAND_UPDATE_VERTEX_BUFFER);
  111. m_submit->m_commands.write(id);
  112. m_submit->m_commands.write(offset);
  113. m_submit->m_commands.write(count);
  114. m_submit->m_commands.write(vertices);
  115. }
  116. /// Destroys the given vertex buffer @a id.
  117. inline void destroy_vertex_buffer(VertexBufferId id)
  118. {
  119. m_submit->m_commands.write(COMMAND_DESTROY_VERTEX_BUFFER);
  120. m_submit->m_commands.write(id);
  121. }
  122. /// Creates a new index buffer optimized for rendering static index buffers.
  123. /// @a indices is the array containing @a count index data elements.
  124. inline IndexBufferId create_index_buffer(size_t count, const void* indices)
  125. {
  126. const IndexBufferId id = m_index_buffers.create();
  127. m_submit->m_commands.write(COMMAND_CREATE_INDEX_BUFFER);
  128. m_submit->m_commands.write(id);
  129. m_submit->m_commands.write(count);
  130. m_submit->m_commands.write(indices);
  131. return id;
  132. }
  133. inline IndexBufferId create_dynamic_index_buffer(size_t count)
  134. {
  135. const IndexBufferId id = m_index_buffers.create();
  136. m_submit->m_commands.write(COMMAND_CREATE_DYNAMIC_INDEX_BUFFER);
  137. m_submit->m_commands.write(id);
  138. m_submit->m_commands.write(count);
  139. return id;
  140. }
  141. inline void update_index_buffer(IndexBufferId id, size_t offset, size_t count, const void* indices)
  142. {
  143. m_submit->m_commands.write(COMMAND_UPDATE_INDEX_BUFFER);
  144. m_submit->m_commands.write(id);
  145. m_submit->m_commands.write(offset);
  146. m_submit->m_commands.write(count);
  147. m_submit->m_commands.write(indices);
  148. }
  149. /// Destroys the @a id index buffer.
  150. inline void destroy_index_buffer(IndexBufferId id)
  151. {
  152. m_submit->m_commands.write(COMMAND_DESTROY_INDEX_BUFFER);
  153. m_submit->m_commands.write(id);
  154. }
  155. inline TextureId create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data)
  156. {
  157. const TextureId id = m_textures.create();
  158. m_submit->m_commands.write(COMMAND_CREATE_TEXTURE);
  159. m_submit->m_commands.write(id);
  160. m_submit->m_commands.write(width);
  161. m_submit->m_commands.write(height);
  162. m_submit->m_commands.write(format);
  163. m_submit->m_commands.write(data);
  164. return id;
  165. }
  166. inline void update_texture(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
  167. {
  168. m_submit->m_commands.write(COMMAND_UPDATE_TEXTURE);
  169. m_submit->m_commands.write(id);
  170. m_submit->m_commands.write(x);
  171. m_submit->m_commands.write(y);
  172. m_submit->m_commands.write(width);
  173. m_submit->m_commands.write(height);
  174. m_submit->m_commands.write(data);
  175. }
  176. inline void destroy_texture(TextureId id)
  177. {
  178. m_submit->m_commands.write(COMMAND_DESTROY_TEXTURE);
  179. m_submit->m_commands.write(id);
  180. }
  181. inline ShaderId create_shader(ShaderType type, const char* text)
  182. {
  183. const ShaderId id = m_shaders.create();
  184. m_submit->m_commands.write(COMMAND_CREATE_SHADER);
  185. m_submit->m_commands.write(id);
  186. m_submit->m_commands.write(type);
  187. m_submit->m_commands.write(text);
  188. return id;
  189. }
  190. inline void destroy_shader(ShaderId id)
  191. {
  192. m_submit->m_commands.write(COMMAND_DESTROY_SHADER);
  193. m_submit->m_commands.write(id);
  194. }
  195. inline GPUProgramId create_gpu_program(ShaderId vertex, ShaderId pixel)
  196. {
  197. const GPUProgramId id = m_gpu_programs.create();
  198. m_submit->m_commands.write(COMMAND_CREATE_GPU_PROGRAM);
  199. m_submit->m_commands.write(id);
  200. m_submit->m_commands.write(vertex);
  201. m_submit->m_commands.write(pixel);
  202. return id;
  203. }
  204. inline void destroy_gpu_program(GPUProgramId id)
  205. {
  206. m_submit->m_commands.write(COMMAND_DESTROY_GPU_PROGRAM);
  207. m_submit->m_commands.write(id);
  208. }
  209. inline UniformId create_uniform(const char* name, UniformType type, uint8_t num)
  210. {
  211. CE_ASSERT(name_to_stock_uniform(name) == UNIFORM_COUNT, "Uniform name '%s' is a stock uniform.", name);
  212. const UniformId id = m_uniforms.create();
  213. size_t len = string::strlen(name);
  214. CE_ASSERT(len < CROWN_MAX_UNIFORM_NAME_LENGTH, "Max uniform name length is %d", CROWN_MAX_UNIFORM_NAME_LENGTH);
  215. m_submit->m_commands.write(COMMAND_CREATE_UNIFORM);
  216. m_submit->m_commands.write(id);
  217. m_submit->m_commands.write(len);
  218. m_submit->m_commands.write(name, len);
  219. m_submit->m_commands.write(type);
  220. m_submit->m_commands.write(num);
  221. return id;
  222. }
  223. inline void destroy_uniform(UniformId id)
  224. {
  225. m_submit->m_commands.write(COMMAND_DESTROY_UNIFORM);
  226. m_submit->m_commands.write(id);
  227. }
  228. //
  229. // RenderTargetId create_render_target(uint16_t width, uint16_t height, RenderTargetFormat format)
  230. // {
  231. // }
  232. // void destroy_render_target(RenderTargetId id)
  233. // {
  234. // }
  235. //-----------------------------------------------------------------------------
  236. inline void execute_commands(CommandBuffer& cmds)
  237. {
  238. bool end = false;
  239. do
  240. {
  241. CommandType command;
  242. cmds.read(command);
  243. switch (command)
  244. {
  245. case COMMAND_INIT_RENDERER:
  246. {
  247. init_impl();
  248. m_is_initialized = true;
  249. break;
  250. }
  251. case COMMAND_SHUTDOWN_RENDERER:
  252. {
  253. shutdown_impl();
  254. m_is_initialized = false;
  255. break;
  256. }
  257. case COMMAND_CREATE_VERTEX_BUFFER:
  258. {
  259. VertexBufferId id;
  260. size_t count;
  261. VertexFormat format;
  262. void* vertices;
  263. cmds.read(id);
  264. cmds.read(count);
  265. cmds.read(format);
  266. cmds.read(vertices);
  267. create_vertex_buffer_impl(id, count, format, vertices);
  268. break;
  269. }
  270. case COMMAND_CREATE_DYNAMIC_VERTEX_BUFFER:
  271. {
  272. VertexBufferId id;
  273. size_t count;
  274. VertexFormat format;
  275. cmds.read(id);
  276. cmds.read(count);
  277. cmds.read(format);
  278. create_dynamic_vertex_buffer_impl(id, count, format);
  279. break;
  280. }
  281. case COMMAND_UPDATE_VERTEX_BUFFER:
  282. {
  283. VertexBufferId id;
  284. size_t offset;
  285. size_t count;
  286. void* vertices;
  287. cmds.read(id);
  288. cmds.read(offset);
  289. cmds.read(count);
  290. cmds.read(vertices);
  291. update_vertex_buffer_impl(id, offset, count, vertices);
  292. break;
  293. }
  294. case COMMAND_DESTROY_VERTEX_BUFFER:
  295. {
  296. VertexBufferId id;
  297. cmds.read(id);
  298. destroy_vertex_buffer_impl(id);
  299. break;
  300. }
  301. case COMMAND_CREATE_INDEX_BUFFER:
  302. {
  303. IndexBufferId id;
  304. size_t count;
  305. void* indices;
  306. cmds.read(id);
  307. cmds.read(count);
  308. cmds.read(indices);
  309. create_index_buffer_impl(id, count, indices);
  310. break;
  311. }
  312. case COMMAND_CREATE_DYNAMIC_INDEX_BUFFER:
  313. {
  314. IndexBufferId id;
  315. size_t count;
  316. cmds.read(id);
  317. cmds.read(count);
  318. create_dynamic_index_buffer_impl(id, count);
  319. break;
  320. }
  321. case COMMAND_UPDATE_INDEX_BUFFER:
  322. {
  323. IndexBufferId id;
  324. size_t offset;
  325. size_t count;
  326. void* indices;
  327. cmds.read(id);
  328. cmds.read(offset);
  329. cmds.read(count);
  330. cmds.read(indices);
  331. update_index_buffer_impl(id, offset, count, indices);
  332. break;
  333. }
  334. case COMMAND_DESTROY_INDEX_BUFFER:
  335. {
  336. IndexBufferId id;
  337. cmds.read(id);
  338. destroy_index_buffer_impl(id);
  339. break;
  340. }
  341. case COMMAND_CREATE_TEXTURE:
  342. {
  343. TextureId id;
  344. uint32_t width;
  345. uint32_t height;
  346. PixelFormat format;
  347. void* data;
  348. cmds.read(id);
  349. cmds.read(width);
  350. cmds.read(height);
  351. cmds.read(format);
  352. cmds.read(data);
  353. create_texture_impl(id, width, height, format, data);
  354. break;
  355. }
  356. case COMMAND_UPDATE_TEXTURE:
  357. {
  358. TextureId id;
  359. uint32_t x;
  360. uint32_t y;
  361. uint32_t width;
  362. uint32_t height;
  363. void* data;
  364. cmds.read(id);
  365. cmds.read(x);
  366. cmds.read(y);
  367. cmds.read(width);
  368. cmds.read(height);
  369. cmds.read(data);
  370. update_texture_impl(id, x, y, width, height, data);
  371. break;
  372. }
  373. case COMMAND_DESTROY_TEXTURE:
  374. {
  375. TextureId id;
  376. cmds.read(id);
  377. destroy_texture_impl(id);
  378. break;
  379. }
  380. case COMMAND_CREATE_SHADER:
  381. {
  382. ShaderId id;
  383. ShaderType type;
  384. char* text;
  385. cmds.read(id);
  386. cmds.read(type);
  387. cmds.read(text);
  388. create_shader_impl(id, type, text);
  389. break;
  390. }
  391. case COMMAND_DESTROY_SHADER:
  392. {
  393. ShaderId id;
  394. cmds.read(id);
  395. destroy_shader_impl(id);
  396. break;
  397. }
  398. case COMMAND_CREATE_GPU_PROGRAM:
  399. {
  400. GPUProgramId id;
  401. ShaderId vertex;
  402. ShaderId pixel;
  403. cmds.read(id);
  404. cmds.read(vertex);
  405. cmds.read(pixel);
  406. create_gpu_program_impl(id, vertex, pixel);
  407. break;
  408. }
  409. case COMMAND_DESTROY_GPU_PROGRAM:
  410. {
  411. GPUProgramId id;
  412. cmds.read(id);
  413. destroy_gpu_program_impl(id);
  414. break;
  415. }
  416. case COMMAND_CREATE_UNIFORM:
  417. {
  418. UniformId id;
  419. size_t len;
  420. char name[CROWN_MAX_UNIFORM_NAME_LENGTH];
  421. UniformType type;
  422. uint8_t num;
  423. cmds.read(id);
  424. cmds.read(len);
  425. cmds.read(name, len);
  426. name[len] = '\0';
  427. cmds.read(type);
  428. cmds.read(num);
  429. create_uniform_impl(id, name, type, num);
  430. break;
  431. }
  432. case COMMAND_DESTROY_UNIFORM:
  433. {
  434. UniformId id;
  435. cmds.read(id);
  436. destroy_uniform_impl(id);
  437. break;
  438. }
  439. case COMMAND_END:
  440. {
  441. end = true;
  442. break;
  443. }
  444. default:
  445. {
  446. CE_ASSERT(false, "Oops, unknown command");
  447. break;
  448. }
  449. }
  450. }
  451. while (!end);
  452. cmds.clear();
  453. }
  454. inline void update_uniforms(ConstantBuffer& cbuf)
  455. {
  456. UniformType type;
  457. while ((type = (UniformType)cbuf.read()) != UNIFORM_END)
  458. {
  459. UniformId id;
  460. size_t size;
  461. cbuf.read(&id, sizeof(UniformId));
  462. cbuf.read(&size, sizeof(size_t));
  463. const void* data = cbuf.read(size);
  464. update_uniform_impl(id, size, data);
  465. }
  466. cbuf.clear();
  467. }
  468. inline void set_state(uint64_t flags)
  469. {
  470. m_submit->set_state(flags);
  471. }
  472. inline void set_pose(const Mat4& pose)
  473. {
  474. m_submit->set_pose(pose);
  475. }
  476. inline void set_program(GPUProgramId program)
  477. {
  478. m_submit->set_program(program);
  479. }
  480. inline void set_vertex_buffer(VertexBufferId vb)
  481. {
  482. m_submit->set_vertex_buffer(vb);
  483. }
  484. inline void set_index_buffer(IndexBufferId ib)
  485. {
  486. m_submit->set_index_buffer(ib);
  487. }
  488. inline void set_uniform(UniformId id, UniformType type, void* value, uint8_t num)
  489. {
  490. m_submit->set_uniform(id, type, value, num);
  491. }
  492. inline void set_texture(uint8_t unit, UniformId sampler_uniform, TextureId texture, uint32_t flags)
  493. {
  494. m_submit->set_texture(unit, sampler_uniform, texture, flags);
  495. }
  496. inline void set_layer_render_target(uint8_t layer, RenderTargetId target)
  497. {
  498. m_submit->set_layer_render_target(layer, target);
  499. }
  500. inline void set_layer_clear(uint8_t layer, uint8_t flags, const Color4& color, float depth)
  501. {
  502. m_submit->set_layer_clear(layer, flags, color, depth);
  503. }
  504. inline void set_layer_view(uint8_t layer, const Mat4& view)
  505. {
  506. m_submit->set_layer_view(layer, view);
  507. }
  508. inline void set_layer_projection(uint8_t layer, const Mat4& projection)
  509. {
  510. m_submit->set_layer_projection(layer, projection);
  511. }
  512. inline void set_layer_viewport(uint8_t layer, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
  513. {
  514. m_submit->set_layer_viewport(layer, x, y, width, height);
  515. }
  516. inline void set_layer_scissor(uint8_t layer, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
  517. {
  518. m_submit->set_layer_scissor(layer, x, y, width, height);
  519. }
  520. inline void commit(uint8_t layer)
  521. {
  522. m_submit->commit(layer);
  523. }
  524. static int32_t render_thread(void* thiz)
  525. {
  526. Renderer* renderer = (Renderer*)thiz;
  527. while (renderer->m_should_run)
  528. {
  529. renderer->render_all();
  530. }
  531. return 0;
  532. }
  533. inline void swap_contexts()
  534. {
  535. // Ensure COMMAND_END at the end of submit command buffer
  536. m_submit->push();
  537. RenderContext* temp = m_submit;
  538. m_submit = m_draw;
  539. m_draw = temp;
  540. m_main_wait.post();
  541. }
  542. inline void frame()
  543. {
  544. // Signal main thread finished updating
  545. m_render_wait.post();
  546. m_main_wait.wait();
  547. }
  548. // Do all the processing needed to render a frame
  549. inline void render_all()
  550. {
  551. // Waits for main thread to finish update
  552. m_render_wait.wait();
  553. swap_contexts();
  554. execute_commands(m_draw->m_commands);
  555. update_uniforms(m_draw->m_constants);
  556. if (m_is_initialized)
  557. {
  558. render_impl();
  559. }
  560. }
  561. protected:
  562. Allocator& m_allocator;
  563. RendererImplementation* m_impl;
  564. OsThread m_thread;
  565. Semaphore m_render_wait;
  566. Semaphore m_main_wait;
  567. RenderContext m_contexts[2];
  568. RenderContext* m_submit;
  569. RenderContext* m_draw;
  570. // Id tables
  571. IdTable<CROWN_MAX_VERTEX_BUFFERS> m_vertex_buffers;
  572. IdTable<CROWN_MAX_INDEX_BUFFERS> m_index_buffers;
  573. IdTable<CROWN_MAX_TEXTURES> m_textures;
  574. IdTable<CROWN_MAX_SHADERS> m_shaders;
  575. IdTable<CROWN_MAX_GPU_PROGRAMS> m_gpu_programs;
  576. IdTable<CROWN_MAX_UNIFORMS> m_uniforms;
  577. // IdTable<CROWN_MAX_RENDER_TARGETS> m_render_targets;
  578. bool m_is_initialized;
  579. bool m_should_run;
  580. };
  581. } // namespace crown