Gr.cpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <tests/framework/Framework.h>
  6. #include <anki/Gr.h>
  7. #include <anki/core/NativeWindow.h>
  8. #include <anki/core/Config.h>
  9. #include <anki/util/HighRezTimer.h>
  10. #include <anki/core/StagingGpuMemoryManager.h>
  11. #include <anki/resource/TransferGpuAllocator.h>
  12. #include <ctime>
  13. namespace anki
  14. {
  15. const U WIDTH = 1024;
  16. const U HEIGHT = 768;
  17. static const char* VERT_SRC = R"(
  18. out gl_PerVertex
  19. {
  20. vec4 gl_Position;
  21. };
  22. void main()
  23. {
  24. const vec2 POSITIONS[3] = vec2[](vec2(-1.0, 1.0), vec2(0.0, -1.0), vec2(1.0, 1.0));
  25. gl_Position = vec4(POSITIONS[gl_VertexID % 3], 0.0, 1.0);
  26. })";
  27. static const char* VERT_QUAD_STRIP_SRC = R"(
  28. out gl_PerVertex
  29. {
  30. vec4 gl_Position;
  31. };
  32. void main()
  33. {
  34. const vec2 POSITIONS[4] = vec2[](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0));
  35. gl_Position = vec4(POSITIONS[gl_VertexID % 4], 0.0, 1.0);
  36. })";
  37. static const char* VERT_UBO_SRC = R"(
  38. out gl_PerVertex
  39. {
  40. vec4 gl_Position;
  41. };
  42. layout(ANKI_UBO_BINDING(0, 0)) uniform u0_
  43. {
  44. vec4 u_color[3];
  45. };
  46. layout(ANKI_UBO_BINDING(0, 1)) uniform u1_
  47. {
  48. vec4 u_rotation2d;
  49. };
  50. layout(location = 0) out vec3 out_color;
  51. void main()
  52. {
  53. out_color = u_color[gl_VertexID].rgb;
  54. const vec2 POSITIONS[3] = vec2[](vec2(-1.0, 1.0), vec2(0.0, -1.0), vec2(1.0, 1.0));
  55. mat2 rot = mat2(
  56. u_rotation2d.x, u_rotation2d.y, u_rotation2d.z, u_rotation2d.w);
  57. vec2 pos = rot * POSITIONS[gl_VertexID % 3];
  58. gl_Position = vec4(pos, 0.0, 1.0);
  59. })";
  60. static const char* VERT_INP_SRC = R"(
  61. layout(location = 0) in vec3 in_position;
  62. layout(location = 1) in vec3 in_color0;
  63. layout(location = 2) in vec3 in_color1;
  64. out gl_PerVertex
  65. {
  66. vec4 gl_Position;
  67. };
  68. layout(location = 0) out vec3 out_color0;
  69. layout(location = 1) out vec3 out_color1;
  70. void main()
  71. {
  72. gl_Position = vec4(in_position, 1.0);
  73. out_color0 = in_color0;
  74. out_color1 = in_color1;
  75. })";
  76. static const char* VERT_QUAD_SRC = R"(
  77. out gl_PerVertex
  78. {
  79. vec4 gl_Position;
  80. };
  81. layout(location = 0) out vec2 out_uv;
  82. void main()
  83. {
  84. const vec2 POSITIONS[6] =
  85. vec2[](vec2(-1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, -1.0),
  86. vec2(1.0, -1.0), vec2(1.0, 1.0), vec2(-1.0, 1.0));
  87. gl_Position = vec4(POSITIONS[gl_VertexID], 0.0, 1.0);
  88. out_uv = POSITIONS[gl_VertexID] / 2.0 + 0.5;
  89. })";
  90. static const char* VERT_MRT_SRC = R"(
  91. out gl_PerVertex
  92. {
  93. vec4 gl_Position;
  94. };
  95. layout(location = 0) in vec3 in_pos;
  96. layout(ANKI_UBO_BINDING(0, 0), std140, row_major) uniform u0_
  97. {
  98. mat4 u_mvp;
  99. };
  100. void main()
  101. {
  102. gl_Position = u_mvp * vec4(in_pos, 1.0);
  103. })";
  104. static const char* FRAG_SRC = R"(layout (location = 0) out vec4 out_color;
  105. void main()
  106. {
  107. out_color = vec4(0.5);
  108. })";
  109. static const char* FRAG_UBO_SRC = R"(layout (location = 0) out vec4 out_color;
  110. layout(location = 0) in vec3 in_color;
  111. void main()
  112. {
  113. out_color = vec4(in_color, 1.0);
  114. })";
  115. static const char* FRAG_INP_SRC = R"(layout (location = 0) out vec4 out_color;
  116. layout(location = 0) in vec3 in_color0;
  117. layout(location = 1) in vec3 in_color1;
  118. void main()
  119. {
  120. out_color = vec4(in_color0 + in_color1, 1.0);
  121. })";
  122. static const char* FRAG_TEX_SRC = R"(layout (location = 0) out vec4 out_color;
  123. layout(location = 0) in vec2 in_uv;
  124. layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex0;
  125. void main()
  126. {
  127. out_color = texture(u_tex0, in_uv);
  128. })";
  129. static const char* FRAG_2TEX_SRC = R"(layout (location = 0) out vec4 out_color;
  130. layout(location = 0) in vec2 in_uv;
  131. layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex0;
  132. layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_tex1;
  133. ANKI_USING_FRAG_COORD(768)
  134. void main()
  135. {
  136. if(anki_fragCoord.x < 1024 / 2)
  137. {
  138. if(anki_fragCoord.y < 768 / 2)
  139. {
  140. vec2 uv = in_uv * 2.0;
  141. out_color = textureLod(u_tex0, uv, 0.0);
  142. }
  143. else
  144. {
  145. vec2 uv = in_uv * 2.0 - vec2(0.0, 1.0);
  146. out_color = textureLod(u_tex0, uv, 1.0);
  147. }
  148. }
  149. else
  150. {
  151. if(anki_fragCoord.y < 768 / 2)
  152. {
  153. vec2 uv = in_uv * 2.0 - vec2(1.0, 0.0);
  154. out_color = textureLod(u_tex1, uv, 0.0);
  155. }
  156. else
  157. {
  158. vec2 uv = in_uv * 2.0 - vec2(1.0, 1.0);
  159. out_color = textureLod(u_tex1, uv, 1.0);
  160. }
  161. }
  162. })";
  163. static const char* FRAG_TEX3D_SRC = R"(layout (location = 0) out vec4 out_color;
  164. layout(ANKI_UBO_BINDING(0, 0)) uniform u0_
  165. {
  166. vec4 u_uv;
  167. };
  168. layout(ANKI_TEX_BINDING(0, 0)) uniform sampler3D u_tex;
  169. void main()
  170. {
  171. out_color = textureLod(u_tex, u_uv.xyz, u_uv.w);
  172. })";
  173. static const char* FRAG_MRT_SRC = R"(layout (location = 0) out vec4 out_color0;
  174. layout (location = 1) out vec4 out_color1;
  175. layout(ANKI_UBO_BINDING(0, 1), std140) uniform u1_
  176. {
  177. vec4 u_color0;
  178. vec4 u_color1;
  179. };
  180. void main()
  181. {
  182. out_color0 = u_color0;
  183. out_color1 = u_color1;
  184. })";
  185. static const char* FRAG_MRT2_SRC = R"(layout (location = 0) out vec4 out_color;
  186. layout(location = 0) in vec2 in_uv;
  187. layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex0;
  188. layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_tex1;
  189. void main()
  190. {
  191. vec2 uv = in_uv;
  192. #ifdef ANKI_VK
  193. uv.y = 1.0 - uv.y;
  194. #endif
  195. float factor = uv.x;
  196. vec3 col0 = texture(u_tex0, uv).rgb;
  197. vec3 col1 = texture(u_tex1, uv).rgb;
  198. out_color = vec4(col1 + col0, 1.0);
  199. })";
  200. static const char* FRAG_SIMPLE_TEX_SRC = R"(
  201. layout (location = 0) out vec4 out_color;
  202. layout(location = 0) in vec2 in_uv;
  203. layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex0;
  204. void main()
  205. {
  206. out_color = textureLod(u_tex0, in_uv, 1.0);
  207. })";
  208. static const char* COMP_WRITE_IMAGE_SRC = R"(
  209. layout(ANKI_IMAGE_BINDING(0, 0), rgba8) writeonly uniform image2D u_img;
  210. layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
  211. layout(ANKI_SS_BINDING(1, 0)) buffer ss1_
  212. {
  213. vec4 u_color;
  214. };
  215. void main()
  216. {
  217. imageStore(u_img, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), u_color);
  218. })";
  219. static NativeWindow* win = nullptr;
  220. static GrManager* gr = nullptr;
  221. static StagingGpuMemoryManager* stagingMem = nullptr;
  222. #define COMMON_BEGIN() \
  223. stagingMem = new StagingGpuMemoryManager(); \
  224. Config cfg; \
  225. cfg.set("width", WIDTH); \
  226. cfg.set("height", HEIGHT); \
  227. cfg.set("window.debugContext", true); \
  228. cfg.set("window.vsync", false); \
  229. win = createWindow(cfg); \
  230. gr = createGrManager(cfg, win); \
  231. ANKI_TEST_EXPECT_NO_ERR(stagingMem->init(gr, Config())); \
  232. TransferGpuAllocator* transfAlloc = new TransferGpuAllocator(); \
  233. ANKI_TEST_EXPECT_NO_ERR(transfAlloc->init(128_MB, gr, gr->getAllocator())); \
  234. {
  235. #define COMMON_END() \
  236. } \
  237. gr->finish(); \
  238. delete transfAlloc; \
  239. delete stagingMem; \
  240. GrManager::deleteInstance(gr); \
  241. delete win; \
  242. win = nullptr; \
  243. gr = nullptr; \
  244. stagingMem = nullptr;
  245. static void* setUniforms(PtrSize size, CommandBufferPtr& cmdb, U set, U binding)
  246. {
  247. StagingGpuMemoryToken token;
  248. void* ptr = stagingMem->allocateFrame(size, StagingGpuMemoryType::UNIFORM, token);
  249. cmdb->bindUniformBuffer(set, binding, token.m_buffer, token.m_offset, token.m_range);
  250. return ptr;
  251. }
  252. static void* setStorage(PtrSize size, CommandBufferPtr& cmdb, U set, U binding)
  253. {
  254. StagingGpuMemoryToken token;
  255. void* ptr = stagingMem->allocateFrame(size, StagingGpuMemoryType::STORAGE, token);
  256. cmdb->bindStorageBuffer(set, binding, token.m_buffer, token.m_offset, token.m_range);
  257. return ptr;
  258. }
  259. #define SET_UNIFORMS(type_, size_, cmdb_, set_, binding_) static_cast<type_>(setUniforms(size_, cmdb_, set_, binding_))
  260. #define SET_STORAGE(type_, size_, cmdb_, set_, binding_) static_cast<type_>(setStorage(size_, cmdb_, set_, binding_))
  261. #define UPLOAD_TEX_SURFACE(cmdb_, tex_, surf_, ptr_, size_, handle_) \
  262. do \
  263. { \
  264. ANKI_TEST_EXPECT_NO_ERR(transfAlloc->allocate(size_, handle_)); \
  265. void* f = handle_.getMappedMemory(); \
  266. memcpy(f, ptr_, size_); \
  267. TextureViewPtr view = gr->newTextureView(TextureViewInitInfo(tex_, surf_)); \
  268. cmdb_->copyBufferToTextureView(handle_.getBuffer(), handle_.getOffset(), handle_.getRange(), view); \
  269. } while(0)
  270. #define UPLOAD_TEX_VOL(cmdb_, tex_, vol_, ptr_, size_, handle_) \
  271. do \
  272. { \
  273. ANKI_TEST_EXPECT_NO_ERR(transfAlloc->allocate(size_, handle_)); \
  274. void* f = handle_.getMappedMemory(); \
  275. memcpy(f, ptr_, size_); \
  276. TextureViewPtr view = gr->newTextureView(TextureViewInitInfo(tex_, vol_)); \
  277. cmdb_->copyBufferToTextureView(handle_.getBuffer(), handle_.getOffset(), handle_.getRange(), view); \
  278. } while(0)
  279. const PixelFormat DS_FORMAT = PixelFormat(ComponentFormat::D24S8, TransformFormat::UNORM);
  280. static ShaderProgramPtr createProgram(CString vertSrc, CString fragSrc, GrManager& gr)
  281. {
  282. ShaderPtr vert = gr.newShader({ShaderType::VERTEX, vertSrc});
  283. ShaderPtr frag = gr.newShader({ShaderType::FRAGMENT, fragSrc});
  284. ShaderProgramInitInfo inf;
  285. inf.m_shaders[ShaderType::VERTEX] = vert;
  286. inf.m_shaders[ShaderType::FRAGMENT] = frag;
  287. return gr.newShaderProgram(inf);
  288. }
  289. static FramebufferPtr createDefaultFb(GrManager& gr)
  290. {
  291. FramebufferInitInfo fbinit;
  292. fbinit.m_colorAttachmentCount = 1;
  293. fbinit.m_colorAttachments[0].m_clearValue.m_colorf = {{1.0, 0.0, 1.0, 1.0}};
  294. return gr.newFramebuffer(fbinit);
  295. }
  296. static void createCube(GrManager& gr, BufferPtr& verts, BufferPtr& indices)
  297. {
  298. static const Array<F32, 8 * 3> pos = {
  299. {1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1}};
  300. static const Array<U16, 6 * 2 * 3> idx = {
  301. {0, 1, 3, 3, 1, 2, 1, 5, 6, 1, 6, 2, 7, 4, 0, 7, 0, 3, 6, 5, 7, 7, 5, 4, 0, 4, 5, 0, 5, 1, 3, 2, 6, 3, 6, 7}};
  302. verts = gr.newBuffer(BufferInitInfo(sizeof(pos), BufferUsageBit::VERTEX, BufferMapAccessBit::WRITE));
  303. void* mapped = verts->map(0, sizeof(pos), BufferMapAccessBit::WRITE);
  304. memcpy(mapped, &pos[0], sizeof(pos));
  305. verts->unmap();
  306. indices = gr.newBuffer(BufferInitInfo(sizeof(idx), BufferUsageBit::INDEX, BufferMapAccessBit::WRITE));
  307. mapped = indices->map(0, sizeof(idx), BufferMapAccessBit::WRITE);
  308. memcpy(mapped, &idx[0], sizeof(idx));
  309. indices->unmap();
  310. }
  311. ANKI_TEST(Gr, GrManager){COMMON_BEGIN() COMMON_END()}
  312. ANKI_TEST(Gr, Shader)
  313. {
  314. COMMON_BEGIN()
  315. ShaderPtr shader = gr->newShader({ShaderType::FRAGMENT, FRAG_MRT_SRC});
  316. COMMON_END()
  317. }
  318. ANKI_TEST(Gr, ShaderProgram)
  319. {
  320. COMMON_BEGIN()
  321. ShaderProgramPtr ppline = createProgram(VERT_SRC, FRAG_SRC, *gr);
  322. COMMON_END()
  323. }
  324. ANKI_TEST(Gr, ClearScreen)
  325. {
  326. COMMON_BEGIN()
  327. ANKI_TEST_LOGI("Expect to see a magenta background");
  328. FramebufferPtr fb = createDefaultFb(*gr);
  329. U iterations = 100;
  330. while(iterations--)
  331. {
  332. HighRezTimer timer;
  333. timer.start();
  334. gr->beginFrame();
  335. CommandBufferInitInfo cinit;
  336. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  337. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  338. cmdb->beginRenderPass(fb, {}, {});
  339. cmdb->endRenderPass();
  340. cmdb->flush();
  341. gr->swapBuffers();
  342. timer.stop();
  343. const F32 TICK = 1.0 / 30.0;
  344. if(timer.getElapsedTime() < TICK)
  345. {
  346. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  347. }
  348. }
  349. COMMON_END()
  350. }
  351. ANKI_TEST(Gr, SimpleDrawcall)
  352. {
  353. COMMON_BEGIN()
  354. ANKI_TEST_LOGI("Expect to see a grey triangle");
  355. ShaderProgramPtr prog = createProgram(VERT_SRC, FRAG_SRC, *gr);
  356. FramebufferPtr fb = createDefaultFb(*gr);
  357. const U ITERATIONS = 200;
  358. for(U i = 0; i < ITERATIONS; ++i)
  359. {
  360. HighRezTimer timer;
  361. timer.start();
  362. gr->beginFrame();
  363. CommandBufferInitInfo cinit;
  364. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
  365. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  366. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  367. cmdb->bindShaderProgram(prog);
  368. cmdb->beginRenderPass(fb, {}, {});
  369. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
  370. cmdb->endRenderPass();
  371. cmdb->flush();
  372. gr->swapBuffers();
  373. timer.stop();
  374. const F32 TICK = 1.0 / 30.0;
  375. if(timer.getElapsedTime() < TICK)
  376. {
  377. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  378. }
  379. }
  380. COMMON_END()
  381. }
  382. ANKI_TEST(Gr, ViewportAndScissor)
  383. {
  384. COMMON_BEGIN()
  385. ANKI_TEST_LOGI("Expect to see a grey quad appearing in the 4 corners. The clear color will change and affect only"
  386. "the area around the quad");
  387. ShaderProgramPtr prog = createProgram(VERT_QUAD_STRIP_SRC, FRAG_SRC, *gr);
  388. srand(time(nullptr));
  389. Array<FramebufferPtr, 4> fb;
  390. for(FramebufferPtr& f : fb)
  391. {
  392. FramebufferInitInfo fbinit;
  393. fbinit.m_colorAttachmentCount = 1;
  394. fbinit.m_colorAttachments[0].m_clearValue.m_colorf = {{randFloat(1.0), randFloat(1.0), randFloat(1.0), 1.0}};
  395. f = gr->newFramebuffer(fbinit);
  396. }
  397. static const Array2d<U, 4, 4> VIEWPORTS = {{{{0, 0, WIDTH / 2, HEIGHT / 2}},
  398. {{WIDTH / 2, 0, WIDTH / 2, HEIGHT / 2}},
  399. {{WIDTH / 2, HEIGHT / 2, WIDTH / 2, HEIGHT / 2}},
  400. {{0, HEIGHT / 2, WIDTH / 2, HEIGHT / 2}}}};
  401. const U ITERATIONS = 400;
  402. const U SCISSOR_MARGIN = 20;
  403. const U RENDER_AREA_MARGIN = 10;
  404. for(U i = 0; i < ITERATIONS; ++i)
  405. {
  406. HighRezTimer timer;
  407. timer.start();
  408. gr->beginFrame();
  409. CommandBufferInitInfo cinit;
  410. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  411. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  412. U idx = (i / 30) % 4;
  413. auto vp = VIEWPORTS[idx];
  414. cmdb->setViewport(vp[0], vp[1], vp[2], vp[3]);
  415. cmdb->setScissor(
  416. vp[0] + SCISSOR_MARGIN, vp[1] + SCISSOR_MARGIN, vp[2] - SCISSOR_MARGIN * 2, vp[3] - SCISSOR_MARGIN * 2);
  417. cmdb->bindShaderProgram(prog);
  418. cmdb->beginRenderPass(fb[i % 4],
  419. {},
  420. {},
  421. vp[0] + RENDER_AREA_MARGIN,
  422. vp[1] + RENDER_AREA_MARGIN,
  423. vp[2] - RENDER_AREA_MARGIN * 2,
  424. vp[3] - RENDER_AREA_MARGIN * 2);
  425. cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4);
  426. cmdb->endRenderPass();
  427. cmdb->flush();
  428. gr->swapBuffers();
  429. timer.stop();
  430. const F32 TICK = 1.0 / 30.0;
  431. if(timer.getElapsedTime() < TICK)
  432. {
  433. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  434. }
  435. }
  436. COMMON_END()
  437. }
  438. ANKI_TEST(Gr, ViewportAndScissorOffscreen)
  439. {
  440. srand(time(nullptr));
  441. COMMON_BEGIN()
  442. ANKI_TEST_LOGI("Expect to see a grey quad appearing in the 4 corners. "
  443. "Around that quad is a border that changes color. "
  444. "The quads appear counter-clockwise");
  445. ShaderProgramPtr prog = createProgram(VERT_QUAD_STRIP_SRC, FRAG_SRC, *gr);
  446. ShaderProgramPtr blitProg = createProgram(VERT_QUAD_SRC, FRAG_TEX_SRC, *gr);
  447. const PixelFormat COL_FORMAT = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  448. const U RT_WIDTH = 32;
  449. const U RT_HEIGHT = 16;
  450. TextureInitInfo init;
  451. init.m_depth = 1;
  452. init.m_format = COL_FORMAT;
  453. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE;
  454. init.m_height = RT_HEIGHT;
  455. init.m_width = RT_WIDTH;
  456. init.m_mipmapsCount = 1;
  457. init.m_depth = 1;
  458. init.m_layerCount = 1;
  459. init.m_samples = 1;
  460. init.m_type = TextureType::_2D;
  461. TexturePtr rt = gr->newTexture(init);
  462. TextureViewInitInfo viewInit(rt);
  463. TextureViewPtr texView = gr->newTextureView(viewInit);
  464. Array<FramebufferPtr, 4> fb;
  465. for(FramebufferPtr& f : fb)
  466. {
  467. TextureViewInitInfo viewInf(rt);
  468. TextureViewPtr view = gr->newTextureView(viewInf);
  469. FramebufferInitInfo fbinit;
  470. fbinit.m_colorAttachmentCount = 1;
  471. fbinit.m_colorAttachments[0].m_clearValue.m_colorf = {{randFloat(1.0), randFloat(1.0), randFloat(1.0), 1.0}};
  472. fbinit.m_colorAttachments[0].m_textureView = view;
  473. f = gr->newFramebuffer(fbinit);
  474. }
  475. FramebufferPtr defaultFb = createDefaultFb(*gr);
  476. SamplerInitInfo samplerInit;
  477. samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
  478. samplerInit.m_mipmapFilter = SamplingFilter::BASE;
  479. SamplerPtr sampler = gr->newSampler(samplerInit);
  480. static const Array2d<U, 4, 4> VIEWPORTS = {{{{0, 0, RT_WIDTH / 2, RT_HEIGHT / 2}},
  481. {{RT_WIDTH / 2, 0, RT_WIDTH / 2, RT_HEIGHT / 2}},
  482. {{RT_WIDTH / 2, RT_HEIGHT / 2, RT_WIDTH / 2, RT_HEIGHT / 2}},
  483. {{0, RT_HEIGHT / 2, RT_WIDTH / 2, RT_HEIGHT / 2}}}};
  484. const U ITERATIONS = 400;
  485. const U SCISSOR_MARGIN = 2;
  486. const U RENDER_AREA_MARGIN = 1;
  487. for(U i = 0; i < ITERATIONS; ++i)
  488. {
  489. HighRezTimer timer;
  490. timer.start();
  491. gr->beginFrame();
  492. if(i == 0)
  493. {
  494. CommandBufferInitInfo cinit;
  495. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  496. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  497. cmdb->setViewport(0, 0, RT_WIDTH, RT_HEIGHT);
  498. cmdb->setTextureSurfaceBarrier(rt,
  499. TextureUsageBit::NONE,
  500. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  501. TextureSurfaceInfo(0, 0, 0, 0));
  502. cmdb->beginRenderPass(fb[0], {{TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE}}, {});
  503. cmdb->endRenderPass();
  504. cmdb->setTextureSurfaceBarrier(rt,
  505. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  506. TextureUsageBit::SAMPLED_FRAGMENT,
  507. TextureSurfaceInfo(0, 0, 0, 0));
  508. cmdb->flush();
  509. }
  510. CommandBufferInitInfo cinit;
  511. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  512. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  513. // Draw offscreen
  514. cmdb->setTextureSurfaceBarrier(rt,
  515. TextureUsageBit::SAMPLED_FRAGMENT,
  516. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  517. TextureSurfaceInfo(0, 0, 0, 0));
  518. auto vp = VIEWPORTS[(i / 30) % 4];
  519. cmdb->setViewport(vp[0], vp[1], vp[2], vp[3]);
  520. cmdb->setScissor(
  521. vp[0] + SCISSOR_MARGIN, vp[1] + SCISSOR_MARGIN, vp[2] - SCISSOR_MARGIN * 2, vp[3] - SCISSOR_MARGIN * 2);
  522. cmdb->bindShaderProgram(prog);
  523. cmdb->beginRenderPass(fb[i % 4],
  524. {{TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE}},
  525. {},
  526. vp[0] + RENDER_AREA_MARGIN,
  527. vp[1] + RENDER_AREA_MARGIN,
  528. vp[2] - RENDER_AREA_MARGIN * 2,
  529. vp[3] - RENDER_AREA_MARGIN * 2);
  530. cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4);
  531. cmdb->endRenderPass();
  532. // Draw onscreen
  533. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  534. cmdb->setScissor(0, 0, WIDTH, HEIGHT);
  535. cmdb->bindShaderProgram(blitProg);
  536. cmdb->setTextureSurfaceBarrier(rt,
  537. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  538. TextureUsageBit::SAMPLED_FRAGMENT,
  539. TextureSurfaceInfo(0, 0, 0, 0));
  540. cmdb->bindTextureAndSampler(0, 0, texView, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  541. cmdb->beginRenderPass(defaultFb, {}, {});
  542. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  543. cmdb->endRenderPass();
  544. cmdb->flush();
  545. gr->swapBuffers();
  546. timer.stop();
  547. const F32 TICK = 1.0 / 30.0;
  548. if(timer.getElapsedTime() < TICK)
  549. {
  550. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  551. }
  552. }
  553. COMMON_END()
  554. }
  555. ANKI_TEST(Gr, Buffer)
  556. {
  557. COMMON_BEGIN()
  558. BufferPtr a = gr->newBuffer(BufferInitInfo(512, BufferUsageBit::UNIFORM_ALL, BufferMapAccessBit::NONE));
  559. BufferPtr b = gr->newBuffer(
  560. BufferInitInfo(64, BufferUsageBit::STORAGE_ALL, BufferMapAccessBit::WRITE | BufferMapAccessBit::READ));
  561. void* ptr = b->map(0, 64, BufferMapAccessBit::WRITE);
  562. ANKI_TEST_EXPECT_NEQ(ptr, nullptr);
  563. U8 ptr2[64];
  564. memset(ptr, 0xCC, 64);
  565. memset(ptr2, 0xCC, 64);
  566. b->unmap();
  567. ptr = b->map(0, 64, BufferMapAccessBit::READ);
  568. ANKI_TEST_EXPECT_NEQ(ptr, nullptr);
  569. ANKI_TEST_EXPECT_EQ(memcmp(ptr, ptr2, 64), 0);
  570. b->unmap();
  571. COMMON_END()
  572. }
  573. ANKI_TEST(Gr, DrawWithUniforms)
  574. {
  575. COMMON_BEGIN()
  576. // A non-uploaded buffer
  577. BufferPtr b =
  578. gr->newBuffer(BufferInitInfo(sizeof(Vec4) * 3, BufferUsageBit::UNIFORM_ALL, BufferMapAccessBit::WRITE));
  579. Vec4* ptr = static_cast<Vec4*>(b->map(0, sizeof(Vec4) * 3, BufferMapAccessBit::WRITE));
  580. ANKI_TEST_EXPECT_NEQ(ptr, nullptr);
  581. ptr[0] = Vec4(1.0, 0.0, 0.0, 0.0);
  582. ptr[1] = Vec4(0.0, 1.0, 0.0, 0.0);
  583. ptr[2] = Vec4(0.0, 0.0, 1.0, 0.0);
  584. b->unmap();
  585. // Progm
  586. ShaderProgramPtr prog = createProgram(VERT_UBO_SRC, FRAG_UBO_SRC, *gr);
  587. // FB
  588. FramebufferPtr fb = createDefaultFb(*gr);
  589. const U ITERATION_COUNT = 100;
  590. U iterations = ITERATION_COUNT;
  591. while(iterations--)
  592. {
  593. HighRezTimer timer;
  594. timer.start();
  595. gr->beginFrame();
  596. CommandBufferInitInfo cinit;
  597. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
  598. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  599. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  600. cmdb->bindShaderProgram(prog);
  601. cmdb->beginRenderPass(fb, {}, {});
  602. cmdb->bindUniformBuffer(0, 0, b, 0, MAX_PTR_SIZE);
  603. // Uploaded buffer
  604. Vec4* rotMat = SET_UNIFORMS(Vec4*, sizeof(Vec4), cmdb, 0, 1);
  605. F32 angle = toRad(360.0f / ITERATION_COUNT * iterations);
  606. (*rotMat)[0] = cos(angle);
  607. (*rotMat)[1] = -sin(angle);
  608. (*rotMat)[2] = sin(angle);
  609. (*rotMat)[3] = cos(angle);
  610. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
  611. cmdb->endRenderPass();
  612. cmdb->flush();
  613. gr->swapBuffers();
  614. timer.stop();
  615. const F32 TICK = 1.0 / 30.0;
  616. if(timer.getElapsedTime() < TICK)
  617. {
  618. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  619. }
  620. }
  621. COMMON_END()
  622. }
  623. ANKI_TEST(Gr, DrawWithVertex)
  624. {
  625. COMMON_BEGIN()
  626. // The buffers
  627. struct Vert
  628. {
  629. Vec3 m_pos;
  630. Array<U8, 4> m_color;
  631. };
  632. static_assert(sizeof(Vert) == sizeof(Vec4), "See file");
  633. BufferPtr b = gr->newBuffer(BufferInitInfo(sizeof(Vert) * 3, BufferUsageBit::VERTEX, BufferMapAccessBit::WRITE));
  634. Vert* ptr = static_cast<Vert*>(b->map(0, sizeof(Vert) * 3, BufferMapAccessBit::WRITE));
  635. ANKI_TEST_EXPECT_NEQ(ptr, nullptr);
  636. ptr[0].m_pos = Vec3(-1.0, 1.0, 0.0);
  637. ptr[1].m_pos = Vec3(0.0, -1.0, 0.0);
  638. ptr[2].m_pos = Vec3(1.0, 1.0, 0.0);
  639. ptr[0].m_color = {{255, 0, 0}};
  640. ptr[1].m_color = {{0, 255, 0}};
  641. ptr[2].m_color = {{0, 0, 255}};
  642. b->unmap();
  643. BufferPtr c = gr->newBuffer(BufferInitInfo(sizeof(Vec3) * 3, BufferUsageBit::VERTEX, BufferMapAccessBit::WRITE));
  644. Vec3* otherColor = static_cast<Vec3*>(c->map(0, sizeof(Vec3) * 3, BufferMapAccessBit::WRITE));
  645. otherColor[0] = Vec3(0.0, 1.0, 1.0);
  646. otherColor[1] = Vec3(1.0, 0.0, 1.0);
  647. otherColor[2] = Vec3(1.0, 1.0, 0.0);
  648. c->unmap();
  649. // Prog
  650. ShaderProgramPtr prog = createProgram(VERT_INP_SRC, FRAG_INP_SRC, *gr);
  651. // FB
  652. FramebufferPtr fb = createDefaultFb(*gr);
  653. U iterations = 100;
  654. while(iterations--)
  655. {
  656. HighRezTimer timer;
  657. timer.start();
  658. gr->beginFrame();
  659. CommandBufferInitInfo cinit;
  660. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
  661. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  662. cmdb->bindVertexBuffer(0, b, 0, sizeof(Vert));
  663. cmdb->bindVertexBuffer(1, c, 0, sizeof(Vec3));
  664. cmdb->setVertexAttribute(0, 0, PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT), 0);
  665. cmdb->setVertexAttribute(1, 0, PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM), sizeof(Vec3));
  666. cmdb->setVertexAttribute(2, 1, PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT), 0);
  667. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  668. cmdb->setPolygonOffset(0.0, 0.0);
  669. cmdb->bindShaderProgram(prog);
  670. cmdb->beginRenderPass(fb, {}, {});
  671. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
  672. cmdb->endRenderPass();
  673. cmdb->flush();
  674. gr->swapBuffers();
  675. timer.stop();
  676. const F32 TICK = 1.0 / 30.0;
  677. if(timer.getElapsedTime() < TICK)
  678. {
  679. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  680. }
  681. }
  682. COMMON_END()
  683. }
  684. ANKI_TEST(Gr, Sampler)
  685. {
  686. COMMON_BEGIN()
  687. SamplerInitInfo init;
  688. SamplerPtr b = gr->newSampler(init);
  689. COMMON_END()
  690. }
  691. ANKI_TEST(Gr, Texture)
  692. {
  693. COMMON_BEGIN()
  694. TextureInitInfo init;
  695. init.m_depth = 1;
  696. init.m_format = PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM);
  697. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT;
  698. init.m_height = 4;
  699. init.m_width = 4;
  700. init.m_mipmapsCount = 2;
  701. init.m_depth = 1;
  702. init.m_layerCount = 1;
  703. init.m_samples = 1;
  704. init.m_type = TextureType::_2D;
  705. TexturePtr b = gr->newTexture(init);
  706. TextureViewInitInfo view(b);
  707. TextureViewPtr v = gr->newTextureView(view);
  708. COMMON_END()
  709. }
  710. ANKI_TEST(Gr, DrawWithTexture)
  711. {
  712. COMMON_BEGIN()
  713. //
  714. // Create sampler
  715. //
  716. SamplerInitInfo samplerInit;
  717. samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
  718. samplerInit.m_mipmapFilter = SamplingFilter::LINEAR;
  719. samplerInit.m_repeat = false;
  720. SamplerPtr sampler = gr->newSampler(samplerInit);
  721. //
  722. // Create texture A
  723. //
  724. TextureInitInfo init;
  725. init.m_depth = 1;
  726. init.m_format = PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM);
  727. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION;
  728. init.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
  729. init.m_height = 2;
  730. init.m_width = 2;
  731. init.m_mipmapsCount = 2;
  732. init.m_samples = 1;
  733. init.m_depth = 1;
  734. init.m_layerCount = 1;
  735. init.m_type = TextureType::_2D;
  736. TexturePtr a = gr->newTexture(init);
  737. TextureViewPtr aView = gr->newTextureView(TextureViewInitInfo(a));
  738. //
  739. // Create texture B
  740. //
  741. init.m_width = 4;
  742. init.m_height = 4;
  743. init.m_mipmapsCount = 3;
  744. init.m_usage =
  745. TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::GENERATE_MIPMAPS;
  746. init.m_initialUsage = TextureUsageBit::NONE;
  747. TexturePtr b = gr->newTexture(init);
  748. TextureViewPtr bView = gr->newTextureView(TextureViewInitInfo(b));
  749. //
  750. // Upload all textures
  751. //
  752. Array<U8, 2 * 2 * 3> mip0 = {{255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 0, 255}};
  753. Array<U8, 3> mip1 = {{128, 128, 128}};
  754. Array<U8, 4 * 4 * 3> bmip0 = {{255,
  755. 0,
  756. 0,
  757. 0,
  758. 255,
  759. 0,
  760. 0,
  761. 0,
  762. 255,
  763. 255,
  764. 255,
  765. 0,
  766. 255,
  767. 0,
  768. 255,
  769. 0,
  770. 255,
  771. 255,
  772. 255,
  773. 255,
  774. 255,
  775. 128,
  776. 0,
  777. 0,
  778. 0,
  779. 128,
  780. 0,
  781. 0,
  782. 0,
  783. 128,
  784. 128,
  785. 128,
  786. 0,
  787. 128,
  788. 0,
  789. 128,
  790. 0,
  791. 128,
  792. 128,
  793. 128,
  794. 128,
  795. 128,
  796. 255,
  797. 128,
  798. 0,
  799. 0,
  800. 128,
  801. 255}};
  802. CommandBufferInitInfo cmdbinit;
  803. cmdbinit.m_flags = CommandBufferFlag::TRANSFER_WORK;
  804. CommandBufferPtr cmdb = gr->newCommandBuffer(cmdbinit);
  805. // Set barriers
  806. cmdb->setTextureSurfaceBarrier(
  807. a, TextureUsageBit::SAMPLED_FRAGMENT, TextureUsageBit::TRANSFER_DESTINATION, TextureSurfaceInfo(0, 0, 0, 0));
  808. cmdb->setTextureSurfaceBarrier(
  809. a, TextureUsageBit::SAMPLED_FRAGMENT, TextureUsageBit::TRANSFER_DESTINATION, TextureSurfaceInfo(1, 0, 0, 0));
  810. cmdb->setTextureSurfaceBarrier(
  811. b, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, TextureSurfaceInfo(0, 0, 0, 0));
  812. TransferGpuAllocatorHandle handle0, handle1, handle2;
  813. UPLOAD_TEX_SURFACE(cmdb, a, TextureSurfaceInfo(0, 0, 0, 0), &mip0[0], sizeof(mip0), handle0);
  814. UPLOAD_TEX_SURFACE(cmdb, a, TextureSurfaceInfo(1, 0, 0, 0), &mip1[0], sizeof(mip1), handle1);
  815. UPLOAD_TEX_SURFACE(cmdb, b, TextureSurfaceInfo(0, 0, 0, 0), &bmip0[0], sizeof(bmip0), handle2);
  816. // Gen mips
  817. cmdb->setTextureSurfaceBarrier(
  818. b, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::GENERATE_MIPMAPS, TextureSurfaceInfo(0, 0, 0, 0));
  819. cmdb->generateMipmaps2d(gr->newTextureView(TextureViewInitInfo(b)));
  820. // Set barriers
  821. cmdb->setTextureSurfaceBarrier(
  822. a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(0, 0, 0, 0));
  823. cmdb->setTextureSurfaceBarrier(
  824. a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(1, 0, 0, 0));
  825. for(U i = 0; i < 3; ++i)
  826. {
  827. cmdb->setTextureSurfaceBarrier(
  828. b, TextureUsageBit::GENERATE_MIPMAPS, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(i, 0, 0, 0));
  829. }
  830. FencePtr fence;
  831. cmdb->flush(&fence);
  832. transfAlloc->release(handle0, fence);
  833. transfAlloc->release(handle1, fence);
  834. transfAlloc->release(handle2, fence);
  835. //
  836. // Create prog
  837. //
  838. ShaderProgramPtr prog = createProgram(VERT_QUAD_SRC, FRAG_2TEX_SRC, *gr);
  839. //
  840. // Create FB
  841. //
  842. FramebufferPtr fb = createDefaultFb(*gr);
  843. //
  844. // Draw
  845. //
  846. const U ITERATION_COUNT = 200;
  847. U iterations = ITERATION_COUNT;
  848. while(iterations--)
  849. {
  850. HighRezTimer timer;
  851. timer.start();
  852. gr->beginFrame();
  853. CommandBufferInitInfo cinit;
  854. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  855. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  856. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  857. cmdb->bindShaderProgram(prog);
  858. cmdb->beginRenderPass(fb, {}, {});
  859. cmdb->bindTextureAndSampler(0, 0, aView, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  860. cmdb->bindTextureAndSampler(0, 1, bView, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  861. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  862. cmdb->endRenderPass();
  863. cmdb->flush();
  864. gr->swapBuffers();
  865. timer.stop();
  866. const F32 TICK = 1.0 / 30.0;
  867. if(timer.getElapsedTime() < TICK)
  868. {
  869. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  870. }
  871. }
  872. COMMON_END()
  873. }
  874. static void drawOffscreenDrawcalls(GrManager& gr,
  875. ShaderProgramPtr prog,
  876. CommandBufferPtr cmdb,
  877. U viewPortSize,
  878. BufferPtr indexBuff,
  879. BufferPtr vertBuff)
  880. {
  881. static F32 ang = -2.5f;
  882. ang += toRad(2.5f);
  883. Mat4 viewMat(Vec4(0.0, 0.0, 5.0, 1.0), Mat3::getIdentity(), 1.0f);
  884. viewMat.invert();
  885. Mat4 projMat = Mat4::calculatePerspectiveProjectionMatrix(toRad(60.0), toRad(60.0), 0.1f, 100.0f);
  886. Mat4 modelMat(Vec4(-0.5, -0.5, 0.0, 1.0), Mat3(Euler(ang, ang / 2.0f, ang / 3.0f)), 1.0f);
  887. Mat4* mvp = SET_UNIFORMS(Mat4*, sizeof(*mvp), cmdb, 0, 0);
  888. *mvp = projMat * viewMat * modelMat;
  889. Vec4* color = SET_UNIFORMS(Vec4*, sizeof(*color) * 2, cmdb, 0, 1);
  890. *color++ = Vec4(1.0, 0.0, 0.0, 0.0);
  891. *color = Vec4(0.0, 1.0, 0.0, 0.0);
  892. cmdb->bindVertexBuffer(0, vertBuff, 0, sizeof(Vec3));
  893. cmdb->setVertexAttribute(0, 0, PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT), 0);
  894. cmdb->bindShaderProgram(prog);
  895. cmdb->bindIndexBuffer(indexBuff, 0, IndexType::U16);
  896. cmdb->setViewport(0, 0, viewPortSize, viewPortSize);
  897. cmdb->drawElements(PrimitiveTopology::TRIANGLES, 6 * 2 * 3);
  898. // 2nd draw
  899. modelMat = Mat4(Vec4(0.5, 0.5, 0.0, 1.0), Mat3(Euler(ang * 2.0, ang, ang / 3.0f * 2.0)), 1.0f);
  900. mvp = SET_UNIFORMS(Mat4*, sizeof(*mvp), cmdb, 0, 0);
  901. *mvp = projMat * viewMat * modelMat;
  902. color = SET_UNIFORMS(Vec4*, sizeof(*color) * 2, cmdb, 0, 1);
  903. *color++ = Vec4(0.0, 0.0, 1.0, 0.0);
  904. *color = Vec4(0.0, 1.0, 1.0, 0.0);
  905. cmdb->drawElements(PrimitiveTopology::TRIANGLES, 6 * 2 * 3);
  906. }
  907. static void drawOffscreen(GrManager& gr, Bool useSecondLevel)
  908. {
  909. //
  910. // Create textures
  911. //
  912. SamplerInitInfo samplerInit;
  913. samplerInit.m_minMagFilter = SamplingFilter::LINEAR;
  914. samplerInit.m_mipmapFilter = SamplingFilter::LINEAR;
  915. SamplerPtr sampler = gr.newSampler(samplerInit);
  916. const PixelFormat COL_FORMAT = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  917. const U TEX_SIZE = 256;
  918. TextureInitInfo init;
  919. init.m_format = COL_FORMAT;
  920. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE;
  921. init.m_height = TEX_SIZE;
  922. init.m_width = TEX_SIZE;
  923. init.m_type = TextureType::_2D;
  924. TexturePtr col0 = gr.newTexture(init);
  925. TexturePtr col1 = gr.newTexture(init);
  926. TextureViewPtr col0View = gr.newTextureView(TextureViewInitInfo(col0));
  927. TextureViewPtr col1View = gr.newTextureView(TextureViewInitInfo(col1));
  928. init.m_format = DS_FORMAT;
  929. TexturePtr dp = gr.newTexture(init);
  930. //
  931. // Create FB
  932. //
  933. FramebufferInitInfo fbinit;
  934. fbinit.m_colorAttachmentCount = 2;
  935. fbinit.m_colorAttachments[0].m_textureView = gr.newTextureView(TextureViewInitInfo(col0));
  936. fbinit.m_colorAttachments[0].m_clearValue.m_colorf = {{0.1, 0.0, 0.0, 0.0}};
  937. fbinit.m_colorAttachments[1].m_textureView = gr.newTextureView(TextureViewInitInfo(col1));
  938. fbinit.m_colorAttachments[1].m_clearValue.m_colorf = {{0.0, 0.1, 0.0, 0.0}};
  939. TextureViewInitInfo viewInit(dp);
  940. viewInit.m_depthStencilAspect = DepthStencilAspectBit::DEPTH;
  941. fbinit.m_depthStencilAttachment.m_textureView = gr.newTextureView(viewInit);
  942. fbinit.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0;
  943. FramebufferPtr fb = gr.newFramebuffer(fbinit);
  944. //
  945. // Create default FB
  946. //
  947. FramebufferPtr dfb = createDefaultFb(gr);
  948. //
  949. // Create buffs
  950. //
  951. BufferPtr verts, indices;
  952. createCube(gr, verts, indices);
  953. //
  954. // Create progs
  955. //
  956. ShaderProgramPtr prog = createProgram(VERT_MRT_SRC, FRAG_MRT_SRC, gr);
  957. ShaderProgramPtr resolveProg = createProgram(VERT_QUAD_SRC, FRAG_MRT2_SRC, gr);
  958. //
  959. // Draw
  960. //
  961. const U ITERATION_COUNT = 200;
  962. U iterations = ITERATION_COUNT;
  963. while(iterations--)
  964. {
  965. HighRezTimer timer;
  966. timer.start();
  967. gr.beginFrame();
  968. CommandBufferInitInfo cinit;
  969. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
  970. CommandBufferPtr cmdb = gr.newCommandBuffer(cinit);
  971. cmdb->setPolygonOffset(0.0, 0.0);
  972. cmdb->setTextureSurfaceBarrier(
  973. col0, TextureUsageBit::NONE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, TextureSurfaceInfo(0, 0, 0, 0));
  974. cmdb->setTextureSurfaceBarrier(
  975. col1, TextureUsageBit::NONE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, TextureSurfaceInfo(0, 0, 0, 0));
  976. cmdb->setTextureSurfaceBarrier(dp,
  977. TextureUsageBit::NONE,
  978. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
  979. TextureSurfaceInfo(0, 0, 0, 0));
  980. cmdb->beginRenderPass(fb,
  981. {{TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE}},
  982. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE);
  983. if(!useSecondLevel)
  984. {
  985. drawOffscreenDrawcalls(gr, prog, cmdb, TEX_SIZE, indices, verts);
  986. }
  987. else
  988. {
  989. CommandBufferInitInfo cinit;
  990. cinit.m_flags = CommandBufferFlag::SECOND_LEVEL | CommandBufferFlag::GRAPHICS_WORK;
  991. cinit.m_framebuffer = fb;
  992. CommandBufferPtr cmdb2 = gr.newCommandBuffer(cinit);
  993. drawOffscreenDrawcalls(gr, prog, cmdb2, TEX_SIZE, indices, verts);
  994. cmdb2->flush();
  995. cmdb->pushSecondLevelCommandBuffer(cmdb2);
  996. }
  997. cmdb->endRenderPass();
  998. cmdb->setTextureSurfaceBarrier(col0,
  999. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  1000. TextureUsageBit::SAMPLED_FRAGMENT,
  1001. TextureSurfaceInfo(0, 0, 0, 0));
  1002. cmdb->setTextureSurfaceBarrier(col1,
  1003. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  1004. TextureUsageBit::SAMPLED_FRAGMENT,
  1005. TextureSurfaceInfo(0, 0, 0, 0));
  1006. cmdb->setTextureSurfaceBarrier(dp,
  1007. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
  1008. TextureUsageBit::SAMPLED_FRAGMENT,
  1009. TextureSurfaceInfo(0, 0, 0, 0));
  1010. // Draw quad
  1011. cmdb->beginRenderPass(dfb, {}, {});
  1012. cmdb->bindShaderProgram(resolveProg);
  1013. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  1014. cmdb->bindTextureAndSampler(0, 0, col0View, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  1015. cmdb->bindTextureAndSampler(0, 1, col1View, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  1016. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  1017. cmdb->endRenderPass();
  1018. cmdb->flush();
  1019. // End
  1020. gr.swapBuffers();
  1021. timer.stop();
  1022. const F32 TICK = 1.0 / 30.0;
  1023. if(timer.getElapsedTime() < TICK)
  1024. {
  1025. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  1026. }
  1027. }
  1028. }
  1029. ANKI_TEST(Gr, DrawOffscreen)
  1030. {
  1031. COMMON_BEGIN()
  1032. drawOffscreen(*gr, false);
  1033. COMMON_END()
  1034. }
  1035. ANKI_TEST(Gr, DrawWithSecondLevel)
  1036. {
  1037. COMMON_BEGIN()
  1038. drawOffscreen(*gr, true);
  1039. COMMON_END()
  1040. }
  1041. ANKI_TEST(Gr, ImageLoadStore)
  1042. {
  1043. COMMON_BEGIN()
  1044. SamplerInitInfo samplerInit;
  1045. samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
  1046. samplerInit.m_mipmapFilter = SamplingFilter::BASE;
  1047. SamplerPtr sampler = gr->newSampler(samplerInit);
  1048. TextureInitInfo init;
  1049. init.m_width = init.m_height = 4;
  1050. init.m_mipmapsCount = 2;
  1051. init.m_usage = TextureUsageBit::CLEAR | TextureUsageBit::SAMPLED_ALL | TextureUsageBit::IMAGE_COMPUTE_WRITE;
  1052. init.m_type = TextureType::_2D;
  1053. init.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  1054. TexturePtr tex = gr->newTexture(init);
  1055. TextureViewInitInfo viewInit(tex);
  1056. viewInit.m_firstMipmap = 1;
  1057. viewInit.m_mipmapCount = 1;
  1058. TextureViewPtr view = gr->newTextureView(viewInit);
  1059. // Prog
  1060. ShaderProgramPtr prog = createProgram(VERT_QUAD_SRC, FRAG_SIMPLE_TEX_SRC, *gr);
  1061. // Create shader & compute prog
  1062. ShaderPtr shader = gr->newShader({ShaderType::COMPUTE, COMP_WRITE_IMAGE_SRC});
  1063. ShaderProgramInitInfo sprogInit;
  1064. sprogInit.m_shaders[ShaderType::COMPUTE] = shader;
  1065. ShaderProgramPtr compProg = gr->newShaderProgram(sprogInit);
  1066. // FB
  1067. FramebufferPtr dfb = createDefaultFb(*gr);
  1068. // Write texture data
  1069. CommandBufferInitInfo cmdbinit;
  1070. CommandBufferPtr cmdb = gr->newCommandBuffer(cmdbinit);
  1071. cmdb->setTextureSurfaceBarrier(tex, TextureUsageBit::NONE, TextureUsageBit::CLEAR, TextureSurfaceInfo(0, 0, 0, 0));
  1072. ClearValue clear;
  1073. clear.m_colorf = {{0.0, 1.0, 0.0, 1.0}};
  1074. TextureViewInitInfo viewInit2(tex, TextureSurfaceInfo(0, 0, 0, 0));
  1075. cmdb->clearTextureView(gr->newTextureView(viewInit2), clear);
  1076. cmdb->setTextureSurfaceBarrier(
  1077. tex, TextureUsageBit::CLEAR, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(0, 0, 0, 0));
  1078. cmdb->setTextureSurfaceBarrier(tex, TextureUsageBit::NONE, TextureUsageBit::CLEAR, TextureSurfaceInfo(1, 0, 0, 0));
  1079. clear.m_colorf = {{0.0, 0.0, 1.0, 1.0}};
  1080. TextureViewInitInfo viewInit3(tex, TextureSurfaceInfo(1, 0, 0, 0));
  1081. cmdb->clearTextureView(gr->newTextureView(viewInit3), clear);
  1082. cmdb->setTextureSurfaceBarrier(
  1083. tex, TextureUsageBit::CLEAR, TextureUsageBit::IMAGE_COMPUTE_WRITE, TextureSurfaceInfo(1, 0, 0, 0));
  1084. cmdb->flush();
  1085. const U ITERATION_COUNT = 100;
  1086. U iterations = ITERATION_COUNT;
  1087. while(iterations--)
  1088. {
  1089. HighRezTimer timer;
  1090. timer.start();
  1091. gr->beginFrame();
  1092. CommandBufferInitInfo cinit;
  1093. cinit.m_flags =
  1094. CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::COMPUTE_WORK | CommandBufferFlag::SMALL_BATCH;
  1095. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  1096. // Write image
  1097. Vec4* col = SET_STORAGE(Vec4*, sizeof(*col), cmdb, 1, 0);
  1098. *col = Vec4(iterations / F32(ITERATION_COUNT));
  1099. cmdb->setTextureSurfaceBarrier(
  1100. tex, TextureUsageBit::NONE, TextureUsageBit::IMAGE_COMPUTE_WRITE, TextureSurfaceInfo(1, 0, 0, 0));
  1101. cmdb->bindShaderProgram(compProg);
  1102. cmdb->bindImage(0, 0, view);
  1103. cmdb->dispatchCompute(WIDTH / 2, HEIGHT / 2, 1);
  1104. cmdb->setTextureSurfaceBarrier(tex,
  1105. TextureUsageBit::IMAGE_COMPUTE_WRITE,
  1106. TextureUsageBit::SAMPLED_FRAGMENT,
  1107. TextureSurfaceInfo(1, 0, 0, 0));
  1108. // Present image
  1109. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  1110. cmdb->bindShaderProgram(prog);
  1111. cmdb->beginRenderPass(dfb, {}, {});
  1112. cmdb->bindTextureAndSampler(
  1113. 0, 0, gr->newTextureView(TextureViewInitInfo(tex)), sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  1114. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  1115. cmdb->endRenderPass();
  1116. cmdb->flush();
  1117. // End
  1118. gr->swapBuffers();
  1119. timer.stop();
  1120. const F32 TICK = 1.0 / 30.0;
  1121. if(timer.getElapsedTime() < TICK)
  1122. {
  1123. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  1124. }
  1125. }
  1126. COMMON_END()
  1127. }
  1128. ANKI_TEST(Gr, 3DTextures)
  1129. {
  1130. COMMON_BEGIN()
  1131. SamplerInitInfo samplerInit;
  1132. samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
  1133. samplerInit.m_mipmapFilter = SamplingFilter::BASE;
  1134. samplerInit.m_repeat = false;
  1135. SamplerPtr sampler = gr->newSampler(samplerInit);
  1136. //
  1137. // Create texture A
  1138. //
  1139. TextureInitInfo init;
  1140. init.m_depth = 1;
  1141. init.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  1142. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION;
  1143. init.m_initialUsage = TextureUsageBit::TRANSFER_DESTINATION;
  1144. init.m_height = 2;
  1145. init.m_width = 2;
  1146. init.m_mipmapsCount = 2;
  1147. init.m_samples = 1;
  1148. init.m_depth = 2;
  1149. init.m_layerCount = 1;
  1150. init.m_type = TextureType::_3D;
  1151. TexturePtr a = gr->newTexture(init);
  1152. //
  1153. // Upload all textures
  1154. //
  1155. Array<U8, 2 * 2 * 2 * 4> mip0 = {{255,
  1156. 0,
  1157. 0,
  1158. 0,
  1159. 0,
  1160. 255,
  1161. 0,
  1162. 0,
  1163. 0,
  1164. 0,
  1165. 255,
  1166. 0,
  1167. 255,
  1168. 255,
  1169. 0,
  1170. 0,
  1171. 255,
  1172. 0,
  1173. 255,
  1174. 0,
  1175. 0,
  1176. 255,
  1177. 255,
  1178. 0,
  1179. 255,
  1180. 255,
  1181. 255,
  1182. 0,
  1183. 0,
  1184. 0,
  1185. 0,
  1186. 0}};
  1187. Array<U8, 4> mip1 = {{128, 128, 128, 0}};
  1188. CommandBufferInitInfo cmdbinit;
  1189. cmdbinit.m_flags = CommandBufferFlag::TRANSFER_WORK | CommandBufferFlag::SMALL_BATCH;
  1190. CommandBufferPtr cmdb = gr->newCommandBuffer(cmdbinit);
  1191. cmdb->setTextureVolumeBarrier(
  1192. a, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, TextureVolumeInfo(0));
  1193. cmdb->setTextureVolumeBarrier(
  1194. a, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, TextureVolumeInfo(1));
  1195. TransferGpuAllocatorHandle handle0, handle1;
  1196. UPLOAD_TEX_VOL(cmdb, a, TextureVolumeInfo(0), &mip0[0], sizeof(mip0), handle0);
  1197. UPLOAD_TEX_VOL(cmdb, a, TextureVolumeInfo(1), &mip1[0], sizeof(mip1), handle1);
  1198. cmdb->setTextureVolumeBarrier(
  1199. a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureVolumeInfo(0));
  1200. cmdb->setTextureVolumeBarrier(
  1201. a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureVolumeInfo(1));
  1202. FencePtr fence;
  1203. cmdb->flush(&fence);
  1204. transfAlloc->release(handle0, fence);
  1205. transfAlloc->release(handle1, fence);
  1206. //
  1207. // Rest
  1208. //
  1209. ShaderProgramPtr prog = createProgram(VERT_QUAD_SRC, FRAG_TEX3D_SRC, *gr);
  1210. FramebufferPtr dfb = createDefaultFb(*gr);
  1211. static Array<Vec4, 9> TEX_COORDS_LOD = {{Vec4(0, 0, 0, 0),
  1212. Vec4(1, 0, 0, 0),
  1213. Vec4(0, 1, 0, 0),
  1214. Vec4(1, 1, 0, 0),
  1215. Vec4(0, 0, 1, 0),
  1216. Vec4(1, 0, 1, 0),
  1217. Vec4(0, 1, 1, 0),
  1218. Vec4(1, 1, 1, 0),
  1219. Vec4(0, 0, 0, 1)}};
  1220. const U ITERATION_COUNT = 100;
  1221. U iterations = ITERATION_COUNT;
  1222. while(iterations--)
  1223. {
  1224. HighRezTimer timer;
  1225. timer.start();
  1226. gr->beginFrame();
  1227. CommandBufferInitInfo cinit;
  1228. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  1229. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  1230. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  1231. cmdb->beginRenderPass(dfb, {}, {});
  1232. cmdb->bindShaderProgram(prog);
  1233. Vec4* uv = SET_UNIFORMS(Vec4*, sizeof(Vec4), cmdb, 0, 0);
  1234. U idx = (F32(ITERATION_COUNT - iterations - 1) / ITERATION_COUNT) * TEX_COORDS_LOD.getSize();
  1235. *uv = TEX_COORDS_LOD[idx];
  1236. cmdb->bindTextureAndSampler(
  1237. 0, 0, gr->newTextureView(TextureViewInitInfo(a)), sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  1238. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  1239. cmdb->endRenderPass();
  1240. cmdb->flush();
  1241. // End
  1242. gr->swapBuffers();
  1243. timer.stop();
  1244. const F32 TICK = 1.0 / 15.0;
  1245. if(timer.getElapsedTime() < TICK)
  1246. {
  1247. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  1248. }
  1249. }
  1250. COMMON_END()
  1251. }
  1252. static RenderTargetDescription newRTDescr(CString name)
  1253. {
  1254. RenderTargetDescription texInf(name);
  1255. texInf.m_width = texInf.m_height = 16;
  1256. texInf.m_usage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT;
  1257. texInf.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  1258. texInf.bake();
  1259. return texInf;
  1260. }
  1261. ANKI_TEST(Gr, RenderGraph)
  1262. {
  1263. COMMON_BEGIN()
  1264. StackAllocator<U8> alloc(allocAligned, nullptr, 2_MB);
  1265. RenderGraphDescription descr(alloc);
  1266. RenderGraphPtr rgraph = gr->newRenderGraph();
  1267. const U GI_MIP_COUNT = 4;
  1268. TextureInitInfo texI("dummy");
  1269. texI.m_width = texI.m_height = 16;
  1270. texI.m_usage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT;
  1271. texI.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  1272. TexturePtr dummyTex = gr->newTexture(texI);
  1273. // SM
  1274. RenderTargetHandle smScratchRt = descr.newRenderTarget(newRTDescr("SM scratch"));
  1275. {
  1276. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("SM");
  1277. pass.newConsumer({smScratchRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE});
  1278. pass.newProducer({smScratchRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE});
  1279. }
  1280. // SM to exponential SM
  1281. RenderTargetHandle smExpRt = descr.importRenderTarget("ESM", dummyTex, TextureUsageBit::SAMPLED_FRAGMENT);
  1282. {
  1283. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("ESM");
  1284. pass.newConsumer({smScratchRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1285. pass.newConsumer({smExpRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1286. pass.newProducer({smExpRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1287. }
  1288. // GI gbuff
  1289. RenderTargetHandle giGbuffNormRt = descr.newRenderTarget(newRTDescr("GI GBuff norm"));
  1290. RenderTargetHandle giGbuffDiffRt = descr.newRenderTarget(newRTDescr("GI GBuff diff"));
  1291. RenderTargetHandle giGbuffDepthRt = descr.newRenderTarget(newRTDescr("GI GBuff depth"));
  1292. {
  1293. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("GI gbuff");
  1294. pass.newConsumer({giGbuffNormRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1295. pass.newConsumer({giGbuffDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1296. pass.newConsumer({giGbuffDiffRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1297. pass.newProducer({giGbuffNormRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1298. pass.newProducer({giGbuffDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1299. pass.newProducer({giGbuffDiffRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1300. }
  1301. // GI light
  1302. RenderTargetHandle giGiLightRt = descr.importRenderTarget("GI light", dummyTex, TextureUsageBit::SAMPLED_FRAGMENT);
  1303. for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
  1304. {
  1305. TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, 0));
  1306. GraphicsRenderPassDescription& pass =
  1307. descr.newGraphicsRenderPass(StringAuto(alloc).sprintf("GI lp%u", faceIdx).toCString());
  1308. pass.newConsumer({giGiLightRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, subresource});
  1309. pass.newConsumer({giGbuffNormRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1310. pass.newConsumer({giGbuffDepthRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1311. pass.newConsumer({giGbuffDiffRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1312. pass.newProducer({giGiLightRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, subresource});
  1313. }
  1314. // GI light mips
  1315. {
  1316. for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
  1317. {
  1318. GraphicsRenderPassDescription& pass =
  1319. descr.newGraphicsRenderPass(StringAuto(alloc).sprintf("GI mip%u", faceIdx).toCString());
  1320. for(U mip = 0; mip < GI_MIP_COUNT; ++mip)
  1321. {
  1322. TextureSurfaceInfo surf(mip, 0, faceIdx, 0);
  1323. pass.newConsumer({giGiLightRt, TextureUsageBit::GENERATE_MIPMAPS, surf});
  1324. pass.newProducer({giGiLightRt, TextureUsageBit::GENERATE_MIPMAPS, surf});
  1325. }
  1326. }
  1327. }
  1328. // Gbuffer
  1329. RenderTargetHandle gbuffRt0 = descr.newRenderTarget(newRTDescr("GBuff RT0"));
  1330. RenderTargetHandle gbuffRt1 = descr.newRenderTarget(newRTDescr("GBuff RT1"));
  1331. RenderTargetHandle gbuffRt2 = descr.newRenderTarget(newRTDescr("GBuff RT2"));
  1332. RenderTargetHandle gbuffDepth = descr.newRenderTarget(newRTDescr("GBuff RT2"));
  1333. {
  1334. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("G-Buffer");
  1335. pass.newConsumer({gbuffRt0, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1336. pass.newConsumer({gbuffRt1, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1337. pass.newConsumer({gbuffRt2, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1338. pass.newConsumer({gbuffDepth, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1339. pass.newProducer({gbuffRt0, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1340. pass.newProducer({gbuffRt1, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1341. pass.newProducer({gbuffRt2, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1342. pass.newProducer({gbuffDepth, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1343. }
  1344. // Half depth
  1345. RenderTargetHandle halfDepthRt = descr.newRenderTarget(newRTDescr("Depth/2"));
  1346. {
  1347. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("HalfDepth");
  1348. pass.newConsumer({gbuffDepth, TextureUsageBit::SAMPLED_FRAGMENT});
  1349. pass.newConsumer({halfDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1350. pass.newProducer({halfDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1351. }
  1352. // Quarter depth
  1353. RenderTargetHandle quarterDepthRt = descr.newRenderTarget(newRTDescr("Depth/4"));
  1354. {
  1355. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("QuarterDepth");
  1356. pass.newConsumer({quarterDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1357. pass.newConsumer({halfDepthRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1358. pass.newProducer({quarterDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1359. }
  1360. // SSAO
  1361. RenderTargetHandle ssaoRt = descr.newRenderTarget(newRTDescr("SSAO"));
  1362. {
  1363. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("SSAO main");
  1364. pass.newConsumer({ssaoRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1365. pass.newConsumer({quarterDepthRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1366. pass.newConsumer({gbuffRt2, TextureUsageBit::SAMPLED_FRAGMENT});
  1367. pass.newProducer({ssaoRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1368. RenderTargetHandle ssaoVBlurRt = descr.newRenderTarget(newRTDescr("SSAO tmp"));
  1369. GraphicsRenderPassDescription& pass2 = descr.newGraphicsRenderPass("SSAO vblur");
  1370. pass2.newConsumer({ssaoRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1371. pass2.newConsumer({ssaoVBlurRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1372. pass2.newProducer({ssaoVBlurRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1373. GraphicsRenderPassDescription& pass3 = descr.newGraphicsRenderPass("SSAO hblur");
  1374. pass3.newConsumer({ssaoRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1375. pass3.newProducer({ssaoRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1376. pass3.newConsumer({ssaoVBlurRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1377. }
  1378. // Volumetric
  1379. RenderTargetHandle volRt = descr.newRenderTarget(newRTDescr("Vol"));
  1380. {
  1381. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("Vol main");
  1382. pass.newConsumer({volRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1383. pass.newConsumer({quarterDepthRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1384. pass.newProducer({volRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1385. RenderTargetHandle volVBlurRt = descr.newRenderTarget(newRTDescr("Vol tmp"));
  1386. GraphicsRenderPassDescription& pass2 = descr.newGraphicsRenderPass("Vol vblur");
  1387. pass2.newConsumer({volRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1388. pass2.newConsumer({volVBlurRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1389. pass2.newProducer({volVBlurRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1390. GraphicsRenderPassDescription& pass3 = descr.newGraphicsRenderPass("Vol hblur");
  1391. pass3.newConsumer({volRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1392. pass3.newProducer({volRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1393. pass3.newConsumer({volVBlurRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1394. }
  1395. // Forward shading
  1396. RenderTargetHandle fsRt = descr.newRenderTarget(newRTDescr("FS"));
  1397. {
  1398. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("Forward shading");
  1399. pass.newConsumer({fsRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1400. pass.newProducer({fsRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1401. pass.newConsumer(
  1402. {halfDepthRt, TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ});
  1403. pass.newConsumer({volRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1404. }
  1405. // Light shading
  1406. RenderTargetHandle lightRt = descr.importRenderTarget("Light", dummyTex, TextureUsageBit::NONE);
  1407. {
  1408. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("Light shading");
  1409. pass.newConsumer({lightRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1410. pass.newConsumer({gbuffRt0, TextureUsageBit::SAMPLED_FRAGMENT});
  1411. pass.newConsumer({gbuffRt1, TextureUsageBit::SAMPLED_FRAGMENT});
  1412. pass.newConsumer({gbuffRt2, TextureUsageBit::SAMPLED_FRAGMENT});
  1413. pass.newConsumer({gbuffDepth, TextureUsageBit::SAMPLED_FRAGMENT});
  1414. pass.newConsumer({smExpRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1415. pass.newConsumer({giGiLightRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1416. pass.newConsumer({ssaoRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1417. pass.newConsumer({fsRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1418. pass.newProducer({lightRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1419. }
  1420. // TAA
  1421. RenderTargetHandle taaHistoryRt = descr.importRenderTarget("TAA hist", dummyTex, TextureUsageBit::SAMPLED_FRAGMENT);
  1422. RenderTargetHandle taaRt = descr.importRenderTarget("TAA", dummyTex, TextureUsageBit::NONE);
  1423. {
  1424. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("Temporal AA");
  1425. pass.newConsumer({lightRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1426. pass.newConsumer({taaRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1427. pass.newProducer({taaRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1428. pass.newConsumer({taaHistoryRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1429. }
  1430. rgraph->compileNewGraph(descr, alloc);
  1431. COMMON_END()
  1432. }
  1433. } // end namespace anki