CommandBufferHandle.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. // Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "anki/gr/CommandBufferHandle.h"
  6. #include "anki/gr/GlDevice.h"
  7. #include "anki/gr/gl/FramebufferImpl.h"
  8. #include "anki/gr/TextureHandle.h"
  9. #include "anki/gr/gl/TextureImpl.h"
  10. #include "anki/gr/BufferHandle.h"
  11. #include "anki/gr/gl/BufferImpl.h"
  12. #include "anki/gr/OcclusionQueryHandle.h"
  13. #include "anki/gr/gl/OcclusionQueryImpl.h"
  14. #include "anki/core/Counters.h"
  15. #include <utility>
  16. namespace anki {
  17. //==============================================================================
  18. // Macros because we are bored to type
  19. #define ANKI_STATE_CMD_0(type_, glfunc_) \
  20. class Command: public GlCommand \
  21. { \
  22. public: \
  23. Command() = default \
  24. Error operator()(CommandBufferImpl*) \
  25. { \
  26. glfunc_(); \
  27. return ErrorCode::NONE; \
  28. } \
  29. }; \
  30. _pushBackNewCommand<Command>(value_)
  31. #define ANKI_STATE_CMD_1(type_, glfunc_, value_) \
  32. class Command: public GlCommand \
  33. { \
  34. public: \
  35. type_ m_value; \
  36. Command(type_ v) \
  37. : m_value(v) \
  38. {} \
  39. Error operator()(CommandBufferImpl*) \
  40. { \
  41. glfunc_(m_value); \
  42. return ErrorCode::NONE; \
  43. } \
  44. }; \
  45. _pushBackNewCommand<Command>(value_)
  46. #define ANKI_STATE_CMD_2(type_, glfunc_, a_, b_) \
  47. class Command: public GlCommand \
  48. { \
  49. public: \
  50. Array<type_, 2> m_value; \
  51. Command(type_ a, type_ b) \
  52. { \
  53. m_value = {{a, b}}; \
  54. } \
  55. Error operator()(CommandBufferImpl*) \
  56. { \
  57. glfunc_(m_value[0], m_value[1]); \
  58. return ErrorCode::NONE; \
  59. } \
  60. }; \
  61. _pushBackNewCommand<Command>(a_, b_)
  62. #define ANKI_STATE_CMD_3(type_, glfunc_, a_, b_, c_) \
  63. class Command: public GlCommand \
  64. { \
  65. public: \
  66. Array<type_, 3> m_value; \
  67. Command(type_ a, type_ b, type_ c) \
  68. { \
  69. m_value = {{a, b, c}}; \
  70. } \
  71. Error operator()(CommandBufferImpl*) \
  72. { \
  73. glfunc_(m_value[0], m_value[1], m_value[2]); \
  74. return ErrorCode::NONE; \
  75. } \
  76. }; \
  77. _pushBackNewCommand<Command>(a_, b_, c_)
  78. #define ANKI_STATE_CMD_4(type_, glfunc_, a_, b_, c_, d_) \
  79. class Command: public GlCommand \
  80. { \
  81. public: \
  82. Array<type_, 4> m_value; \
  83. Command(type_ a, type_ b, type_ c, type_ d) \
  84. { \
  85. m_value = {{a, b, c, d}}; \
  86. } \
  87. Error operator()(CommandBufferImpl*) \
  88. { \
  89. glfunc_(m_value[0], m_value[1], m_value[2], m_value[3]); \
  90. return ErrorCode::NONE; \
  91. } \
  92. }; \
  93. _pushBackNewCommand<Command>(a_, b_, c_, d_)
  94. #define ANKI_STATE_CMD_ENABLE(enum_, enable_) \
  95. class Command: public GlCommand \
  96. { \
  97. public: \
  98. Bool8 m_enable; \
  99. Command(Bool enable) \
  100. : m_enable(enable) \
  101. {} \
  102. Error operator()(CommandBufferImpl*) \
  103. { \
  104. if(m_enable) \
  105. { \
  106. glEnable(enum_); \
  107. } \
  108. else \
  109. { \
  110. glDisable(enum_); \
  111. } \
  112. return ErrorCode::NONE; \
  113. } \
  114. }; \
  115. _pushBackNewCommand<Command>(enable_)
  116. //==============================================================================
  117. CommandBufferHandle::CommandBufferHandle()
  118. {}
  119. //==============================================================================
  120. CommandBufferHandle::~CommandBufferHandle()
  121. {}
  122. //==============================================================================
  123. Error CommandBufferHandle::create(GlDevice* gl,
  124. CommandBufferImplInitHints hints)
  125. {
  126. ANKI_ASSERT(!isCreated());
  127. ANKI_ASSERT(gl);
  128. using Alloc = GlAllocator<CommandBufferImpl>;
  129. Alloc alloc = gl->_getAllocator();
  130. Error err = _createAdvanced(
  131. gl,
  132. alloc,
  133. GlHandleDefaultDeleter<CommandBufferImpl, Alloc>());
  134. if(!err)
  135. {
  136. err = _get().create(&gl->_getRenderingThread(), hints);
  137. }
  138. return err;
  139. }
  140. //==============================================================================
  141. void CommandBufferHandle::pushBackUserCommand(
  142. UserCallback callback, void* data)
  143. {
  144. class Command: public GlCommand
  145. {
  146. public:
  147. UserCallback m_callback;
  148. void* m_userData;
  149. Command(UserCallback callback, void* userData)
  150. : m_callback(callback),
  151. m_userData(userData)
  152. {
  153. ANKI_ASSERT(m_callback);
  154. }
  155. Error operator()(CommandBufferImpl* commands)
  156. {
  157. return (*m_callback)(m_userData);
  158. }
  159. };
  160. _pushBackNewCommand<Command>(callback, data);
  161. }
  162. //==============================================================================
  163. void CommandBufferHandle::pushBackOtherCommandBuffer(
  164. CommandBufferHandle& commands)
  165. {
  166. class Command: public GlCommand
  167. {
  168. public:
  169. CommandBufferHandle m_commands;
  170. Command(CommandBufferHandle& commands)
  171. : m_commands(commands)
  172. {}
  173. Error operator()(CommandBufferImpl*)
  174. {
  175. return m_commands._executeAllCommands();
  176. }
  177. };
  178. commands._get().makeImmutable();
  179. _pushBackNewCommand<Command>(commands);
  180. }
  181. //==============================================================================
  182. void CommandBufferHandle::flush()
  183. {
  184. _get().getRenderingThread().flushCommandBuffer(*this);
  185. }
  186. //==============================================================================
  187. void CommandBufferHandle::finish()
  188. {
  189. _get().getRenderingThread().finishCommandBuffer(*this);
  190. }
  191. //==============================================================================
  192. void CommandBufferHandle::setClearColor(F32 r, F32 g, F32 b, F32 a)
  193. {
  194. ANKI_STATE_CMD_4(F32, glClearColor, r, g, b, a);
  195. }
  196. //==============================================================================
  197. void CommandBufferHandle::setClearDepth(F32 value)
  198. {
  199. ANKI_STATE_CMD_1(F32, glClearDepth, value);
  200. }
  201. //==============================================================================
  202. void CommandBufferHandle::setClearStencil(U32 value)
  203. {
  204. ANKI_STATE_CMD_1(U32, glClearStencil, value);
  205. }
  206. //==============================================================================
  207. void CommandBufferHandle::clearBuffers(U32 mask)
  208. {
  209. ANKI_STATE_CMD_1(U32, glClear, mask);
  210. }
  211. //==============================================================================
  212. void CommandBufferHandle::setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
  213. {
  214. class Command: public GlCommand
  215. {
  216. public:
  217. Array<U16, 4> m_value;
  218. Command(U16 a, U16 b, U16 c, U16 d)
  219. {
  220. m_value = {{a, b, c, d}};
  221. }
  222. Error operator()(CommandBufferImpl* commands)
  223. {
  224. State& state = commands->getRenderingThread().getState();
  225. if(state.m_viewport[0] != m_value[0]
  226. || state.m_viewport[1] != m_value[1]
  227. || state.m_viewport[2] != m_value[2]
  228. || state.m_viewport[3] != m_value[3])
  229. {
  230. glViewport(m_value[0], m_value[1], m_value[2], m_value[3]);
  231. state.m_viewport = m_value;
  232. }
  233. return ErrorCode::NONE;
  234. }
  235. };
  236. _pushBackNewCommand<Command>(minx, miny, maxx, maxy);
  237. }
  238. //==============================================================================
  239. void CommandBufferHandle::setColorWriteMask(
  240. Bool red, Bool green, Bool blue, Bool alpha)
  241. {
  242. ANKI_STATE_CMD_4(Bool8, glColorMask, red, green, blue, alpha);
  243. }
  244. //==============================================================================
  245. void CommandBufferHandle::enableDepthTest(Bool enable)
  246. {
  247. ANKI_STATE_CMD_ENABLE(GL_DEPTH_TEST, enable);
  248. }
  249. //==============================================================================
  250. void CommandBufferHandle::setDepthFunction(GLenum func)
  251. {
  252. ANKI_STATE_CMD_1(GLenum, glDepthFunc, func);
  253. }
  254. //==============================================================================
  255. void CommandBufferHandle::setDepthWriteMask(Bool write)
  256. {
  257. ANKI_STATE_CMD_1(Bool8, glDepthMask, write);
  258. }
  259. //==============================================================================
  260. void CommandBufferHandle::enableStencilTest(Bool enable)
  261. {
  262. ANKI_STATE_CMD_ENABLE(GL_STENCIL_TEST, enable);
  263. }
  264. //==============================================================================
  265. void CommandBufferHandle::setStencilFunction(
  266. GLenum function, U32 reference, U32 mask)
  267. {
  268. ANKI_STATE_CMD_3(U32, glStencilFunc, function, reference, mask);
  269. }
  270. //==============================================================================
  271. void CommandBufferHandle::setStencilPlaneMask(U32 mask)
  272. {
  273. ANKI_STATE_CMD_1(U32, glStencilMask, mask);
  274. }
  275. //==============================================================================
  276. void CommandBufferHandle::setStencilOperations(GLenum stencFail, GLenum depthFail,
  277. GLenum depthPass)
  278. {
  279. ANKI_STATE_CMD_3(GLenum, glStencilOp, stencFail, depthFail, depthPass);
  280. }
  281. //==============================================================================
  282. void CommandBufferHandle::enableBlend(Bool enable)
  283. {
  284. ANKI_STATE_CMD_ENABLE(GL_BLEND, enable);
  285. }
  286. //==============================================================================
  287. void CommandBufferHandle::setBlendEquation(GLenum equation)
  288. {
  289. ANKI_STATE_CMD_1(GLenum, glBlendEquation, equation);
  290. }
  291. //==============================================================================
  292. void CommandBufferHandle::setBlendFunctions(GLenum sfactor, GLenum dfactor)
  293. {
  294. class Command: public GlCommand
  295. {
  296. public:
  297. GLenum m_sfactor;
  298. GLenum m_dfactor;
  299. Command(GLenum sfactor, GLenum dfactor)
  300. : m_sfactor(sfactor), m_dfactor(dfactor)
  301. {}
  302. Error operator()(CommandBufferImpl* commands)
  303. {
  304. State& state = commands->getRenderingThread().getState();
  305. if(state.m_blendSfunc != m_sfactor
  306. || state.m_blendDfunc != m_dfactor)
  307. {
  308. glBlendFunc(m_sfactor, m_dfactor);
  309. state.m_blendSfunc = m_sfactor;
  310. state.m_blendDfunc = m_dfactor;
  311. }
  312. return ErrorCode::NONE;
  313. }
  314. };
  315. _pushBackNewCommand<Command>(sfactor, dfactor);
  316. }
  317. //==============================================================================
  318. void CommandBufferHandle::setBlendColor(F32 r, F32 g, F32 b, F32 a)
  319. {
  320. ANKI_STATE_CMD_4(F32, glBlendColor, r, g, b, a);
  321. }
  322. //==============================================================================
  323. void CommandBufferHandle::enablePrimitiveRestart(Bool enable)
  324. {
  325. ANKI_STATE_CMD_ENABLE(GL_PRIMITIVE_RESTART, enable);
  326. }
  327. //==============================================================================
  328. void CommandBufferHandle::setPatchVertexCount(U32 count)
  329. {
  330. ANKI_STATE_CMD_2(GLint, glPatchParameteri, GL_PATCH_VERTICES, count);
  331. }
  332. //==============================================================================
  333. void CommandBufferHandle::enableCulling(Bool enable)
  334. {
  335. ANKI_STATE_CMD_ENABLE(GL_CULL_FACE, enable);
  336. }
  337. //==============================================================================
  338. void CommandBufferHandle::setCullFace(GLenum mode)
  339. {
  340. ANKI_STATE_CMD_1(GLenum, glCullFace, mode);
  341. }
  342. //==============================================================================
  343. void CommandBufferHandle::setPolygonOffset(F32 factor, F32 units)
  344. {
  345. ANKI_STATE_CMD_2(F32, glPolygonOffset, factor, units);
  346. }
  347. //==============================================================================
  348. void CommandBufferHandle::enablePolygonOffset(Bool enable)
  349. {
  350. ANKI_STATE_CMD_ENABLE(GL_POLYGON_OFFSET_FILL, enable);
  351. }
  352. //==============================================================================
  353. void CommandBufferHandle::setPolygonMode(GLenum face, GLenum mode)
  354. {
  355. ANKI_STATE_CMD_2(GLenum, glPolygonMode, face, mode);
  356. }
  357. //==============================================================================
  358. void CommandBufferHandle::enablePointSize(Bool enable)
  359. {
  360. ANKI_STATE_CMD_ENABLE(GL_PROGRAM_POINT_SIZE, enable);
  361. }
  362. //==============================================================================
  363. class BindTexturesCommand: public GlCommand
  364. {
  365. public:
  366. static const U MAX_BIND_TEXTURES = 8;
  367. Array<TextureHandle, MAX_BIND_TEXTURES> m_texes;
  368. U32 m_texCount;
  369. U32 m_first;
  370. BindTexturesCommand(
  371. TextureHandle textures[], U count, U32 first)
  372. : m_first(first)
  373. {
  374. m_texCount = count;
  375. TextureHandle* t = textures;
  376. while(count-- != 0)
  377. {
  378. m_texes[count] = *t;
  379. ++t;
  380. }
  381. }
  382. Error operator()(CommandBufferImpl* commands)
  383. {
  384. Array<GLuint, MAX_BIND_TEXTURES> names;
  385. U count = m_texCount;
  386. U i = 0;
  387. while(count-- != 0)
  388. {
  389. names[i++] = m_texes[count]._get().getGlName();
  390. }
  391. glBindTextures(m_first, m_texCount, &names[0]);
  392. return ErrorCode::NONE;
  393. }
  394. };
  395. void CommandBufferHandle::bindTextures(U32 first,
  396. TextureHandle textures[], U32 count)
  397. {
  398. ANKI_ASSERT(count > 0);
  399. _pushBackNewCommand<BindTexturesCommand>(&textures[0], count, first);
  400. }
  401. //==============================================================================
  402. class DrawElementsCondCommand: public GlCommand
  403. {
  404. public:
  405. GLenum m_mode;
  406. U8 m_indexSize;
  407. GlDrawElementsIndirectInfo m_info;
  408. OcclusionQueryHandle m_query;
  409. DrawElementsCondCommand(
  410. GLenum mode,
  411. U8 indexSize,
  412. GlDrawElementsIndirectInfo& info,
  413. OcclusionQueryHandle query = OcclusionQueryHandle())
  414. : m_mode(mode),
  415. m_indexSize(indexSize),
  416. m_info(info),
  417. m_query(query)
  418. {}
  419. Error operator()(CommandBufferImpl*)
  420. {
  421. ANKI_ASSERT(m_indexSize != 0);
  422. GLenum indicesType = 0;
  423. switch(m_indexSize)
  424. {
  425. case 1:
  426. indicesType = GL_UNSIGNED_BYTE;
  427. break;
  428. case 2:
  429. indicesType = GL_UNSIGNED_SHORT;
  430. break;
  431. case 4:
  432. indicesType = GL_UNSIGNED_INT;
  433. break;
  434. default:
  435. ANKI_ASSERT(0);
  436. break;
  437. };
  438. if(!m_query.isCreated() || !m_query._get().skipDrawcall())
  439. {
  440. glDrawElementsInstancedBaseVertexBaseInstance(
  441. m_mode,
  442. m_info.m_count,
  443. indicesType,
  444. (const void*)(PtrSize)(m_info.m_firstIndex * m_indexSize),
  445. m_info.m_instanceCount,
  446. m_info.m_baseVertex,
  447. m_info.m_baseInstance);
  448. ANKI_COUNTER_INC(GL_DRAWCALLS_COUNT, (U64)1);
  449. }
  450. return ErrorCode::NONE;
  451. }
  452. };
  453. void CommandBufferHandle::drawElements(
  454. GLenum mode, U8 indexSize, U32 count, U32 instanceCount, U32 firstIndex,
  455. U32 baseVertex, U32 baseInstance)
  456. {
  457. GlDrawElementsIndirectInfo info(count, instanceCount, firstIndex,
  458. baseVertex, baseInstance);
  459. _pushBackNewCommand<DrawElementsCondCommand>(mode, indexSize, info);
  460. }
  461. //==============================================================================
  462. class DrawArraysCondCommand: public GlCommand
  463. {
  464. public:
  465. GLenum m_mode;
  466. GlDrawArraysIndirectInfo m_info;
  467. OcclusionQueryHandle m_query;
  468. DrawArraysCondCommand(
  469. GLenum mode,
  470. GlDrawArraysIndirectInfo& info,
  471. OcclusionQueryHandle query = OcclusionQueryHandle())
  472. : m_mode(mode),
  473. m_info(info),
  474. m_query(query)
  475. {}
  476. Error operator()(CommandBufferImpl*)
  477. {
  478. if(!m_query.isCreated() || !m_query._get().skipDrawcall())
  479. {
  480. glDrawArraysInstancedBaseInstance(
  481. m_mode,
  482. m_info.m_first,
  483. m_info.m_count,
  484. m_info.m_instanceCount,
  485. m_info.m_baseInstance);
  486. ANKI_COUNTER_INC(GL_DRAWCALLS_COUNT, (U64)1);
  487. }
  488. return ErrorCode::NONE;
  489. }
  490. };
  491. void CommandBufferHandle::drawArrays(
  492. GLenum mode, U32 count, U32 instanceCount, U32 first, U32 baseInstance)
  493. {
  494. GlDrawArraysIndirectInfo info(count, instanceCount, first, baseInstance);
  495. _pushBackNewCommand<DrawArraysCondCommand>(mode, info);
  496. }
  497. //==============================================================================
  498. void CommandBufferHandle::drawElementsConditional(
  499. OcclusionQueryHandle& query,
  500. GLenum mode, U8 indexSize, U32 count, U32 instanceCount, U32 firstIndex,
  501. U32 baseVertex, U32 baseInstance)
  502. {
  503. GlDrawElementsIndirectInfo info(count, instanceCount, firstIndex,
  504. baseVertex, baseInstance);
  505. _pushBackNewCommand<DrawElementsCondCommand>(mode, indexSize, info, query);
  506. }
  507. //==============================================================================
  508. void CommandBufferHandle::drawArraysConditional(
  509. OcclusionQueryHandle& query,
  510. GLenum mode, U32 count, U32 instanceCount, U32 first, U32 baseInstance)
  511. {
  512. GlDrawArraysIndirectInfo info(count, instanceCount, first, baseInstance);
  513. _pushBackNewCommand<DrawArraysCondCommand>(mode, info, query);
  514. }
  515. //==============================================================================
  516. class CopyBuffTex: public GlCommand
  517. {
  518. public:
  519. TextureHandle m_tex;
  520. BufferHandle m_buff;
  521. CopyBuffTex(TextureHandle& from, BufferHandle& to)
  522. : m_tex(from),
  523. m_buff(to)
  524. {}
  525. Error operator()(CommandBufferImpl* cmd)
  526. {
  527. TextureImpl& tex = m_tex._get();
  528. BufferImpl& buff = m_buff._get();
  529. // Bind
  530. GLuint copyFbo = cmd->getRenderingThread().getCopyFbo();
  531. glBindFramebuffer(GL_FRAMEBUFFER, copyFbo);
  532. // Attach texture
  533. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  534. tex.getTarget(), tex.getGlName(), 0);
  535. // Set draw buffers
  536. GLuint drawBuff = GL_COLOR_ATTACHMENT0;
  537. glDrawBuffers(1, &drawBuff);
  538. // Bind buffer
  539. ANKI_ASSERT(m_buff.getTarget() == GL_PIXEL_PACK_BUFFER);
  540. buff.bind();
  541. // Read pixels
  542. GLuint format, type;
  543. if(tex.getInternalFormat() == GL_RG32UI)
  544. {
  545. format = GL_RG_INTEGER;
  546. type = GL_UNSIGNED_INT;
  547. }
  548. else if(tex.getInternalFormat() == GL_RG32F)
  549. {
  550. format = GL_RG;
  551. type = GL_FLOAT;
  552. }
  553. else
  554. {
  555. ANKI_ASSERT(0 && "Not implemented");
  556. }
  557. glReadPixels(0, 0, tex.getWidth(), tex.getHeight(),
  558. format, type, nullptr);
  559. // End
  560. buff.unbind();
  561. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  562. return ErrorCode::NONE;
  563. }
  564. };
  565. void CommandBufferHandle::copyTextureToBuffer(
  566. TextureHandle& from, BufferHandle& to)
  567. {
  568. _pushBackNewCommand<CopyBuffTex>(from, to);
  569. }
  570. } // end namespace anki