GrMeshShaders.cpp 7.7 KB

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