triangle-vulkan.c 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229
  1. /*
  2. * Copyright (c) 2015-2016 The Khronos Group Inc.
  3. * Copyright (c) 2015-2016 Valve Corporation
  4. * Copyright (c) 2015-2016 LunarG, Inc.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * Author: Chia-I Wu <[email protected]>
  19. * Author: Cody Northrop <[email protected]>
  20. * Author: Courtney Goeltzenleuchter <[email protected]>
  21. * Author: Ian Elliott <[email protected]>
  22. * Author: Jon Ashburn <[email protected]>
  23. * Author: Piers Daniell <[email protected]>
  24. * Author: Gwan-gyeong Mun <[email protected]>
  25. * Porter: Camilla Löwy <[email protected]>
  26. */
  27. /*
  28. * Draw a textured triangle with depth testing. This is written against Intel
  29. * ICD. It does not do state transition nor object memory binding like it
  30. * should. It also does no error checking.
  31. */
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <stdbool.h>
  36. #include <assert.h>
  37. #include <signal.h>
  38. #ifdef _WIN32
  39. #include <windows.h>
  40. #endif
  41. #include <glad/vulkan.h>
  42. #define GLFW_INCLUDE_NONE
  43. #include <GLFW/glfw3.h>
  44. #define DEMO_TEXTURE_COUNT 1
  45. #define VERTEX_BUFFER_BIND_ID 0
  46. #define APP_SHORT_NAME "tri"
  47. #define APP_LONG_NAME "The Vulkan Triangle Demo Program"
  48. #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
  49. #if defined(NDEBUG) && defined(__GNUC__)
  50. #define U_ASSERT_ONLY __attribute__((unused))
  51. #else
  52. #define U_ASSERT_ONLY
  53. #endif
  54. #define ERR_EXIT(err_msg, err_class) \
  55. do { \
  56. printf(err_msg); \
  57. fflush(stdout); \
  58. exit(1); \
  59. } while (0)
  60. static GLADapiproc glad_vulkan_callback(const char* name, void* user)
  61. {
  62. return glfwGetInstanceProcAddress((VkInstance) user, name);
  63. }
  64. static const char fragShaderCode[] = {
  65. 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00,
  66. 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
  67. 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
  68. 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
  69. 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
  70. 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00,
  71. 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
  72. 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
  73. 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
  74. 0x02, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00,
  75. 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x65, 0x70, 0x61, 0x72,
  76. 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6f,
  77. 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00,
  78. 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73, 0x68, 0x61, 0x64, 0x69,
  79. 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f,
  80. 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x00, 0x05, 0x00, 0x04, 0x00,
  81. 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
  82. 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x75, 0x46, 0x72, 0x61,
  83. 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
  84. 0x0d, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x00, 0x05, 0x00, 0x05, 0x00,
  85. 0x11, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64,
  86. 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
  87. 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
  88. 0x0d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  89. 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
  90. 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
  91. 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
  92. 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
  93. 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
  94. 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
  95. 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
  96. 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  97. 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
  98. 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, 0x00,
  99. 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  100. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  101. 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00,
  102. 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
  103. 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
  104. 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  105. 0x17, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
  106. 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
  107. 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
  108. 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  109. 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  110. 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
  111. 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
  112. 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
  113. 0x0f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
  114. 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
  115. 0x0e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
  116. 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
  117. 0x38, 0x00, 0x01, 0x00
  118. };
  119. static const char vertShaderCode[] = {
  120. 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00,
  121. 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
  122. 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
  123. 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
  124. 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
  125. 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00,
  126. 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
  127. 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
  128. 0x17, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
  129. 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
  130. 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73,
  131. 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x64,
  132. 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00,
  133. 0x04, 0x00, 0x09, 0x00, 0x47, 0x4c, 0x5f, 0x41, 0x52, 0x42, 0x5f, 0x73,
  134. 0x68, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75,
  135. 0x61, 0x67, 0x65, 0x5f, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6b, 0x00,
  136. 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
  137. 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
  138. 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00,
  139. 0x05, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x61, 0x74, 0x74, 0x72,
  140. 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00,
  141. 0x67, 0x6c, 0x5f, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78,
  142. 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00,
  143. 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74,
  144. 0x69, 0x6f, 0x6e, 0x00, 0x06, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x00,
  145. 0x01, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74,
  146. 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00,
  147. 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43,
  148. 0x6c, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00,
  149. 0x05, 0x00, 0x03, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  150. 0x05, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x00,
  151. 0x05, 0x00, 0x05, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x56,
  152. 0x65, 0x72, 0x74, 0x65, 0x78, 0x49, 0x44, 0x00, 0x05, 0x00, 0x06, 0x00,
  153. 0x1d, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x49, 0x6e, 0x73, 0x74, 0x61,
  154. 0x6e, 0x63, 0x65, 0x49, 0x44, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
  155. 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  156. 0x47, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
  157. 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00,
  158. 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  159. 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  160. 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
  161. 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
  162. 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00,
  163. 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
  164. 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
  165. 0x1c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
  166. 0x47, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
  167. 0x06, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
  168. 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  169. 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
  170. 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
  171. 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
  172. 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
  173. 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
  174. 0x20, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  175. 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
  176. 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
  177. 0x0d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  178. 0x15, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
  179. 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
  180. 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
  181. 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
  182. 0x1e, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
  183. 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
  184. 0x12, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
  185. 0x3b, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
  186. 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
  187. 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
  188. 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  189. 0x20, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  190. 0x0d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00,
  191. 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
  192. 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
  193. 0x20, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  194. 0x14, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00,
  195. 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
  196. 0x1b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  197. 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  198. 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
  199. 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
  200. 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
  201. 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
  202. 0x0d, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
  203. 0x41, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
  204. 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
  205. 0x1a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
  206. 0x38, 0x00, 0x01, 0x00
  207. };
  208. struct texture_object {
  209. VkSampler sampler;
  210. VkImage image;
  211. VkImageLayout imageLayout;
  212. VkDeviceMemory mem;
  213. VkImageView view;
  214. int32_t tex_width, tex_height;
  215. };
  216. static int validation_error = 0;
  217. VKAPI_ATTR VkBool32 VKAPI_CALL
  218. BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
  219. uint64_t srcObject, size_t location, int32_t msgCode,
  220. const char *pLayerPrefix, const char *pMsg,
  221. void *pUserData) {
  222. #ifdef _WIN32
  223. DebugBreak();
  224. #else
  225. raise(SIGTRAP);
  226. #endif
  227. return false;
  228. }
  229. typedef struct {
  230. VkImage image;
  231. VkCommandBuffer cmd;
  232. VkImageView view;
  233. } SwapchainBuffers;
  234. struct demo {
  235. GLFWwindow* window;
  236. VkSurfaceKHR surface;
  237. bool use_staging_buffer;
  238. VkInstance inst;
  239. VkPhysicalDevice gpu;
  240. VkDevice device;
  241. VkQueue queue;
  242. VkPhysicalDeviceProperties gpu_props;
  243. VkPhysicalDeviceFeatures gpu_features;
  244. VkQueueFamilyProperties *queue_props;
  245. uint32_t graphics_queue_node_index;
  246. uint32_t enabled_extension_count;
  247. uint32_t enabled_layer_count;
  248. const char *extension_names[64];
  249. const char *enabled_layers[64];
  250. int width, height;
  251. VkFormat format;
  252. VkColorSpaceKHR color_space;
  253. uint32_t swapchainImageCount;
  254. VkSwapchainKHR swapchain;
  255. SwapchainBuffers *buffers;
  256. VkCommandPool cmd_pool;
  257. struct {
  258. VkFormat format;
  259. VkImage image;
  260. VkDeviceMemory mem;
  261. VkImageView view;
  262. } depth;
  263. struct texture_object textures[DEMO_TEXTURE_COUNT];
  264. struct {
  265. VkBuffer buf;
  266. VkDeviceMemory mem;
  267. VkPipelineVertexInputStateCreateInfo vi;
  268. VkVertexInputBindingDescription vi_bindings[1];
  269. VkVertexInputAttributeDescription vi_attrs[2];
  270. } vertices;
  271. VkCommandBuffer setup_cmd; // Command Buffer for initialization commands
  272. VkCommandBuffer draw_cmd; // Command Buffer for drawing commands
  273. VkPipelineLayout pipeline_layout;
  274. VkDescriptorSetLayout desc_layout;
  275. VkPipelineCache pipelineCache;
  276. VkRenderPass render_pass;
  277. VkPipeline pipeline;
  278. VkShaderModule vert_shader_module;
  279. VkShaderModule frag_shader_module;
  280. VkDescriptorPool desc_pool;
  281. VkDescriptorSet desc_set;
  282. VkFramebuffer *framebuffers;
  283. VkPhysicalDeviceMemoryProperties memory_properties;
  284. int32_t curFrame;
  285. int32_t frameCount;
  286. bool validate;
  287. bool use_break;
  288. VkDebugReportCallbackEXT msg_callback;
  289. float depthStencil;
  290. float depthIncrement;
  291. uint32_t current_buffer;
  292. uint32_t queue_count;
  293. };
  294. VKAPI_ATTR VkBool32 VKAPI_CALL
  295. dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
  296. uint64_t srcObject, size_t location, int32_t msgCode,
  297. const char *pLayerPrefix, const char *pMsg, void *pUserData) {
  298. char *message = (char *)malloc(strlen(pMsg) + 100);
  299. assert(message);
  300. validation_error = 1;
  301. if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
  302. sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode,
  303. pMsg);
  304. } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
  305. sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode,
  306. pMsg);
  307. } else {
  308. return false;
  309. }
  310. printf("%s\n", message);
  311. fflush(stdout);
  312. free(message);
  313. /*
  314. * false indicates that layer should not bail-out of an
  315. * API call that had validation failures. This may mean that the
  316. * app dies inside the driver due to invalid parameter(s).
  317. * That's what would happen without validation layers, so we'll
  318. * keep that behavior here.
  319. */
  320. return false;
  321. }
  322. // Forward declaration:
  323. static void demo_resize(struct demo *demo);
  324. static bool memory_type_from_properties(struct demo *demo, uint32_t typeBits,
  325. VkFlags requirements_mask,
  326. uint32_t *typeIndex) {
  327. uint32_t i;
  328. // Search memtypes to find first index with those properties
  329. for (i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
  330. if ((typeBits & 1) == 1) {
  331. // Type is available, does it match user properties?
  332. if ((demo->memory_properties.memoryTypes[i].propertyFlags &
  333. requirements_mask) == requirements_mask) {
  334. *typeIndex = i;
  335. return true;
  336. }
  337. }
  338. typeBits >>= 1;
  339. }
  340. // No memory types matched, return failure
  341. return false;
  342. }
  343. static void demo_flush_init_cmd(struct demo *demo) {
  344. VkResult U_ASSERT_ONLY err;
  345. if (demo->setup_cmd == VK_NULL_HANDLE)
  346. return;
  347. err = vkEndCommandBuffer(demo->setup_cmd);
  348. assert(!err);
  349. const VkCommandBuffer cmd_bufs[] = {demo->setup_cmd};
  350. VkFence nullFence = {VK_NULL_HANDLE};
  351. VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
  352. .pNext = NULL,
  353. .waitSemaphoreCount = 0,
  354. .pWaitSemaphores = NULL,
  355. .pWaitDstStageMask = NULL,
  356. .commandBufferCount = 1,
  357. .pCommandBuffers = cmd_bufs,
  358. .signalSemaphoreCount = 0,
  359. .pSignalSemaphores = NULL};
  360. err = vkQueueSubmit(demo->queue, 1, &submit_info, nullFence);
  361. assert(!err);
  362. err = vkQueueWaitIdle(demo->queue);
  363. assert(!err);
  364. vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, cmd_bufs);
  365. demo->setup_cmd = VK_NULL_HANDLE;
  366. }
  367. static void demo_set_image_layout(struct demo *demo, VkImage image,
  368. VkImageAspectFlags aspectMask,
  369. VkImageLayout old_image_layout,
  370. VkImageLayout new_image_layout,
  371. VkAccessFlagBits srcAccessMask) {
  372. VkResult U_ASSERT_ONLY err;
  373. if (demo->setup_cmd == VK_NULL_HANDLE) {
  374. const VkCommandBufferAllocateInfo cmd = {
  375. .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
  376. .pNext = NULL,
  377. .commandPool = demo->cmd_pool,
  378. .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
  379. .commandBufferCount = 1,
  380. };
  381. err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->setup_cmd);
  382. assert(!err);
  383. VkCommandBufferBeginInfo cmd_buf_info = {
  384. .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
  385. .pNext = NULL,
  386. .flags = 0,
  387. .pInheritanceInfo = NULL,
  388. };
  389. err = vkBeginCommandBuffer(demo->setup_cmd, &cmd_buf_info);
  390. assert(!err);
  391. }
  392. VkImageMemoryBarrier image_memory_barrier = {
  393. .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
  394. .pNext = NULL,
  395. .srcAccessMask = srcAccessMask,
  396. .dstAccessMask = 0,
  397. .oldLayout = old_image_layout,
  398. .newLayout = new_image_layout,
  399. .image = image,
  400. .subresourceRange = {aspectMask, 0, 1, 0, 1}};
  401. if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
  402. /* Make sure anything that was copying from this image has completed */
  403. image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
  404. }
  405. if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
  406. image_memory_barrier.dstAccessMask =
  407. VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  408. }
  409. if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
  410. image_memory_barrier.dstAccessMask =
  411. VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  412. }
  413. if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
  414. /* Make sure any Copy or CPU writes to image are flushed */
  415. image_memory_barrier.dstAccessMask =
  416. VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
  417. }
  418. VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
  419. VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  420. VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  421. vkCmdPipelineBarrier(demo->setup_cmd, src_stages, dest_stages, 0, 0, NULL,
  422. 0, NULL, 1, pmemory_barrier);
  423. }
  424. static void demo_draw_build_cmd(struct demo *demo) {
  425. const VkCommandBufferBeginInfo cmd_buf_info = {
  426. .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
  427. .pNext = NULL,
  428. .flags = 0,
  429. .pInheritanceInfo = NULL,
  430. };
  431. const VkClearValue clear_values[2] = {
  432. [0] = {.color.float32 = {0.2f, 0.2f, 0.2f, 0.2f}},
  433. [1] = {.depthStencil = {demo->depthStencil, 0}},
  434. };
  435. const VkRenderPassBeginInfo rp_begin = {
  436. .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
  437. .pNext = NULL,
  438. .renderPass = demo->render_pass,
  439. .framebuffer = demo->framebuffers[demo->current_buffer],
  440. .renderArea.offset.x = 0,
  441. .renderArea.offset.y = 0,
  442. .renderArea.extent.width = demo->width,
  443. .renderArea.extent.height = demo->height,
  444. .clearValueCount = 2,
  445. .pClearValues = clear_values,
  446. };
  447. VkResult U_ASSERT_ONLY err;
  448. err = vkBeginCommandBuffer(demo->draw_cmd, &cmd_buf_info);
  449. assert(!err);
  450. // We can use LAYOUT_UNDEFINED as a wildcard here because we don't care what
  451. // happens to the previous contents of the image
  452. VkImageMemoryBarrier image_memory_barrier = {
  453. .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
  454. .pNext = NULL,
  455. .srcAccessMask = 0,
  456. .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  457. .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
  458. .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  459. .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
  460. .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
  461. .image = demo->buffers[demo->current_buffer].image,
  462. .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
  463. vkCmdPipelineBarrier(demo->draw_cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
  464. VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0,
  465. NULL, 1, &image_memory_barrier);
  466. vkCmdBeginRenderPass(demo->draw_cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
  467. vkCmdBindPipeline(demo->draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
  468. demo->pipeline);
  469. vkCmdBindDescriptorSets(demo->draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
  470. demo->pipeline_layout, 0, 1, &demo->desc_set, 0,
  471. NULL);
  472. VkViewport viewport;
  473. memset(&viewport, 0, sizeof(viewport));
  474. viewport.height = (float)demo->height;
  475. viewport.width = (float)demo->width;
  476. viewport.minDepth = (float)0.0f;
  477. viewport.maxDepth = (float)1.0f;
  478. vkCmdSetViewport(demo->draw_cmd, 0, 1, &viewport);
  479. VkRect2D scissor;
  480. memset(&scissor, 0, sizeof(scissor));
  481. scissor.extent.width = demo->width;
  482. scissor.extent.height = demo->height;
  483. scissor.offset.x = 0;
  484. scissor.offset.y = 0;
  485. vkCmdSetScissor(demo->draw_cmd, 0, 1, &scissor);
  486. VkDeviceSize offsets[1] = {0};
  487. vkCmdBindVertexBuffers(demo->draw_cmd, VERTEX_BUFFER_BIND_ID, 1,
  488. &demo->vertices.buf, offsets);
  489. vkCmdDraw(demo->draw_cmd, 3, 1, 0, 0);
  490. vkCmdEndRenderPass(demo->draw_cmd);
  491. VkImageMemoryBarrier prePresentBarrier = {
  492. .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
  493. .pNext = NULL,
  494. .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  495. .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
  496. .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  497. .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
  498. .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
  499. .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
  500. .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
  501. prePresentBarrier.image = demo->buffers[demo->current_buffer].image;
  502. VkImageMemoryBarrier *pmemory_barrier = &prePresentBarrier;
  503. vkCmdPipelineBarrier(demo->draw_cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
  504. VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0,
  505. NULL, 1, pmemory_barrier);
  506. err = vkEndCommandBuffer(demo->draw_cmd);
  507. assert(!err);
  508. }
  509. static void demo_draw(struct demo *demo) {
  510. VkResult U_ASSERT_ONLY err;
  511. VkSemaphore imageAcquiredSemaphore, drawCompleteSemaphore;
  512. VkSemaphoreCreateInfo semaphoreCreateInfo = {
  513. .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
  514. .pNext = NULL,
  515. .flags = 0,
  516. };
  517. err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo,
  518. NULL, &imageAcquiredSemaphore);
  519. assert(!err);
  520. err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo,
  521. NULL, &drawCompleteSemaphore);
  522. assert(!err);
  523. // Get the index of the next available swapchain image:
  524. err = vkAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX,
  525. imageAcquiredSemaphore,
  526. (VkFence)0, // TODO: Show use of fence
  527. &demo->current_buffer);
  528. if (err == VK_ERROR_OUT_OF_DATE_KHR) {
  529. // demo->swapchain is out of date (e.g. the window was resized) and
  530. // must be recreated:
  531. demo_resize(demo);
  532. demo_draw(demo);
  533. vkDestroySemaphore(demo->device, imageAcquiredSemaphore, NULL);
  534. vkDestroySemaphore(demo->device, drawCompleteSemaphore, NULL);
  535. return;
  536. } else if (err == VK_SUBOPTIMAL_KHR) {
  537. // demo->swapchain is not as optimal as it could be, but the platform's
  538. // presentation engine will still present the image correctly.
  539. } else {
  540. assert(!err);
  541. }
  542. demo_flush_init_cmd(demo);
  543. // Wait for the present complete semaphore to be signaled to ensure
  544. // that the image won't be rendered to until the presentation
  545. // engine has fully released ownership to the application, and it is
  546. // okay to render to the image.
  547. demo_draw_build_cmd(demo);
  548. VkFence nullFence = VK_NULL_HANDLE;
  549. VkPipelineStageFlags pipe_stage_flags =
  550. VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  551. VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
  552. .pNext = NULL,
  553. .waitSemaphoreCount = 1,
  554. .pWaitSemaphores = &imageAcquiredSemaphore,
  555. .pWaitDstStageMask = &pipe_stage_flags,
  556. .commandBufferCount = 1,
  557. .pCommandBuffers = &demo->draw_cmd,
  558. .signalSemaphoreCount = 1,
  559. .pSignalSemaphores = &drawCompleteSemaphore};
  560. err = vkQueueSubmit(demo->queue, 1, &submit_info, nullFence);
  561. assert(!err);
  562. VkPresentInfoKHR present = {
  563. .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
  564. .pNext = NULL,
  565. .waitSemaphoreCount = 1,
  566. .pWaitSemaphores = &drawCompleteSemaphore,
  567. .swapchainCount = 1,
  568. .pSwapchains = &demo->swapchain,
  569. .pImageIndices = &demo->current_buffer,
  570. };
  571. err = vkQueuePresentKHR(demo->queue, &present);
  572. if (err == VK_ERROR_OUT_OF_DATE_KHR) {
  573. // demo->swapchain is out of date (e.g. the window was resized) and
  574. // must be recreated:
  575. demo_resize(demo);
  576. } else if (err == VK_SUBOPTIMAL_KHR) {
  577. // demo->swapchain is not as optimal as it could be, but the platform's
  578. // presentation engine will still present the image correctly.
  579. } else {
  580. assert(!err);
  581. }
  582. err = vkQueueWaitIdle(demo->queue);
  583. assert(err == VK_SUCCESS);
  584. vkDestroySemaphore(demo->device, imageAcquiredSemaphore, NULL);
  585. vkDestroySemaphore(demo->device, drawCompleteSemaphore, NULL);
  586. }
  587. static void demo_prepare_buffers(struct demo *demo) {
  588. VkResult U_ASSERT_ONLY err;
  589. VkSwapchainKHR oldSwapchain = demo->swapchain;
  590. // Check the surface capabilities and formats
  591. VkSurfaceCapabilitiesKHR surfCapabilities;
  592. err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
  593. demo->gpu, demo->surface, &surfCapabilities);
  594. assert(!err);
  595. uint32_t presentModeCount;
  596. err = vkGetPhysicalDeviceSurfacePresentModesKHR(
  597. demo->gpu, demo->surface, &presentModeCount, NULL);
  598. assert(!err);
  599. VkPresentModeKHR *presentModes =
  600. (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
  601. assert(presentModes);
  602. err = vkGetPhysicalDeviceSurfacePresentModesKHR(
  603. demo->gpu, demo->surface, &presentModeCount, presentModes);
  604. assert(!err);
  605. VkExtent2D swapchainExtent;
  606. // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
  607. if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) {
  608. // If the surface size is undefined, the size is set to the size
  609. // of the images requested, which must fit within the minimum and
  610. // maximum values.
  611. swapchainExtent.width = demo->width;
  612. swapchainExtent.height = demo->height;
  613. if (swapchainExtent.width < surfCapabilities.minImageExtent.width) {
  614. swapchainExtent.width = surfCapabilities.minImageExtent.width;
  615. } else if (swapchainExtent.width > surfCapabilities.maxImageExtent.width) {
  616. swapchainExtent.width = surfCapabilities.maxImageExtent.width;
  617. }
  618. if (swapchainExtent.height < surfCapabilities.minImageExtent.height) {
  619. swapchainExtent.height = surfCapabilities.minImageExtent.height;
  620. } else if (swapchainExtent.height > surfCapabilities.maxImageExtent.height) {
  621. swapchainExtent.height = surfCapabilities.maxImageExtent.height;
  622. }
  623. } else {
  624. // If the surface size is defined, the swap chain size must match
  625. swapchainExtent = surfCapabilities.currentExtent;
  626. demo->width = surfCapabilities.currentExtent.width;
  627. demo->height = surfCapabilities.currentExtent.height;
  628. }
  629. VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
  630. // Determine the number of VkImage's to use in the swap chain.
  631. // Application desires to only acquire 1 image at a time (which is
  632. // "surfCapabilities.minImageCount").
  633. uint32_t desiredNumOfSwapchainImages = surfCapabilities.minImageCount;
  634. // If maxImageCount is 0, we can ask for as many images as we want;
  635. // otherwise we're limited to maxImageCount
  636. if ((surfCapabilities.maxImageCount > 0) &&
  637. (desiredNumOfSwapchainImages > surfCapabilities.maxImageCount)) {
  638. // Application must settle for fewer images than desired:
  639. desiredNumOfSwapchainImages = surfCapabilities.maxImageCount;
  640. }
  641. VkSurfaceTransformFlagsKHR preTransform;
  642. if (surfCapabilities.supportedTransforms &
  643. VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
  644. preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
  645. } else {
  646. preTransform = surfCapabilities.currentTransform;
  647. }
  648. const VkSwapchainCreateInfoKHR swapchain = {
  649. .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
  650. .pNext = NULL,
  651. .surface = demo->surface,
  652. .minImageCount = desiredNumOfSwapchainImages,
  653. .imageFormat = demo->format,
  654. .imageColorSpace = demo->color_space,
  655. .imageExtent =
  656. {
  657. .width = swapchainExtent.width, .height = swapchainExtent.height,
  658. },
  659. .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
  660. .preTransform = preTransform,
  661. .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
  662. .imageArrayLayers = 1,
  663. .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
  664. .queueFamilyIndexCount = 0,
  665. .pQueueFamilyIndices = NULL,
  666. .presentMode = swapchainPresentMode,
  667. .oldSwapchain = oldSwapchain,
  668. .clipped = true,
  669. };
  670. uint32_t i;
  671. err = vkCreateSwapchainKHR(demo->device, &swapchain, NULL, &demo->swapchain);
  672. assert(!err);
  673. // If we just re-created an existing swapchain, we should destroy the old
  674. // swapchain at this point.
  675. // Note: destroying the swapchain also cleans up all its associated
  676. // presentable images once the platform is done with them.
  677. if (oldSwapchain != VK_NULL_HANDLE) {
  678. vkDestroySwapchainKHR(demo->device, oldSwapchain, NULL);
  679. }
  680. err = vkGetSwapchainImagesKHR(demo->device, demo->swapchain,
  681. &demo->swapchainImageCount, NULL);
  682. assert(!err);
  683. VkImage *swapchainImages =
  684. (VkImage *)malloc(demo->swapchainImageCount * sizeof(VkImage));
  685. assert(swapchainImages);
  686. err = vkGetSwapchainImagesKHR(demo->device, demo->swapchain,
  687. &demo->swapchainImageCount,
  688. swapchainImages);
  689. assert(!err);
  690. demo->buffers = (SwapchainBuffers *)malloc(sizeof(SwapchainBuffers) *
  691. demo->swapchainImageCount);
  692. assert(demo->buffers);
  693. for (i = 0; i < demo->swapchainImageCount; i++) {
  694. VkImageViewCreateInfo color_attachment_view = {
  695. .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
  696. .pNext = NULL,
  697. .format = demo->format,
  698. .components =
  699. {
  700. .r = VK_COMPONENT_SWIZZLE_R,
  701. .g = VK_COMPONENT_SWIZZLE_G,
  702. .b = VK_COMPONENT_SWIZZLE_B,
  703. .a = VK_COMPONENT_SWIZZLE_A,
  704. },
  705. .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
  706. .baseMipLevel = 0,
  707. .levelCount = 1,
  708. .baseArrayLayer = 0,
  709. .layerCount = 1},
  710. .viewType = VK_IMAGE_VIEW_TYPE_2D,
  711. .flags = 0,
  712. };
  713. demo->buffers[i].image = swapchainImages[i];
  714. color_attachment_view.image = demo->buffers[i].image;
  715. err = vkCreateImageView(demo->device, &color_attachment_view, NULL,
  716. &demo->buffers[i].view);
  717. assert(!err);
  718. }
  719. demo->current_buffer = 0;
  720. if (NULL != presentModes) {
  721. free(presentModes);
  722. }
  723. }
  724. static void demo_prepare_depth(struct demo *demo) {
  725. const VkFormat depth_format = VK_FORMAT_D16_UNORM;
  726. const VkImageCreateInfo image = {
  727. .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
  728. .pNext = NULL,
  729. .imageType = VK_IMAGE_TYPE_2D,
  730. .format = depth_format,
  731. .extent = {demo->width, demo->height, 1},
  732. .mipLevels = 1,
  733. .arrayLayers = 1,
  734. .samples = VK_SAMPLE_COUNT_1_BIT,
  735. .tiling = VK_IMAGE_TILING_OPTIMAL,
  736. .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
  737. .flags = 0,
  738. };
  739. VkMemoryAllocateInfo mem_alloc = {
  740. .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
  741. .pNext = NULL,
  742. .allocationSize = 0,
  743. .memoryTypeIndex = 0,
  744. };
  745. VkImageViewCreateInfo view = {
  746. .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
  747. .pNext = NULL,
  748. .image = VK_NULL_HANDLE,
  749. .format = depth_format,
  750. .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
  751. .baseMipLevel = 0,
  752. .levelCount = 1,
  753. .baseArrayLayer = 0,
  754. .layerCount = 1},
  755. .flags = 0,
  756. .viewType = VK_IMAGE_VIEW_TYPE_2D,
  757. };
  758. VkMemoryRequirements mem_reqs;
  759. VkResult U_ASSERT_ONLY err;
  760. bool U_ASSERT_ONLY pass;
  761. demo->depth.format = depth_format;
  762. /* create image */
  763. err = vkCreateImage(demo->device, &image, NULL, &demo->depth.image);
  764. assert(!err);
  765. /* get memory requirements for this object */
  766. vkGetImageMemoryRequirements(demo->device, demo->depth.image, &mem_reqs);
  767. /* select memory size and type */
  768. mem_alloc.allocationSize = mem_reqs.size;
  769. pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
  770. 0, /* No requirements */
  771. &mem_alloc.memoryTypeIndex);
  772. assert(pass);
  773. /* allocate memory */
  774. err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &demo->depth.mem);
  775. assert(!err);
  776. /* bind memory */
  777. err =
  778. vkBindImageMemory(demo->device, demo->depth.image, demo->depth.mem, 0);
  779. assert(!err);
  780. demo_set_image_layout(demo, demo->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT,
  781. VK_IMAGE_LAYOUT_UNDEFINED,
  782. VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
  783. 0);
  784. /* create image view */
  785. view.image = demo->depth.image;
  786. err = vkCreateImageView(demo->device, &view, NULL, &demo->depth.view);
  787. assert(!err);
  788. }
  789. static void
  790. demo_prepare_texture_image(struct demo *demo, const uint32_t *tex_colors,
  791. struct texture_object *tex_obj, VkImageTiling tiling,
  792. VkImageUsageFlags usage, VkFlags required_props) {
  793. const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
  794. const int32_t tex_width = 2;
  795. const int32_t tex_height = 2;
  796. VkResult U_ASSERT_ONLY err;
  797. bool U_ASSERT_ONLY pass;
  798. tex_obj->tex_width = tex_width;
  799. tex_obj->tex_height = tex_height;
  800. const VkImageCreateInfo image_create_info = {
  801. .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
  802. .pNext = NULL,
  803. .imageType = VK_IMAGE_TYPE_2D,
  804. .format = tex_format,
  805. .extent = {tex_width, tex_height, 1},
  806. .mipLevels = 1,
  807. .arrayLayers = 1,
  808. .samples = VK_SAMPLE_COUNT_1_BIT,
  809. .tiling = tiling,
  810. .usage = usage,
  811. .flags = 0,
  812. .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED
  813. };
  814. VkMemoryAllocateInfo mem_alloc = {
  815. .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
  816. .pNext = NULL,
  817. .allocationSize = 0,
  818. .memoryTypeIndex = 0,
  819. };
  820. VkMemoryRequirements mem_reqs;
  821. err =
  822. vkCreateImage(demo->device, &image_create_info, NULL, &tex_obj->image);
  823. assert(!err);
  824. vkGetImageMemoryRequirements(demo->device, tex_obj->image, &mem_reqs);
  825. mem_alloc.allocationSize = mem_reqs.size;
  826. pass =
  827. memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
  828. required_props, &mem_alloc.memoryTypeIndex);
  829. assert(pass);
  830. /* allocate memory */
  831. err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &tex_obj->mem);
  832. assert(!err);
  833. /* bind memory */
  834. err = vkBindImageMemory(demo->device, tex_obj->image, tex_obj->mem, 0);
  835. assert(!err);
  836. if (required_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
  837. const VkImageSubresource subres = {
  838. .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
  839. .mipLevel = 0,
  840. .arrayLayer = 0,
  841. };
  842. VkSubresourceLayout layout;
  843. void *data;
  844. int32_t x, y;
  845. vkGetImageSubresourceLayout(demo->device, tex_obj->image, &subres,
  846. &layout);
  847. err = vkMapMemory(demo->device, tex_obj->mem, 0,
  848. mem_alloc.allocationSize, 0, &data);
  849. assert(!err);
  850. for (y = 0; y < tex_height; y++) {
  851. uint32_t *row = (uint32_t *)((char *)data + layout.rowPitch * y);
  852. for (x = 0; x < tex_width; x++)
  853. row[x] = tex_colors[(x & 1) ^ (y & 1)];
  854. }
  855. vkUnmapMemory(demo->device, tex_obj->mem);
  856. }
  857. tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  858. demo_set_image_layout(demo, tex_obj->image, VK_IMAGE_ASPECT_COLOR_BIT,
  859. VK_IMAGE_LAYOUT_PREINITIALIZED, tex_obj->imageLayout,
  860. VK_ACCESS_HOST_WRITE_BIT);
  861. /* setting the image layout does not reference the actual memory so no need
  862. * to add a mem ref */
  863. }
  864. static void demo_destroy_texture_image(struct demo *demo,
  865. struct texture_object *tex_obj) {
  866. /* clean up staging resources */
  867. vkDestroyImage(demo->device, tex_obj->image, NULL);
  868. vkFreeMemory(demo->device, tex_obj->mem, NULL);
  869. }
  870. static void demo_prepare_textures(struct demo *demo) {
  871. const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
  872. VkFormatProperties props;
  873. const uint32_t tex_colors[DEMO_TEXTURE_COUNT][2] = {
  874. {0xffff0000, 0xff00ff00},
  875. };
  876. uint32_t i;
  877. VkResult U_ASSERT_ONLY err;
  878. vkGetPhysicalDeviceFormatProperties(demo->gpu, tex_format, &props);
  879. for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
  880. if ((props.linearTilingFeatures &
  881. VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) &&
  882. !demo->use_staging_buffer) {
  883. /* Device can texture using linear textures */
  884. demo_prepare_texture_image(
  885. demo, tex_colors[i], &demo->textures[i], VK_IMAGE_TILING_LINEAR,
  886. VK_IMAGE_USAGE_SAMPLED_BIT,
  887. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  888. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
  889. } else if (props.optimalTilingFeatures &
  890. VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
  891. /* Must use staging buffer to copy linear texture to optimized */
  892. struct texture_object staging_texture;
  893. memset(&staging_texture, 0, sizeof(staging_texture));
  894. demo_prepare_texture_image(
  895. demo, tex_colors[i], &staging_texture, VK_IMAGE_TILING_LINEAR,
  896. VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
  897. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  898. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
  899. demo_prepare_texture_image(
  900. demo, tex_colors[i], &demo->textures[i],
  901. VK_IMAGE_TILING_OPTIMAL,
  902. (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
  903. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
  904. demo_set_image_layout(demo, staging_texture.image,
  905. VK_IMAGE_ASPECT_COLOR_BIT,
  906. staging_texture.imageLayout,
  907. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  908. 0);
  909. demo_set_image_layout(demo, demo->textures[i].image,
  910. VK_IMAGE_ASPECT_COLOR_BIT,
  911. demo->textures[i].imageLayout,
  912. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  913. 0);
  914. VkImageCopy copy_region = {
  915. .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
  916. .srcOffset = {0, 0, 0},
  917. .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
  918. .dstOffset = {0, 0, 0},
  919. .extent = {staging_texture.tex_width,
  920. staging_texture.tex_height, 1},
  921. };
  922. vkCmdCopyImage(
  923. demo->setup_cmd, staging_texture.image,
  924. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, demo->textures[i].image,
  925. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_region);
  926. demo_set_image_layout(demo, demo->textures[i].image,
  927. VK_IMAGE_ASPECT_COLOR_BIT,
  928. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  929. demo->textures[i].imageLayout,
  930. 0);
  931. demo_flush_init_cmd(demo);
  932. demo_destroy_texture_image(demo, &staging_texture);
  933. } else {
  934. /* Can't support VK_FORMAT_B8G8R8A8_UNORM !? */
  935. assert(!"No support for B8G8R8A8_UNORM as texture image format");
  936. }
  937. const VkSamplerCreateInfo sampler = {
  938. .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
  939. .pNext = NULL,
  940. .magFilter = VK_FILTER_NEAREST,
  941. .minFilter = VK_FILTER_NEAREST,
  942. .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
  943. .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
  944. .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
  945. .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
  946. .mipLodBias = 0.0f,
  947. .anisotropyEnable = VK_FALSE,
  948. .maxAnisotropy = 1,
  949. .compareOp = VK_COMPARE_OP_NEVER,
  950. .minLod = 0.0f,
  951. .maxLod = 0.0f,
  952. .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
  953. .unnormalizedCoordinates = VK_FALSE,
  954. };
  955. VkImageViewCreateInfo view = {
  956. .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
  957. .pNext = NULL,
  958. .image = VK_NULL_HANDLE,
  959. .viewType = VK_IMAGE_VIEW_TYPE_2D,
  960. .format = tex_format,
  961. .components =
  962. {
  963. VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
  964. VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A,
  965. },
  966. .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
  967. .flags = 0,
  968. };
  969. /* create sampler */
  970. err = vkCreateSampler(demo->device, &sampler, NULL,
  971. &demo->textures[i].sampler);
  972. assert(!err);
  973. /* create image view */
  974. view.image = demo->textures[i].image;
  975. err = vkCreateImageView(demo->device, &view, NULL,
  976. &demo->textures[i].view);
  977. assert(!err);
  978. }
  979. }
  980. static void demo_prepare_vertices(struct demo *demo) {
  981. // clang-format off
  982. const float vb[3][5] = {
  983. /* position texcoord */
  984. { -1.0f, -1.0f, 0.25f, 0.0f, 0.0f },
  985. { 1.0f, -1.0f, 0.25f, 1.0f, 0.0f },
  986. { 0.0f, 1.0f, 1.0f, 0.5f, 1.0f },
  987. };
  988. // clang-format on
  989. const VkBufferCreateInfo buf_info = {
  990. .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
  991. .pNext = NULL,
  992. .size = sizeof(vb),
  993. .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
  994. .flags = 0,
  995. };
  996. VkMemoryAllocateInfo mem_alloc = {
  997. .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
  998. .pNext = NULL,
  999. .allocationSize = 0,
  1000. .memoryTypeIndex = 0,
  1001. };
  1002. VkMemoryRequirements mem_reqs;
  1003. VkResult U_ASSERT_ONLY err;
  1004. bool U_ASSERT_ONLY pass;
  1005. void *data;
  1006. memset(&demo->vertices, 0, sizeof(demo->vertices));
  1007. err = vkCreateBuffer(demo->device, &buf_info, NULL, &demo->vertices.buf);
  1008. assert(!err);
  1009. vkGetBufferMemoryRequirements(demo->device, demo->vertices.buf, &mem_reqs);
  1010. assert(!err);
  1011. mem_alloc.allocationSize = mem_reqs.size;
  1012. pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
  1013. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  1014. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
  1015. &mem_alloc.memoryTypeIndex);
  1016. assert(pass);
  1017. err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &demo->vertices.mem);
  1018. assert(!err);
  1019. err = vkMapMemory(demo->device, demo->vertices.mem, 0,
  1020. mem_alloc.allocationSize, 0, &data);
  1021. assert(!err);
  1022. memcpy(data, vb, sizeof(vb));
  1023. vkUnmapMemory(demo->device, demo->vertices.mem);
  1024. err = vkBindBufferMemory(demo->device, demo->vertices.buf,
  1025. demo->vertices.mem, 0);
  1026. assert(!err);
  1027. demo->vertices.vi.sType =
  1028. VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  1029. demo->vertices.vi.pNext = NULL;
  1030. demo->vertices.vi.vertexBindingDescriptionCount = 1;
  1031. demo->vertices.vi.pVertexBindingDescriptions = demo->vertices.vi_bindings;
  1032. demo->vertices.vi.vertexAttributeDescriptionCount = 2;
  1033. demo->vertices.vi.pVertexAttributeDescriptions = demo->vertices.vi_attrs;
  1034. demo->vertices.vi_bindings[0].binding = VERTEX_BUFFER_BIND_ID;
  1035. demo->vertices.vi_bindings[0].stride = sizeof(vb[0]);
  1036. demo->vertices.vi_bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
  1037. demo->vertices.vi_attrs[0].binding = VERTEX_BUFFER_BIND_ID;
  1038. demo->vertices.vi_attrs[0].location = 0;
  1039. demo->vertices.vi_attrs[0].format = VK_FORMAT_R32G32B32_SFLOAT;
  1040. demo->vertices.vi_attrs[0].offset = 0;
  1041. demo->vertices.vi_attrs[1].binding = VERTEX_BUFFER_BIND_ID;
  1042. demo->vertices.vi_attrs[1].location = 1;
  1043. demo->vertices.vi_attrs[1].format = VK_FORMAT_R32G32_SFLOAT;
  1044. demo->vertices.vi_attrs[1].offset = sizeof(float) * 3;
  1045. }
  1046. static void demo_prepare_descriptor_layout(struct demo *demo) {
  1047. const VkDescriptorSetLayoutBinding layout_binding = {
  1048. .binding = 0,
  1049. .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
  1050. .descriptorCount = DEMO_TEXTURE_COUNT,
  1051. .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
  1052. .pImmutableSamplers = NULL,
  1053. };
  1054. const VkDescriptorSetLayoutCreateInfo descriptor_layout = {
  1055. .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
  1056. .pNext = NULL,
  1057. .bindingCount = 1,
  1058. .pBindings = &layout_binding,
  1059. };
  1060. VkResult U_ASSERT_ONLY err;
  1061. err = vkCreateDescriptorSetLayout(demo->device, &descriptor_layout, NULL,
  1062. &demo->desc_layout);
  1063. assert(!err);
  1064. const VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {
  1065. .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
  1066. .pNext = NULL,
  1067. .setLayoutCount = 1,
  1068. .pSetLayouts = &demo->desc_layout,
  1069. };
  1070. err = vkCreatePipelineLayout(demo->device, &pPipelineLayoutCreateInfo, NULL,
  1071. &demo->pipeline_layout);
  1072. assert(!err);
  1073. }
  1074. static void demo_prepare_render_pass(struct demo *demo) {
  1075. const VkAttachmentDescription attachments[2] = {
  1076. [0] =
  1077. {
  1078. .format = demo->format,
  1079. .samples = VK_SAMPLE_COUNT_1_BIT,
  1080. .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
  1081. .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
  1082. .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
  1083. .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
  1084. .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  1085. .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  1086. },
  1087. [1] =
  1088. {
  1089. .format = demo->depth.format,
  1090. .samples = VK_SAMPLE_COUNT_1_BIT,
  1091. .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
  1092. .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
  1093. .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
  1094. .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
  1095. .initialLayout =
  1096. VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
  1097. .finalLayout =
  1098. VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
  1099. },
  1100. };
  1101. const VkAttachmentReference color_reference = {
  1102. .attachment = 0, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  1103. };
  1104. const VkAttachmentReference depth_reference = {
  1105. .attachment = 1,
  1106. .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
  1107. };
  1108. const VkSubpassDescription subpass = {
  1109. .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
  1110. .flags = 0,
  1111. .inputAttachmentCount = 0,
  1112. .pInputAttachments = NULL,
  1113. .colorAttachmentCount = 1,
  1114. .pColorAttachments = &color_reference,
  1115. .pResolveAttachments = NULL,
  1116. .pDepthStencilAttachment = &depth_reference,
  1117. .preserveAttachmentCount = 0,
  1118. .pPreserveAttachments = NULL,
  1119. };
  1120. const VkRenderPassCreateInfo rp_info = {
  1121. .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
  1122. .pNext = NULL,
  1123. .attachmentCount = 2,
  1124. .pAttachments = attachments,
  1125. .subpassCount = 1,
  1126. .pSubpasses = &subpass,
  1127. .dependencyCount = 0,
  1128. .pDependencies = NULL,
  1129. };
  1130. VkResult U_ASSERT_ONLY err;
  1131. err = vkCreateRenderPass(demo->device, &rp_info, NULL, &demo->render_pass);
  1132. assert(!err);
  1133. }
  1134. static VkShaderModule
  1135. demo_prepare_shader_module(struct demo *demo, const void *code, size_t size) {
  1136. VkShaderModuleCreateInfo moduleCreateInfo;
  1137. VkShaderModule module;
  1138. VkResult U_ASSERT_ONLY err;
  1139. moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  1140. moduleCreateInfo.pNext = NULL;
  1141. moduleCreateInfo.codeSize = size;
  1142. moduleCreateInfo.pCode = code;
  1143. moduleCreateInfo.flags = 0;
  1144. err = vkCreateShaderModule(demo->device, &moduleCreateInfo, NULL, &module);
  1145. assert(!err);
  1146. return module;
  1147. }
  1148. static VkShaderModule demo_prepare_vs(struct demo *demo) {
  1149. size_t size = sizeof(vertShaderCode);
  1150. demo->vert_shader_module =
  1151. demo_prepare_shader_module(demo, vertShaderCode, size);
  1152. return demo->vert_shader_module;
  1153. }
  1154. static VkShaderModule demo_prepare_fs(struct demo *demo) {
  1155. size_t size = sizeof(fragShaderCode);
  1156. demo->frag_shader_module =
  1157. demo_prepare_shader_module(demo, fragShaderCode, size);
  1158. return demo->frag_shader_module;
  1159. }
  1160. static void demo_prepare_pipeline(struct demo *demo) {
  1161. VkGraphicsPipelineCreateInfo pipeline;
  1162. VkPipelineCacheCreateInfo pipelineCache;
  1163. VkPipelineVertexInputStateCreateInfo vi;
  1164. VkPipelineInputAssemblyStateCreateInfo ia;
  1165. VkPipelineRasterizationStateCreateInfo rs;
  1166. VkPipelineColorBlendStateCreateInfo cb;
  1167. VkPipelineDepthStencilStateCreateInfo ds;
  1168. VkPipelineViewportStateCreateInfo vp;
  1169. VkPipelineMultisampleStateCreateInfo ms;
  1170. VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE];
  1171. VkPipelineDynamicStateCreateInfo dynamicState;
  1172. VkResult U_ASSERT_ONLY err;
  1173. memset(dynamicStateEnables, 0, sizeof dynamicStateEnables);
  1174. memset(&dynamicState, 0, sizeof dynamicState);
  1175. dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
  1176. dynamicState.pDynamicStates = dynamicStateEnables;
  1177. memset(&pipeline, 0, sizeof(pipeline));
  1178. pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  1179. pipeline.layout = demo->pipeline_layout;
  1180. vi = demo->vertices.vi;
  1181. memset(&ia, 0, sizeof(ia));
  1182. ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  1183. ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  1184. memset(&rs, 0, sizeof(rs));
  1185. rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  1186. rs.polygonMode = VK_POLYGON_MODE_FILL;
  1187. rs.cullMode = VK_CULL_MODE_BACK_BIT;
  1188. rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
  1189. rs.depthClampEnable = VK_FALSE;
  1190. rs.rasterizerDiscardEnable = VK_FALSE;
  1191. rs.depthBiasEnable = VK_FALSE;
  1192. rs.lineWidth = 1.0f;
  1193. memset(&cb, 0, sizeof(cb));
  1194. cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  1195. VkPipelineColorBlendAttachmentState att_state[1];
  1196. memset(att_state, 0, sizeof(att_state));
  1197. att_state[0].colorWriteMask = 0xf;
  1198. att_state[0].blendEnable = VK_FALSE;
  1199. cb.attachmentCount = 1;
  1200. cb.pAttachments = att_state;
  1201. memset(&vp, 0, sizeof(vp));
  1202. vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  1203. vp.viewportCount = 1;
  1204. dynamicStateEnables[dynamicState.dynamicStateCount++] =
  1205. VK_DYNAMIC_STATE_VIEWPORT;
  1206. vp.scissorCount = 1;
  1207. dynamicStateEnables[dynamicState.dynamicStateCount++] =
  1208. VK_DYNAMIC_STATE_SCISSOR;
  1209. memset(&ds, 0, sizeof(ds));
  1210. ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
  1211. ds.depthTestEnable = VK_TRUE;
  1212. ds.depthWriteEnable = VK_TRUE;
  1213. ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
  1214. ds.depthBoundsTestEnable = VK_FALSE;
  1215. ds.back.failOp = VK_STENCIL_OP_KEEP;
  1216. ds.back.passOp = VK_STENCIL_OP_KEEP;
  1217. ds.back.compareOp = VK_COMPARE_OP_ALWAYS;
  1218. ds.stencilTestEnable = VK_FALSE;
  1219. ds.front = ds.back;
  1220. memset(&ms, 0, sizeof(ms));
  1221. ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  1222. ms.pSampleMask = NULL;
  1223. ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
  1224. // Two stages: vs and fs
  1225. pipeline.stageCount = 2;
  1226. VkPipelineShaderStageCreateInfo shaderStages[2];
  1227. memset(&shaderStages, 0, 2 * sizeof(VkPipelineShaderStageCreateInfo));
  1228. shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  1229. shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
  1230. shaderStages[0].module = demo_prepare_vs(demo);
  1231. shaderStages[0].pName = "main";
  1232. shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  1233. shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
  1234. shaderStages[1].module = demo_prepare_fs(demo);
  1235. shaderStages[1].pName = "main";
  1236. pipeline.pVertexInputState = &vi;
  1237. pipeline.pInputAssemblyState = &ia;
  1238. pipeline.pRasterizationState = &rs;
  1239. pipeline.pColorBlendState = &cb;
  1240. pipeline.pMultisampleState = &ms;
  1241. pipeline.pViewportState = &vp;
  1242. pipeline.pDepthStencilState = &ds;
  1243. pipeline.pStages = shaderStages;
  1244. pipeline.renderPass = demo->render_pass;
  1245. pipeline.pDynamicState = &dynamicState;
  1246. memset(&pipelineCache, 0, sizeof(pipelineCache));
  1247. pipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
  1248. err = vkCreatePipelineCache(demo->device, &pipelineCache, NULL,
  1249. &demo->pipelineCache);
  1250. assert(!err);
  1251. err = vkCreateGraphicsPipelines(demo->device, demo->pipelineCache, 1,
  1252. &pipeline, NULL, &demo->pipeline);
  1253. assert(!err);
  1254. vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL);
  1255. vkDestroyShaderModule(demo->device, demo->frag_shader_module, NULL);
  1256. vkDestroyShaderModule(demo->device, demo->vert_shader_module, NULL);
  1257. }
  1258. static void demo_prepare_descriptor_pool(struct demo *demo) {
  1259. const VkDescriptorPoolSize type_count = {
  1260. .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
  1261. .descriptorCount = DEMO_TEXTURE_COUNT,
  1262. };
  1263. const VkDescriptorPoolCreateInfo descriptor_pool = {
  1264. .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
  1265. .pNext = NULL,
  1266. .maxSets = 1,
  1267. .poolSizeCount = 1,
  1268. .pPoolSizes = &type_count,
  1269. };
  1270. VkResult U_ASSERT_ONLY err;
  1271. err = vkCreateDescriptorPool(demo->device, &descriptor_pool, NULL,
  1272. &demo->desc_pool);
  1273. assert(!err);
  1274. }
  1275. static void demo_prepare_descriptor_set(struct demo *demo) {
  1276. VkDescriptorImageInfo tex_descs[DEMO_TEXTURE_COUNT];
  1277. VkWriteDescriptorSet write;
  1278. VkResult U_ASSERT_ONLY err;
  1279. uint32_t i;
  1280. VkDescriptorSetAllocateInfo alloc_info = {
  1281. .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
  1282. .pNext = NULL,
  1283. .descriptorPool = demo->desc_pool,
  1284. .descriptorSetCount = 1,
  1285. .pSetLayouts = &demo->desc_layout};
  1286. err = vkAllocateDescriptorSets(demo->device, &alloc_info, &demo->desc_set);
  1287. assert(!err);
  1288. memset(&tex_descs, 0, sizeof(tex_descs));
  1289. for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
  1290. tex_descs[i].sampler = demo->textures[i].sampler;
  1291. tex_descs[i].imageView = demo->textures[i].view;
  1292. tex_descs[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
  1293. }
  1294. memset(&write, 0, sizeof(write));
  1295. write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  1296. write.dstSet = demo->desc_set;
  1297. write.descriptorCount = DEMO_TEXTURE_COUNT;
  1298. write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  1299. write.pImageInfo = tex_descs;
  1300. vkUpdateDescriptorSets(demo->device, 1, &write, 0, NULL);
  1301. }
  1302. static void demo_prepare_framebuffers(struct demo *demo) {
  1303. VkImageView attachments[2];
  1304. attachments[1] = demo->depth.view;
  1305. const VkFramebufferCreateInfo fb_info = {
  1306. .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
  1307. .pNext = NULL,
  1308. .renderPass = demo->render_pass,
  1309. .attachmentCount = 2,
  1310. .pAttachments = attachments,
  1311. .width = demo->width,
  1312. .height = demo->height,
  1313. .layers = 1,
  1314. };
  1315. VkResult U_ASSERT_ONLY err;
  1316. uint32_t i;
  1317. demo->framebuffers = (VkFramebuffer *)malloc(demo->swapchainImageCount *
  1318. sizeof(VkFramebuffer));
  1319. assert(demo->framebuffers);
  1320. for (i = 0; i < demo->swapchainImageCount; i++) {
  1321. attachments[0] = demo->buffers[i].view;
  1322. err = vkCreateFramebuffer(demo->device, &fb_info, NULL,
  1323. &demo->framebuffers[i]);
  1324. assert(!err);
  1325. }
  1326. }
  1327. static void demo_prepare(struct demo *demo) {
  1328. VkResult U_ASSERT_ONLY err;
  1329. const VkCommandPoolCreateInfo cmd_pool_info = {
  1330. .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
  1331. .pNext = NULL,
  1332. .queueFamilyIndex = demo->graphics_queue_node_index,
  1333. .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
  1334. };
  1335. err = vkCreateCommandPool(demo->device, &cmd_pool_info, NULL,
  1336. &demo->cmd_pool);
  1337. assert(!err);
  1338. const VkCommandBufferAllocateInfo cmd = {
  1339. .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
  1340. .pNext = NULL,
  1341. .commandPool = demo->cmd_pool,
  1342. .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
  1343. .commandBufferCount = 1,
  1344. };
  1345. err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->draw_cmd);
  1346. assert(!err);
  1347. demo_prepare_buffers(demo);
  1348. demo_prepare_depth(demo);
  1349. demo_prepare_textures(demo);
  1350. demo_prepare_vertices(demo);
  1351. demo_prepare_descriptor_layout(demo);
  1352. demo_prepare_render_pass(demo);
  1353. demo_prepare_pipeline(demo);
  1354. demo_prepare_descriptor_pool(demo);
  1355. demo_prepare_descriptor_set(demo);
  1356. demo_prepare_framebuffers(demo);
  1357. }
  1358. static void demo_error_callback(int error, const char* description) {
  1359. printf("GLFW error: %s\n", description);
  1360. fflush(stdout);
  1361. }
  1362. static void demo_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
  1363. if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
  1364. glfwSetWindowShouldClose(window, GLFW_TRUE);
  1365. }
  1366. static void demo_refresh_callback(GLFWwindow* window) {
  1367. struct demo* demo = glfwGetWindowUserPointer(window);
  1368. demo_draw(demo);
  1369. }
  1370. static void demo_resize_callback(GLFWwindow* window, int width, int height) {
  1371. struct demo* demo = glfwGetWindowUserPointer(window);
  1372. demo->width = width;
  1373. demo->height = height;
  1374. demo_resize(demo);
  1375. }
  1376. static void demo_run(struct demo *demo) {
  1377. while (!glfwWindowShouldClose(demo->window)) {
  1378. glfwPollEvents();
  1379. demo_draw(demo);
  1380. if (demo->depthStencil > 0.99f)
  1381. demo->depthIncrement = -0.001f;
  1382. if (demo->depthStencil < 0.8f)
  1383. demo->depthIncrement = 0.001f;
  1384. demo->depthStencil += demo->depthIncrement;
  1385. // Wait for work to finish before updating MVP.
  1386. vkDeviceWaitIdle(demo->device);
  1387. demo->curFrame++;
  1388. if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
  1389. glfwSetWindowShouldClose(demo->window, GLFW_TRUE);
  1390. }
  1391. }
  1392. static void demo_create_window(struct demo *demo) {
  1393. glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
  1394. demo->window = glfwCreateWindow(demo->width,
  1395. demo->height,
  1396. APP_LONG_NAME,
  1397. NULL,
  1398. NULL);
  1399. if (!demo->window) {
  1400. // It didn't work, so try to give a useful error:
  1401. printf("Cannot create a window in which to draw!\n");
  1402. fflush(stdout);
  1403. exit(1);
  1404. }
  1405. glfwSetWindowUserPointer(demo->window, demo);
  1406. glfwSetWindowRefreshCallback(demo->window, demo_refresh_callback);
  1407. glfwSetFramebufferSizeCallback(demo->window, demo_resize_callback);
  1408. glfwSetKeyCallback(demo->window, demo_key_callback);
  1409. }
  1410. /*
  1411. * Return 1 (true) if all layer names specified in check_names
  1412. * can be found in given layer properties.
  1413. */
  1414. static VkBool32 demo_check_layers(uint32_t check_count, const char **check_names,
  1415. uint32_t layer_count,
  1416. VkLayerProperties *layers) {
  1417. uint32_t i, j;
  1418. for (i = 0; i < check_count; i++) {
  1419. VkBool32 found = 0;
  1420. for (j = 0; j < layer_count; j++) {
  1421. if (!strcmp(check_names[i], layers[j].layerName)) {
  1422. found = 1;
  1423. break;
  1424. }
  1425. }
  1426. if (!found) {
  1427. fprintf(stderr, "Cannot find layer: %s\n", check_names[i]);
  1428. return 0;
  1429. }
  1430. }
  1431. return 1;
  1432. }
  1433. static void demo_init_vk(struct demo *demo) {
  1434. VkResult err;
  1435. uint32_t i = 0;
  1436. uint32_t required_extension_count = 0;
  1437. uint32_t instance_extension_count = 0;
  1438. uint32_t instance_layer_count = 0;
  1439. uint32_t validation_layer_count = 0;
  1440. const char **required_extensions = NULL;
  1441. const char **instance_validation_layers = NULL;
  1442. demo->enabled_extension_count = 0;
  1443. demo->enabled_layer_count = 0;
  1444. char *instance_validation_layers_alt1[] = {
  1445. "VK_LAYER_LUNARG_standard_validation"
  1446. };
  1447. char *instance_validation_layers_alt2[] = {
  1448. "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
  1449. "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_image",
  1450. "VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain",
  1451. "VK_LAYER_GOOGLE_unique_objects"
  1452. };
  1453. /* Look for validation layers */
  1454. VkBool32 validation_found = 0;
  1455. if (demo->validate) {
  1456. err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
  1457. assert(!err);
  1458. instance_validation_layers = (const char**) instance_validation_layers_alt1;
  1459. if (instance_layer_count > 0) {
  1460. VkLayerProperties *instance_layers =
  1461. malloc(sizeof (VkLayerProperties) * instance_layer_count);
  1462. err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
  1463. instance_layers);
  1464. assert(!err);
  1465. validation_found = demo_check_layers(
  1466. ARRAY_SIZE(instance_validation_layers_alt1),
  1467. instance_validation_layers, instance_layer_count,
  1468. instance_layers);
  1469. if (validation_found) {
  1470. demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt1);
  1471. demo->enabled_layers[0] = "VK_LAYER_LUNARG_standard_validation";
  1472. validation_layer_count = 1;
  1473. } else {
  1474. // use alternative set of validation layers
  1475. instance_validation_layers =
  1476. (const char**) instance_validation_layers_alt2;
  1477. demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
  1478. validation_found = demo_check_layers(
  1479. ARRAY_SIZE(instance_validation_layers_alt2),
  1480. instance_validation_layers, instance_layer_count,
  1481. instance_layers);
  1482. validation_layer_count =
  1483. ARRAY_SIZE(instance_validation_layers_alt2);
  1484. for (i = 0; i < validation_layer_count; i++) {
  1485. demo->enabled_layers[i] = instance_validation_layers[i];
  1486. }
  1487. }
  1488. free(instance_layers);
  1489. }
  1490. if (!validation_found) {
  1491. ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find "
  1492. "required validation layer.\n\n"
  1493. "Please look at the Getting Started guide for additional "
  1494. "information.\n",
  1495. "vkCreateInstance Failure");
  1496. }
  1497. }
  1498. /* Look for instance extensions */
  1499. required_extensions = glfwGetRequiredInstanceExtensions(&required_extension_count);
  1500. if (!required_extensions) {
  1501. ERR_EXIT("glfwGetRequiredInstanceExtensions failed to find the "
  1502. "platform surface extensions.\n\nDo you have a compatible "
  1503. "Vulkan installable client driver (ICD) installed?\nPlease "
  1504. "look at the Getting Started guide for additional "
  1505. "information.\n",
  1506. "vkCreateInstance Failure");
  1507. }
  1508. for (i = 0; i < required_extension_count; i++) {
  1509. demo->extension_names[demo->enabled_extension_count++] = required_extensions[i];
  1510. assert(demo->enabled_extension_count < 64);
  1511. }
  1512. err = vkEnumerateInstanceExtensionProperties(
  1513. NULL, &instance_extension_count, NULL);
  1514. assert(!err);
  1515. if (instance_extension_count > 0) {
  1516. VkExtensionProperties *instance_extensions =
  1517. malloc(sizeof(VkExtensionProperties) * instance_extension_count);
  1518. err = vkEnumerateInstanceExtensionProperties(
  1519. NULL, &instance_extension_count, instance_extensions);
  1520. assert(!err);
  1521. for (i = 0; i < instance_extension_count; i++) {
  1522. if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
  1523. instance_extensions[i].extensionName)) {
  1524. if (demo->validate) {
  1525. demo->extension_names[demo->enabled_extension_count++] =
  1526. VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
  1527. }
  1528. }
  1529. assert(demo->enabled_extension_count < 64);
  1530. }
  1531. free(instance_extensions);
  1532. }
  1533. const VkApplicationInfo app = {
  1534. .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
  1535. .pNext = NULL,
  1536. .pApplicationName = APP_SHORT_NAME,
  1537. .applicationVersion = 0,
  1538. .pEngineName = APP_SHORT_NAME,
  1539. .engineVersion = 0,
  1540. .apiVersion = VK_API_VERSION_1_0,
  1541. };
  1542. VkInstanceCreateInfo inst_info = {
  1543. .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
  1544. .pNext = NULL,
  1545. .pApplicationInfo = &app,
  1546. .enabledLayerCount = demo->enabled_layer_count,
  1547. .ppEnabledLayerNames = (const char *const *)instance_validation_layers,
  1548. .enabledExtensionCount = demo->enabled_extension_count,
  1549. .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
  1550. };
  1551. uint32_t gpu_count;
  1552. err = vkCreateInstance(&inst_info, NULL, &demo->inst);
  1553. if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
  1554. ERR_EXIT("Cannot find a compatible Vulkan installable client driver "
  1555. "(ICD).\n\nPlease look at the Getting Started guide for "
  1556. "additional information.\n",
  1557. "vkCreateInstance Failure");
  1558. } else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) {
  1559. ERR_EXIT("Cannot find a specified extension library"
  1560. ".\nMake sure your layers path is set appropriately\n",
  1561. "vkCreateInstance Failure");
  1562. } else if (err) {
  1563. ERR_EXIT("vkCreateInstance failed.\n\nDo you have a compatible Vulkan "
  1564. "installable client driver (ICD) installed?\nPlease look at "
  1565. "the Getting Started guide for additional information.\n",
  1566. "vkCreateInstance Failure");
  1567. }
  1568. gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, demo->inst);
  1569. /* Make initial call to query gpu_count, then second call for gpu info*/
  1570. err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
  1571. assert(!err && gpu_count > 0);
  1572. if (gpu_count > 0) {
  1573. VkPhysicalDevice *physical_devices =
  1574. malloc(sizeof(VkPhysicalDevice) * gpu_count);
  1575. err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count,
  1576. physical_devices);
  1577. assert(!err);
  1578. /* For tri demo we just grab the first physical device */
  1579. demo->gpu = physical_devices[0];
  1580. free(physical_devices);
  1581. } else {
  1582. ERR_EXIT("vkEnumeratePhysicalDevices reported zero accessible devices."
  1583. "\n\nDo you have a compatible Vulkan installable client"
  1584. " driver (ICD) installed?\nPlease look at the Getting Started"
  1585. " guide for additional information.\n",
  1586. "vkEnumeratePhysicalDevices Failure");
  1587. }
  1588. gladLoadVulkanUserPtr(demo->gpu, glad_vulkan_callback, demo->inst);
  1589. /* Look for device extensions */
  1590. uint32_t device_extension_count = 0;
  1591. VkBool32 swapchainExtFound = 0;
  1592. demo->enabled_extension_count = 0;
  1593. err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL,
  1594. &device_extension_count, NULL);
  1595. assert(!err);
  1596. if (device_extension_count > 0) {
  1597. VkExtensionProperties *device_extensions =
  1598. malloc(sizeof(VkExtensionProperties) * device_extension_count);
  1599. err = vkEnumerateDeviceExtensionProperties(
  1600. demo->gpu, NULL, &device_extension_count, device_extensions);
  1601. assert(!err);
  1602. for (i = 0; i < device_extension_count; i++) {
  1603. if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
  1604. device_extensions[i].extensionName)) {
  1605. swapchainExtFound = 1;
  1606. demo->extension_names[demo->enabled_extension_count++] =
  1607. VK_KHR_SWAPCHAIN_EXTENSION_NAME;
  1608. }
  1609. assert(demo->enabled_extension_count < 64);
  1610. }
  1611. free(device_extensions);
  1612. }
  1613. if (!swapchainExtFound) {
  1614. ERR_EXIT("vkEnumerateDeviceExtensionProperties failed to find "
  1615. "the " VK_KHR_SWAPCHAIN_EXTENSION_NAME
  1616. " extension.\n\nDo you have a compatible "
  1617. "Vulkan installable client driver (ICD) installed?\nPlease "
  1618. "look at the Getting Started guide for additional "
  1619. "information.\n",
  1620. "vkCreateInstance Failure");
  1621. }
  1622. if (demo->validate) {
  1623. VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
  1624. dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
  1625. dbgCreateInfo.flags =
  1626. VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
  1627. dbgCreateInfo.pfnCallback = demo->use_break ? BreakCallback : dbgFunc;
  1628. dbgCreateInfo.pUserData = demo;
  1629. dbgCreateInfo.pNext = NULL;
  1630. err = vkCreateDebugReportCallbackEXT(demo->inst, &dbgCreateInfo, NULL,
  1631. &demo->msg_callback);
  1632. switch (err) {
  1633. case VK_SUCCESS:
  1634. break;
  1635. case VK_ERROR_OUT_OF_HOST_MEMORY:
  1636. ERR_EXIT("CreateDebugReportCallback: out of host memory\n",
  1637. "CreateDebugReportCallback Failure");
  1638. break;
  1639. default:
  1640. ERR_EXIT("CreateDebugReportCallback: unknown failure\n",
  1641. "CreateDebugReportCallback Failure");
  1642. break;
  1643. }
  1644. }
  1645. vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props);
  1646. // Query with NULL data to get count
  1647. vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_count,
  1648. NULL);
  1649. demo->queue_props = (VkQueueFamilyProperties *)malloc(
  1650. demo->queue_count * sizeof(VkQueueFamilyProperties));
  1651. vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_count,
  1652. demo->queue_props);
  1653. assert(demo->queue_count >= 1);
  1654. vkGetPhysicalDeviceFeatures(demo->gpu, &demo->gpu_features);
  1655. // Graphics queue and MemMgr queue can be separate.
  1656. // TODO: Add support for separate queues, including synchronization,
  1657. // and appropriate tracking for QueueSubmit
  1658. }
  1659. static void demo_init_device(struct demo *demo) {
  1660. VkResult U_ASSERT_ONLY err;
  1661. float queue_priorities[1] = {0.0};
  1662. const VkDeviceQueueCreateInfo queue = {
  1663. .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
  1664. .pNext = NULL,
  1665. .queueFamilyIndex = demo->graphics_queue_node_index,
  1666. .queueCount = 1,
  1667. .pQueuePriorities = queue_priorities};
  1668. VkPhysicalDeviceFeatures features;
  1669. memset(&features, 0, sizeof(features));
  1670. if (demo->gpu_features.shaderClipDistance) {
  1671. features.shaderClipDistance = VK_TRUE;
  1672. }
  1673. VkDeviceCreateInfo device = {
  1674. .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
  1675. .pNext = NULL,
  1676. .queueCreateInfoCount = 1,
  1677. .pQueueCreateInfos = &queue,
  1678. .enabledLayerCount = 0,
  1679. .ppEnabledLayerNames = NULL,
  1680. .enabledExtensionCount = demo->enabled_extension_count,
  1681. .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
  1682. .pEnabledFeatures = &features,
  1683. };
  1684. err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device);
  1685. assert(!err);
  1686. }
  1687. static void demo_init_vk_swapchain(struct demo *demo) {
  1688. VkResult U_ASSERT_ONLY err;
  1689. uint32_t i;
  1690. // Create a WSI surface for the window:
  1691. glfwCreateWindowSurface(demo->inst, demo->window, NULL, &demo->surface);
  1692. // Iterate over each queue to learn whether it supports presenting:
  1693. VkBool32 *supportsPresent =
  1694. (VkBool32 *)malloc(demo->queue_count * sizeof(VkBool32));
  1695. for (i = 0; i < demo->queue_count; i++) {
  1696. vkGetPhysicalDeviceSurfaceSupportKHR(demo->gpu, i, demo->surface,
  1697. &supportsPresent[i]);
  1698. }
  1699. // Search for a graphics and a present queue in the array of queue
  1700. // families, try to find one that supports both
  1701. uint32_t graphicsQueueNodeIndex = UINT32_MAX;
  1702. uint32_t presentQueueNodeIndex = UINT32_MAX;
  1703. for (i = 0; i < demo->queue_count; i++) {
  1704. if ((demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
  1705. if (graphicsQueueNodeIndex == UINT32_MAX) {
  1706. graphicsQueueNodeIndex = i;
  1707. }
  1708. if (supportsPresent[i] == VK_TRUE) {
  1709. graphicsQueueNodeIndex = i;
  1710. presentQueueNodeIndex = i;
  1711. break;
  1712. }
  1713. }
  1714. }
  1715. if (presentQueueNodeIndex == UINT32_MAX) {
  1716. // If didn't find a queue that supports both graphics and present, then
  1717. // find a separate present queue.
  1718. for (i = 0; i < demo->queue_count; ++i) {
  1719. if (supportsPresent[i] == VK_TRUE) {
  1720. presentQueueNodeIndex = i;
  1721. break;
  1722. }
  1723. }
  1724. }
  1725. free(supportsPresent);
  1726. // Generate error if could not find both a graphics and a present queue
  1727. if (graphicsQueueNodeIndex == UINT32_MAX ||
  1728. presentQueueNodeIndex == UINT32_MAX) {
  1729. ERR_EXIT("Could not find a graphics and a present queue\n",
  1730. "Swapchain Initialization Failure");
  1731. }
  1732. // TODO: Add support for separate queues, including presentation,
  1733. // synchronization, and appropriate tracking for QueueSubmit.
  1734. // NOTE: While it is possible for an application to use a separate graphics
  1735. // and a present queues, this demo program assumes it is only using
  1736. // one:
  1737. if (graphicsQueueNodeIndex != presentQueueNodeIndex) {
  1738. ERR_EXIT("Could not find a common graphics and a present queue\n",
  1739. "Swapchain Initialization Failure");
  1740. }
  1741. demo->graphics_queue_node_index = graphicsQueueNodeIndex;
  1742. demo_init_device(demo);
  1743. vkGetDeviceQueue(demo->device, demo->graphics_queue_node_index, 0,
  1744. &demo->queue);
  1745. // Get the list of VkFormat's that are supported:
  1746. uint32_t formatCount;
  1747. err = vkGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface,
  1748. &formatCount, NULL);
  1749. assert(!err);
  1750. VkSurfaceFormatKHR *surfFormats =
  1751. (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
  1752. err = vkGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface,
  1753. &formatCount, surfFormats);
  1754. assert(!err);
  1755. // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
  1756. // the surface has no preferred format. Otherwise, at least one
  1757. // supported format will be returned.
  1758. if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) {
  1759. demo->format = VK_FORMAT_B8G8R8A8_UNORM;
  1760. } else {
  1761. assert(formatCount >= 1);
  1762. demo->format = surfFormats[0].format;
  1763. }
  1764. demo->color_space = surfFormats[0].colorSpace;
  1765. demo->curFrame = 0;
  1766. // Get Memory information and properties
  1767. vkGetPhysicalDeviceMemoryProperties(demo->gpu, &demo->memory_properties);
  1768. }
  1769. static void demo_init_connection(struct demo *demo) {
  1770. glfwSetErrorCallback(demo_error_callback);
  1771. if (!glfwInit()) {
  1772. printf("Cannot initialize GLFW.\nExiting ...\n");
  1773. fflush(stdout);
  1774. exit(1);
  1775. }
  1776. if (!glfwVulkanSupported()) {
  1777. printf("GLFW failed to find the Vulkan loader.\nExiting ...\n");
  1778. fflush(stdout);
  1779. exit(1);
  1780. }
  1781. gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, NULL);
  1782. }
  1783. static void demo_init(struct demo *demo, const int argc, const char *argv[])
  1784. {
  1785. int i;
  1786. memset(demo, 0, sizeof(*demo));
  1787. demo->frameCount = INT32_MAX;
  1788. for (i = 1; i < argc; i++) {
  1789. if (strcmp(argv[i], "--use_staging") == 0) {
  1790. demo->use_staging_buffer = true;
  1791. continue;
  1792. }
  1793. if (strcmp(argv[i], "--break") == 0) {
  1794. demo->use_break = true;
  1795. continue;
  1796. }
  1797. if (strcmp(argv[i], "--validate") == 0) {
  1798. demo->validate = true;
  1799. continue;
  1800. }
  1801. if (strcmp(argv[i], "--c") == 0 && demo->frameCount == INT32_MAX &&
  1802. i < argc - 1 && sscanf(argv[i + 1], "%d", &demo->frameCount) == 1 &&
  1803. demo->frameCount >= 0) {
  1804. i++;
  1805. continue;
  1806. }
  1807. fprintf(stderr, "Usage:\n %s [--use_staging] [--validate] [--break] "
  1808. "[--c <framecount>]\n",
  1809. APP_SHORT_NAME);
  1810. fflush(stderr);
  1811. exit(1);
  1812. }
  1813. demo_init_connection(demo);
  1814. demo_init_vk(demo);
  1815. demo->width = 300;
  1816. demo->height = 300;
  1817. demo->depthStencil = 1.0;
  1818. demo->depthIncrement = -0.01f;
  1819. }
  1820. static void demo_cleanup(struct demo *demo) {
  1821. uint32_t i;
  1822. for (i = 0; i < demo->swapchainImageCount; i++) {
  1823. vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
  1824. }
  1825. free(demo->framebuffers);
  1826. vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
  1827. if (demo->setup_cmd) {
  1828. vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->setup_cmd);
  1829. }
  1830. vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->draw_cmd);
  1831. vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
  1832. vkDestroyPipeline(demo->device, demo->pipeline, NULL);
  1833. vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
  1834. vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
  1835. vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
  1836. vkDestroyBuffer(demo->device, demo->vertices.buf, NULL);
  1837. vkFreeMemory(demo->device, demo->vertices.mem, NULL);
  1838. for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
  1839. vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
  1840. vkDestroyImage(demo->device, demo->textures[i].image, NULL);
  1841. vkFreeMemory(demo->device, demo->textures[i].mem, NULL);
  1842. vkDestroySampler(demo->device, demo->textures[i].sampler, NULL);
  1843. }
  1844. for (i = 0; i < demo->swapchainImageCount; i++) {
  1845. vkDestroyImageView(demo->device, demo->buffers[i].view, NULL);
  1846. }
  1847. vkDestroyImageView(demo->device, demo->depth.view, NULL);
  1848. vkDestroyImage(demo->device, demo->depth.image, NULL);
  1849. vkFreeMemory(demo->device, demo->depth.mem, NULL);
  1850. vkDestroySwapchainKHR(demo->device, demo->swapchain, NULL);
  1851. free(demo->buffers);
  1852. vkDestroyDevice(demo->device, NULL);
  1853. if (demo->validate) {
  1854. vkDestroyDebugReportCallbackEXT(demo->inst, demo->msg_callback, NULL);
  1855. }
  1856. vkDestroySurfaceKHR(demo->inst, demo->surface, NULL);
  1857. vkDestroyInstance(demo->inst, NULL);
  1858. free(demo->queue_props);
  1859. glfwDestroyWindow(demo->window);
  1860. glfwTerminate();
  1861. }
  1862. static void demo_resize(struct demo *demo) {
  1863. uint32_t i;
  1864. // In order to properly resize the window, we must re-create the swapchain
  1865. // AND redo the command buffers, etc.
  1866. //
  1867. // First, perform part of the demo_cleanup() function:
  1868. for (i = 0; i < demo->swapchainImageCount; i++) {
  1869. vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
  1870. }
  1871. free(demo->framebuffers);
  1872. vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
  1873. if (demo->setup_cmd) {
  1874. vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->setup_cmd);
  1875. demo->setup_cmd = VK_NULL_HANDLE;
  1876. }
  1877. vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->draw_cmd);
  1878. vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
  1879. vkDestroyPipeline(demo->device, demo->pipeline, NULL);
  1880. vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
  1881. vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
  1882. vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
  1883. vkDestroyBuffer(demo->device, demo->vertices.buf, NULL);
  1884. vkFreeMemory(demo->device, demo->vertices.mem, NULL);
  1885. for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
  1886. vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
  1887. vkDestroyImage(demo->device, demo->textures[i].image, NULL);
  1888. vkFreeMemory(demo->device, demo->textures[i].mem, NULL);
  1889. vkDestroySampler(demo->device, demo->textures[i].sampler, NULL);
  1890. }
  1891. for (i = 0; i < demo->swapchainImageCount; i++) {
  1892. vkDestroyImageView(demo->device, demo->buffers[i].view, NULL);
  1893. }
  1894. vkDestroyImageView(demo->device, demo->depth.view, NULL);
  1895. vkDestroyImage(demo->device, demo->depth.image, NULL);
  1896. vkFreeMemory(demo->device, demo->depth.mem, NULL);
  1897. free(demo->buffers);
  1898. // Second, re-perform the demo_prepare() function, which will re-create the
  1899. // swapchain:
  1900. demo_prepare(demo);
  1901. }
  1902. int main(const int argc, const char *argv[]) {
  1903. struct demo demo;
  1904. demo_init(&demo, argc, argv);
  1905. demo_create_window(&demo);
  1906. demo_init_vk_swapchain(&demo);
  1907. demo_prepare(&demo);
  1908. demo_run(&demo);
  1909. demo_cleanup(&demo);
  1910. return validation_error;
  1911. }