No Description

TestApp1.cpp 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. // TestApp1.cpp : Defines the entry point for the application.
  2. //
  3. #ifdef _WIN32
  4. #include "Win32/stdafx.h"
  5. #endif
  6. #include <DK.h>
  7. DKString ShaderStageNames(uint32_t s)
  8. {
  9. DKArray<const char*> stages;
  10. if (s & (uint32_t)DKShaderStage::Vertex)
  11. stages.Add("Vertex");
  12. if (s & (uint32_t)DKShaderStage::TessellationControl)
  13. stages.Add("TessCtrl");
  14. if (s & (uint32_t)DKShaderStage::TessellationEvaluation)
  15. stages.Add("TessEval");
  16. if (s & (uint32_t)DKShaderStage::Geometry)
  17. stages.Add("Geometry");
  18. if (s & (uint32_t)DKShaderStage::Fragment)
  19. stages.Add("Fragment");
  20. if (s & (uint32_t)DKShaderStage::Compute)
  21. stages.Add("Compute");
  22. if (stages.IsEmpty())
  23. return "";
  24. DKString str = stages.Value(0);
  25. for (int i = 1; i < stages.Count(); ++i)
  26. str += DKString::Format(", %ls", stages.Value(i));
  27. return str;
  28. }
  29. const char* ShaderDataTypeStr(DKShaderDataType t)
  30. {
  31. switch (t) {
  32. case DKShaderDataType::Unknown: return "Unknown";
  33. case DKShaderDataType::None: return "None";
  34. case DKShaderDataType::Struct: return "Struct";
  35. case DKShaderDataType::Texture: return "Texture";
  36. case DKShaderDataType::Sampler: return "Sampler";
  37. case DKShaderDataType::Float: return "Float";
  38. case DKShaderDataType::Float2: return "Float2";
  39. case DKShaderDataType::Float3: return "Float3";
  40. case DKShaderDataType::Float4: return "Float4";
  41. case DKShaderDataType::Float2x2: return "Float2x2";
  42. case DKShaderDataType::Float2x3: return "Float2x3";
  43. case DKShaderDataType::Float2x4: return "Float2x4";
  44. case DKShaderDataType::Float3x2: return "Float3x2";
  45. case DKShaderDataType::Float3x3: return "Float3x3";
  46. case DKShaderDataType::Float3x4: return "Float3x4";
  47. case DKShaderDataType::Float4x2: return "Float4x2";
  48. case DKShaderDataType::Float4x3: return "Float4x3";
  49. case DKShaderDataType::Float4x4: return "Float4x4";
  50. case DKShaderDataType::Half: return "Half";
  51. case DKShaderDataType::Half2: return "Half2";
  52. case DKShaderDataType::Half3: return "Half3";
  53. case DKShaderDataType::Half4: return "Half4";
  54. case DKShaderDataType::Half2x2: return "Half2x2";
  55. case DKShaderDataType::Half2x3: return "Half2x3";
  56. case DKShaderDataType::Half2x4: return "Half2x4";
  57. case DKShaderDataType::Half3x2: return "Half3x2";
  58. case DKShaderDataType::Half3x3: return "Half3x3";
  59. case DKShaderDataType::Half3x4: return "Half3x4";
  60. case DKShaderDataType::Half4x2: return "Half4x2";
  61. case DKShaderDataType::Half4x3: return "Half4x3";
  62. case DKShaderDataType::Half4x4: return "Half4x4";
  63. case DKShaderDataType::Int: return "Int";
  64. case DKShaderDataType::Int2: return "Int2";
  65. case DKShaderDataType::Int3: return "Int3";
  66. case DKShaderDataType::Int4: return "Int4";
  67. case DKShaderDataType::UInt: return "UInt";
  68. case DKShaderDataType::UInt2: return "UInt2";
  69. case DKShaderDataType::UInt3: return "UInt3";
  70. case DKShaderDataType::UInt4: return "UInt4";
  71. case DKShaderDataType::Short: return "Short";
  72. case DKShaderDataType::Short2: return "Short2";
  73. case DKShaderDataType::Short3: return "Short3";
  74. case DKShaderDataType::Short4: return "Short4";
  75. case DKShaderDataType::UShort: return "UShort";
  76. case DKShaderDataType::UShort2: return "UShort2";
  77. case DKShaderDataType::UShort3: return "UShort3";
  78. case DKShaderDataType::UShort4: return "UShort4";
  79. case DKShaderDataType::Char: return "Char";
  80. case DKShaderDataType::Char2: return "Char2";
  81. case DKShaderDataType::Char3: return "Char3";
  82. case DKShaderDataType::Char4: return "Char4";
  83. case DKShaderDataType::UChar: return "UChar";
  84. case DKShaderDataType::UChar2: return "UChar2";
  85. case DKShaderDataType::UChar3: return "UChar3";
  86. case DKShaderDataType::UChar4: return "UChar4";
  87. case DKShaderDataType::Bool: return "Bool";
  88. case DKShaderDataType::Bool2: return "Bool2";
  89. case DKShaderDataType::Bool3: return "Bool3";
  90. case DKShaderDataType::Bool4: return "Bool4";
  91. }
  92. return "Error";
  93. }
  94. DKVertexDescriptor VertexDescriptorForVertexAttributes(const DKArray<DKShaderAttribute>& attrs)
  95. {
  96. uint32_t vertexSize = 0;
  97. DKVertexDescriptor descriptor = {};
  98. for (uint32_t i = 0; i < attrs.Count(); ++i)
  99. {
  100. if (const DKShaderAttribute& attr = attrs.Value(i); attr.enabled)
  101. {
  102. DKVertexAttributeDescriptor desc = {};
  103. switch (attr.type)
  104. {
  105. case DKShaderDataType::Float:
  106. case DKShaderDataType::Half:
  107. case DKShaderDataType::Int:
  108. case DKShaderDataType::UInt:
  109. case DKShaderDataType::Short:
  110. case DKShaderDataType::UShort:
  111. case DKShaderDataType::Char:
  112. case DKShaderDataType::UChar:
  113. case DKShaderDataType::Bool:
  114. desc.format = DKVertexFormat::Float;
  115. desc.offset = vertexSize;
  116. vertexSize += 4;
  117. break;
  118. case DKShaderDataType::Float2:
  119. case DKShaderDataType::Half2:
  120. case DKShaderDataType::Int2:
  121. case DKShaderDataType::UInt2:
  122. case DKShaderDataType::Short2:
  123. case DKShaderDataType::UShort2:
  124. case DKShaderDataType::Char2:
  125. case DKShaderDataType::UChar2:
  126. case DKShaderDataType::Bool2:
  127. desc.format = DKVertexFormat::Float2;
  128. desc.offset = vertexSize;
  129. vertexSize += 8;
  130. break;
  131. case DKShaderDataType::Float3:
  132. case DKShaderDataType::Half3:
  133. case DKShaderDataType::Int3:
  134. case DKShaderDataType::UInt3:
  135. case DKShaderDataType::Short3:
  136. case DKShaderDataType::UShort3:
  137. case DKShaderDataType::Char3:
  138. case DKShaderDataType::UChar3:
  139. case DKShaderDataType::Bool3:
  140. desc.format = DKVertexFormat::Float3;
  141. desc.offset = vertexSize;
  142. vertexSize += 12;
  143. break;
  144. case DKShaderDataType::Float4:
  145. case DKShaderDataType::Half4:
  146. case DKShaderDataType::Int4:
  147. case DKShaderDataType::UInt4:
  148. case DKShaderDataType::Short4:
  149. case DKShaderDataType::UShort4:
  150. case DKShaderDataType::Char4:
  151. case DKShaderDataType::UChar4:
  152. case DKShaderDataType::Bool4:
  153. desc.format = DKVertexFormat::Float4;
  154. desc.offset = vertexSize;
  155. vertexSize += 16;
  156. break;
  157. default:
  158. DKASSERT_DESC(0, "Unsupported type!");
  159. break;
  160. }
  161. desc.location = attr.location;
  162. descriptor.attributes.Add(desc);
  163. }
  164. }
  165. descriptor.layouts = { { DKVertexStepRate::Vertex, vertexSize}, };
  166. return descriptor;
  167. };
  168. void PrintShaderResource(const DKShaderResource& res, DKLogCategory c = DKLogCategory::Info)
  169. {
  170. struct MemberPrinter
  171. {
  172. const DKShaderResource& res;
  173. int indent;
  174. DKLogCategory c;
  175. void operator()(const DKShaderResourceStruct& str) const
  176. {
  177. DKString indentStr = "";
  178. for (int i = 0; i < indent; ++i)
  179. {
  180. indentStr += " ";
  181. }
  182. for (const DKShaderResourceStructMember& mem : str.members)
  183. {
  184. if (mem.count > 1)
  185. {
  186. DKLog(c, " %ls+ %ls[%d] (%s, Offset: %d, Stride: %d)",
  187. (const wchar_t*)indentStr,
  188. (const wchar_t*)mem.name,
  189. mem.count,
  190. ShaderDataTypeStr(mem.dataType),
  191. mem.offset, mem.stride);
  192. }
  193. else
  194. {
  195. DKLog(c, " %ls+ %ls (%s, Offset: %d)",
  196. (const wchar_t*)indentStr,
  197. (const wchar_t*)mem.name,
  198. ShaderDataTypeStr(mem.dataType),
  199. mem.offset);
  200. }
  201. auto* p = res.structTypeMemberMap.Find(mem.typeInfoKey);
  202. if (p)
  203. {
  204. DKLog(c, " %ls Struct \"%ls\"",
  205. (const wchar_t*)indentStr,
  206. (const wchar_t*)mem.typeInfoKey);
  207. MemberPrinter{ res, indent + 1, c}.operator()(p->value);
  208. }
  209. }
  210. }
  211. };
  212. if (res.count > 1)
  213. DKLog(c, "ShaderResource: %ls[%d] (set=%d, binding=%d, stages=%ls)",
  214. (const wchar_t*)res.name, res.count, res.set, res.binding,
  215. (const wchar_t*)ShaderStageNames(res.stages));
  216. else
  217. DKLog(c, "ShaderResource: %ls (set=%d, binding=%d, stages=%ls)",
  218. (const wchar_t*)res.name, res.set, res.binding,
  219. (const wchar_t*)ShaderStageNames(res.stages));
  220. const char* type = "Unknown (ERROR)";
  221. switch (res.type)
  222. {
  223. case DKShaderResource::TypeBuffer: type = "Buffer"; break;
  224. case DKShaderResource::TypeTexture: type = "Texture"; break;
  225. case DKShaderResource::TypeSampler: type = "Sampler"; break;
  226. case DKShaderResource::TypeTextureSampler: type = "SampledTexture"; break;
  227. }
  228. const char* access = "Unknown (ERROR)";
  229. switch (res.access)
  230. {
  231. case DKShaderResource::AccessReadOnly: access = "ReadOnly"; break;
  232. case DKShaderResource::AccessWriteOnly: access = "WriteOnly"; break;
  233. case DKShaderResource::AccessReadWrite: access = "ReadWrite"; break;
  234. }
  235. if (res.type == DKShaderResource::TypeBuffer)
  236. {
  237. DKLog(c, " Type:%s, Access:%s, Enabled:%d, Size:%d",
  238. type,
  239. access,
  240. int(res.enabled),
  241. res.typeInfo.buffer.size);
  242. }
  243. else
  244. {
  245. DKLog(c, " Type:%s, Access:%s, Enabled:%d",
  246. type,
  247. access,
  248. int(res.enabled));
  249. }
  250. if (res.typeInfoKey.Length() > 0)
  251. DKLog(c, " Struct \"%ls\"", (const wchar_t*)res.typeInfoKey);
  252. if (res.type == DKShaderResource::TypeBuffer)
  253. {
  254. auto p = res.structTypeMemberMap.Find(res.typeInfoKey);
  255. if (p)
  256. MemberPrinter{ res, 1 , c}.operator()(p->value);
  257. }
  258. }
  259. class TestApp1 : public DKApplication
  260. {
  261. DKResourcePool resourcePool;
  262. DKString userConfigPath;
  263. DKObject<DKGraphicsDevice> device;
  264. void PrintShaderReflection(const DKShader* shader, DKLogCategory c = DKLogCategory::Warning)
  265. {
  266. DKString stage = ShaderStageNames((uint32_t)shader->Stage());
  267. if (stage.Length() == 0)
  268. stage = "Unknown";
  269. DKLog(c, "=========================================================");
  270. DKLog(c, "Shader<%ls.SPIR-V>.InputAttributes: %d",
  271. (const wchar_t*)stage, shader->InputAttributes().Count());
  272. for (int i = 0; i < shader->InputAttributes().Count(); ++i)
  273. {
  274. const DKShaderAttribute& attr = shader->InputAttributes().Value(i);
  275. DKLog(c, " [in] ShaderAttribute[%d]: \"%ls\" (location:%u)",
  276. i, (const wchar_t*)attr.name, attr.location);
  277. }
  278. DKLog(c, "---------------------------------------------------------");
  279. DKLog(c, "Shader<%ls.SPIR-V>.OutputAttributes: %d",
  280. (const wchar_t*)stage, shader->OutputAttributes().Count());
  281. for (int i = 0; i < shader->OutputAttributes().Count(); ++i)
  282. {
  283. const DKShaderAttribute& attr = shader->OutputAttributes().Value(i);
  284. DKLog(c, " [out] ShaderAttribute[%d]: \"%ls\" (location:%u)",
  285. i, (const wchar_t*)attr.name, attr.location);
  286. }
  287. DKLog(c, "---------------------------------------------------------");
  288. DKLog(c, "Shader<%ls.SPIR-V>.Resources: %d",
  289. (const wchar_t*)stage, shader->Resources().Count());
  290. for (auto& arg : shader->Resources())
  291. PrintShaderResource(arg, c);
  292. for (int i = 0; i < shader->PushConstantBufferLayouts().Count(); ++i)
  293. {
  294. const DKShaderPushConstantLayout& layout = shader->PushConstantBufferLayouts().Value(i);
  295. DKLog(c, " PushConstant:%d \"%ls\" (offset:%u, size:%u, stages:%ls)",
  296. i, (const wchar_t*)layout.name, layout.offset, layout.size,
  297. (const wchar_t*)ShaderStageNames(layout.stages));
  298. }
  299. DKLog(c, "=========================================================");
  300. }
  301. void PrintPipelineReflection(const DKPipelineReflection* reflection, DKLogCategory c = DKLogCategory::Error)
  302. {
  303. DKLog(c, "=========================================================");
  304. DKLog(c, "PipelineReflection.InputAttributes: %d", reflection->inputAttributes.Count());
  305. for (int i = 0; i < reflection->inputAttributes.Count(); ++i)
  306. {
  307. const DKShaderAttribute& attr = reflection->inputAttributes.Value(i);
  308. DKLog(c, " [in] ShaderAttribute[%d]: \"%ls\" (location:%u)",
  309. i, (const wchar_t*)attr.name, attr.location);
  310. }
  311. DKLog(c, "---------------------------------------------------------");
  312. DKLog(c, "PipelineReflection.Resources: %d", reflection->resources.Count());
  313. for (auto& arg : reflection->resources)
  314. PrintShaderResource(arg, c);
  315. for (int i = 0; i < reflection->pushConstantLayouts.Count(); ++i)
  316. {
  317. const DKShaderPushConstantLayout& layout = reflection->pushConstantLayouts.Value(i);
  318. DKLog(c, " PushConstant:%d \"%ls\" (offset:%u, size:%u, stages:%ls)",
  319. i, (const wchar_t*)layout.name, layout.offset, layout.size,
  320. (const wchar_t*)ShaderStageNames(layout.stages));
  321. }
  322. DKLog(c, "=========================================================");
  323. }
  324. void TestRenderPipelineReflection(const DKString& path)
  325. {
  326. DKObject<DKData> vertData = resourcePool.LoadResourceData(path + ".vert.spv");
  327. DKObject<DKData> fragData = resourcePool.LoadResourceData(path + ".frag.spv");
  328. DKASSERT(vertData);
  329. DKASSERT(fragData);
  330. DKShader vertShader(vertData);
  331. DKShader fragShader(fragData);
  332. PrintShaderReflection(&vertShader, DKLogCategory::Warning);
  333. PrintShaderReflection(&fragShader, DKLogCategory::Warning);
  334. DKObject<DKShaderModule> vertShaderModule = device->CreateShaderModule(&vertShader);
  335. DKObject<DKShaderModule> fragShaderModule = device->CreateShaderModule(&fragShader);
  336. DKObject<DKShaderFunction> vertShaderFunction = vertShaderModule->CreateFunction(vertShaderModule->FunctionNames().Value(0));
  337. DKObject<DKShaderFunction> fragShaderFunction = fragShaderModule->CreateFunction(fragShaderModule->FunctionNames().Value(0));
  338. // setup dummy vertex-descriptor
  339. DKVertexDescriptor vertexDescriptor = VertexDescriptorForVertexAttributes(vertShaderFunction->StageInputAttributes());
  340. // setup rendering pipeline state object (PSO)
  341. DKRenderPipelineDescriptor pipelineDescriptor = {};
  342. pipelineDescriptor.vertexFunction = vertShaderFunction;
  343. pipelineDescriptor.fragmentFunction = fragShaderFunction;
  344. pipelineDescriptor.colorAttachments.Resize(1);
  345. pipelineDescriptor.colorAttachments.Value(0).pixelFormat = DKPixelFormat::RGBA8Unorm;
  346. pipelineDescriptor.depthStencilAttachmentPixelFormat = DKPixelFormat::Invalid; // no depth buffer
  347. pipelineDescriptor.vertexDescriptor = vertexDescriptor;
  348. pipelineDescriptor.primitiveTopology = DKPrimitiveType::Triangle;
  349. pipelineDescriptor.frontFace = DKFrontFace::CCW;
  350. pipelineDescriptor.triangleFillMode = DKTriangleFillMode::Fill;
  351. pipelineDescriptor.depthClipMode = DKDepthClipMode::Clip;
  352. pipelineDescriptor.cullMode = DKCullMode::None;
  353. pipelineDescriptor.rasterizationEnabled = true;
  354. DKPipelineReflection reflection;
  355. DKObject<DKRenderPipelineState> pipelineState = device->CreateRenderPipeline(pipelineDescriptor, &reflection);
  356. if (pipelineState)
  357. {
  358. PrintPipelineReflection(&reflection, DKLogCategory::Error);
  359. }
  360. else
  361. {
  362. DKLogE("CreateRenderPipeline failed.");
  363. }
  364. }
  365. void TestComputePipelineReflection(const DKString& path)
  366. {
  367. DKObject<DKData> shaderData = resourcePool.LoadResourceData(path + ".comp.spv");
  368. DKASSERT(shaderData);
  369. DKShader shader(shaderData);
  370. PrintShaderReflection(&shader, DKLogCategory::Warning);
  371. DKObject<DKShaderModule> shaderModule = device->CreateShaderModule(&shader);
  372. DKObject<DKShaderFunction> shaderFunction = shaderModule->CreateFunction(shaderModule->FunctionNames().Value(0));
  373. // setup pipeline state object (PSO)
  374. DKComputePipelineDescriptor pipelineDescriptor = {};
  375. pipelineDescriptor.computeFunction = shaderFunction;
  376. DKPipelineReflection reflection;
  377. DKObject<DKComputePipelineState> pipelineState = device->CreateComputePipeline(pipelineDescriptor, &reflection);
  378. if (pipelineState)
  379. {
  380. PrintPipelineReflection(&reflection, DKLogCategory::Error);
  381. }
  382. else
  383. {
  384. DKLogE("CreateComputePipeline failed.");
  385. }
  386. }
  387. public:
  388. void OnInitialize(void) override
  389. {
  390. DKLogD("%s", DKGL_FUNCTION_NAME);
  391. DKLogD("NumCores: %d", DKNumberOfCpuCores());
  392. DKLogD("NumProcessors: %d", DKNumberOfProcessors());
  393. DKString resPath = DefaultPath(SystemPath::AppResource);
  394. resPath = resPath.FilePathStringByAppendingPath("Data");
  395. DKLog("resPath: %ls", (const wchar_t*)resPath);
  396. resourcePool.AddLocatorForPath(resPath);
  397. userConfigPath = DefaultPath(SystemPath::AppExecutable).FilePathStringByAppendingPath("app.config.xml");
  398. int numItemsImported = DKPropertySet::DefaultSet().Import(userConfigPath, true);
  399. if (numItemsImported >= 0)
  400. DKLogI("UserSettings: %ls (%d items imported)", (const wchar_t*)userConfigPath, numItemsImported);
  401. device = DKGraphicsDevice::SharedInstance();
  402. TestRenderPipelineReflection("shaders/conditionalrender/model");
  403. TestComputePipelineReflection("shaders/computeshader/emboss");
  404. Terminate(0);
  405. }
  406. void OnTerminate(void) override
  407. {
  408. DKLogD("%s", DKGL_FUNCTION_NAME);
  409. device = NULL;
  410. int numItemsExported = DKPropertySet::DefaultSet().Export(userConfigPath, true);
  411. DKLogI("Setting saved: %ls (%d items exported)", (const wchar_t*)userConfigPath, numItemsExported);
  412. DKLogI("Memory Pool Statistics");
  413. size_t numBuckets = DKMemoryPoolNumberOfBuckets();
  414. DKMemoryPoolBucketStatus* buckets = new DKMemoryPoolBucketStatus[numBuckets];
  415. DKMemoryPoolQueryAllocationStatus(buckets, numBuckets);
  416. size_t usedBytes = 0;
  417. for (int i = 0; i < numBuckets; ++i)
  418. {
  419. if (buckets[i].totalChunks > 0)
  420. {
  421. DKLogI("--> %5lu: %5lu/%5lu, usage: %.1f%%, used: %.1fKB, total: %.1fKB",
  422. buckets[i].chunkSize,
  423. buckets[i].usedChunks, buckets[i].totalChunks,
  424. double(buckets[i].usedChunks) / double(buckets[i].totalChunks) * 100.0,
  425. double(buckets[i].chunkSize * buckets[i].usedChunks) / 1024.0,
  426. double(buckets[i].chunkSize * buckets[i].totalChunks) / 1024.0
  427. );
  428. usedBytes += buckets[i].chunkSize * buckets[i].usedChunks;
  429. }
  430. }
  431. DKLogI("MemoryPool Usage: %.1fMB / %.1fMB", double(usedBytes) / (1024 * 1024), double(DKMemoryPoolSize()) / (1024 * 1024));
  432. delete[] buckets;
  433. }
  434. };
  435. #ifdef _WIN32
  436. int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
  437. _In_opt_ HINSTANCE hPrevInstance,
  438. _In_ LPWSTR lpCmdLine,
  439. _In_ int nCmdShow)
  440. #else
  441. int main(int argc, const char * argv[])
  442. #endif
  443. {
  444. TestApp1 app;
  445. DKPropertySet::SystemConfig().SetValue("AppDelegate", "AppDelegate");
  446. DKPropertySet::SystemConfig().SetValue("GraphicsAPI", "Vulkan");
  447. return app.Run();
  448. }