Gr.cpp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923
  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. return gr.newShaderProgram(ShaderProgramInitInfo(vert, frag));
  285. }
  286. static FramebufferPtr createDefaultFb(GrManager& gr)
  287. {
  288. FramebufferInitInfo fbinit;
  289. fbinit.m_colorAttachmentCount = 1;
  290. fbinit.m_colorAttachments[0].m_clearValue.m_colorf = {{1.0, 0.0, 1.0, 1.0}};
  291. return gr.newFramebuffer(fbinit);
  292. }
  293. static void createCube(GrManager& gr, BufferPtr& verts, BufferPtr& indices)
  294. {
  295. static const Array<F32, 8 * 3> pos = {
  296. {1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1}};
  297. static const Array<U16, 6 * 2 * 3> idx = {
  298. {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}};
  299. verts = gr.newBuffer(BufferInitInfo(sizeof(pos), BufferUsageBit::VERTEX, BufferMapAccessBit::WRITE));
  300. void* mapped = verts->map(0, sizeof(pos), BufferMapAccessBit::WRITE);
  301. memcpy(mapped, &pos[0], sizeof(pos));
  302. verts->unmap();
  303. indices = gr.newBuffer(BufferInitInfo(sizeof(idx), BufferUsageBit::INDEX, BufferMapAccessBit::WRITE));
  304. mapped = indices->map(0, sizeof(idx), BufferMapAccessBit::WRITE);
  305. memcpy(mapped, &idx[0], sizeof(idx));
  306. indices->unmap();
  307. }
  308. ANKI_TEST(Gr, GrManager){COMMON_BEGIN() COMMON_END()}
  309. ANKI_TEST(Gr, Shader)
  310. {
  311. COMMON_BEGIN()
  312. ShaderPtr shader = gr->newShader({ShaderType::FRAGMENT, FRAG_MRT_SRC});
  313. COMMON_END()
  314. }
  315. ANKI_TEST(Gr, ShaderProgram)
  316. {
  317. COMMON_BEGIN()
  318. ShaderProgramPtr ppline = createProgram(VERT_SRC, FRAG_SRC, *gr);
  319. COMMON_END()
  320. }
  321. ANKI_TEST(Gr, ClearScreen)
  322. {
  323. COMMON_BEGIN()
  324. ANKI_TEST_LOGI("Expect to see a magenta background");
  325. FramebufferPtr fb = createDefaultFb(*gr);
  326. U iterations = 100;
  327. while(iterations--)
  328. {
  329. HighRezTimer timer;
  330. timer.start();
  331. gr->beginFrame();
  332. CommandBufferInitInfo cinit;
  333. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  334. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  335. cmdb->beginRenderPass(fb, {}, {});
  336. cmdb->endRenderPass();
  337. cmdb->flush();
  338. gr->swapBuffers();
  339. timer.stop();
  340. const F32 TICK = 1.0 / 30.0;
  341. if(timer.getElapsedTime() < TICK)
  342. {
  343. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  344. }
  345. }
  346. COMMON_END()
  347. }
  348. ANKI_TEST(Gr, SimpleDrawcall)
  349. {
  350. COMMON_BEGIN()
  351. ANKI_TEST_LOGI("Expect to see a grey triangle");
  352. ShaderProgramPtr prog = createProgram(VERT_SRC, FRAG_SRC, *gr);
  353. FramebufferPtr fb = createDefaultFb(*gr);
  354. const U ITERATIONS = 200;
  355. for(U i = 0; i < ITERATIONS; ++i)
  356. {
  357. HighRezTimer timer;
  358. timer.start();
  359. gr->beginFrame();
  360. CommandBufferInitInfo cinit;
  361. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
  362. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  363. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  364. cmdb->bindShaderProgram(prog);
  365. cmdb->beginRenderPass(fb, {}, {});
  366. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
  367. cmdb->endRenderPass();
  368. cmdb->flush();
  369. gr->swapBuffers();
  370. timer.stop();
  371. const F32 TICK = 1.0 / 30.0;
  372. if(timer.getElapsedTime() < TICK)
  373. {
  374. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  375. }
  376. }
  377. COMMON_END()
  378. }
  379. ANKI_TEST(Gr, ViewportAndScissor)
  380. {
  381. COMMON_BEGIN()
  382. ANKI_TEST_LOGI("Expect to see a grey quad appearing in the 4 corners. The clear color will change and affect only"
  383. "the area around the quad");
  384. ShaderProgramPtr prog = createProgram(VERT_QUAD_STRIP_SRC, FRAG_SRC, *gr);
  385. srand(time(nullptr));
  386. Array<FramebufferPtr, 4> fb;
  387. for(FramebufferPtr& f : fb)
  388. {
  389. FramebufferInitInfo fbinit;
  390. fbinit.m_colorAttachmentCount = 1;
  391. fbinit.m_colorAttachments[0].m_clearValue.m_colorf = {{randFloat(1.0), randFloat(1.0), randFloat(1.0), 1.0}};
  392. f = gr->newFramebuffer(fbinit);
  393. }
  394. static const Array2d<U, 4, 4> VIEWPORTS = {{{{0, 0, WIDTH / 2, HEIGHT / 2}},
  395. {{WIDTH / 2, 0, WIDTH / 2, HEIGHT / 2}},
  396. {{WIDTH / 2, HEIGHT / 2, WIDTH / 2, HEIGHT / 2}},
  397. {{0, HEIGHT / 2, WIDTH / 2, HEIGHT / 2}}}};
  398. const U ITERATIONS = 400;
  399. const U SCISSOR_MARGIN = 20;
  400. const U RENDER_AREA_MARGIN = 10;
  401. for(U i = 0; i < ITERATIONS; ++i)
  402. {
  403. HighRezTimer timer;
  404. timer.start();
  405. gr->beginFrame();
  406. CommandBufferInitInfo cinit;
  407. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  408. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  409. U idx = (i / 30) % 4;
  410. auto vp = VIEWPORTS[idx];
  411. cmdb->setViewport(vp[0], vp[1], vp[2], vp[3]);
  412. cmdb->setScissor(
  413. vp[0] + SCISSOR_MARGIN, vp[1] + SCISSOR_MARGIN, vp[2] - SCISSOR_MARGIN * 2, vp[3] - SCISSOR_MARGIN * 2);
  414. cmdb->bindShaderProgram(prog);
  415. cmdb->beginRenderPass(fb[i % 4],
  416. {},
  417. {},
  418. vp[0] + RENDER_AREA_MARGIN,
  419. vp[1] + RENDER_AREA_MARGIN,
  420. vp[2] - RENDER_AREA_MARGIN * 2,
  421. vp[3] - RENDER_AREA_MARGIN * 2);
  422. cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4);
  423. cmdb->endRenderPass();
  424. cmdb->flush();
  425. gr->swapBuffers();
  426. timer.stop();
  427. const F32 TICK = 1.0 / 30.0;
  428. if(timer.getElapsedTime() < TICK)
  429. {
  430. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  431. }
  432. }
  433. COMMON_END()
  434. }
  435. ANKI_TEST(Gr, ViewportAndScissorOffscreen)
  436. {
  437. srand(time(nullptr));
  438. COMMON_BEGIN()
  439. ANKI_TEST_LOGI("Expect to see a grey quad appearing in the 4 corners. "
  440. "Around that quad is a border that changes color. "
  441. "The quads appear counter-clockwise");
  442. ShaderProgramPtr prog = createProgram(VERT_QUAD_STRIP_SRC, FRAG_SRC, *gr);
  443. ShaderProgramPtr blitProg = createProgram(VERT_QUAD_SRC, FRAG_TEX_SRC, *gr);
  444. const PixelFormat COL_FORMAT = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  445. const U RT_WIDTH = 32;
  446. const U RT_HEIGHT = 16;
  447. TextureInitInfo init;
  448. init.m_depth = 1;
  449. init.m_format = COL_FORMAT;
  450. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE;
  451. init.m_height = RT_HEIGHT;
  452. init.m_width = RT_WIDTH;
  453. init.m_mipmapCount = 1;
  454. init.m_depth = 1;
  455. init.m_layerCount = 1;
  456. init.m_samples = 1;
  457. init.m_type = TextureType::_2D;
  458. TexturePtr rt = gr->newTexture(init);
  459. TextureViewInitInfo viewInit(rt);
  460. TextureViewPtr texView = gr->newTextureView(viewInit);
  461. Array<FramebufferPtr, 4> fb;
  462. for(FramebufferPtr& f : fb)
  463. {
  464. TextureViewInitInfo viewInf(rt);
  465. TextureViewPtr view = gr->newTextureView(viewInf);
  466. FramebufferInitInfo fbinit;
  467. fbinit.m_colorAttachmentCount = 1;
  468. fbinit.m_colorAttachments[0].m_clearValue.m_colorf = {{randFloat(1.0), randFloat(1.0), randFloat(1.0), 1.0}};
  469. fbinit.m_colorAttachments[0].m_textureView = view;
  470. f = gr->newFramebuffer(fbinit);
  471. }
  472. FramebufferPtr defaultFb = createDefaultFb(*gr);
  473. SamplerInitInfo samplerInit;
  474. samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
  475. samplerInit.m_mipmapFilter = SamplingFilter::BASE;
  476. SamplerPtr sampler = gr->newSampler(samplerInit);
  477. static const Array2d<U, 4, 4> VIEWPORTS = {{{{0, 0, RT_WIDTH / 2, RT_HEIGHT / 2}},
  478. {{RT_WIDTH / 2, 0, RT_WIDTH / 2, RT_HEIGHT / 2}},
  479. {{RT_WIDTH / 2, RT_HEIGHT / 2, RT_WIDTH / 2, RT_HEIGHT / 2}},
  480. {{0, RT_HEIGHT / 2, RT_WIDTH / 2, RT_HEIGHT / 2}}}};
  481. const U ITERATIONS = 400;
  482. const U SCISSOR_MARGIN = 2;
  483. const U RENDER_AREA_MARGIN = 1;
  484. for(U i = 0; i < ITERATIONS; ++i)
  485. {
  486. HighRezTimer timer;
  487. timer.start();
  488. gr->beginFrame();
  489. if(i == 0)
  490. {
  491. CommandBufferInitInfo cinit;
  492. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  493. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  494. cmdb->setViewport(0, 0, RT_WIDTH, RT_HEIGHT);
  495. cmdb->setTextureSurfaceBarrier(rt,
  496. TextureUsageBit::NONE,
  497. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  498. TextureSurfaceInfo(0, 0, 0, 0));
  499. cmdb->beginRenderPass(fb[0], {{TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE}}, {});
  500. cmdb->endRenderPass();
  501. cmdb->setTextureSurfaceBarrier(rt,
  502. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  503. TextureUsageBit::SAMPLED_FRAGMENT,
  504. TextureSurfaceInfo(0, 0, 0, 0));
  505. cmdb->flush();
  506. }
  507. CommandBufferInitInfo cinit;
  508. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  509. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  510. // Draw offscreen
  511. cmdb->setTextureSurfaceBarrier(rt,
  512. TextureUsageBit::SAMPLED_FRAGMENT,
  513. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  514. TextureSurfaceInfo(0, 0, 0, 0));
  515. auto vp = VIEWPORTS[(i / 30) % 4];
  516. cmdb->setViewport(vp[0], vp[1], vp[2], vp[3]);
  517. cmdb->setScissor(
  518. vp[0] + SCISSOR_MARGIN, vp[1] + SCISSOR_MARGIN, vp[2] - SCISSOR_MARGIN * 2, vp[3] - SCISSOR_MARGIN * 2);
  519. cmdb->bindShaderProgram(prog);
  520. cmdb->beginRenderPass(fb[i % 4],
  521. {{TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE}},
  522. {},
  523. vp[0] + RENDER_AREA_MARGIN,
  524. vp[1] + RENDER_AREA_MARGIN,
  525. vp[2] - RENDER_AREA_MARGIN * 2,
  526. vp[3] - RENDER_AREA_MARGIN * 2);
  527. cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4);
  528. cmdb->endRenderPass();
  529. // Draw onscreen
  530. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  531. cmdb->setScissor(0, 0, WIDTH, HEIGHT);
  532. cmdb->bindShaderProgram(blitProg);
  533. cmdb->setTextureSurfaceBarrier(rt,
  534. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  535. TextureUsageBit::SAMPLED_FRAGMENT,
  536. TextureSurfaceInfo(0, 0, 0, 0));
  537. cmdb->bindTextureAndSampler(0, 0, texView, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  538. cmdb->beginRenderPass(defaultFb, {}, {});
  539. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  540. cmdb->endRenderPass();
  541. cmdb->flush();
  542. gr->swapBuffers();
  543. timer.stop();
  544. const F32 TICK = 1.0 / 30.0;
  545. if(timer.getElapsedTime() < TICK)
  546. {
  547. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  548. }
  549. }
  550. COMMON_END()
  551. }
  552. ANKI_TEST(Gr, Buffer)
  553. {
  554. COMMON_BEGIN()
  555. BufferPtr a = gr->newBuffer(BufferInitInfo(512, BufferUsageBit::UNIFORM_ALL, BufferMapAccessBit::NONE));
  556. BufferPtr b = gr->newBuffer(
  557. BufferInitInfo(64, BufferUsageBit::STORAGE_ALL, BufferMapAccessBit::WRITE | BufferMapAccessBit::READ));
  558. void* ptr = b->map(0, 64, BufferMapAccessBit::WRITE);
  559. ANKI_TEST_EXPECT_NEQ(ptr, nullptr);
  560. U8 ptr2[64];
  561. memset(ptr, 0xCC, 64);
  562. memset(ptr2, 0xCC, 64);
  563. b->unmap();
  564. ptr = b->map(0, 64, BufferMapAccessBit::READ);
  565. ANKI_TEST_EXPECT_NEQ(ptr, nullptr);
  566. ANKI_TEST_EXPECT_EQ(memcmp(ptr, ptr2, 64), 0);
  567. b->unmap();
  568. COMMON_END()
  569. }
  570. ANKI_TEST(Gr, DrawWithUniforms)
  571. {
  572. COMMON_BEGIN()
  573. // A non-uploaded buffer
  574. BufferPtr b =
  575. gr->newBuffer(BufferInitInfo(sizeof(Vec4) * 3, BufferUsageBit::UNIFORM_ALL, BufferMapAccessBit::WRITE));
  576. Vec4* ptr = static_cast<Vec4*>(b->map(0, sizeof(Vec4) * 3, BufferMapAccessBit::WRITE));
  577. ANKI_TEST_EXPECT_NEQ(ptr, nullptr);
  578. ptr[0] = Vec4(1.0, 0.0, 0.0, 0.0);
  579. ptr[1] = Vec4(0.0, 1.0, 0.0, 0.0);
  580. ptr[2] = Vec4(0.0, 0.0, 1.0, 0.0);
  581. b->unmap();
  582. // Progm
  583. ShaderProgramPtr prog = createProgram(VERT_UBO_SRC, FRAG_UBO_SRC, *gr);
  584. // FB
  585. FramebufferPtr fb = createDefaultFb(*gr);
  586. const U ITERATION_COUNT = 100;
  587. U iterations = ITERATION_COUNT;
  588. while(iterations--)
  589. {
  590. HighRezTimer timer;
  591. timer.start();
  592. gr->beginFrame();
  593. CommandBufferInitInfo cinit;
  594. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
  595. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  596. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  597. cmdb->bindShaderProgram(prog);
  598. cmdb->beginRenderPass(fb, {}, {});
  599. cmdb->bindUniformBuffer(0, 0, b, 0, MAX_PTR_SIZE);
  600. // Uploaded buffer
  601. Vec4* rotMat = SET_UNIFORMS(Vec4*, sizeof(Vec4), cmdb, 0, 1);
  602. F32 angle = toRad(360.0f / ITERATION_COUNT * iterations);
  603. (*rotMat)[0] = cos(angle);
  604. (*rotMat)[1] = -sin(angle);
  605. (*rotMat)[2] = sin(angle);
  606. (*rotMat)[3] = cos(angle);
  607. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
  608. cmdb->endRenderPass();
  609. cmdb->flush();
  610. gr->swapBuffers();
  611. timer.stop();
  612. const F32 TICK = 1.0 / 30.0;
  613. if(timer.getElapsedTime() < TICK)
  614. {
  615. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  616. }
  617. }
  618. COMMON_END()
  619. }
  620. ANKI_TEST(Gr, DrawWithVertex)
  621. {
  622. COMMON_BEGIN()
  623. // The buffers
  624. struct Vert
  625. {
  626. Vec3 m_pos;
  627. Array<U8, 4> m_color;
  628. };
  629. static_assert(sizeof(Vert) == sizeof(Vec4), "See file");
  630. BufferPtr b = gr->newBuffer(BufferInitInfo(sizeof(Vert) * 3, BufferUsageBit::VERTEX, BufferMapAccessBit::WRITE));
  631. Vert* ptr = static_cast<Vert*>(b->map(0, sizeof(Vert) * 3, BufferMapAccessBit::WRITE));
  632. ANKI_TEST_EXPECT_NEQ(ptr, nullptr);
  633. ptr[0].m_pos = Vec3(-1.0, 1.0, 0.0);
  634. ptr[1].m_pos = Vec3(0.0, -1.0, 0.0);
  635. ptr[2].m_pos = Vec3(1.0, 1.0, 0.0);
  636. ptr[0].m_color = {{255, 0, 0}};
  637. ptr[1].m_color = {{0, 255, 0}};
  638. ptr[2].m_color = {{0, 0, 255}};
  639. b->unmap();
  640. BufferPtr c = gr->newBuffer(BufferInitInfo(sizeof(Vec3) * 3, BufferUsageBit::VERTEX, BufferMapAccessBit::WRITE));
  641. Vec3* otherColor = static_cast<Vec3*>(c->map(0, sizeof(Vec3) * 3, BufferMapAccessBit::WRITE));
  642. otherColor[0] = Vec3(0.0, 1.0, 1.0);
  643. otherColor[1] = Vec3(1.0, 0.0, 1.0);
  644. otherColor[2] = Vec3(1.0, 1.0, 0.0);
  645. c->unmap();
  646. // Prog
  647. ShaderProgramPtr prog = createProgram(VERT_INP_SRC, FRAG_INP_SRC, *gr);
  648. // FB
  649. FramebufferPtr fb = createDefaultFb(*gr);
  650. U iterations = 100;
  651. while(iterations--)
  652. {
  653. HighRezTimer timer;
  654. timer.start();
  655. gr->beginFrame();
  656. CommandBufferInitInfo cinit;
  657. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
  658. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  659. cmdb->bindVertexBuffer(0, b, 0, sizeof(Vert));
  660. cmdb->bindVertexBuffer(1, c, 0, sizeof(Vec3));
  661. cmdb->setVertexAttribute(0, 0, PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT), 0);
  662. cmdb->setVertexAttribute(1, 0, PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM), sizeof(Vec3));
  663. cmdb->setVertexAttribute(2, 1, PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT), 0);
  664. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  665. cmdb->setPolygonOffset(0.0, 0.0);
  666. cmdb->bindShaderProgram(prog);
  667. cmdb->beginRenderPass(fb, {}, {});
  668. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
  669. cmdb->endRenderPass();
  670. cmdb->flush();
  671. gr->swapBuffers();
  672. timer.stop();
  673. const F32 TICK = 1.0 / 30.0;
  674. if(timer.getElapsedTime() < TICK)
  675. {
  676. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  677. }
  678. }
  679. COMMON_END()
  680. }
  681. ANKI_TEST(Gr, Sampler)
  682. {
  683. COMMON_BEGIN()
  684. SamplerInitInfo init;
  685. SamplerPtr b = gr->newSampler(init);
  686. COMMON_END()
  687. }
  688. ANKI_TEST(Gr, Texture)
  689. {
  690. COMMON_BEGIN()
  691. TextureInitInfo init;
  692. init.m_depth = 1;
  693. init.m_format = PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM);
  694. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT;
  695. init.m_height = 4;
  696. init.m_width = 4;
  697. init.m_mipmapCount = 2;
  698. init.m_depth = 1;
  699. init.m_layerCount = 1;
  700. init.m_samples = 1;
  701. init.m_type = TextureType::_2D;
  702. TexturePtr b = gr->newTexture(init);
  703. TextureViewInitInfo view(b);
  704. TextureViewPtr v = gr->newTextureView(view);
  705. COMMON_END()
  706. }
  707. ANKI_TEST(Gr, DrawWithTexture)
  708. {
  709. COMMON_BEGIN()
  710. //
  711. // Create sampler
  712. //
  713. SamplerInitInfo samplerInit;
  714. samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
  715. samplerInit.m_mipmapFilter = SamplingFilter::LINEAR;
  716. samplerInit.m_repeat = false;
  717. SamplerPtr sampler = gr->newSampler(samplerInit);
  718. //
  719. // Create texture A
  720. //
  721. TextureInitInfo init;
  722. init.m_depth = 1;
  723. init.m_format = PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM);
  724. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION;
  725. init.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
  726. init.m_height = 2;
  727. init.m_width = 2;
  728. init.m_mipmapCount = 2;
  729. init.m_samples = 1;
  730. init.m_depth = 1;
  731. init.m_layerCount = 1;
  732. init.m_type = TextureType::_2D;
  733. TexturePtr a = gr->newTexture(init);
  734. TextureViewPtr aView = gr->newTextureView(TextureViewInitInfo(a));
  735. //
  736. // Create texture B
  737. //
  738. init.m_width = 4;
  739. init.m_height = 4;
  740. init.m_mipmapCount = 3;
  741. init.m_usage =
  742. TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::GENERATE_MIPMAPS;
  743. init.m_initialUsage = TextureUsageBit::NONE;
  744. TexturePtr b = gr->newTexture(init);
  745. TextureViewPtr bView = gr->newTextureView(TextureViewInitInfo(b));
  746. //
  747. // Upload all textures
  748. //
  749. Array<U8, 2 * 2 * 3> mip0 = {{255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 0, 255}};
  750. Array<U8, 3> mip1 = {{128, 128, 128}};
  751. Array<U8, 4 * 4 * 3> bmip0 = {{255,
  752. 0,
  753. 0,
  754. 0,
  755. 255,
  756. 0,
  757. 0,
  758. 0,
  759. 255,
  760. 255,
  761. 255,
  762. 0,
  763. 255,
  764. 0,
  765. 255,
  766. 0,
  767. 255,
  768. 255,
  769. 255,
  770. 255,
  771. 255,
  772. 128,
  773. 0,
  774. 0,
  775. 0,
  776. 128,
  777. 0,
  778. 0,
  779. 0,
  780. 128,
  781. 128,
  782. 128,
  783. 0,
  784. 128,
  785. 0,
  786. 128,
  787. 0,
  788. 128,
  789. 128,
  790. 128,
  791. 128,
  792. 128,
  793. 255,
  794. 128,
  795. 0,
  796. 0,
  797. 128,
  798. 255}};
  799. CommandBufferInitInfo cmdbinit;
  800. cmdbinit.m_flags = CommandBufferFlag::TRANSFER_WORK;
  801. CommandBufferPtr cmdb = gr->newCommandBuffer(cmdbinit);
  802. // Set barriers
  803. cmdb->setTextureSurfaceBarrier(
  804. a, TextureUsageBit::SAMPLED_FRAGMENT, TextureUsageBit::TRANSFER_DESTINATION, TextureSurfaceInfo(0, 0, 0, 0));
  805. cmdb->setTextureSurfaceBarrier(
  806. a, TextureUsageBit::SAMPLED_FRAGMENT, TextureUsageBit::TRANSFER_DESTINATION, TextureSurfaceInfo(1, 0, 0, 0));
  807. cmdb->setTextureSurfaceBarrier(
  808. b, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, TextureSurfaceInfo(0, 0, 0, 0));
  809. TransferGpuAllocatorHandle handle0, handle1, handle2;
  810. UPLOAD_TEX_SURFACE(cmdb, a, TextureSurfaceInfo(0, 0, 0, 0), &mip0[0], sizeof(mip0), handle0);
  811. UPLOAD_TEX_SURFACE(cmdb, a, TextureSurfaceInfo(1, 0, 0, 0), &mip1[0], sizeof(mip1), handle1);
  812. UPLOAD_TEX_SURFACE(cmdb, b, TextureSurfaceInfo(0, 0, 0, 0), &bmip0[0], sizeof(bmip0), handle2);
  813. // Gen mips
  814. cmdb->setTextureSurfaceBarrier(
  815. b, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::GENERATE_MIPMAPS, TextureSurfaceInfo(0, 0, 0, 0));
  816. cmdb->generateMipmaps2d(gr->newTextureView(TextureViewInitInfo(b)));
  817. // Set barriers
  818. cmdb->setTextureSurfaceBarrier(
  819. a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(0, 0, 0, 0));
  820. cmdb->setTextureSurfaceBarrier(
  821. a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(1, 0, 0, 0));
  822. for(U i = 0; i < 3; ++i)
  823. {
  824. cmdb->setTextureSurfaceBarrier(
  825. b, TextureUsageBit::GENERATE_MIPMAPS, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(i, 0, 0, 0));
  826. }
  827. FencePtr fence;
  828. cmdb->flush(&fence);
  829. transfAlloc->release(handle0, fence);
  830. transfAlloc->release(handle1, fence);
  831. transfAlloc->release(handle2, fence);
  832. //
  833. // Create prog
  834. //
  835. ShaderProgramPtr prog = createProgram(VERT_QUAD_SRC, FRAG_2TEX_SRC, *gr);
  836. //
  837. // Create FB
  838. //
  839. FramebufferPtr fb = createDefaultFb(*gr);
  840. //
  841. // Draw
  842. //
  843. const U ITERATION_COUNT = 200;
  844. U iterations = ITERATION_COUNT;
  845. while(iterations--)
  846. {
  847. HighRezTimer timer;
  848. timer.start();
  849. gr->beginFrame();
  850. CommandBufferInitInfo cinit;
  851. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  852. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  853. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  854. cmdb->bindShaderProgram(prog);
  855. cmdb->beginRenderPass(fb, {}, {});
  856. cmdb->bindTextureAndSampler(0, 0, aView, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  857. cmdb->bindTextureAndSampler(0, 1, bView, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  858. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  859. cmdb->endRenderPass();
  860. cmdb->flush();
  861. gr->swapBuffers();
  862. timer.stop();
  863. const F32 TICK = 1.0 / 30.0;
  864. if(timer.getElapsedTime() < TICK)
  865. {
  866. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  867. }
  868. }
  869. COMMON_END()
  870. }
  871. static void drawOffscreenDrawcalls(GrManager& gr,
  872. ShaderProgramPtr prog,
  873. CommandBufferPtr cmdb,
  874. U viewPortSize,
  875. BufferPtr indexBuff,
  876. BufferPtr vertBuff)
  877. {
  878. static F32 ang = -2.5f;
  879. ang += toRad(2.5f);
  880. Mat4 viewMat(Vec4(0.0, 0.0, 5.0, 1.0), Mat3::getIdentity(), 1.0f);
  881. viewMat.invert();
  882. Mat4 projMat = Mat4::calculatePerspectiveProjectionMatrix(toRad(60.0), toRad(60.0), 0.1f, 100.0f);
  883. Mat4 modelMat(Vec4(-0.5, -0.5, 0.0, 1.0), Mat3(Euler(ang, ang / 2.0f, ang / 3.0f)), 1.0f);
  884. Mat4* mvp = SET_UNIFORMS(Mat4*, sizeof(*mvp), cmdb, 0, 0);
  885. *mvp = projMat * viewMat * modelMat;
  886. Vec4* color = SET_UNIFORMS(Vec4*, sizeof(*color) * 2, cmdb, 0, 1);
  887. *color++ = Vec4(1.0, 0.0, 0.0, 0.0);
  888. *color = Vec4(0.0, 1.0, 0.0, 0.0);
  889. cmdb->bindVertexBuffer(0, vertBuff, 0, sizeof(Vec3));
  890. cmdb->setVertexAttribute(0, 0, PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT), 0);
  891. cmdb->bindShaderProgram(prog);
  892. cmdb->bindIndexBuffer(indexBuff, 0, IndexType::U16);
  893. cmdb->setViewport(0, 0, viewPortSize, viewPortSize);
  894. cmdb->drawElements(PrimitiveTopology::TRIANGLES, 6 * 2 * 3);
  895. // 2nd draw
  896. modelMat = Mat4(Vec4(0.5, 0.5, 0.0, 1.0), Mat3(Euler(ang * 2.0, ang, ang / 3.0f * 2.0)), 1.0f);
  897. mvp = SET_UNIFORMS(Mat4*, sizeof(*mvp), cmdb, 0, 0);
  898. *mvp = projMat * viewMat * modelMat;
  899. color = SET_UNIFORMS(Vec4*, sizeof(*color) * 2, cmdb, 0, 1);
  900. *color++ = Vec4(0.0, 0.0, 1.0, 0.0);
  901. *color = Vec4(0.0, 1.0, 1.0, 0.0);
  902. cmdb->drawElements(PrimitiveTopology::TRIANGLES, 6 * 2 * 3);
  903. }
  904. static void drawOffscreen(GrManager& gr, Bool useSecondLevel)
  905. {
  906. //
  907. // Create textures
  908. //
  909. SamplerInitInfo samplerInit;
  910. samplerInit.m_minMagFilter = SamplingFilter::LINEAR;
  911. samplerInit.m_mipmapFilter = SamplingFilter::LINEAR;
  912. SamplerPtr sampler = gr.newSampler(samplerInit);
  913. const PixelFormat COL_FORMAT = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  914. const U TEX_SIZE = 256;
  915. TextureInitInfo init;
  916. init.m_format = COL_FORMAT;
  917. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE;
  918. init.m_height = TEX_SIZE;
  919. init.m_width = TEX_SIZE;
  920. init.m_type = TextureType::_2D;
  921. TexturePtr col0 = gr.newTexture(init);
  922. TexturePtr col1 = gr.newTexture(init);
  923. TextureViewPtr col0View = gr.newTextureView(TextureViewInitInfo(col0));
  924. TextureViewPtr col1View = gr.newTextureView(TextureViewInitInfo(col1));
  925. init.m_format = DS_FORMAT;
  926. TexturePtr dp = gr.newTexture(init);
  927. //
  928. // Create FB
  929. //
  930. FramebufferInitInfo fbinit;
  931. fbinit.m_colorAttachmentCount = 2;
  932. fbinit.m_colorAttachments[0].m_textureView = gr.newTextureView(TextureViewInitInfo(col0));
  933. fbinit.m_colorAttachments[0].m_clearValue.m_colorf = {{0.1, 0.0, 0.0, 0.0}};
  934. fbinit.m_colorAttachments[1].m_textureView = gr.newTextureView(TextureViewInitInfo(col1));
  935. fbinit.m_colorAttachments[1].m_clearValue.m_colorf = {{0.0, 0.1, 0.0, 0.0}};
  936. TextureViewInitInfo viewInit(dp);
  937. viewInit.m_depthStencilAspect = DepthStencilAspectBit::DEPTH;
  938. fbinit.m_depthStencilAttachment.m_textureView = gr.newTextureView(viewInit);
  939. fbinit.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0;
  940. FramebufferPtr fb = gr.newFramebuffer(fbinit);
  941. //
  942. // Create default FB
  943. //
  944. FramebufferPtr dfb = createDefaultFb(gr);
  945. //
  946. // Create buffs
  947. //
  948. BufferPtr verts, indices;
  949. createCube(gr, verts, indices);
  950. //
  951. // Create progs
  952. //
  953. ShaderProgramPtr prog = createProgram(VERT_MRT_SRC, FRAG_MRT_SRC, gr);
  954. ShaderProgramPtr resolveProg = createProgram(VERT_QUAD_SRC, FRAG_MRT2_SRC, gr);
  955. //
  956. // Draw
  957. //
  958. const U ITERATION_COUNT = 200;
  959. U iterations = ITERATION_COUNT;
  960. while(iterations--)
  961. {
  962. HighRezTimer timer;
  963. timer.start();
  964. gr.beginFrame();
  965. CommandBufferInitInfo cinit;
  966. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
  967. CommandBufferPtr cmdb = gr.newCommandBuffer(cinit);
  968. cmdb->setPolygonOffset(0.0, 0.0);
  969. cmdb->setTextureSurfaceBarrier(
  970. col0, TextureUsageBit::NONE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, TextureSurfaceInfo(0, 0, 0, 0));
  971. cmdb->setTextureSurfaceBarrier(
  972. col1, TextureUsageBit::NONE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, TextureSurfaceInfo(0, 0, 0, 0));
  973. cmdb->setTextureSurfaceBarrier(dp,
  974. TextureUsageBit::NONE,
  975. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
  976. TextureSurfaceInfo(0, 0, 0, 0));
  977. cmdb->beginRenderPass(fb,
  978. {{TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE}},
  979. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE);
  980. if(!useSecondLevel)
  981. {
  982. drawOffscreenDrawcalls(gr, prog, cmdb, TEX_SIZE, indices, verts);
  983. }
  984. else
  985. {
  986. CommandBufferInitInfo cinit;
  987. cinit.m_flags = CommandBufferFlag::SECOND_LEVEL | CommandBufferFlag::GRAPHICS_WORK;
  988. cinit.m_framebuffer = fb;
  989. CommandBufferPtr cmdb2 = gr.newCommandBuffer(cinit);
  990. drawOffscreenDrawcalls(gr, prog, cmdb2, TEX_SIZE, indices, verts);
  991. cmdb2->flush();
  992. cmdb->pushSecondLevelCommandBuffer(cmdb2);
  993. }
  994. cmdb->endRenderPass();
  995. cmdb->setTextureSurfaceBarrier(col0,
  996. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  997. TextureUsageBit::SAMPLED_FRAGMENT,
  998. TextureSurfaceInfo(0, 0, 0, 0));
  999. cmdb->setTextureSurfaceBarrier(col1,
  1000. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
  1001. TextureUsageBit::SAMPLED_FRAGMENT,
  1002. TextureSurfaceInfo(0, 0, 0, 0));
  1003. cmdb->setTextureSurfaceBarrier(dp,
  1004. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
  1005. TextureUsageBit::SAMPLED_FRAGMENT,
  1006. TextureSurfaceInfo(0, 0, 0, 0));
  1007. // Draw quad
  1008. cmdb->beginRenderPass(dfb, {}, {});
  1009. cmdb->bindShaderProgram(resolveProg);
  1010. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  1011. cmdb->bindTextureAndSampler(0, 0, col0View, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  1012. cmdb->bindTextureAndSampler(0, 1, col1View, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  1013. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  1014. cmdb->endRenderPass();
  1015. cmdb->flush();
  1016. // End
  1017. gr.swapBuffers();
  1018. timer.stop();
  1019. const F32 TICK = 1.0 / 30.0;
  1020. if(timer.getElapsedTime() < TICK)
  1021. {
  1022. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  1023. }
  1024. }
  1025. }
  1026. ANKI_TEST(Gr, DrawOffscreen)
  1027. {
  1028. COMMON_BEGIN()
  1029. drawOffscreen(*gr, false);
  1030. COMMON_END()
  1031. }
  1032. ANKI_TEST(Gr, DrawWithSecondLevel)
  1033. {
  1034. COMMON_BEGIN()
  1035. drawOffscreen(*gr, true);
  1036. COMMON_END()
  1037. }
  1038. ANKI_TEST(Gr, ImageLoadStore)
  1039. {
  1040. COMMON_BEGIN()
  1041. SamplerInitInfo samplerInit;
  1042. samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
  1043. samplerInit.m_mipmapFilter = SamplingFilter::BASE;
  1044. SamplerPtr sampler = gr->newSampler(samplerInit);
  1045. TextureInitInfo init;
  1046. init.m_width = init.m_height = 4;
  1047. init.m_mipmapCount = 2;
  1048. init.m_usage = TextureUsageBit::CLEAR | TextureUsageBit::SAMPLED_ALL | TextureUsageBit::IMAGE_COMPUTE_WRITE;
  1049. init.m_type = TextureType::_2D;
  1050. init.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  1051. TexturePtr tex = gr->newTexture(init);
  1052. TextureViewInitInfo viewInit(tex);
  1053. viewInit.m_firstMipmap = 1;
  1054. viewInit.m_mipmapCount = 1;
  1055. TextureViewPtr view = gr->newTextureView(viewInit);
  1056. // Prog
  1057. ShaderProgramPtr prog = createProgram(VERT_QUAD_SRC, FRAG_SIMPLE_TEX_SRC, *gr);
  1058. // Create shader & compute prog
  1059. ShaderPtr shader = gr->newShader({ShaderType::COMPUTE, COMP_WRITE_IMAGE_SRC});
  1060. ShaderProgramInitInfo sprogInit;
  1061. sprogInit.m_shaders[ShaderType::COMPUTE] = shader;
  1062. ShaderProgramPtr compProg = gr->newShaderProgram(sprogInit);
  1063. // FB
  1064. FramebufferPtr dfb = createDefaultFb(*gr);
  1065. // Write texture data
  1066. CommandBufferInitInfo cmdbinit;
  1067. CommandBufferPtr cmdb = gr->newCommandBuffer(cmdbinit);
  1068. cmdb->setTextureSurfaceBarrier(tex, TextureUsageBit::NONE, TextureUsageBit::CLEAR, TextureSurfaceInfo(0, 0, 0, 0));
  1069. ClearValue clear;
  1070. clear.m_colorf = {{0.0, 1.0, 0.0, 1.0}};
  1071. TextureViewInitInfo viewInit2(tex, TextureSurfaceInfo(0, 0, 0, 0));
  1072. cmdb->clearTextureView(gr->newTextureView(viewInit2), clear);
  1073. cmdb->setTextureSurfaceBarrier(
  1074. tex, TextureUsageBit::CLEAR, TextureUsageBit::SAMPLED_FRAGMENT, TextureSurfaceInfo(0, 0, 0, 0));
  1075. cmdb->setTextureSurfaceBarrier(tex, TextureUsageBit::NONE, TextureUsageBit::CLEAR, TextureSurfaceInfo(1, 0, 0, 0));
  1076. clear.m_colorf = {{0.0, 0.0, 1.0, 1.0}};
  1077. TextureViewInitInfo viewInit3(tex, TextureSurfaceInfo(1, 0, 0, 0));
  1078. cmdb->clearTextureView(gr->newTextureView(viewInit3), clear);
  1079. cmdb->setTextureSurfaceBarrier(
  1080. tex, TextureUsageBit::CLEAR, TextureUsageBit::IMAGE_COMPUTE_WRITE, TextureSurfaceInfo(1, 0, 0, 0));
  1081. cmdb->flush();
  1082. const U ITERATION_COUNT = 100;
  1083. U iterations = ITERATION_COUNT;
  1084. while(iterations--)
  1085. {
  1086. HighRezTimer timer;
  1087. timer.start();
  1088. gr->beginFrame();
  1089. CommandBufferInitInfo cinit;
  1090. cinit.m_flags =
  1091. CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::COMPUTE_WORK | CommandBufferFlag::SMALL_BATCH;
  1092. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  1093. // Write image
  1094. Vec4* col = SET_STORAGE(Vec4*, sizeof(*col), cmdb, 1, 0);
  1095. *col = Vec4(iterations / F32(ITERATION_COUNT));
  1096. cmdb->setTextureSurfaceBarrier(
  1097. tex, TextureUsageBit::NONE, TextureUsageBit::IMAGE_COMPUTE_WRITE, TextureSurfaceInfo(1, 0, 0, 0));
  1098. cmdb->bindShaderProgram(compProg);
  1099. cmdb->bindImage(0, 0, view);
  1100. cmdb->dispatchCompute(WIDTH / 2, HEIGHT / 2, 1);
  1101. cmdb->setTextureSurfaceBarrier(tex,
  1102. TextureUsageBit::IMAGE_COMPUTE_WRITE,
  1103. TextureUsageBit::SAMPLED_FRAGMENT,
  1104. TextureSurfaceInfo(1, 0, 0, 0));
  1105. // Present image
  1106. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  1107. cmdb->bindShaderProgram(prog);
  1108. cmdb->beginRenderPass(dfb, {}, {});
  1109. cmdb->bindTextureAndSampler(
  1110. 0, 0, gr->newTextureView(TextureViewInitInfo(tex)), sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  1111. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  1112. cmdb->endRenderPass();
  1113. cmdb->flush();
  1114. // End
  1115. gr->swapBuffers();
  1116. timer.stop();
  1117. const F32 TICK = 1.0 / 30.0;
  1118. if(timer.getElapsedTime() < TICK)
  1119. {
  1120. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  1121. }
  1122. }
  1123. COMMON_END()
  1124. }
  1125. ANKI_TEST(Gr, 3DTextures)
  1126. {
  1127. COMMON_BEGIN()
  1128. SamplerInitInfo samplerInit;
  1129. samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
  1130. samplerInit.m_mipmapFilter = SamplingFilter::BASE;
  1131. samplerInit.m_repeat = false;
  1132. SamplerPtr sampler = gr->newSampler(samplerInit);
  1133. //
  1134. // Create texture A
  1135. //
  1136. TextureInitInfo init;
  1137. init.m_depth = 1;
  1138. init.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  1139. init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION;
  1140. init.m_initialUsage = TextureUsageBit::TRANSFER_DESTINATION;
  1141. init.m_height = 2;
  1142. init.m_width = 2;
  1143. init.m_mipmapCount = 2;
  1144. init.m_samples = 1;
  1145. init.m_depth = 2;
  1146. init.m_layerCount = 1;
  1147. init.m_type = TextureType::_3D;
  1148. TexturePtr a = gr->newTexture(init);
  1149. //
  1150. // Upload all textures
  1151. //
  1152. Array<U8, 2 * 2 * 2 * 4> mip0 = {{255,
  1153. 0,
  1154. 0,
  1155. 0,
  1156. 0,
  1157. 255,
  1158. 0,
  1159. 0,
  1160. 0,
  1161. 0,
  1162. 255,
  1163. 0,
  1164. 255,
  1165. 255,
  1166. 0,
  1167. 0,
  1168. 255,
  1169. 0,
  1170. 255,
  1171. 0,
  1172. 0,
  1173. 255,
  1174. 255,
  1175. 0,
  1176. 255,
  1177. 255,
  1178. 255,
  1179. 0,
  1180. 0,
  1181. 0,
  1182. 0,
  1183. 0}};
  1184. Array<U8, 4> mip1 = {{128, 128, 128, 0}};
  1185. CommandBufferInitInfo cmdbinit;
  1186. cmdbinit.m_flags = CommandBufferFlag::TRANSFER_WORK | CommandBufferFlag::SMALL_BATCH;
  1187. CommandBufferPtr cmdb = gr->newCommandBuffer(cmdbinit);
  1188. cmdb->setTextureVolumeBarrier(
  1189. a, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, TextureVolumeInfo(0));
  1190. cmdb->setTextureVolumeBarrier(
  1191. a, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, TextureVolumeInfo(1));
  1192. TransferGpuAllocatorHandle handle0, handle1;
  1193. UPLOAD_TEX_VOL(cmdb, a, TextureVolumeInfo(0), &mip0[0], sizeof(mip0), handle0);
  1194. UPLOAD_TEX_VOL(cmdb, a, TextureVolumeInfo(1), &mip1[0], sizeof(mip1), handle1);
  1195. cmdb->setTextureVolumeBarrier(
  1196. a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureVolumeInfo(0));
  1197. cmdb->setTextureVolumeBarrier(
  1198. a, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_FRAGMENT, TextureVolumeInfo(1));
  1199. FencePtr fence;
  1200. cmdb->flush(&fence);
  1201. transfAlloc->release(handle0, fence);
  1202. transfAlloc->release(handle1, fence);
  1203. //
  1204. // Rest
  1205. //
  1206. ShaderProgramPtr prog = createProgram(VERT_QUAD_SRC, FRAG_TEX3D_SRC, *gr);
  1207. FramebufferPtr dfb = createDefaultFb(*gr);
  1208. static Array<Vec4, 9> TEX_COORDS_LOD = {{Vec4(0, 0, 0, 0),
  1209. Vec4(1, 0, 0, 0),
  1210. Vec4(0, 1, 0, 0),
  1211. Vec4(1, 1, 0, 0),
  1212. Vec4(0, 0, 1, 0),
  1213. Vec4(1, 0, 1, 0),
  1214. Vec4(0, 1, 1, 0),
  1215. Vec4(1, 1, 1, 0),
  1216. Vec4(0, 0, 0, 1)}};
  1217. const U ITERATION_COUNT = 100;
  1218. U iterations = ITERATION_COUNT;
  1219. while(iterations--)
  1220. {
  1221. HighRezTimer timer;
  1222. timer.start();
  1223. gr->beginFrame();
  1224. CommandBufferInitInfo cinit;
  1225. cinit.m_flags = CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SMALL_BATCH;
  1226. CommandBufferPtr cmdb = gr->newCommandBuffer(cinit);
  1227. cmdb->setViewport(0, 0, WIDTH, HEIGHT);
  1228. cmdb->beginRenderPass(dfb, {}, {});
  1229. cmdb->bindShaderProgram(prog);
  1230. Vec4* uv = SET_UNIFORMS(Vec4*, sizeof(Vec4), cmdb, 0, 0);
  1231. U idx = (F32(ITERATION_COUNT - iterations - 1) / ITERATION_COUNT) * TEX_COORDS_LOD.getSize();
  1232. *uv = TEX_COORDS_LOD[idx];
  1233. cmdb->bindTextureAndSampler(
  1234. 0, 0, gr->newTextureView(TextureViewInitInfo(a)), sampler, TextureUsageBit::SAMPLED_FRAGMENT);
  1235. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
  1236. cmdb->endRenderPass();
  1237. cmdb->flush();
  1238. // End
  1239. gr->swapBuffers();
  1240. timer.stop();
  1241. const F32 TICK = 1.0 / 15.0;
  1242. if(timer.getElapsedTime() < TICK)
  1243. {
  1244. HighRezTimer::sleep(TICK - timer.getElapsedTime());
  1245. }
  1246. }
  1247. COMMON_END()
  1248. }
  1249. static RenderTargetDescription newRTDescr(CString name)
  1250. {
  1251. RenderTargetDescription texInf(name);
  1252. texInf.m_width = texInf.m_height = 16;
  1253. texInf.m_usage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT;
  1254. texInf.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  1255. texInf.bake();
  1256. return texInf;
  1257. }
  1258. ANKI_TEST(Gr, RenderGraph)
  1259. {
  1260. COMMON_BEGIN()
  1261. StackAllocator<U8> alloc(allocAligned, nullptr, 2_MB);
  1262. RenderGraphDescription descr(alloc);
  1263. RenderGraphPtr rgraph = gr->newRenderGraph();
  1264. const U GI_MIP_COUNT = 4;
  1265. TextureInitInfo texI("dummy");
  1266. texI.m_width = texI.m_height = 16;
  1267. texI.m_usage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT;
  1268. texI.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  1269. TexturePtr dummyTex = gr->newTexture(texI);
  1270. // SM
  1271. RenderTargetHandle smScratchRt = descr.newRenderTarget(newRTDescr("SM scratch"));
  1272. {
  1273. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("SM");
  1274. pass.newConsumer({smScratchRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE});
  1275. pass.newProducer({smScratchRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE});
  1276. }
  1277. // SM to exponential SM
  1278. RenderTargetHandle smExpRt = descr.importRenderTarget("ESM", dummyTex, TextureUsageBit::SAMPLED_FRAGMENT);
  1279. {
  1280. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("ESM");
  1281. pass.newConsumer({smScratchRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1282. pass.newConsumer({smExpRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1283. pass.newProducer({smExpRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1284. }
  1285. // GI gbuff
  1286. RenderTargetHandle giGbuffNormRt = descr.newRenderTarget(newRTDescr("GI GBuff norm"));
  1287. RenderTargetHandle giGbuffDiffRt = descr.newRenderTarget(newRTDescr("GI GBuff diff"));
  1288. RenderTargetHandle giGbuffDepthRt = descr.newRenderTarget(newRTDescr("GI GBuff depth"));
  1289. {
  1290. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("GI gbuff");
  1291. pass.newConsumer({giGbuffNormRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1292. pass.newConsumer({giGbuffDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1293. pass.newConsumer({giGbuffDiffRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1294. pass.newProducer({giGbuffNormRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1295. pass.newProducer({giGbuffDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1296. pass.newProducer({giGbuffDiffRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1297. }
  1298. // GI light
  1299. RenderTargetHandle giGiLightRt = descr.importRenderTarget("GI light", dummyTex, TextureUsageBit::SAMPLED_FRAGMENT);
  1300. for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
  1301. {
  1302. TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, 0));
  1303. GraphicsRenderPassDescription& pass =
  1304. descr.newGraphicsRenderPass(StringAuto(alloc).sprintf("GI lp%u", faceIdx).toCString());
  1305. pass.newConsumer({giGiLightRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, subresource});
  1306. pass.newConsumer({giGbuffNormRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1307. pass.newConsumer({giGbuffDepthRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1308. pass.newConsumer({giGbuffDiffRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1309. pass.newProducer({giGiLightRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, subresource});
  1310. }
  1311. // GI light mips
  1312. {
  1313. for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
  1314. {
  1315. GraphicsRenderPassDescription& pass =
  1316. descr.newGraphicsRenderPass(StringAuto(alloc).sprintf("GI mip%u", faceIdx).toCString());
  1317. for(U mip = 0; mip < GI_MIP_COUNT; ++mip)
  1318. {
  1319. TextureSurfaceInfo surf(mip, 0, faceIdx, 0);
  1320. pass.newConsumer({giGiLightRt, TextureUsageBit::GENERATE_MIPMAPS, surf});
  1321. pass.newProducer({giGiLightRt, TextureUsageBit::GENERATE_MIPMAPS, surf});
  1322. }
  1323. }
  1324. }
  1325. // Gbuffer
  1326. RenderTargetHandle gbuffRt0 = descr.newRenderTarget(newRTDescr("GBuff RT0"));
  1327. RenderTargetHandle gbuffRt1 = descr.newRenderTarget(newRTDescr("GBuff RT1"));
  1328. RenderTargetHandle gbuffRt2 = descr.newRenderTarget(newRTDescr("GBuff RT2"));
  1329. RenderTargetHandle gbuffDepth = descr.newRenderTarget(newRTDescr("GBuff RT2"));
  1330. {
  1331. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("G-Buffer");
  1332. pass.newConsumer({gbuffRt0, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1333. pass.newConsumer({gbuffRt1, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1334. pass.newConsumer({gbuffRt2, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1335. pass.newConsumer({gbuffDepth, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1336. pass.newProducer({gbuffRt0, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1337. pass.newProducer({gbuffRt1, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1338. pass.newProducer({gbuffRt2, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1339. pass.newProducer({gbuffDepth, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1340. }
  1341. // Half depth
  1342. RenderTargetHandle halfDepthRt = descr.newRenderTarget(newRTDescr("Depth/2"));
  1343. {
  1344. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("HalfDepth");
  1345. pass.newConsumer({gbuffDepth, TextureUsageBit::SAMPLED_FRAGMENT});
  1346. pass.newConsumer({halfDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1347. pass.newProducer({halfDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1348. }
  1349. // Quarter depth
  1350. RenderTargetHandle quarterDepthRt = descr.newRenderTarget(newRTDescr("Depth/4"));
  1351. {
  1352. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("QuarterDepth");
  1353. pass.newConsumer({quarterDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1354. pass.newConsumer({halfDepthRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1355. pass.newProducer({quarterDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1356. }
  1357. // SSAO
  1358. RenderTargetHandle ssaoRt = descr.newRenderTarget(newRTDescr("SSAO"));
  1359. {
  1360. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("SSAO main");
  1361. pass.newConsumer({ssaoRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1362. pass.newConsumer({quarterDepthRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1363. pass.newConsumer({gbuffRt2, TextureUsageBit::SAMPLED_FRAGMENT});
  1364. pass.newProducer({ssaoRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1365. RenderTargetHandle ssaoVBlurRt = descr.newRenderTarget(newRTDescr("SSAO tmp"));
  1366. GraphicsRenderPassDescription& pass2 = descr.newGraphicsRenderPass("SSAO vblur");
  1367. pass2.newConsumer({ssaoRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1368. pass2.newConsumer({ssaoVBlurRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1369. pass2.newProducer({ssaoVBlurRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1370. GraphicsRenderPassDescription& pass3 = descr.newGraphicsRenderPass("SSAO hblur");
  1371. pass3.newConsumer({ssaoRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1372. pass3.newProducer({ssaoRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1373. pass3.newConsumer({ssaoVBlurRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1374. }
  1375. // Volumetric
  1376. RenderTargetHandle volRt = descr.newRenderTarget(newRTDescr("Vol"));
  1377. {
  1378. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("Vol main");
  1379. pass.newConsumer({volRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1380. pass.newConsumer({quarterDepthRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1381. pass.newProducer({volRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1382. RenderTargetHandle volVBlurRt = descr.newRenderTarget(newRTDescr("Vol tmp"));
  1383. GraphicsRenderPassDescription& pass2 = descr.newGraphicsRenderPass("Vol vblur");
  1384. pass2.newConsumer({volRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1385. pass2.newConsumer({volVBlurRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1386. pass2.newProducer({volVBlurRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1387. GraphicsRenderPassDescription& pass3 = descr.newGraphicsRenderPass("Vol hblur");
  1388. pass3.newConsumer({volRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1389. pass3.newProducer({volRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1390. pass3.newConsumer({volVBlurRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1391. }
  1392. // Forward shading
  1393. RenderTargetHandle fsRt = descr.newRenderTarget(newRTDescr("FS"));
  1394. {
  1395. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("Forward shading");
  1396. pass.newConsumer({fsRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1397. pass.newProducer({fsRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1398. pass.newConsumer(
  1399. {halfDepthRt, TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ});
  1400. pass.newConsumer({volRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1401. }
  1402. // Light shading
  1403. RenderTargetHandle lightRt = descr.importRenderTarget("Light", dummyTex, TextureUsageBit::NONE);
  1404. {
  1405. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("Light shading");
  1406. pass.newConsumer({lightRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1407. pass.newConsumer({gbuffRt0, TextureUsageBit::SAMPLED_FRAGMENT});
  1408. pass.newConsumer({gbuffRt1, TextureUsageBit::SAMPLED_FRAGMENT});
  1409. pass.newConsumer({gbuffRt2, TextureUsageBit::SAMPLED_FRAGMENT});
  1410. pass.newConsumer({gbuffDepth, TextureUsageBit::SAMPLED_FRAGMENT});
  1411. pass.newConsumer({smExpRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1412. pass.newConsumer({giGiLightRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1413. pass.newConsumer({ssaoRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1414. pass.newConsumer({fsRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1415. pass.newProducer({lightRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1416. }
  1417. // TAA
  1418. RenderTargetHandle taaHistoryRt = descr.importRenderTarget("TAA hist", dummyTex, TextureUsageBit::SAMPLED_FRAGMENT);
  1419. RenderTargetHandle taaRt = descr.importRenderTarget("TAA", dummyTex, TextureUsageBit::NONE);
  1420. {
  1421. GraphicsRenderPassDescription& pass = descr.newGraphicsRenderPass("Temporal AA");
  1422. pass.newConsumer({lightRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1423. pass.newConsumer({taaRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1424. pass.newProducer({taaRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  1425. pass.newConsumer({taaHistoryRt, TextureUsageBit::SAMPLED_FRAGMENT});
  1426. }
  1427. rgraph->compileNewGraph(descr, alloc);
  1428. COMMON_END()
  1429. }
  1430. /// Test workarounds for some unsupported formats
  1431. ANKI_TEST(Gr, VkWorkarounds)
  1432. {
  1433. COMMON_BEGIN()
  1434. // Create program
  1435. static const char* COMP_SRC = R"(
  1436. layout(local_size_x = 8, local_size_y = 8, local_size_z = 2) in;
  1437. layout(ANKI_TEX_BINDING(0, 0)) uniform usampler2D u_tex;
  1438. layout(ANKI_SS_BINDING(0, 0)) buffer s_
  1439. {
  1440. uvec4 u_result;
  1441. };
  1442. shared uint g_wrong;
  1443. void main()
  1444. {
  1445. g_wrong = 0;
  1446. memoryBarrierShared();
  1447. barrier();
  1448. int lod;
  1449. uint idx;
  1450. if(gl_LocalInvocationID.z == 0)
  1451. {
  1452. // First mip
  1453. lod = 0;
  1454. uint idx = gl_LocalInvocationID.y * 8 + gl_LocalInvocationID.x;
  1455. }
  1456. else if(gl_LocalInvocationID.x < 4u && gl_LocalInvocationID.y < 4u)
  1457. {
  1458. lod = 1;
  1459. idx = gl_LocalInvocationID.y * 4 + gl_LocalInvocationID.x;
  1460. }
  1461. uvec3 col = texelFetch(u_tex, ivec2(gl_LocalInvocationID.x, gl_LocalInvocationID.x), lod).rgb;
  1462. if(col.x != idx || col.y != idx + 1 || col.z != idx + 2)
  1463. {
  1464. atomicAdd(g_wrong, 1);
  1465. }
  1466. memoryBarrierShared();
  1467. barrier();
  1468. if(g_wrong != 0)
  1469. {
  1470. u_result = uvec4(1);
  1471. }
  1472. else
  1473. {
  1474. u_result = uvec4(2);
  1475. }
  1476. })";
  1477. ShaderPtr comp = gr->newShader(ShaderInitInfo(ShaderType::COMPUTE, COMP_SRC));
  1478. ShaderProgramPtr prog = gr->newShaderProgram(ShaderProgramInitInfo(comp));
  1479. // Create the texture
  1480. TextureInitInfo texInit;
  1481. texInit.m_width = texInit.m_height = 8;
  1482. texInit.m_format = PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UINT);
  1483. texInit.m_type = TextureType::_2D;
  1484. texInit.m_usage = TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::SAMPLED_ALL;
  1485. texInit.m_mipmapCount = 2;
  1486. TexturePtr tex = gr->newTexture(texInit);
  1487. TextureViewPtr texView = gr->newTextureView(TextureViewInitInfo(tex));
  1488. SamplerInitInfo samplerInit;
  1489. SamplerPtr sampler = gr->newSampler(samplerInit);
  1490. // Create the buffer to copy to the texture
  1491. BufferPtr uploadBuff = gr->newBuffer(BufferInitInfo(
  1492. texInit.m_width * texInit.m_height * 3, BufferUsageBit::TRANSFER_ALL, BufferMapAccessBit::WRITE));
  1493. U8* data = static_cast<U8*>(uploadBuff->map(0, uploadBuff->getSize(), BufferMapAccessBit::WRITE));
  1494. for(U i = 0; i < texInit.m_width * texInit.m_height; ++i)
  1495. {
  1496. data[0] = i;
  1497. data[1] = i + 1;
  1498. data[2] = i + 2;
  1499. data += 3;
  1500. }
  1501. BufferPtr uploadBuff2 = gr->newBuffer(BufferInitInfo(
  1502. (texInit.m_width >> 1) * (texInit.m_height >> 1) * 3, BufferUsageBit::TRANSFER_ALL, BufferMapAccessBit::WRITE));
  1503. data = static_cast<U8*>(uploadBuff2->map(0, uploadBuff2->getSize(), BufferMapAccessBit::WRITE));
  1504. for(U i = 0; i < (texInit.m_width >> 1) * (texInit.m_height >> 1); ++i)
  1505. {
  1506. data[0] = i;
  1507. data[1] = i + 1;
  1508. data[2] = i + 2;
  1509. data += 3;
  1510. }
  1511. // Create the result buffer
  1512. BufferPtr resultBuff =
  1513. gr->newBuffer(BufferInitInfo(sizeof(UVec4), BufferUsageBit::STORAGE_COMPUTE_WRITE, BufferMapAccessBit::READ));
  1514. // Upload data and test them
  1515. CommandBufferInitInfo cmdbInit;
  1516. cmdbInit.m_flags = CommandBufferFlag::TRANSFER_WORK | CommandBufferFlag::SMALL_BATCH;
  1517. CommandBufferPtr cmdb = gr->newCommandBuffer(cmdbInit);
  1518. TextureSubresourceInfo subresource;
  1519. subresource.m_mipmapCount = texInit.m_mipmapCount;
  1520. cmdb->setTextureBarrier(tex, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, subresource);
  1521. cmdb->copyBufferToTextureView(uploadBuff,
  1522. 0,
  1523. uploadBuff->getSize(),
  1524. gr->newTextureView(TextureViewInitInfo(tex, TextureSurfaceInfo(0, 0, 0, 0))));
  1525. cmdb->copyBufferToTextureView(uploadBuff2,
  1526. 0,
  1527. uploadBuff2->getSize(),
  1528. gr->newTextureView(TextureViewInitInfo(tex, TextureSurfaceInfo(1, 0, 0, 0))));
  1529. cmdb->setTextureBarrier(tex, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::SAMPLED_COMPUTE, subresource);
  1530. cmdb->bindShaderProgram(prog);
  1531. cmdb->bindTextureAndSampler(0, 0, texView, sampler, TextureUsageBit::SAMPLED_COMPUTE);
  1532. cmdb->bindStorageBuffer(0, 0, resultBuff, 0, resultBuff->getSize());
  1533. cmdb->setBufferBarrier(resultBuff,
  1534. BufferUsageBit::STORAGE_COMPUTE_WRITE,
  1535. BufferUsageBit::STORAGE_COMPUTE_WRITE,
  1536. 0,
  1537. resultBuff->getSize());
  1538. cmdb->finish();
  1539. // Get the result
  1540. UVec4* result = static_cast<UVec4*>(resultBuff->map(0, resultBuff->getSize(), BufferMapAccessBit::READ));
  1541. ANKI_TEST_EXPECT_EQ(result->x(), 2);
  1542. ANKI_TEST_EXPECT_EQ(result->y(), 2);
  1543. ANKI_TEST_EXPECT_EQ(result->z(), 2);
  1544. ANKI_TEST_EXPECT_EQ(result->w(), 2);
  1545. COMMON_END()
  1546. }
  1547. } // end namespace anki