gpudrivenrendering.cpp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226
  1. /*
  2. * Copyright 2018 Kostas Anagnostou. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. /*
  6. * References:
  7. *
  8. * Experiments in GPU-based occlusion culling
  9. * https://interplayoflight.wordpress.com/2017/11/15/experiments-in-gpu-based-occlusion-culling/
  10. *
  11. * Experiments in GPU-based occlusion culling part 2: MultiDrawIndirect and mesh lodding
  12. * https://interplayoflight.wordpress.com/2018/01/15/experiments-in-gpu-based-occlusion-culling-part-2-multidrawindirect-and-mesh-lodding/
  13. */
  14. #include "common.h"
  15. #include "bgfx_utils.h"
  16. #include "imgui/imgui.h"
  17. namespace
  18. {
  19. #define RENDER_PASS_HIZ_ID 0
  20. #define RENDER_PASS_HIZ_DOWNSCALE_ID 1
  21. #define RENDER_PASS_OCCLUDE_PROPS_ID 2
  22. #define RENDER_PASS_COMPACT_STREAM_ID 3
  23. #define RENDER_PASS_MAIN_ID 4
  24. struct Camera
  25. {
  26. Camera()
  27. {
  28. reset();
  29. }
  30. void reset()
  31. {
  32. m_target.curr[0] = 0.0f;
  33. m_target.curr[1] = 0.0f;
  34. m_target.curr[2] = 0.0f;
  35. m_target.dest[0] = 0.0f;
  36. m_target.dest[1] = 0.0f;
  37. m_target.dest[2] = 0.0f;
  38. m_pos.curr[0] = 55.0f;
  39. m_pos.curr[1] = 20.0f;
  40. m_pos.curr[2] = 65.0f;
  41. m_pos.dest[0] = 55.0f;
  42. m_pos.dest[1] = 20.0f;
  43. m_pos.dest[2] = 65.0f;
  44. m_orbit[0] = 0.0f;
  45. m_orbit[1] = 0.0f;
  46. }
  47. void mtxLookAt(float* _outViewMtx)
  48. {
  49. bx::mtxLookAt(_outViewMtx, m_pos.curr, m_target.curr);
  50. }
  51. void orbit(float _dx, float _dy)
  52. {
  53. m_orbit[0] += _dx;
  54. m_orbit[1] += _dy;
  55. }
  56. void dolly(float _dz)
  57. {
  58. const float cnear = 1.0f;
  59. const float cfar = 100.0f;
  60. const float toTarget[3] =
  61. {
  62. m_target.dest[0] - m_pos.dest[0],
  63. m_target.dest[1] - m_pos.dest[1],
  64. m_target.dest[2] - m_pos.dest[2],
  65. };
  66. const float toTargetLen = bx::vec3Length(toTarget);
  67. const float invToTargetLen = 1.0f / (toTargetLen + FLT_MIN);
  68. const float toTargetNorm[3] =
  69. {
  70. toTarget[0] * invToTargetLen,
  71. toTarget[1] * invToTargetLen,
  72. toTarget[2] * invToTargetLen,
  73. };
  74. float delta = toTargetLen*_dz;
  75. float newLen = toTargetLen + delta;
  76. if ((cnear < newLen || _dz < 0.0f)
  77. && (newLen < cfar || _dz > 0.0f))
  78. {
  79. m_pos.dest[0] += toTargetNorm[0] * delta;
  80. m_pos.dest[1] += toTargetNorm[1] * delta;
  81. m_pos.dest[2] += toTargetNorm[2] * delta;
  82. }
  83. }
  84. void consumeOrbit(float _amount)
  85. {
  86. float consume[2];
  87. consume[0] = m_orbit[0] * _amount;
  88. consume[1] = m_orbit[1] * _amount;
  89. m_orbit[0] -= consume[0];
  90. m_orbit[1] -= consume[1];
  91. const float toPos[3] =
  92. {
  93. m_pos.curr[0] - m_target.curr[0],
  94. m_pos.curr[1] - m_target.curr[1],
  95. m_pos.curr[2] - m_target.curr[2],
  96. };
  97. const float toPosLen = bx::vec3Length(toPos);
  98. const float invToPosLen = 1.0f / (toPosLen + FLT_MIN);
  99. const float toPosNorm[3] =
  100. {
  101. toPos[0] * invToPosLen,
  102. toPos[1] * invToPosLen,
  103. toPos[2] * invToPosLen,
  104. };
  105. float ll[2];
  106. latLongFromVec(ll[0], ll[1], toPosNorm);
  107. ll[0] += consume[0];
  108. ll[1] -= consume[1];
  109. ll[1] = bx::clamp(ll[1], 0.02f, 0.98f);
  110. float tmp[3];
  111. vecFromLatLong(tmp, ll[0], ll[1]);
  112. float diff[3];
  113. diff[0] = (tmp[0] - toPosNorm[0])*toPosLen;
  114. diff[1] = (tmp[1] - toPosNorm[1])*toPosLen;
  115. diff[2] = (tmp[2] - toPosNorm[2])*toPosLen;
  116. m_pos.curr[0] += diff[0];
  117. m_pos.curr[1] += diff[1];
  118. m_pos.curr[2] += diff[2];
  119. m_pos.dest[0] += diff[0];
  120. m_pos.dest[1] += diff[1];
  121. m_pos.dest[2] += diff[2];
  122. }
  123. void update(float _dt)
  124. {
  125. const float amount = bx::min(_dt / 0.12f, 1.0f);
  126. consumeOrbit(amount);
  127. m_target.curr[0] = bx::lerp(m_target.curr[0], m_target.dest[0], amount);
  128. m_target.curr[1] = bx::lerp(m_target.curr[1], m_target.dest[1], amount);
  129. m_target.curr[2] = bx::lerp(m_target.curr[2], m_target.dest[2], amount);
  130. m_pos.curr[0] = bx::lerp(m_pos.curr[0], m_pos.dest[0], amount);
  131. m_pos.curr[1] = bx::lerp(m_pos.curr[1], m_pos.dest[1], amount);
  132. m_pos.curr[2] = bx::lerp(m_pos.curr[2], m_pos.dest[2], amount);
  133. }
  134. void envViewMtx(float* _mtx)
  135. {
  136. const float toTarget[3] =
  137. {
  138. m_target.curr[0] - m_pos.curr[0],
  139. m_target.curr[1] - m_pos.curr[1],
  140. m_target.curr[2] - m_pos.curr[2],
  141. };
  142. const float toTargetLen = bx::vec3Length(toTarget);
  143. const float invToTargetLen = 1.0f / (toTargetLen + FLT_MIN);
  144. const float toTargetNorm[3] =
  145. {
  146. toTarget[0] * invToTargetLen,
  147. toTarget[1] * invToTargetLen,
  148. toTarget[2] * invToTargetLen,
  149. };
  150. float tmp[3];
  151. const float fakeUp[3] = { 0.0f, 1.0f, 0.0f };
  152. float right[3];
  153. bx::vec3Cross(tmp, fakeUp, toTargetNorm);
  154. bx::vec3Norm(right, tmp);
  155. float up[3];
  156. bx::vec3Cross(tmp, toTargetNorm, right);
  157. bx::vec3Norm(up, tmp);
  158. _mtx[0] = right[0];
  159. _mtx[1] = right[1];
  160. _mtx[2] = right[2];
  161. _mtx[3] = 0.0f;
  162. _mtx[4] = up[0];
  163. _mtx[5] = up[1];
  164. _mtx[6] = up[2];
  165. _mtx[7] = 0.0f;
  166. _mtx[8] = toTargetNorm[0];
  167. _mtx[9] = toTargetNorm[1];
  168. _mtx[10] = toTargetNorm[2];
  169. _mtx[11] = 0.0f;
  170. _mtx[12] = 0.0f;
  171. _mtx[13] = 0.0f;
  172. _mtx[14] = 0.0f;
  173. _mtx[15] = 1.0f;
  174. }
  175. static inline void vecFromLatLong(float _vec[3], float _u, float _v)
  176. {
  177. const float phi = _u * 2.0f*bx::kPi;
  178. const float theta = _v * bx::kPi;
  179. const float st = bx::sin(theta);
  180. const float sp = bx::sin(phi);
  181. const float ct = bx::cos(theta);
  182. const float cp = bx::cos(phi);
  183. _vec[0] = -st*sp;
  184. _vec[1] = ct;
  185. _vec[2] = -st*cp;
  186. }
  187. static inline void latLongFromVec(float& _u, float& _v, const float _vec[3])
  188. {
  189. const float phi = bx::atan2(_vec[0], _vec[2]);
  190. const float theta = bx::acos(_vec[1]);
  191. _u = (bx::kPi + phi)*bx::kInvPi*0.5f;
  192. _v = theta*bx::kInvPi;
  193. }
  194. struct Interp3f
  195. {
  196. float curr[3];
  197. float dest[3];
  198. };
  199. Interp3f m_target;
  200. Interp3f m_pos;
  201. float m_orbit[2];
  202. };
  203. struct Mouse
  204. {
  205. Mouse()
  206. : m_dx(0.0f)
  207. , m_dy(0.0f)
  208. , m_prevMx(0.0f)
  209. , m_prevMy(0.0f)
  210. , m_scroll(0)
  211. , m_scrollPrev(0)
  212. {
  213. }
  214. void update(float _mx, float _my, int32_t _mz, uint32_t _width, uint32_t _height)
  215. {
  216. const float widthf = float(int32_t(_width));
  217. const float heightf = float(int32_t(_height));
  218. // Delta movement.
  219. m_dx = float(_mx - m_prevMx) / widthf;
  220. m_dy = float(_my - m_prevMy) / heightf;
  221. m_prevMx = _mx;
  222. m_prevMy = _my;
  223. // Scroll.
  224. m_scroll = _mz - m_scrollPrev;
  225. m_scrollPrev = _mz;
  226. }
  227. float m_dx; // Screen space.
  228. float m_dy;
  229. float m_prevMx;
  230. float m_prevMy;
  231. int32_t m_scroll;
  232. int32_t m_scrollPrev;
  233. };
  234. struct PosVertex
  235. {
  236. float m_x;
  237. float m_y;
  238. float m_z;
  239. static void init()
  240. {
  241. ms_decl
  242. .begin()
  243. .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
  244. .end();
  245. };
  246. static bgfx::VertexDecl ms_decl;
  247. };
  248. bgfx::VertexDecl PosVertex::ms_decl;
  249. static PosVertex s_cubeVertices[8] =
  250. {
  251. {-0.5f, 0.5f, 0.5f},
  252. { 0.5f, 0.5f, 0.5f},
  253. {-0.5f, -0.5f, 0.5f},
  254. { 0.5f, -0.5f, 0.5f},
  255. {-0.5f, 0.5f, -0.5f},
  256. { 0.5f, 0.5f, -0.5f},
  257. {-0.5f, -0.5f, -0.5f},
  258. { 0.5f, -0.5f, -0.5f},
  259. };
  260. static const uint16_t s_cubeIndices[36] =
  261. {
  262. 0, 1, 2, // 0
  263. 1, 3, 2,
  264. 4, 6, 5, // 2
  265. 5, 6, 7,
  266. 0, 2, 4, // 4
  267. 4, 2, 6,
  268. 1, 5, 3, // 6
  269. 5, 7, 3,
  270. 0, 4, 1, // 8
  271. 4, 5, 1,
  272. 2, 3, 6, // 10
  273. 6, 3, 7,
  274. };
  275. struct RenderPass
  276. {
  277. enum Enum
  278. {
  279. Occlusion = 1 << 0,
  280. MainPass = 1 << 1,
  281. All = Occlusion | MainPass
  282. };
  283. };
  284. // All the per-instance data we store
  285. struct InstanceData
  286. {
  287. float m_world[16];
  288. float m_bboxMin[4];
  289. float m_bboxMax[4];
  290. };
  291. //A description of each prop
  292. struct Prop
  293. {
  294. PosVertex* m_vertices;
  295. uint16_t* m_indices;
  296. InstanceData* m_instances;
  297. bgfx::VertexBufferHandle m_vertexbufferHandle;
  298. bgfx::IndexBufferHandle m_indexbufferHandle;
  299. uint16_t m_noofVertices;
  300. uint16_t m_noofIndices;
  301. uint16_t m_noofInstances;
  302. uint16_t m_materialID;
  303. RenderPass::Enum m_renderPass;
  304. };
  305. //A simplistic material, comprised of a color only
  306. struct Material
  307. {
  308. float m_color[4];
  309. };
  310. inline void setVector4(float* dest, float x, float y, float z, float w)
  311. {
  312. dest[0] = x;
  313. dest[1] = y;
  314. dest[2] = z;
  315. dest[3] = w;
  316. }
  317. //Sets up a prop
  318. void createCubeMesh(Prop& prop)
  319. {
  320. prop.m_noofVertices = 8;
  321. prop.m_noofIndices = 36;
  322. prop.m_vertices = new PosVertex[prop.m_noofVertices];
  323. prop.m_indices = new uint16_t[prop.m_noofIndices];
  324. bx::memCopy(prop.m_vertices, s_cubeVertices, prop.m_noofVertices * PosVertex::ms_decl.getStride());
  325. bx::memCopy(prop.m_indices, s_cubeIndices, prop.m_noofIndices * sizeof(uint16_t));
  326. prop.m_vertexbufferHandle = bgfx::createVertexBuffer(
  327. bgfx::makeRef(prop.m_vertices, prop.m_noofVertices * PosVertex::ms_decl.getStride()),
  328. PosVertex::ms_decl);
  329. prop.m_indexbufferHandle = bgfx::createIndexBuffer(bgfx::makeRef(prop.m_indices, prop.m_noofIndices * sizeof(uint16_t)));
  330. }
  331. //returns a random number between 0 and 1
  332. float rand01()
  333. {
  334. return rand() / (float)RAND_MAX;
  335. }
  336. class GPUDrivenRendering : public entry::AppI
  337. {
  338. public:
  339. GPUDrivenRendering(const char* _name, const char* _description)
  340. : entry::AppI(_name, _description)
  341. {
  342. }
  343. void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
  344. {
  345. Args args(_argc, _argv);
  346. m_width = _width;
  347. m_height = _height;
  348. //find largest pow of two dims less than backbuffer size
  349. m_hiZwidth = (uint32_t)bx::pow(2.0f, bx::floor(bx::log2(float(m_width ) ) ) );
  350. m_hiZheight = (uint32_t)bx::pow(2.0f, bx::floor(bx::log2(float(m_height) ) ) );
  351. m_debug = BGFX_DEBUG_TEXT;
  352. m_reset = BGFX_RESET_VSYNC;
  353. bgfx::Init init;
  354. init.type = args.m_type;
  355. init.vendorId = args.m_pciId;
  356. init.resolution.width = m_width;
  357. init.resolution.height = m_height;
  358. init.resolution.reset = m_reset;
  359. bgfx::init(init);
  360. // Enable debug text.
  361. bgfx::setDebug(m_debug);
  362. // Create uniforms and samplers.
  363. u_inputRTSize = bgfx::createUniform("u_inputRTSize", bgfx::UniformType::Vec4);
  364. u_cullingConfig = bgfx::createUniform("u_cullingConfig", bgfx::UniformType::Vec4);
  365. u_color = bgfx::createUniform("u_color", bgfx::UniformType::Vec4, 32);
  366. s_texOcclusionDepth = bgfx::createUniform("s_texOcclusionDepth", bgfx::UniformType::Int1);
  367. //create props
  368. {
  369. m_totalInstancesCount = 0;
  370. // Create vertex stream declaration.
  371. PosVertex::init();
  372. m_noofProps = 0;
  373. m_props = new Prop[s_maxNoofProps];
  374. //first create space for some materials
  375. m_materials = new Material[s_maxNoofProps];
  376. m_noofMaterials = 0;
  377. //add a ground plane
  378. {
  379. Prop& prop = m_props[m_noofProps++];
  380. prop.m_renderPass = RenderPass::MainPass;
  381. createCubeMesh(prop);
  382. prop.m_noofInstances = 1;
  383. prop.m_instances = new InstanceData[prop.m_noofInstances];
  384. bx::mtxSRT(prop.m_instances->m_world
  385. , 100.0f, 0.1f, 100.0f
  386. , 0.0f, 0.0f, 0.0f
  387. , 0.0f, 0.0f, 0.0f
  388. );
  389. float temp[4];
  390. setVector4(temp, -0.5f, -0.5f, -0.5f, 1.0f);
  391. bx::vec4MulMtx(prop.m_instances->m_bboxMin, temp, prop.m_instances->m_world);
  392. setVector4(temp, 0.5f, 0.5f, 0.5f, 1.0f);
  393. bx::vec4MulMtx(prop.m_instances->m_bboxMax, temp, prop.m_instances->m_world);
  394. prop.m_materialID = m_noofMaterials;
  395. setVector4(m_materials[prop.m_materialID].m_color, 0.0f, 0.6f, 0.0f, 1.0f);
  396. m_noofMaterials++;
  397. m_totalInstancesCount += prop.m_noofInstances;
  398. }
  399. //add a few instances of the occluding mesh
  400. {
  401. Prop& prop = m_props[m_noofProps++];
  402. prop.m_renderPass = RenderPass::All;
  403. //create prop
  404. createCubeMesh(prop);
  405. //add a few instances of the wall mesh
  406. prop.m_noofInstances = 25;
  407. prop.m_instances = new InstanceData[prop.m_noofInstances];
  408. for (int i = 0; i < prop.m_noofInstances; i++)
  409. {
  410. //calculate world position
  411. bx::mtxSRT(prop.m_instances[i].m_world
  412. , 40.0f, 10.0f, 0.1f
  413. , 0.0f, ( rand01() * 120.0f - 60.0f) * 3.1459f / 180.0f, 0.0f
  414. , rand01() * 100.0f - 50.0f, 5.0f, rand01() * 100.0f - 50.0f
  415. );
  416. //calculate bounding box and transform to world space
  417. float temp[4];
  418. setVector4(temp, -0.5f, -0.5f, -0.5f, 1.0f);
  419. bx::vec4MulMtx(prop.m_instances[i].m_bboxMin, temp, prop.m_instances[i].m_world );
  420. setVector4(temp, 0.5f, 0.5f, 0.5f, 1.0f);
  421. bx::vec4MulMtx(prop.m_instances[i].m_bboxMax, temp, prop.m_instances[i].m_world );
  422. }
  423. //set the material ID. Will be used in the shader to select the material
  424. prop.m_materialID = m_noofMaterials;
  425. //add a "material" for this prop
  426. setVector4(m_materials[prop.m_materialID].m_color, 0.0f, 0.0f, 1.0f, 0.0f);
  427. m_noofMaterials++;
  428. m_totalInstancesCount += prop.m_noofInstances;
  429. }
  430. //add a few "regular" props
  431. {
  432. //add cubes
  433. {
  434. Prop& prop = m_props[m_noofProps++];
  435. prop.m_renderPass = RenderPass::MainPass;
  436. createCubeMesh(prop);
  437. prop.m_noofInstances = 200;
  438. prop.m_instances = new InstanceData[prop.m_noofInstances];
  439. for (int i = 0; i < prop.m_noofInstances; i++)
  440. {
  441. bx::mtxSRT(prop.m_instances[i].m_world
  442. , 2.0f, 2.0f, 2.0f
  443. , 0.0f, 0.0f, 0.0f
  444. , rand01() * 100.0f - 50.0f, 1.0f, rand01() * 100.0f - 50.0f
  445. );
  446. float temp[4];
  447. setVector4(temp, -0.5f, -0.5f, -0.5f, 1.0f);
  448. bx::vec4MulMtx(prop.m_instances[i].m_bboxMin, temp, prop.m_instances[i].m_world);
  449. setVector4(temp, 0.5f, 0.5f, 0.5f, 1.0f);
  450. bx::vec4MulMtx(prop.m_instances[i].m_bboxMax, temp, prop.m_instances[i].m_world);
  451. }
  452. prop.m_materialID = m_noofMaterials;
  453. setVector4(m_materials[prop.m_materialID].m_color, 1.0f, 1.0f, 0.0f, 1.0f);
  454. m_noofMaterials++;
  455. m_totalInstancesCount += prop.m_noofInstances;
  456. }
  457. //add some more cubes
  458. {
  459. Prop& prop = m_props[m_noofProps++];
  460. prop.m_renderPass = RenderPass::MainPass;
  461. createCubeMesh(prop);
  462. prop.m_noofInstances = 300;
  463. prop.m_instances = new InstanceData[prop.m_noofInstances];
  464. for (int i = 0; i < prop.m_noofInstances; i++)
  465. {
  466. bx::mtxSRT(prop.m_instances[i].m_world
  467. , 2.0f, 4.0f, 2.0f
  468. , 0.0f, 0.0f, 0.0f
  469. , rand01() * 100.0f - 50.0f, 2.0f, rand01() * 100.0f - 50.0f
  470. );
  471. float temp[4];
  472. setVector4(temp, -0.5f, -0.5f, -0.5f, 1.0f);
  473. bx::vec4MulMtx(prop.m_instances[i].m_bboxMin, temp, prop.m_instances[i].m_world );
  474. setVector4(temp, 0.5f, 0.5f, 0.5f, 1.0f);
  475. bx::vec4MulMtx(prop.m_instances[i].m_bboxMax, temp, prop.m_instances[i].m_world);
  476. }
  477. prop.m_materialID = m_noofMaterials;
  478. setVector4(m_materials[prop.m_materialID].m_color, 1.0f, 0.0f, 0.0f, 1.0f);
  479. m_noofMaterials++;
  480. m_totalInstancesCount += prop.m_noofInstances;
  481. }
  482. }
  483. }
  484. //Setup Occlusion pass
  485. {
  486. const uint32_t samplerFlags = 0
  487. | BGFX_TEXTURE_RT
  488. | BGFX_TEXTURE_MIN_POINT
  489. | BGFX_TEXTURE_MAG_POINT
  490. | BGFX_TEXTURE_MIP_POINT
  491. | BGFX_TEXTURE_U_CLAMP
  492. | BGFX_TEXTURE_V_CLAMP
  493. ;
  494. // Create buffers for the HiZ pass
  495. m_hiZDepthBuffer = bgfx::createFrameBuffer(uint16_t(m_hiZwidth), uint16_t(m_hiZheight), bgfx::TextureFormat::D32, samplerFlags);
  496. bgfx::TextureHandle buffer = bgfx::createTexture2D(uint16_t(m_hiZwidth), uint16_t(m_hiZheight), true, 1, bgfx::TextureFormat::R32F, BGFX_TEXTURE_COMPUTE_WRITE | samplerFlags);
  497. m_hiZBuffer = bgfx::createFrameBuffer(1, &buffer, true);
  498. //how many mip will the Hi Z buffer have?
  499. m_noofHiZMips = (uint8_t)(1 + bx::floor(bx::log2(float(bx::max(m_hiZwidth, m_hiZheight) ) ) ) );
  500. // Setup compute shader buffers
  501. //The compute shader will write how many unoccluded instances per drawcall there are here
  502. m_drawcallInstanceCounts = bgfx::createDynamicIndexBuffer(s_maxNoofProps, BGFX_BUFFER_INDEX32 | BGFX_BUFFER_COMPUTE_READ_WRITE);
  503. //the compute shader will write the result of the occlusion test for each instance here
  504. m_instancePredicates = bgfx::createDynamicIndexBuffer(s_maxNoofInstances, BGFX_BUFFER_COMPUTE_READ_WRITE);
  505. //bounding box for each instance, will be fed to the compute shader to calculate occlusion
  506. {
  507. bgfx::VertexDecl computeVertexDecl;
  508. computeVertexDecl.begin()
  509. .add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Float)
  510. .end();
  511. //initialise the buffer with the bounding boxes of all instances
  512. const int sizeOfBuffer = 2 * 4 * m_totalInstancesCount;
  513. float* boundingBoxes = new float[sizeOfBuffer];
  514. float* data = boundingBoxes;
  515. for (uint16_t i = 0; i < m_noofProps; i++)
  516. {
  517. Prop& prop = m_props[i];
  518. const uint32_t numInstances = prop.m_noofInstances;
  519. for (uint32_t j = 0; j < numInstances; j++)
  520. {
  521. bx::memCopy(data, prop.m_instances[j].m_bboxMin, 3 * sizeof(float));
  522. data[3] = (float)i; // store the drawcall ID here to avoid creating a separate buffer
  523. data += 4;
  524. bx::memCopy(data, prop.m_instances[j].m_bboxMax, 3 * sizeof(float));
  525. data += 4;
  526. }
  527. }
  528. const bgfx::Memory* mem = bgfx::makeRef(boundingBoxes, sizeof(float) * sizeOfBuffer);
  529. m_instanceBoundingBoxes = bgfx::createDynamicVertexBuffer(mem, computeVertexDecl, BGFX_BUFFER_COMPUTE_READ);
  530. }
  531. //pre and post occlusion culling instance data buffers
  532. {
  533. bgfx::VertexDecl instanceBufferVertexDecl;
  534. instanceBufferVertexDecl.begin()
  535. .add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Float)
  536. .add(bgfx::Attrib::TexCoord1, 4, bgfx::AttribType::Float)
  537. .add(bgfx::Attrib::TexCoord2, 4, bgfx::AttribType::Float)
  538. .add(bgfx::Attrib::TexCoord3, 4, bgfx::AttribType::Float)
  539. .end();
  540. //initialise the buffer with data for all instances
  541. //Currently we only store a world matrix (16 floats)
  542. const int sizeOfBuffer = 16 * m_totalInstancesCount;
  543. float* instanceData = new float[sizeOfBuffer];
  544. float* data = instanceData;
  545. for (uint16_t ii = 0; ii < m_noofProps; ++ii)
  546. {
  547. Prop& prop = m_props[ii];
  548. const uint32_t numInstances = prop.m_noofInstances;
  549. for (uint32_t jj = 0; jj < numInstances; ++jj)
  550. {
  551. bx::memCopy(data, prop.m_instances[jj].m_world, 16 * sizeof(float) );
  552. data[3] = float(ii); // store the drawcall ID here to avoid creating a separate buffer
  553. data += 16;
  554. }
  555. }
  556. const bgfx::Memory* mem = bgfx::makeRef(instanceData, sizeof(float) * sizeOfBuffer);
  557. //pre occlusion buffer
  558. m_instanceBuffer = bgfx::createVertexBuffer(mem, instanceBufferVertexDecl, BGFX_BUFFER_COMPUTE_READ);
  559. //post occlusion buffer
  560. m_culledInstanceBuffer = bgfx::createDynamicVertexBuffer(4 * m_totalInstancesCount, instanceBufferVertexDecl, BGFX_BUFFER_COMPUTE_WRITE);
  561. }
  562. //we use one "drawcall" per prop to render all its instances
  563. m_indirectBuffer = bgfx::createIndirectBuffer(m_noofProps);
  564. // Create programs from shaders for occlusion pass.
  565. m_programOcclusionPass = loadProgram("vs_gdr_render_occlusion", NULL);
  566. m_programDownscaleHiZ = loadProgram("cs_gdr_downscale_hi_z", NULL);
  567. m_programOccludeProps = loadProgram("cs_gdr_occlude_props", NULL);
  568. m_programStreamCompaction = loadProgram("cs_gdr_stream_compaction", NULL);
  569. // Set view RENDER_PASS_HIZ_ID clear state.
  570. bgfx::setViewClear(RENDER_PASS_HIZ_ID
  571. , BGFX_CLEAR_DEPTH
  572. , 0x0
  573. , 1.0f
  574. , 0
  575. );
  576. }
  577. // Setup Main pass
  578. {
  579. // Set view 0 clear state.
  580. bgfx::setViewClear(RENDER_PASS_MAIN_ID
  581. , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
  582. , 0x303030ff
  583. , 1.0f
  584. , 0
  585. );
  586. // Create program from shaders.
  587. m_programMainPass = loadProgram("vs_gdr_instanced_indirect_rendering", "fs_gdr_instanced_indirect_rendering");
  588. }
  589. // Create static vertex buffer for all props.
  590. // Calculate how many vertices/indices the master buffers will need.
  591. uint16_t totalNoofVertices = 0;
  592. uint16_t totalNoofIndices = 0;
  593. for (uint16_t i = 0; i < m_noofProps; i++)
  594. {
  595. Prop& prop = m_props[i];
  596. totalNoofVertices += prop.m_noofVertices;
  597. totalNoofIndices += prop.m_noofIndices;
  598. }
  599. // CPU data to fill the master buffers
  600. m_allPropVerticesDataCPU = new PosVertex[totalNoofVertices];
  601. m_allPropIndicesDataCPU = new uint16_t[totalNoofIndices];
  602. m_indirectBufferDataCPU = new uint32_t[m_noofProps * 3];
  603. // Copy data over to the master buffers
  604. PosVertex* propVerticesData = m_allPropVerticesDataCPU;
  605. uint16_t* propIndicesData = m_allPropIndicesDataCPU;
  606. uint16_t vertexBufferOffset = 0;
  607. uint16_t indexBufferOffset = 0;
  608. for (uint16_t i = 0; i < m_noofProps; i++)
  609. {
  610. Prop& prop = m_props[i];
  611. bx::memCopy(propVerticesData, prop.m_vertices, prop.m_noofVertices * sizeof(PosVertex));
  612. bx::memCopy(propIndicesData, prop.m_indices, prop.m_noofIndices * sizeof(uint16_t));
  613. propVerticesData += prop.m_noofVertices;
  614. propIndicesData += prop.m_noofIndices;
  615. m_indirectBufferDataCPU[ i * 3 ] = prop.m_noofIndices;
  616. m_indirectBufferDataCPU[ i * 3 + 1] = indexBufferOffset;
  617. m_indirectBufferDataCPU[ i * 3 + 2] = vertexBufferOffset;
  618. indexBufferOffset += prop.m_noofIndices;
  619. vertexBufferOffset += prop.m_noofVertices;
  620. }
  621. // Create master vertex buffer
  622. m_allPropsVertexbufferHandle = bgfx::createVertexBuffer(
  623. bgfx::makeRef(m_allPropVerticesDataCPU, totalNoofVertices * PosVertex::ms_decl.getStride())
  624. , PosVertex::ms_decl
  625. );
  626. // Create master index buffer.
  627. m_allPropsIndexbufferHandle = bgfx::createIndexBuffer(
  628. bgfx::makeRef(m_allPropIndicesDataCPU, totalNoofIndices * sizeof(uint16_t) )
  629. );
  630. // Create buffer with const drawcall data which will be copied to the indirect buffer later.
  631. m_indirectBufferData = bgfx::createIndexBuffer(
  632. bgfx::makeRef(m_indirectBufferDataCPU, m_noofProps * 3 * sizeof(uint32_t)),
  633. BGFX_BUFFER_COMPUTE_READ | BGFX_BUFFER_INDEX32
  634. );
  635. m_timeOffset = bx::getHPCounter();
  636. m_useIndirect = true;
  637. imguiCreate();
  638. }
  639. int shutdown() override
  640. {
  641. imguiDestroy();
  642. // Cleanup.
  643. bgfx::destroy(m_programMainPass);
  644. bgfx::destroy(m_programOcclusionPass);
  645. bgfx::destroy(m_programDownscaleHiZ);
  646. bgfx::destroy(m_programOccludeProps);
  647. bgfx::destroy(m_programStreamCompaction);
  648. for (uint16_t i = 0; i < m_noofProps; i++)
  649. {
  650. Prop& prop = m_props[i];
  651. bgfx::destroy(prop.m_indexbufferHandle);
  652. bgfx::destroy(prop.m_vertexbufferHandle);
  653. delete[] prop.m_indices;
  654. delete[] prop.m_vertices;
  655. delete[] prop.m_instances;
  656. }
  657. delete[] m_props;
  658. bgfx::destroy(m_hiZDepthBuffer);
  659. bgfx::destroy(m_hiZBuffer);
  660. bgfx::destroy(m_indirectBuffer);
  661. bgfx::destroy(m_indirectBufferData);
  662. bgfx::destroy(m_instanceBoundingBoxes);
  663. bgfx::destroy(m_drawcallInstanceCounts);
  664. bgfx::destroy(m_instancePredicates);
  665. bgfx::destroy(m_instanceBuffer);
  666. bgfx::destroy(m_culledInstanceBuffer);
  667. bgfx::destroy(m_allPropsVertexbufferHandle);
  668. bgfx::destroy(m_allPropsIndexbufferHandle);
  669. bgfx::destroy(s_texOcclusionDepth);
  670. bgfx::destroy(u_inputRTSize);
  671. bgfx::destroy(u_cullingConfig);
  672. bgfx::destroy(u_color);
  673. delete[] m_allPropVerticesDataCPU;
  674. delete[] m_allPropIndicesDataCPU;
  675. delete[] m_indirectBufferDataCPU;
  676. // Shutdown bgfx.
  677. bgfx::shutdown();
  678. return 0;
  679. }
  680. //renders the occluders to a depth buffer
  681. void renderOcclusionBufferPass()
  682. {
  683. // Setup the occlusion pass projection
  684. bx::mtxProj(m_occlusionProj, 60.0f, float(m_hiZwidth) / float(m_hiZheight), 0.1f, 500.0f, bgfx::getCaps()->homogeneousDepth);
  685. bgfx::setViewTransform(RENDER_PASS_HIZ_ID, m_mainView, m_occlusionProj);
  686. bgfx::setViewFrameBuffer(RENDER_PASS_HIZ_ID, m_hiZDepthBuffer);
  687. bgfx::setViewRect(RENDER_PASS_HIZ_ID, 0, 0, uint16_t(m_hiZwidth), uint16_t(m_hiZheight));
  688. const uint16_t instanceStride = sizeof(InstanceData);
  689. // render all instances of the occluder meshes
  690. for (uint16_t i = 0; i < m_noofProps; i++)
  691. {
  692. Prop& prop = m_props[i];
  693. if (prop.m_renderPass & RenderPass::Occlusion)
  694. {
  695. const uint32_t numInstances = prop.m_noofInstances;
  696. // render instances to the occlusion buffer
  697. if (numInstances == bgfx::getAvailInstanceDataBuffer(numInstances, instanceStride))
  698. {
  699. bgfx::InstanceDataBuffer instanceBuffer;
  700. bgfx::allocInstanceDataBuffer(&instanceBuffer, numInstances, instanceStride);
  701. InstanceData *data = (InstanceData *) instanceBuffer.data;
  702. for (uint32_t j = 0; j < numInstances; j++)
  703. {
  704. //we only need the world matrix for the occlusion pass
  705. bx::memCopy(data->m_world, prop.m_instances[j].m_world, sizeof(data->m_world));
  706. data++;
  707. }
  708. // Set vertex and index buffer.
  709. bgfx::setVertexBuffer(0, prop.m_vertexbufferHandle);
  710. bgfx::setIndexBuffer(prop.m_indexbufferHandle);
  711. // Set instance data buffer.
  712. bgfx::setInstanceDataBuffer(&instanceBuffer);
  713. // Set render states.
  714. bgfx::setState(BGFX_STATE_DEFAULT);
  715. // Submit primitive for rendering to view.
  716. bgfx::submit(RENDER_PASS_HIZ_ID, m_programOcclusionPass);
  717. }
  718. }
  719. }
  720. }
  721. // downscale the occluder depth buffer to create a mipmap chain
  722. void renderDownscalePass()
  723. {
  724. uint32_t width = m_hiZwidth;
  725. uint32_t height = m_hiZheight;
  726. for (uint8_t lod = 0; lod < m_noofHiZMips; ++lod)
  727. {
  728. float coordinateScale = lod > 0 ? 2.0f : 1.0f;
  729. float inputRendertargetSize[4] = { (float)width, (float)height, coordinateScale, coordinateScale };
  730. bgfx::setUniform(u_inputRTSize, inputRendertargetSize);
  731. if (lod > 0)
  732. {
  733. // down scale mip 1 onwards
  734. width /= 2;
  735. height /= 2;
  736. bgfx::setImage(0, getTexture(m_hiZBuffer, 0), lod - 1, bgfx::Access::Read);
  737. bgfx::setImage(1, getTexture(m_hiZBuffer, 0), lod, bgfx::Access::Write);
  738. }
  739. else
  740. {
  741. // copy mip zero over to the hi Z buffer.
  742. // We can't currently use blit as it requires same format and CopyResource is not exposed.
  743. bgfx::setImage(0, getTexture(m_hiZDepthBuffer, 0), 0, bgfx::Access::Read);
  744. bgfx::setImage(1, getTexture(m_hiZBuffer, 0), 0, bgfx::Access::Write);
  745. }
  746. bgfx::dispatch(RENDER_PASS_HIZ_DOWNSCALE_ID, m_programDownscaleHiZ, width/16, height/16);
  747. }
  748. }
  749. // perform the occlusion using the mip chain
  750. void renderOccludePropsPass()
  751. {
  752. // run the computer shader to determine visibility of each instance
  753. bgfx::setTexture(0, s_texOcclusionDepth, bgfx::getTexture(m_hiZBuffer, 0) );
  754. bgfx::setBuffer(1, m_instanceBoundingBoxes, bgfx::Access::Read);
  755. bgfx::setBuffer(2, m_drawcallInstanceCounts, bgfx::Access::ReadWrite);
  756. bgfx::setBuffer(3, m_instancePredicates, bgfx::Access::Write);
  757. float inputRendertargetSize[4] = { (float)m_hiZwidth, (float)m_hiZheight, 1.0f/ m_hiZwidth, 1.0f/ m_hiZheight };
  758. bgfx::setUniform(u_inputRTSize, inputRendertargetSize);
  759. // store a rounded-up, power of two instance count for the stream compaction step
  760. float noofInstancesPowOf2 = bx::pow(2.0f, bx::floor(bx::log(m_totalInstancesCount) / bx::log(2.0f) ) + 1.0f);
  761. float cullingConfig[4] =
  762. {
  763. (float)m_totalInstancesCount,
  764. noofInstancesPowOf2,
  765. (float)m_noofHiZMips,
  766. (float)m_noofProps
  767. };
  768. bgfx::setUniform(u_cullingConfig, cullingConfig);
  769. //set the view/projection transforms so that the compute shader can receive the viewProjection matrix automagically
  770. bgfx::setViewTransform(RENDER_PASS_OCCLUDE_PROPS_ID, m_mainView, m_occlusionProj);
  771. uint16_t groupX = bx::max<uint16_t>(m_totalInstancesCount / 64 + 1, 1);
  772. bgfx::dispatch(RENDER_PASS_OCCLUDE_PROPS_ID, m_programOccludeProps, groupX, 1, 1);
  773. // perform stream compaction to remove occluded instances
  774. // the per drawcall data that is constant (noof indices/vertices and offsets to vertex/index buffers)
  775. bgfx::setBuffer(0, m_indirectBufferData, bgfx::Access::Read);
  776. // instance data for all instances (pre culling)
  777. bgfx::setBuffer(1, m_instanceBuffer, bgfx::Access::Read);
  778. // per instance visibility (output of culling pass)
  779. bgfx::setBuffer(2, m_instancePredicates, bgfx::Access::Read);
  780. // how many instances per drawcall
  781. bgfx::setBuffer(3, m_drawcallInstanceCounts, bgfx::Access::ReadWrite);
  782. // drawcall data that will drive drawIndirect
  783. bgfx::setBuffer(4, m_indirectBuffer, bgfx::Access::ReadWrite);
  784. // culled instance data
  785. bgfx::setBuffer(5, m_culledInstanceBuffer, bgfx::Access::Write);
  786. bgfx::setUniform(u_cullingConfig, cullingConfig);
  787. bgfx::dispatch(RENDER_PASS_COMPACT_STREAM_ID, m_programStreamCompaction, 1, 1, 1);
  788. }
  789. // render the unoccluded props to the screen
  790. void renderMainPass()
  791. {
  792. // Set view and projection matrix for view 0.
  793. {
  794. bgfx::setViewTransform(RENDER_PASS_MAIN_ID, m_mainView, m_mainProj);
  795. // Set view 0 default viewport.
  796. bgfx::setViewRect(RENDER_PASS_MAIN_ID, 0, 0, uint16_t(m_width), uint16_t(m_height));
  797. }
  798. // Set render states.
  799. bgfx::setState(BGFX_STATE_DEFAULT);
  800. const uint16_t instanceStride = sizeof(InstanceData);
  801. // Set "material" data (currently a color only)
  802. bgfx::setUniform(u_color, &m_materials[0].m_color, m_noofMaterials);
  803. if (m_useIndirect)
  804. {
  805. // Set vertex and index buffer.
  806. bgfx::setVertexBuffer(0, m_allPropsVertexbufferHandle);
  807. bgfx::setIndexBuffer( m_allPropsIndexbufferHandle);
  808. // Set instance data buffer.
  809. bgfx::setInstanceDataBuffer(m_culledInstanceBuffer, 0, m_totalInstancesCount );
  810. bgfx::submit(RENDER_PASS_MAIN_ID, m_programMainPass, m_indirectBuffer, 0, m_noofProps);
  811. }
  812. else
  813. {
  814. // render all props using regular instancing
  815. for (uint16_t ii = 0; ii < m_noofProps; ++ii)
  816. {
  817. Prop& prop = m_props[ii];
  818. if (prop.m_renderPass & RenderPass::MainPass)
  819. {
  820. const uint32_t numInstances = prop.m_noofInstances;
  821. if (numInstances == bgfx::getAvailInstanceDataBuffer(numInstances, instanceStride))
  822. {
  823. bgfx::InstanceDataBuffer instanceBuffer;
  824. bgfx::allocInstanceDataBuffer(&instanceBuffer, numInstances, instanceStride);
  825. InstanceData *data = (InstanceData *)instanceBuffer.data;
  826. for (uint32_t jj = 0; jj < numInstances; ++jj)
  827. {
  828. //copy world matrix
  829. bx::memCopy(data->m_world, prop.m_instances[jj].m_world, sizeof(data->m_world) );
  830. //pack the material ID into the world transform
  831. data->m_world[3] = float(prop.m_materialID);
  832. data++;
  833. }
  834. // Set vertex and index buffer.
  835. bgfx::setVertexBuffer(0, prop.m_vertexbufferHandle);
  836. bgfx::setIndexBuffer(prop.m_indexbufferHandle);
  837. // Set instance data buffer.
  838. bgfx::setInstanceDataBuffer(&instanceBuffer);
  839. bgfx::submit(RENDER_PASS_MAIN_ID, m_programMainPass);
  840. }
  841. }
  842. }
  843. }
  844. }
  845. bool update() override
  846. {
  847. if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
  848. {
  849. imguiBeginFrame(m_mouseState.m_mx
  850. , m_mouseState.m_my
  851. , (m_mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
  852. | (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0)
  853. | (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
  854. , m_mouseState.m_mz
  855. , uint16_t(m_width)
  856. , uint16_t(m_height)
  857. );
  858. showExampleDialog(this);
  859. ImGui::SetNextWindowPos(
  860. ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
  861. , ImGuiCond_FirstUseEver
  862. );
  863. ImGui::SetNextWindowSize(
  864. ImVec2(m_width / 5.0f, m_height / 6.0f)
  865. , ImGuiCond_FirstUseEver
  866. );
  867. ImGui::Begin("Settings"
  868. , NULL
  869. , 0
  870. );
  871. ImGui::Checkbox("Use Draw Indirect", &m_useIndirect);
  872. ImGui::End();
  873. imguiEndFrame();
  874. // This dummy draw call is here to make sure that view 0 is cleared
  875. // if no other draw calls are submitted to view 0.
  876. bgfx::touch(0);
  877. int64_t now = bx::getHPCounter();
  878. static int64_t last = now;
  879. const int64_t frameTime = now - last;
  880. last = now;
  881. const double freq = double(bx::getHPFrequency());
  882. const float deltaTimeSec = float(double(frameTime) / freq);
  883. // Camera.
  884. const bool mouseOverGui = ImGui::MouseOverArea();
  885. m_mouse.update(float(m_mouseState.m_mx), float(m_mouseState.m_my), m_mouseState.m_mz, m_width, m_height);
  886. if (!mouseOverGui)
  887. {
  888. if (m_mouseState.m_buttons[entry::MouseButton::Left])
  889. {
  890. m_camera.orbit(m_mouse.m_dx, m_mouse.m_dy);
  891. }
  892. else if (m_mouseState.m_buttons[entry::MouseButton::Right])
  893. {
  894. m_camera.dolly(m_mouse.m_dx + m_mouse.m_dy);
  895. }
  896. else if (0 != m_mouse.m_scroll)
  897. {
  898. m_camera.dolly(float(m_mouse.m_scroll)*0.05f);
  899. }
  900. }
  901. m_camera.update(deltaTimeSec);
  902. // Get renderer capabilities info.
  903. const bgfx::Caps* caps = bgfx::getCaps();
  904. // Check if instancing is supported.
  905. if (0 == (BGFX_CAPS_INSTANCING & caps->supported) )
  906. {
  907. // When instancing is not supported by GPU, implement alternative
  908. // code path that doesn't use instancing.
  909. float time = (float)((bx::getHPCounter() - m_timeOffset) / double(bx::getHPFrequency()));
  910. bool blink = uint32_t(time*3.0f)&1;
  911. bgfx::dbgTextPrintf(0, 0, blink ? 0x1f : 0x01, " Instancing is not supported by GPU. ");
  912. }
  913. else
  914. {
  915. // calculate main view and project matrices as they are typically reused between passes.
  916. m_camera.mtxLookAt(m_mainView);
  917. bx::mtxProj(m_mainProj, 60.0f, float(m_width) / float(m_height), 0.1f, 500.0f, bgfx::getCaps()->homogeneousDepth);
  918. //submit drawcalls for all passes
  919. renderOcclusionBufferPass();
  920. renderDownscalePass();
  921. renderOccludePropsPass();
  922. renderMainPass();
  923. }
  924. // Advance to next frame. Rendering thread will be kicked to
  925. // process submitted rendering primitives.
  926. bgfx::frame();
  927. return true;
  928. }
  929. return false;
  930. }
  931. entry::MouseState m_mouseState;
  932. uint32_t m_width;
  933. uint32_t m_height;
  934. uint32_t m_hiZwidth;
  935. uint32_t m_hiZheight;
  936. uint32_t m_debug;
  937. uint32_t m_reset;
  938. float m_mainView[16];
  939. float m_mainProj[16];
  940. float m_occlusionProj[16];
  941. bgfx::ProgramHandle m_programMainPass;
  942. bgfx::ProgramHandle m_programOcclusionPass;
  943. bgfx::ProgramHandle m_programDownscaleHiZ;
  944. bgfx::ProgramHandle m_programOccludeProps;
  945. bgfx::ProgramHandle m_programStreamCompaction;
  946. bgfx::FrameBufferHandle m_hiZDepthBuffer;
  947. bgfx::FrameBufferHandle m_hiZBuffer;
  948. bgfx::IndirectBufferHandle m_indirectBuffer;
  949. bgfx::VertexBufferHandle m_allPropsVertexbufferHandle;
  950. bgfx::IndexBufferHandle m_allPropsIndexbufferHandle;
  951. bgfx::IndexBufferHandle m_indirectBufferData;
  952. PosVertex* m_allPropVerticesDataCPU;
  953. uint16_t* m_allPropIndicesDataCPU;
  954. uint32_t* m_indirectBufferDataCPU;
  955. bgfx::DynamicVertexBufferHandle m_instanceBoundingBoxes;
  956. bgfx::DynamicIndexBufferHandle m_drawcallInstanceCounts;
  957. bgfx::DynamicIndexBufferHandle m_instancePredicates;
  958. bgfx::VertexBufferHandle m_instanceBuffer;
  959. bgfx::DynamicVertexBufferHandle m_culledInstanceBuffer;
  960. bgfx::UniformHandle s_texOcclusionDepth;
  961. bgfx::UniformHandle u_inputRTSize;
  962. bgfx::UniformHandle u_cullingConfig;
  963. bgfx::UniformHandle u_color;
  964. Prop* m_props;
  965. Material* m_materials;
  966. uint16_t m_noofProps;
  967. uint16_t m_noofMaterials;
  968. uint16_t m_totalInstancesCount;
  969. static const uint16_t s_maxNoofProps = 10;
  970. static const uint16_t s_maxNoofInstances = 2048;
  971. int64_t m_timeOffset;
  972. uint8_t m_noofHiZMips;
  973. bool m_useIndirect;
  974. Camera m_camera;
  975. Mouse m_mouse;
  976. };
  977. } // namespace
  978. ENTRY_IMPLEMENT_MAIN(GPUDrivenRendering, "37-gpudrivenrendering", "GPU-Driven Rendering.");