GrCommon.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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 <AnKi/Gr.h>
  6. #include <AnKi/ShaderCompiler.h>
  7. #include <AnKi/ShaderCompiler/ShaderParser.h>
  8. #include <AnKi/ShaderCompiler/Dxc.h>
  9. #include <AnKi/Util/Filesystem.h>
  10. #include <AnKi/Core/CoreTracer.h>
  11. #include <Tests/Framework/Framework.h>
  12. namespace anki {
  13. inline ShaderPtr createShader(CString src, ShaderType type, ConstWeakArray<CString> extraCompilerArgs = {})
  14. {
  15. ShaderCompilerString header;
  16. ShaderParser::generateAnkiShaderHeader(type, header);
  17. header += src;
  18. ShaderCompilerDynamicArray<U8> bin;
  19. ShaderCompilerString errorLog;
  20. #if ANKI_GR_BACKEND_VULKAN
  21. Error err = compileHlslToSpirv(header, type, false, true, ShaderModel::k6_8, extraCompilerArgs, bin, errorLog);
  22. #else
  23. Error err = compileHlslToDxil(header, type, false, true, ShaderModel::k6_8, extraCompilerArgs, bin, errorLog);
  24. #endif
  25. if(err)
  26. {
  27. ANKI_TEST_LOGE("Compile error:\n%s", errorLog.cstr());
  28. }
  29. ANKI_TEST_EXPECT_NO_ERR(err);
  30. ShaderReflection refl;
  31. #if ANKI_GR_BACKEND_VULKAN
  32. err = doReflectionSpirv(WeakArray(bin.getBegin(), bin.getSize()), type, refl, errorLog);
  33. #else
  34. err = doReflectionDxil(bin, type, refl, errorLog);
  35. #endif
  36. if(err)
  37. {
  38. ANKI_TEST_LOGE("Reflection error:\n%s", errorLog.cstr());
  39. }
  40. ANKI_TEST_EXPECT_NO_ERR(err);
  41. ShaderInitInfo initInf(type, bin);
  42. initInf.m_reflection = refl;
  43. return GrManager::getSingleton().newShader(initInf);
  44. }
  45. inline ShaderProgramPtr createVertFragProg(CString vert, CString frag, ConstWeakArray<CString> extraCompilerArgs = {})
  46. {
  47. ShaderPtr vertS = createShader(vert, ShaderType::kVertex, extraCompilerArgs);
  48. ShaderPtr fragS = createShader(frag, ShaderType::kPixel, extraCompilerArgs);
  49. ShaderProgramInitInfo init;
  50. init.m_graphicsShaders[ShaderType::kVertex] = vertS.get();
  51. init.m_graphicsShaders[ShaderType::kPixel] = fragS.get();
  52. ShaderProgramPtr prog = GrManager::getSingleton().newShaderProgram(init);
  53. return prog;
  54. }
  55. inline ShaderProgramPtr createComputeProg(CString src, ConstWeakArray<CString> extraCompilerArgs = {})
  56. {
  57. ShaderPtr shader = createShader(src, ShaderType::kCompute, extraCompilerArgs);
  58. ShaderProgramInitInfo init;
  59. init.m_computeShader = shader.get();
  60. ShaderProgramPtr prog = GrManager::getSingleton().newShaderProgram(init);
  61. return prog;
  62. }
  63. inline ShaderPtr loadShader(CString filename, ShaderType type, ConstWeakArray<CString> extraCompilerArgs = {})
  64. {
  65. File file;
  66. ANKI_TEST_EXPECT_NO_ERR(file.open(filename, FileOpenFlag::kRead));
  67. String src;
  68. ANKI_TEST_EXPECT_NO_ERR(file.readAllText(src));
  69. return createShader(src, type, extraCompilerArgs);
  70. }
  71. const U kWidth = 1024;
  72. const U kHeight = 768;
  73. inline void commonInit(Bool validation = true)
  74. {
  75. DefaultMemoryPool::allocateSingleton(allocAligned, nullptr);
  76. ShaderCompilerMemoryPool::allocateSingleton(allocAligned, nullptr);
  77. CoreMemoryPool::allocateSingleton(allocAligned, nullptr);
  78. g_cvarWindowWidth = kWidth;
  79. g_cvarWindowHeight = kHeight;
  80. g_cvarGrVsync = false;
  81. g_cvarGrDebugMarkers = true;
  82. g_cvarWindowFullscreen = 0;
  83. if(validation)
  84. {
  85. g_cvarGrValidation = true;
  86. g_cvarGrDebugMarkers = true;
  87. }
  88. #if ANKI_TRACING_ENABLED
  89. {
  90. String tmpDir;
  91. [[maybe_unused]] Error err = getTempDirectory(tmpDir);
  92. [[maybe_unused]] Error err2 = CoreTracer::allocateSingleton().init(tmpDir);
  93. }
  94. #endif
  95. initWindow();
  96. ANKI_TEST_EXPECT_NO_ERR(Input::allocateSingleton().init());
  97. initGrManager();
  98. }
  99. inline void commonDestroy()
  100. {
  101. GrManager::freeSingleton();
  102. Input::freeSingleton();
  103. NativeWindow::freeSingleton();
  104. Input::freeSingleton();
  105. #if ANKI_TRACING_ENABLED
  106. CoreTracer::freeSingleton();
  107. #endif
  108. CoreMemoryPool::freeSingleton();
  109. ShaderCompilerMemoryPool::freeSingleton();
  110. DefaultMemoryPool::freeSingleton();
  111. }
  112. template<typename T>
  113. inline BufferPtr createBuffer(BufferUsageBit usage, ConstWeakArray<T> data, CString name = {})
  114. {
  115. BufferPtr copyBuff =
  116. GrManager::getSingleton().newBuffer(BufferInitInfo(data.getSizeInBytes(), BufferUsageBit::kCopySource, BufferMapAccessBit::kWrite));
  117. T* inData = static_cast<T*>(copyBuff->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite));
  118. for(U32 i = 0; i < data.getSize(); ++i)
  119. {
  120. inData[i] = data[i];
  121. }
  122. copyBuff->unmap();
  123. BufferPtr buff = GrManager::getSingleton().newBuffer(BufferInitInfo(
  124. data.getSizeInBytes(), usage | BufferUsageBit::kCopyDestination | BufferUsageBit::kCopySource, BufferMapAccessBit::kNone, name));
  125. CommandBufferInitInfo cmdbInit;
  126. cmdbInit.m_flags |= CommandBufferFlag::kSmallBatch;
  127. CommandBufferPtr cmdb = GrManager::getSingleton().newCommandBuffer(cmdbInit);
  128. BufferBarrierInfo barr;
  129. barr.m_bufferView = BufferView(buff.get());
  130. barr.m_previousUsage = BufferUsageBit::kNone;
  131. barr.m_nextUsage = BufferUsageBit::kCopyDestination;
  132. cmdb->setPipelineBarrier({}, {&barr, 1}, {});
  133. cmdb->copyBufferToBuffer(BufferView(copyBuff.get()), BufferView(buff.get()));
  134. barr.m_previousUsage = BufferUsageBit::kCopyDestination;
  135. barr.m_nextUsage = usage;
  136. cmdb->setPipelineBarrier({}, {&barr, 1}, {});
  137. cmdb->endRecording();
  138. FencePtr fence;
  139. GrManager::getSingleton().submit(cmdb.get(), {}, &fence);
  140. fence->clientWait(kMaxSecond);
  141. return buff;
  142. };
  143. template<typename T>
  144. inline BufferPtr createBuffer(BufferUsageBit usage, T pattern, U32 count, CString name = {})
  145. {
  146. DynamicArray<T> arr;
  147. arr.resize(count, pattern);
  148. return createBuffer(usage, ConstWeakArray<T>(arr), name);
  149. }
  150. template<typename T>
  151. inline TexturePtr createTexture2d(const TextureInitInfo texInit_, ConstWeakArray<T> data)
  152. {
  153. TextureInitInfo texInit = texInit_;
  154. texInit.m_usage |= TextureUsageBit::kCopyDestination;
  155. BufferInitInfo buffInit;
  156. buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
  157. buffInit.m_size = texInit.m_height * texInit.m_width * getFormatInfo(texInit.m_format).m_texelSize;
  158. buffInit.m_usage = BufferUsageBit::kCopySource;
  159. ANKI_ASSERT(getFormatInfo(texInit.m_format).m_texelSize == sizeof(T));
  160. ANKI_ASSERT(buffInit.m_size == data.getSizeInBytes());
  161. BufferPtr staging = GrManager::getSingleton().newBuffer(buffInit);
  162. void* inData = staging->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite);
  163. memcpy(inData, data.getBegin(), buffInit.m_size);
  164. staging->unmap();
  165. TexturePtr tex = GrManager::getSingleton().newTexture(texInit);
  166. CommandBufferInitInfo cmdbInit;
  167. cmdbInit.m_flags |= CommandBufferFlag::kSmallBatch;
  168. CommandBufferPtr cmdb = GrManager::getSingleton().newCommandBuffer(cmdbInit);
  169. const TextureBarrierInfo barr = {TextureView(tex.get(), TextureSubresourceDesc::all()), TextureUsageBit::kNone,
  170. TextureUsageBit::kCopyDestination};
  171. cmdb->setPipelineBarrier({&barr, 1}, {}, {});
  172. cmdb->copyBufferToTexture(BufferView(staging.get()), TextureView(tex.get(), TextureSubresourceDesc::all()));
  173. cmdb->endRecording();
  174. FencePtr fence;
  175. GrManager::getSingleton().submit(cmdb.get(), {}, &fence);
  176. fence->clientWait(kMaxSecond);
  177. return tex;
  178. };
  179. template<typename T>
  180. inline TexturePtr createTexture2d(const TextureInitInfo& texInit, T initialValue)
  181. {
  182. DynamicArray<T> arr;
  183. arr.resize(texInit.m_height * texInit.m_width, initialValue);
  184. return createTexture2d(texInit, ConstWeakArray<T>(arr));
  185. };
  186. template<typename T>
  187. inline void readBuffer(BufferPtr buff, DynamicArray<T>& out)
  188. {
  189. BufferPtr tmpBuff;
  190. if(!!(buff->getMapAccess() & BufferMapAccessBit::kRead))
  191. {
  192. tmpBuff = buff;
  193. }
  194. else
  195. {
  196. BufferInitInfo buffInit;
  197. buffInit.m_mapAccess = BufferMapAccessBit::kRead;
  198. buffInit.m_size = buff->getSize();
  199. buffInit.m_usage = BufferUsageBit::kCopyDestination;
  200. tmpBuff = GrManager::getSingleton().newBuffer(buffInit);
  201. CommandBufferPtr cmdb =
  202. GrManager::getSingleton().newCommandBuffer(CommandBufferInitInfo(CommandBufferFlag::kGeneralWork | CommandBufferFlag::kSmallBatch));
  203. cmdb->copyBufferToBuffer(BufferView(buff.get()), BufferView(tmpBuff.get()));
  204. cmdb->endRecording();
  205. FencePtr fence;
  206. GrManager::getSingleton().submit(cmdb.get(), {}, &fence);
  207. fence->clientWait(kMaxSecond);
  208. }
  209. ANKI_ASSERT((buff->getSize() % sizeof(T)) == 0);
  210. out.resize(U32(buff->getSize() / sizeof(T)));
  211. const void* data = tmpBuff->map(0, kMaxPtrSize, BufferMapAccessBit::kRead);
  212. memcpy(out.getBegin(), data, buff->getSize());
  213. tmpBuff->unmap();
  214. }
  215. template<typename T>
  216. inline void validateBuffer(BufferPtr buff, ConstWeakArray<T> values)
  217. {
  218. DynamicArray<T> cpuBuff;
  219. readBuffer<T>(buff, cpuBuff);
  220. ANKI_ASSERT(values.getSize() == cpuBuff.getSize());
  221. for(U32 i = 0; i < values.getSize(); ++i)
  222. {
  223. ANKI_TEST_EXPECT_EQ(cpuBuff[i], values[i]);
  224. }
  225. }
  226. template<typename T>
  227. inline void validateBuffer2(BufferPtr buff, T value)
  228. {
  229. const Array<T, 1> arr = {value};
  230. validateBuffer(buff, ConstWeakArray(arr));
  231. }
  232. } // end namespace anki