GrMeshShaders.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // Copyright (C) 2009-2023, 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 <Tests/Gr/GrCommon.h>
  7. #include <AnKi/Gr.h>
  8. #include <AnKi/Util/MemoryPool.h>
  9. #include <AnKi/Util/HighRezTimer.h>
  10. ANKI_TEST(Gr, MeshShaders)
  11. {
  12. constexpr U32 kTileCount = 4;
  13. constexpr U32 kVertCount = 4;
  14. g_validationCVar.set(true);
  15. g_windowWidthCVar.set(64 * kTileCount);
  16. g_windowHeightCVar.set(64);
  17. g_meshShadersCVar.set(true);
  18. DefaultMemoryPool::allocateSingleton(allocAligned, nullptr);
  19. NativeWindow* win = createWindow();
  20. GrManager* gr = createGrManager(win);
  21. {
  22. const CString taskShaderSrc = R"(
  23. struct Payload
  24. {
  25. uint m_meshletIndices[64];
  26. };
  27. groupshared Payload s_payload;
  28. groupshared uint s_visibleCount;
  29. struct Meshlet
  30. {
  31. uint m_firstIndex;
  32. uint m_firstVertex;
  33. };
  34. [[vk::binding(3)]] StructuredBuffer<Meshlet> g_meshlets;
  35. [numthreads(64, 1, 1)] void main(uint svDispatchThreadId : SV_DISPATCHTHREADID)
  36. {
  37. uint meshletCount, unused;
  38. g_meshlets.GetDimensions(meshletCount, unused);
  39. bool visible = ((svDispatchThreadId & 1u) == 0u) && (svDispatchThreadId < meshletCount);
  40. s_visibleCount = 0;
  41. GroupMemoryBarrierWithGroupSync();
  42. if(visible)
  43. {
  44. uint index;
  45. InterlockedAdd(s_visibleCount, 1u, index);
  46. s_payload.m_meshletIndices[index] = svDispatchThreadId;
  47. }
  48. GroupMemoryBarrierWithGroupSync();
  49. DispatchMesh(s_visibleCount, 1, 1, s_payload);
  50. })";
  51. const CString meshShaderSrc = R"(
  52. struct Payload
  53. {
  54. uint m_meshletIndices[64];
  55. };
  56. struct VertOut
  57. {
  58. float4 m_svPosition : SV_POSITION;
  59. float3 m_color : COLOR0;
  60. };
  61. struct Meshlet
  62. {
  63. uint m_firstIndex;
  64. uint m_firstVertex;
  65. };
  66. [[vk::binding(0)]] StructuredBuffer<uint> g_indices;
  67. [[vk::binding(1)]] StructuredBuffer<float4> g_positions;
  68. [[vk::binding(2)]] StructuredBuffer<float4> g_colors;
  69. [[vk::binding(3)]] StructuredBuffer<Meshlet> g_meshlets;
  70. [numthreads(6, 1, 1)] [outputtopology("triangle")] void main(in payload Payload payload, out vertices VertOut verts[4],
  71. out indices uint3 indices[6], uint svGroupId : SV_GROUPID,
  72. uint svGroupIndex : SV_GROUPINDEX)
  73. {
  74. uint meshletIdx = payload.m_meshletIndices[svGroupId];
  75. Meshlet meshlet = g_meshlets[meshletIdx];
  76. SetMeshOutputCounts(4, 6);
  77. if(svGroupIndex < 4)
  78. {
  79. verts[svGroupIndex].m_svPosition = g_positions[meshlet.m_firstVertex + svGroupIndex];
  80. verts[svGroupIndex].m_color = g_colors[meshlet.m_firstVertex + svGroupIndex];
  81. }
  82. [unroll] for(uint i = 0; i < 6; ++i)
  83. {
  84. indices[svGroupIndex][i] = g_indices[meshlet.m_firstIndex + i];
  85. }
  86. })";
  87. const CString fragShaderSrc = R"(
  88. struct VertOut
  89. {
  90. float4 m_svPosition : SV_POSITION;
  91. float3 m_color : COLOR0;
  92. };
  93. float3 main(VertOut input) : SV_TARGET0
  94. {
  95. return input.m_color;
  96. })";
  97. ShaderProgramPtr prog;
  98. {
  99. ShaderPtr taskShader = createShader(taskShaderSrc, ShaderType::kTask, *gr);
  100. ShaderPtr meshShader = createShader(meshShaderSrc, ShaderType::kMesh, *gr);
  101. ShaderPtr fragShader = createShader(fragShaderSrc, ShaderType::kFragment, *gr);
  102. ShaderProgramInitInfo progInit("Program");
  103. progInit.m_graphicsShaders[ShaderType::kTask] = taskShader.get();
  104. progInit.m_graphicsShaders[ShaderType::kMesh] = meshShader.get();
  105. progInit.m_graphicsShaders[ShaderType::kFragment] = fragShader.get();
  106. prog = gr->newShaderProgram(progInit);
  107. }
  108. BufferPtr indexBuff;
  109. {
  110. BufferInitInfo buffInit("Index");
  111. buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
  112. buffInit.m_usage = BufferUsageBit::kStorageGeometryRead;
  113. buffInit.m_size = sizeof(U32) * 6;
  114. indexBuff = gr->newBuffer(buffInit);
  115. void* mapped = indexBuff->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite);
  116. const U32 indices[] = {0, 1, 2, 2, 1, 3};
  117. memcpy(mapped, indices, sizeof(indices));
  118. indexBuff->unmap();
  119. }
  120. BufferPtr positionsBuff;
  121. {
  122. BufferInitInfo buffInit("Positions");
  123. buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
  124. buffInit.m_usage = BufferUsageBit::kStorageGeometryRead;
  125. buffInit.m_size = kVertCount * sizeof(Vec4) * kTileCount;
  126. positionsBuff = gr->newBuffer(buffInit);
  127. Vec4* mapped = static_cast<Vec4*>(positionsBuff->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
  128. for(U32 t = 0; t < kTileCount; t++)
  129. {
  130. const F32 left = (1.0f / F32(kTileCount) * F32(t)) * 2.0f - 1.0f;
  131. const F32 right = (1.0f / F32(kTileCount) * F32(t + 1)) * 2.0f - 1.0f;
  132. mapped[0] = Vec4(left, -1.0f, 1.0f, 1.0f);
  133. mapped[1] = Vec4(right, -1.0f, 1.0f, 1.0f);
  134. mapped[2] = Vec4(left, 1.0f, 1.0f, 1.0f);
  135. mapped[3] = Vec4(right, 1.0f, 1.0f, 1.0f);
  136. mapped += 4;
  137. }
  138. positionsBuff->unmap();
  139. }
  140. BufferPtr colorsBuff;
  141. {
  142. BufferInitInfo buffInit("Colors");
  143. buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
  144. buffInit.m_usage = BufferUsageBit::kStorageGeometryRead;
  145. buffInit.m_size = kVertCount * sizeof(Vec4) * kTileCount;
  146. colorsBuff = gr->newBuffer(buffInit);
  147. Vec4* mapped = static_cast<Vec4*>(colorsBuff->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
  148. const Array<Vec4, kTileCount> colors = {Vec4(1.0f, 0.0f, 0.0f, 0.0f), Vec4(0.0f, 1.0f, 0.0f, 0.0f), Vec4(0.0f, 0.0f, 1.0f, 0.0f),
  149. Vec4(1.0f, 0.0f, 1.0f, 0.0f)};
  150. for(U32 t = 0; t < kTileCount; t++)
  151. {
  152. mapped[0] = mapped[1] = mapped[2] = mapped[3] = colors[t];
  153. mapped += 4;
  154. }
  155. colorsBuff->unmap();
  156. }
  157. BufferPtr meshletsBuff;
  158. {
  159. class Meshlet
  160. {
  161. public:
  162. U32 m_firstIndex;
  163. U32 m_firstVertex;
  164. };
  165. BufferInitInfo buffInit("Meshlets");
  166. buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
  167. buffInit.m_usage = BufferUsageBit::kStorageGeometryRead;
  168. buffInit.m_size = sizeof(Meshlet) * kTileCount;
  169. meshletsBuff = gr->newBuffer(buffInit);
  170. Meshlet* mapped = static_cast<Meshlet*>(meshletsBuff->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
  171. for(U32 t = 0; t < kTileCount; t++)
  172. {
  173. mapped[t].m_firstIndex = 0;
  174. mapped[t].m_firstVertex = kVertCount * t;
  175. }
  176. meshletsBuff->unmap();
  177. }
  178. for(U32 i = 0; i < 100; ++i)
  179. {
  180. TexturePtr swapchainTex = gr->acquireNextPresentableTexture();
  181. TextureViewInitInfo viewInit(swapchainTex.get(), "RTView");
  182. TextureViewPtr swapchainView = gr->newTextureView(viewInit);
  183. FramebufferInitInfo fbInit("FB");
  184. fbInit.m_colorAttachmentCount = 1;
  185. fbInit.m_colorAttachments[0].m_textureView = swapchainView;
  186. fbInit.m_colorAttachments[0].m_clearValue.m_colorf = {1.0f, 0.0f, 1.0f, 0.0f};
  187. FramebufferPtr fb = gr->newFramebuffer(fbInit);
  188. CommandBufferInitInfo cmdbinit;
  189. CommandBufferPtr cmdb = gr->newCommandBuffer(cmdbinit);
  190. cmdb->setViewport(0, 0, g_windowWidthCVar.get(), g_windowHeightCVar.get());
  191. TextureBarrierInfo barrier;
  192. barrier.m_texture = swapchainTex.get();
  193. barrier.m_previousUsage = TextureUsageBit::kNone;
  194. barrier.m_nextUsage = TextureUsageBit::kFramebufferWrite;
  195. cmdb->setPipelineBarrier({&barrier, 1}, {}, {});
  196. cmdb->beginRenderPass(fb.get(), {TextureUsageBit::kFramebufferWrite}, TextureUsageBit::kNone);
  197. cmdb->bindStorageBuffer(0, 0, indexBuff.get(), 0, kMaxPtrSize);
  198. cmdb->bindStorageBuffer(0, 1, positionsBuff.get(), 0, kMaxPtrSize);
  199. cmdb->bindStorageBuffer(0, 2, colorsBuff.get(), 0, kMaxPtrSize);
  200. cmdb->bindStorageBuffer(0, 3, meshletsBuff.get(), 0, kMaxPtrSize);
  201. cmdb->bindShaderProgram(prog.get());
  202. cmdb->drawMeshTasks(1, 1, 1);
  203. cmdb->endRenderPass();
  204. barrier.m_previousUsage = TextureUsageBit::kFramebufferWrite;
  205. barrier.m_nextUsage = TextureUsageBit::kPresent;
  206. cmdb->setPipelineBarrier({&barrier, 1}, {}, {});
  207. cmdb->flush();
  208. gr->swapBuffers();
  209. HighRezTimer::sleep(1.0_sec / 60.0);
  210. }
  211. }
  212. GrManager::freeSingleton();
  213. NativeWindow::freeSingleton();
  214. DefaultMemoryPool::freeSingleton();
  215. }