vulkan.c 89 KB

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