SDL_render_vulkan.c 210 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "SDL_internal.h"
  19. #ifdef SDL_VIDEO_RENDER_VULKAN
  20. #define SDL_VULKAN_FRAME_QUEUE_DEPTH 2
  21. #define SDL_VULKAN_NUM_VERTEX_BUFFERS 256
  22. #define SDL_VULKAN_VERTEX_BUFFER_DEFAULT_SIZE 65536
  23. #define SDL_VULKAN_CONSTANT_BUFFER_DEFAULT_SIZE 65536
  24. #define SDL_VULKAN_NUM_UPLOAD_BUFFERS 32
  25. #define SDL_VULKAN_MAX_DESCRIPTOR_SETS 4096
  26. #define SDL_VULKAN_VALIDATION_LAYER_NAME "VK_LAYER_KHRONOS_validation"
  27. #define VK_NO_PROTOTYPES
  28. #include "../../video/SDL_vulkan_internal.h"
  29. #include "../../video/SDL_sysvideo.h"
  30. #include "../SDL_sysrender.h"
  31. #include "../SDL_d3dmath.h"
  32. #include "../../video/SDL_pixels_c.h"
  33. #include "SDL_shaders_vulkan.h"
  34. #define SET_ERROR_CODE(message, rc) \
  35. if (SDL_GetHintBoolean(SDL_HINT_RENDER_VULKAN_DEBUG, false)) { \
  36. SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s: %s", message, SDL_Vulkan_GetResultString(rc)); \
  37. SDL_TriggerBreakpoint(); \
  38. } \
  39. SDL_SetError("%s: %s", message, SDL_Vulkan_GetResultString(rc)) \
  40. #define SET_ERROR_MESSAGE(message) \
  41. if (SDL_GetHintBoolean(SDL_HINT_RENDER_VULKAN_DEBUG, false)) { \
  42. SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", message); \
  43. SDL_TriggerBreakpoint(); \
  44. } \
  45. SDL_SetError("%s", message) \
  46. #define VULKAN_FUNCTIONS() \
  47. VULKAN_DEVICE_FUNCTION(vkAcquireNextImageKHR) \
  48. VULKAN_DEVICE_FUNCTION(vkAllocateCommandBuffers) \
  49. VULKAN_DEVICE_FUNCTION(vkAllocateDescriptorSets) \
  50. VULKAN_DEVICE_FUNCTION(vkAllocateMemory) \
  51. VULKAN_DEVICE_FUNCTION(vkBeginCommandBuffer) \
  52. VULKAN_DEVICE_FUNCTION(vkBindBufferMemory) \
  53. VULKAN_DEVICE_FUNCTION(vkBindImageMemory) \
  54. VULKAN_DEVICE_FUNCTION(vkCmdBeginRenderPass) \
  55. VULKAN_DEVICE_FUNCTION(vkCmdBindDescriptorSets) \
  56. VULKAN_DEVICE_FUNCTION(vkCmdBindPipeline) \
  57. VULKAN_DEVICE_FUNCTION(vkCmdBindVertexBuffers) \
  58. VULKAN_DEVICE_FUNCTION(vkCmdClearColorImage) \
  59. VULKAN_DEVICE_FUNCTION(vkCmdCopyBufferToImage) \
  60. VULKAN_DEVICE_FUNCTION(vkCmdCopyImageToBuffer) \
  61. VULKAN_DEVICE_FUNCTION(vkCmdDraw) \
  62. VULKAN_DEVICE_FUNCTION(vkCmdEndRenderPass) \
  63. VULKAN_DEVICE_FUNCTION(vkCmdPipelineBarrier) \
  64. VULKAN_DEVICE_FUNCTION(vkCmdPushConstants) \
  65. VULKAN_DEVICE_FUNCTION(vkCmdSetScissor) \
  66. VULKAN_DEVICE_FUNCTION(vkCmdSetViewport) \
  67. VULKAN_DEVICE_FUNCTION(vkCreateBuffer) \
  68. VULKAN_DEVICE_FUNCTION(vkCreateCommandPool) \
  69. VULKAN_DEVICE_FUNCTION(vkCreateDescriptorPool) \
  70. VULKAN_DEVICE_FUNCTION(vkCreateDescriptorSetLayout) \
  71. VULKAN_DEVICE_FUNCTION(vkCreateFence) \
  72. VULKAN_DEVICE_FUNCTION(vkCreateFramebuffer) \
  73. VULKAN_DEVICE_FUNCTION(vkCreateGraphicsPipelines) \
  74. VULKAN_DEVICE_FUNCTION(vkCreateImage) \
  75. VULKAN_DEVICE_FUNCTION(vkCreateImageView) \
  76. VULKAN_DEVICE_FUNCTION(vkCreatePipelineLayout) \
  77. VULKAN_DEVICE_FUNCTION(vkCreateRenderPass) \
  78. VULKAN_DEVICE_FUNCTION(vkCreateSampler) \
  79. VULKAN_DEVICE_FUNCTION(vkCreateSemaphore) \
  80. VULKAN_DEVICE_FUNCTION(vkCreateShaderModule) \
  81. VULKAN_DEVICE_FUNCTION(vkCreateSwapchainKHR) \
  82. VULKAN_DEVICE_FUNCTION(vkDestroyBuffer) \
  83. VULKAN_DEVICE_FUNCTION(vkDestroyCommandPool) \
  84. VULKAN_DEVICE_FUNCTION(vkDestroyDevice) \
  85. VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorPool) \
  86. VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorSetLayout) \
  87. VULKAN_DEVICE_FUNCTION(vkDestroyFence) \
  88. VULKAN_DEVICE_FUNCTION(vkDestroyFramebuffer) \
  89. VULKAN_DEVICE_FUNCTION(vkDestroyImage) \
  90. VULKAN_DEVICE_FUNCTION(vkDestroyImageView) \
  91. VULKAN_DEVICE_FUNCTION(vkDestroyPipeline) \
  92. VULKAN_DEVICE_FUNCTION(vkDestroyPipelineLayout) \
  93. VULKAN_DEVICE_FUNCTION(vkDestroyRenderPass) \
  94. VULKAN_DEVICE_FUNCTION(vkDestroySampler) \
  95. VULKAN_DEVICE_FUNCTION(vkDestroySemaphore) \
  96. VULKAN_DEVICE_FUNCTION(vkDestroyShaderModule) \
  97. VULKAN_DEVICE_FUNCTION(vkDestroySwapchainKHR) \
  98. VULKAN_DEVICE_FUNCTION(vkDeviceWaitIdle) \
  99. VULKAN_DEVICE_FUNCTION(vkEndCommandBuffer) \
  100. VULKAN_DEVICE_FUNCTION(vkFreeCommandBuffers) \
  101. VULKAN_DEVICE_FUNCTION(vkFreeMemory) \
  102. VULKAN_DEVICE_FUNCTION(vkGetBufferMemoryRequirements) \
  103. VULKAN_DEVICE_FUNCTION(vkGetImageMemoryRequirements) \
  104. VULKAN_DEVICE_FUNCTION(vkGetDeviceQueue) \
  105. VULKAN_DEVICE_FUNCTION(vkGetFenceStatus) \
  106. VULKAN_DEVICE_FUNCTION(vkGetSwapchainImagesKHR) \
  107. VULKAN_DEVICE_FUNCTION(vkMapMemory) \
  108. VULKAN_DEVICE_FUNCTION(vkQueuePresentKHR) \
  109. VULKAN_DEVICE_FUNCTION(vkQueueSubmit) \
  110. VULKAN_DEVICE_FUNCTION(vkResetCommandBuffer) \
  111. VULKAN_DEVICE_FUNCTION(vkResetCommandPool) \
  112. VULKAN_DEVICE_FUNCTION(vkResetDescriptorPool) \
  113. VULKAN_DEVICE_FUNCTION(vkResetFences) \
  114. VULKAN_DEVICE_FUNCTION(vkUnmapMemory) \
  115. VULKAN_DEVICE_FUNCTION(vkUpdateDescriptorSets) \
  116. VULKAN_DEVICE_FUNCTION(vkWaitForFences) \
  117. VULKAN_GLOBAL_FUNCTION(vkCreateInstance) \
  118. VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties) \
  119. VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties) \
  120. VULKAN_INSTANCE_FUNCTION(vkCreateDevice) \
  121. VULKAN_INSTANCE_FUNCTION(vkDestroyInstance) \
  122. VULKAN_INSTANCE_FUNCTION(vkDestroySurfaceKHR) \
  123. VULKAN_INSTANCE_FUNCTION(vkEnumerateDeviceExtensionProperties) \
  124. VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices) \
  125. VULKAN_INSTANCE_FUNCTION(vkGetDeviceProcAddr) \
  126. VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures) \
  127. VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties) \
  128. VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties) \
  129. VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties) \
  130. VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties) \
  131. VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
  132. VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR) \
  133. VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR) \
  134. VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR) \
  135. VULKAN_INSTANCE_FUNCTION(vkQueueWaitIdle) \
  136. VULKAN_OPTIONAL_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2KHR) \
  137. VULKAN_OPTIONAL_INSTANCE_FUNCTION(vkGetPhysicalDeviceFormatProperties2KHR) \
  138. VULKAN_OPTIONAL_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties2KHR) \
  139. VULKAN_OPTIONAL_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2KHR) \
  140. VULKAN_OPTIONAL_DEVICE_FUNCTION(vkCreateSamplerYcbcrConversionKHR) \
  141. VULKAN_OPTIONAL_DEVICE_FUNCTION(vkDestroySamplerYcbcrConversionKHR) \
  142. #define VULKAN_DEVICE_FUNCTION(name) static PFN_##name name = NULL;
  143. #define VULKAN_GLOBAL_FUNCTION(name) static PFN_##name name = NULL;
  144. #define VULKAN_INSTANCE_FUNCTION(name) static PFN_##name name = NULL;
  145. #define VULKAN_OPTIONAL_INSTANCE_FUNCTION(name) static PFN_##name name = NULL;
  146. #define VULKAN_OPTIONAL_DEVICE_FUNCTION(name) static PFN_##name name = NULL;
  147. VULKAN_FUNCTIONS()
  148. #undef VULKAN_DEVICE_FUNCTION
  149. #undef VULKAN_GLOBAL_FUNCTION
  150. #undef VULKAN_INSTANCE_FUNCTION
  151. #undef VULKAN_OPTIONAL_INSTANCE_FUNCTION
  152. #undef VULKAN_OPTIONAL_DEVICE_FUNCTION
  153. // Renderpass types
  154. typedef enum {
  155. VULKAN_RENDERPASS_LOAD = 0,
  156. VULKAN_RENDERPASS_CLEAR = 1,
  157. VULKAN_RENDERPASS_COUNT
  158. } VULKAN_RenderPass;
  159. // Vertex shader, common values
  160. typedef struct
  161. {
  162. Float4X4 model;
  163. Float4X4 projectionAndView;
  164. } VULKAN_VertexShaderConstants;
  165. // These should mirror the definitions in VULKAN_PixelShader_Common.hlsli
  166. static const float TONEMAP_NONE = 0;
  167. //static const float TONEMAP_LINEAR = 1;
  168. static const float TONEMAP_CHROME = 2;
  169. //static const float TEXTURETYPE_NONE = 0;
  170. static const float TEXTURETYPE_RGB = 1;
  171. static const float TEXTURETYPE_RGB_PIXELART = 2;
  172. static const float TEXTURETYPE_PALETTE_NEAREST = 3;
  173. static const float TEXTURETYPE_PALETTE_LINEAR = 4;
  174. static const float TEXTURETYPE_PALETTE_PIXELART = 5;
  175. static const float INPUTTYPE_UNSPECIFIED = 0;
  176. static const float INPUTTYPE_SRGB = 1;
  177. static const float INPUTTYPE_SCRGB = 2;
  178. static const float INPUTTYPE_HDR10 = 3;
  179. // Pixel shader constants, common values
  180. typedef struct
  181. {
  182. float scRGB_output;
  183. float texture_type;
  184. float input_type;
  185. float color_scale;
  186. float texel_width;
  187. float texel_height;
  188. float texture_width;
  189. float texture_height;
  190. float tonemap_method;
  191. float tonemap_factor1;
  192. float tonemap_factor2;
  193. float sdr_white_point;
  194. } VULKAN_PixelShaderConstants;
  195. // Per-vertex data
  196. typedef struct
  197. {
  198. float pos[2];
  199. float tex[2];
  200. SDL_FColor color;
  201. } VULKAN_VertexPositionColor;
  202. // Vulkan Buffer
  203. typedef struct
  204. {
  205. VkDeviceMemory deviceMemory;
  206. VkBuffer buffer;
  207. VkDeviceSize size;
  208. void *mappedBufferPtr;
  209. } VULKAN_Buffer;
  210. // Vulkan image
  211. typedef struct
  212. {
  213. bool allocatedImage;
  214. VkImage image;
  215. VkImageView imageView;
  216. VkDeviceMemory deviceMemory;
  217. VkImageLayout imageLayout;
  218. VkFormat format;
  219. } VULKAN_Image;
  220. // Per-palette data
  221. typedef struct
  222. {
  223. VULKAN_Image image;
  224. } VULKAN_PaletteData;
  225. // Per-texture data
  226. typedef struct
  227. {
  228. VULKAN_Image mainImage;
  229. VkRenderPass mainRenderpasses[VULKAN_RENDERPASS_COUNT];
  230. VkFramebuffer mainFramebuffer;
  231. VULKAN_Buffer stagingBuffer;
  232. SDL_Rect lockedRect;
  233. int width;
  234. int height;
  235. // Object passed to VkImageView and VkSampler for doing Ycbcr -> RGB conversion
  236. VkSamplerYcbcrConversion samplerYcbcrConversion;
  237. // Sampler created with samplerYcbcrConversion, passed to PSO as immutable sampler
  238. VkSampler samplerYcbcr;
  239. // Descriptor set layout with samplerYcbcr baked as immutable sampler
  240. VkDescriptorSetLayout descriptorSetLayoutYcbcr;
  241. // Pipeline layout with immutable sampler descriptor set layout
  242. VkPipelineLayout pipelineLayoutYcbcr;
  243. } VULKAN_TextureData;
  244. // Pipeline State Object data
  245. typedef struct
  246. {
  247. VULKAN_Shader shader;
  248. VULKAN_PixelShaderConstants shader_constants;
  249. SDL_BlendMode blendMode;
  250. VkPrimitiveTopology topology;
  251. VkFormat format;
  252. VkPipelineLayout pipelineLayout;
  253. VkDescriptorSetLayout descriptorSetLayout;
  254. VkPipeline pipeline;
  255. } VULKAN_PipelineState;
  256. typedef struct
  257. {
  258. VkBuffer vertexBuffer;
  259. } VULKAN_DrawStateCache;
  260. // Private renderer data
  261. typedef struct
  262. {
  263. PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
  264. VkInstance instance;
  265. bool instance_external;
  266. VkSurfaceKHR surface;
  267. bool surface_external;
  268. VkPhysicalDevice physicalDevice;
  269. VkPhysicalDeviceProperties physicalDeviceProperties;
  270. VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
  271. VkPhysicalDeviceFeatures physicalDeviceFeatures;
  272. VkQueue graphicsQueue;
  273. VkQueue presentQueue;
  274. VkDevice device;
  275. bool device_external;
  276. uint32_t graphicsQueueFamilyIndex;
  277. uint32_t presentQueueFamilyIndex;
  278. VkSwapchainKHR swapchain;
  279. VkCommandPool commandPool;
  280. VkCommandBuffer *commandBuffers;
  281. uint32_t currentCommandBufferIndex;
  282. VkCommandBuffer currentCommandBuffer;
  283. VkFence *fences;
  284. VkSurfaceCapabilitiesKHR surfaceCapabilities;
  285. VkSurfaceFormatKHR *surfaceFormats;
  286. bool recreateSwapchain;
  287. int vsync;
  288. SDL_PropertiesID create_props;
  289. VkFramebuffer *framebuffers;
  290. VkRenderPass renderPasses[VULKAN_RENDERPASS_COUNT];
  291. VkRenderPass currentRenderPass;
  292. VkShaderModule vertexShaderModules[NUM_SHADERS];
  293. VkShaderModule fragmentShaderModules[NUM_SHADERS];
  294. VkDescriptorSetLayout descriptorSetLayout;
  295. VkPipelineLayout pipelineLayout;
  296. // Vertex buffer data
  297. VULKAN_Buffer vertexBuffers[SDL_VULKAN_NUM_VERTEX_BUFFERS];
  298. VULKAN_VertexShaderConstants vertexShaderConstantsData;
  299. // Data for staging/allocating textures
  300. VULKAN_Buffer **uploadBuffers;
  301. int *currentUploadBuffer;
  302. // Data for updating constants
  303. VULKAN_Buffer **constantBuffers;
  304. uint32_t *numConstantBuffers;
  305. uint32_t currentConstantBufferIndex;
  306. int32_t currentConstantBufferOffset;
  307. VkSampler samplers[RENDER_SAMPLER_COUNT];
  308. VkDescriptorPool **descriptorPools;
  309. uint32_t *numDescriptorPools;
  310. uint32_t currentDescriptorPoolIndex;
  311. uint32_t currentDescriptorSetIndex;
  312. int pipelineStateCount;
  313. VULKAN_PipelineState *pipelineStates;
  314. VULKAN_PipelineState *currentPipelineState;
  315. bool supportsEXTSwapchainColorspace;
  316. bool supportsKHRGetPhysicalDeviceProperties2;
  317. bool supportsKHRSamplerYCbCrConversion;
  318. uint32_t surfaceFormatsAllocatedCount;
  319. uint32_t surfaceFormatsCount;
  320. uint32_t swapchainDesiredImageCount;
  321. VkSurfaceFormatKHR surfaceFormat;
  322. VkExtent2D swapchainSize;
  323. VkSurfaceTransformFlagBitsKHR swapChainPreTransform;
  324. uint32_t swapchainImageCount;
  325. VkImage *swapchainImages;
  326. VkImageView *swapchainImageViews;
  327. VkImageLayout *swapchainImageLayouts;
  328. VkSemaphore *imageAvailableSemaphores;
  329. VkSemaphore *renderingFinishedSemaphores;
  330. VkSemaphore currentImageAvailableSemaphore;
  331. uint32_t currentSwapchainImageIndex;
  332. VkPipelineStageFlags *waitDestStageMasks;
  333. VkSemaphore *waitRenderSemaphores;
  334. uint32_t waitRenderSemaphoreCount;
  335. uint32_t waitRenderSemaphoreMax;
  336. VkSemaphore *signalRenderSemaphores;
  337. uint32_t signalRenderSemaphoreCount;
  338. uint32_t signalRenderSemaphoreMax;
  339. // Cached renderer properties
  340. VULKAN_TextureData *textureRenderTarget;
  341. bool cliprectDirty;
  342. bool currentCliprectEnabled;
  343. SDL_Rect currentCliprect;
  344. SDL_Rect currentViewport;
  345. int currentViewportRotation;
  346. bool viewportDirty;
  347. Float4X4 identity;
  348. VkComponentMapping identitySwizzle;
  349. int currentVertexBuffer;
  350. bool issueBatch;
  351. } VULKAN_RenderData;
  352. static bool VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, VkImage image, VkFormat format, int plane, int x, int y, int w, int h, const void *pixels, int pitch, VkImageLayout *imageLayout);
  353. // TODO: Sort this list based on what the Vulkan driver prefers?
  354. static const struct
  355. {
  356. SDL_PixelFormat sdl;
  357. VkFormat unorm;
  358. VkFormat srgb;
  359. } vk_format_map[] = {
  360. { SDL_PIXELFORMAT_BGRA32, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_SRGB }, // SDL_PIXELFORMAT_ARGB8888 on little endian systems
  361. { SDL_PIXELFORMAT_RGBA32, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SRGB },
  362. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  363. { SDL_PIXELFORMAT_ABGR8888, VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_FORMAT_A8B8G8R8_SRGB_PACK32 },
  364. #endif
  365. { SDL_PIXELFORMAT_ABGR2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
  366. { SDL_PIXELFORMAT_RGBA64_FLOAT, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R16G16B16A16_SFLOAT },
  367. { SDL_PIXELFORMAT_RGB565, VK_FORMAT_R5G6B5_UNORM_PACK16, VK_FORMAT_R5G6B5_UNORM_PACK16 },
  368. { SDL_PIXELFORMAT_BGR565, VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16 },
  369. { SDL_PIXELFORMAT_RGBA5551, VK_FORMAT_R5G5B5A1_UNORM_PACK16, VK_FORMAT_R5G5B5A1_UNORM_PACK16 },
  370. { SDL_PIXELFORMAT_BGRA5551, VK_FORMAT_B5G5R5A1_UNORM_PACK16, VK_FORMAT_B5G5R5A1_UNORM_PACK16 },
  371. { SDL_PIXELFORMAT_ARGB1555, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_A1R5G5B5_UNORM_PACK16 },
  372. { SDL_PIXELFORMAT_RGBA4444, VK_FORMAT_R4G4B4A4_UNORM_PACK16, VK_FORMAT_R4G4B4A4_UNORM_PACK16 },
  373. { SDL_PIXELFORMAT_BGRA4444, VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_B4G4R4A4_UNORM_PACK16 },
  374. { SDL_PIXELFORMAT_ARGB4444, VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT },
  375. { SDL_PIXELFORMAT_ABGR4444, VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT }
  376. };
  377. static SDL_PixelFormat VULKAN_VkFormatToSDLPixelFormat(VkFormat vkFormat)
  378. {
  379. for (int i = 0; i < SDL_arraysize(vk_format_map); i++) {
  380. if (vk_format_map[i].unorm == vkFormat ||
  381. vk_format_map[i].srgb == vkFormat) {
  382. return vk_format_map[i].sdl;
  383. }
  384. }
  385. return SDL_PIXELFORMAT_UNKNOWN;
  386. }
  387. static int VULKAN_VkFormatGetNumPlanes(VkFormat vkFormat)
  388. {
  389. switch (vkFormat) {
  390. case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
  391. return 3;
  392. case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
  393. case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
  394. return 2;
  395. default:
  396. return 1;
  397. }
  398. }
  399. static VkDeviceSize VULKAN_GetBytesPerPixel(VkFormat vkFormat, int plane)
  400. {
  401. switch (vkFormat) {
  402. case VK_FORMAT_R8_UNORM:
  403. return 1;
  404. case VK_FORMAT_R8G8_UNORM:
  405. return 2;
  406. case VK_FORMAT_R16G16_UNORM:
  407. return 4;
  408. case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
  409. return 1;
  410. case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
  411. return (plane == 0) ? 1 : 2;
  412. case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
  413. return (plane == 0) ? 2 : 4;
  414. default:
  415. return SDL_BYTESPERPIXEL(VULKAN_VkFormatToSDLPixelFormat(vkFormat));
  416. }
  417. }
  418. static VkFormat SDLPixelFormatToVkTextureFormat(SDL_PixelFormat format, Uint32 output_colorspace)
  419. {
  420. switch (format) {
  421. case SDL_PIXELFORMAT_INDEX8:
  422. return VK_FORMAT_R8_UNORM;
  423. case SDL_PIXELFORMAT_YUY2:
  424. return VK_FORMAT_G8B8G8R8_422_UNORM;
  425. case SDL_PIXELFORMAT_UYVY:
  426. return VK_FORMAT_B8G8R8G8_422_UNORM;
  427. case SDL_PIXELFORMAT_YV12:
  428. case SDL_PIXELFORMAT_IYUV:
  429. return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
  430. case SDL_PIXELFORMAT_NV12:
  431. case SDL_PIXELFORMAT_NV21:
  432. return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
  433. case SDL_PIXELFORMAT_P010:
  434. return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
  435. default:
  436. for (int i = 0; i < SDL_arraysize(vk_format_map); i++) {
  437. if (vk_format_map[i].sdl == format) {
  438. if (output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
  439. return vk_format_map[i].srgb;
  440. } else {
  441. return vk_format_map[i].unorm;
  442. }
  443. }
  444. }
  445. return VK_FORMAT_UNDEFINED;
  446. }
  447. }
  448. static void VULKAN_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
  449. static void VULKAN_DestroyBuffer(VULKAN_RenderData *rendererData, VULKAN_Buffer *vulkanBuffer);
  450. static void VULKAN_DestroyImage(VULKAN_RenderData *rendererData, VULKAN_Image *vulkanImage);
  451. static void VULKAN_ResetCommandList(VULKAN_RenderData *rendererData);
  452. static void VULKAN_EnsureCommandBuffer(VULKAN_RenderData *rendererData);
  453. static void VULKAN_RecordPipelineImageBarrier(VULKAN_RenderData *rendererData, VkAccessFlags sourceAccessMask, VkAccessFlags destAccessMask, VkPipelineStageFlags srcStageFlags, VkPipelineStageFlags dstStageFlags, VkImageLayout destLayout, VkImage image, VkImageLayout *imageLayout);
  454. static bool VULKAN_FindMemoryTypeIndex(VULKAN_RenderData *rendererData, uint32_t typeBits, VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags desiredFlags, uint32_t *memoryTypeIndexOut);
  455. static VkResult VULKAN_CreateWindowSizeDependentResources(SDL_Renderer *renderer);
  456. static VkDescriptorPool VULKAN_AllocateDescriptorPool(VULKAN_RenderData *rendererData);
  457. static VkResult VULKAN_CreateDescriptorSetAndPipelineLayout(VULKAN_RenderData *rendererData, VkSampler samplerYcbcr, VkDescriptorSetLayout *descriptorSetLayoutOut, VkPipelineLayout *pipelineLayoutOut);
  458. static VkSurfaceTransformFlagBitsKHR VULKAN_GetRotationForCurrentRenderTarget(VULKAN_RenderData *rendererData);
  459. static bool VULKAN_IsDisplayRotated90Degrees(VkSurfaceTransformFlagBitsKHR rotation);
  460. static void VULKAN_DestroyAll(SDL_Renderer *renderer)
  461. {
  462. VULKAN_RenderData *rendererData;
  463. if (renderer == NULL) {
  464. return;
  465. }
  466. rendererData = (VULKAN_RenderData *)renderer->internal;
  467. if (rendererData == NULL) {
  468. return;
  469. }
  470. // Release all textures
  471. for (SDL_Texture *texture = renderer->textures; texture; texture = texture->next) {
  472. VULKAN_DestroyTexture(renderer, texture);
  473. }
  474. if (rendererData->waitDestStageMasks) {
  475. SDL_free(rendererData->waitDestStageMasks);
  476. rendererData->waitDestStageMasks = NULL;
  477. }
  478. if (rendererData->waitRenderSemaphores) {
  479. SDL_free(rendererData->waitRenderSemaphores);
  480. rendererData->waitRenderSemaphores = NULL;
  481. }
  482. if (rendererData->signalRenderSemaphores) {
  483. SDL_free(rendererData->signalRenderSemaphores);
  484. rendererData->signalRenderSemaphores = NULL;
  485. }
  486. if (rendererData->surfaceFormats != NULL) {
  487. SDL_free(rendererData->surfaceFormats);
  488. rendererData->surfaceFormats = NULL;
  489. rendererData->surfaceFormatsAllocatedCount = 0;
  490. }
  491. if (rendererData->swapchainImages != NULL) {
  492. SDL_free(rendererData->swapchainImages);
  493. rendererData->swapchainImages = NULL;
  494. }
  495. if (rendererData->swapchain) {
  496. vkDestroySwapchainKHR(rendererData->device, rendererData->swapchain, NULL);
  497. rendererData->swapchain = VK_NULL_HANDLE;
  498. }
  499. if (rendererData->fences != NULL) {
  500. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  501. if (rendererData->fences[i] != VK_NULL_HANDLE) {
  502. vkDestroyFence(rendererData->device, rendererData->fences[i], NULL);
  503. rendererData->fences[i] = VK_NULL_HANDLE;
  504. }
  505. }
  506. SDL_free(rendererData->fences);
  507. rendererData->fences = NULL;
  508. }
  509. if (rendererData->swapchainImageViews) {
  510. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  511. if (rendererData->swapchainImageViews[i] != VK_NULL_HANDLE) {
  512. vkDestroyImageView(rendererData->device, rendererData->swapchainImageViews[i], NULL);
  513. }
  514. }
  515. SDL_free(rendererData->swapchainImageViews);
  516. rendererData->swapchainImageViews = NULL;
  517. }
  518. if (rendererData->swapchainImageLayouts) {
  519. SDL_free(rendererData->swapchainImageLayouts);
  520. rendererData->swapchainImageLayouts = NULL;
  521. }
  522. if (rendererData->framebuffers) {
  523. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  524. if (rendererData->framebuffers[i] != VK_NULL_HANDLE) {
  525. vkDestroyFramebuffer(rendererData->device, rendererData->framebuffers[i], NULL);
  526. }
  527. }
  528. SDL_free(rendererData->framebuffers);
  529. rendererData->framebuffers = NULL;
  530. }
  531. for (uint32_t i = 0; i < SDL_arraysize(rendererData->samplers); i++) {
  532. if (rendererData->samplers[i] != VK_NULL_HANDLE) {
  533. vkDestroySampler(rendererData->device, rendererData->samplers[i], NULL);
  534. rendererData->samplers[i] = VK_NULL_HANDLE;
  535. }
  536. }
  537. for (uint32_t i = 0; i < SDL_arraysize(rendererData->vertexBuffers); i++ ) {
  538. VULKAN_DestroyBuffer(rendererData, &rendererData->vertexBuffers[i]);
  539. }
  540. SDL_memset(rendererData->vertexBuffers, 0, sizeof(rendererData->vertexBuffers));
  541. for (uint32_t i = 0; i < VULKAN_RENDERPASS_COUNT; i++) {
  542. if (rendererData->renderPasses[i] != VK_NULL_HANDLE) {
  543. vkDestroyRenderPass(rendererData->device, rendererData->renderPasses[i], NULL);
  544. rendererData->renderPasses[i] = VK_NULL_HANDLE;
  545. }
  546. }
  547. if (rendererData->imageAvailableSemaphores) {
  548. for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
  549. if (rendererData->imageAvailableSemaphores[i] != VK_NULL_HANDLE) {
  550. vkDestroySemaphore(rendererData->device, rendererData->imageAvailableSemaphores[i], NULL);
  551. }
  552. }
  553. SDL_free(rendererData->imageAvailableSemaphores);
  554. rendererData->imageAvailableSemaphores = NULL;
  555. }
  556. if (rendererData->renderingFinishedSemaphores) {
  557. for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
  558. if (rendererData->renderingFinishedSemaphores[i] != VK_NULL_HANDLE) {
  559. vkDestroySemaphore(rendererData->device, rendererData->renderingFinishedSemaphores[i], NULL);
  560. }
  561. }
  562. SDL_free(rendererData->renderingFinishedSemaphores);
  563. rendererData->renderingFinishedSemaphores = NULL;
  564. }
  565. if (rendererData->commandBuffers) {
  566. vkFreeCommandBuffers(rendererData->device, rendererData->commandPool, rendererData->swapchainImageCount, rendererData->commandBuffers);
  567. SDL_free(rendererData->commandBuffers);
  568. rendererData->commandBuffers = NULL;
  569. rendererData->currentCommandBuffer = VK_NULL_HANDLE;
  570. rendererData->currentCommandBufferIndex = 0;
  571. }
  572. if (rendererData->commandPool) {
  573. vkDestroyCommandPool(rendererData->device, rendererData->commandPool, NULL);
  574. rendererData->commandPool = VK_NULL_HANDLE;
  575. }
  576. if (rendererData->descriptorPools) {
  577. SDL_assert(rendererData->numDescriptorPools);
  578. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  579. for (uint32_t j = 0; j < rendererData->numDescriptorPools[i]; j++) {
  580. if (rendererData->descriptorPools[i][j] != VK_NULL_HANDLE) {
  581. vkDestroyDescriptorPool(rendererData->device, rendererData->descriptorPools[i][j], NULL);
  582. }
  583. }
  584. SDL_free(rendererData->descriptorPools[i]);
  585. }
  586. SDL_free(rendererData->descriptorPools);
  587. rendererData->descriptorPools = NULL;
  588. SDL_free(rendererData->numDescriptorPools);
  589. rendererData->numDescriptorPools = NULL;
  590. }
  591. for (uint32_t i = 0; i < NUM_SHADERS; i++) {
  592. if (rendererData->vertexShaderModules[i] != VK_NULL_HANDLE) {
  593. vkDestroyShaderModule(rendererData->device, rendererData->vertexShaderModules[i], NULL);
  594. rendererData->vertexShaderModules[i] = VK_NULL_HANDLE;
  595. }
  596. if (rendererData->fragmentShaderModules[i] != VK_NULL_HANDLE) {
  597. vkDestroyShaderModule(rendererData->device, rendererData->fragmentShaderModules[i], NULL);
  598. rendererData->fragmentShaderModules[i] = VK_NULL_HANDLE;
  599. }
  600. }
  601. if (rendererData->descriptorSetLayout != VK_NULL_HANDLE) {
  602. vkDestroyDescriptorSetLayout(rendererData->device, rendererData->descriptorSetLayout, NULL);
  603. rendererData->descriptorSetLayout = VK_NULL_HANDLE;
  604. }
  605. if (rendererData->pipelineLayout != VK_NULL_HANDLE) {
  606. vkDestroyPipelineLayout(rendererData->device, rendererData->pipelineLayout, NULL);
  607. rendererData->pipelineLayout = VK_NULL_HANDLE;
  608. }
  609. for (int i = 0; i < rendererData->pipelineStateCount; i++) {
  610. vkDestroyPipeline(rendererData->device, rendererData->pipelineStates[i].pipeline, NULL);
  611. }
  612. SDL_free(rendererData->pipelineStates);
  613. rendererData->pipelineStates = NULL;
  614. rendererData->pipelineStateCount = 0;
  615. if (rendererData->currentUploadBuffer) {
  616. for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
  617. for (int j = 0; j < rendererData->currentUploadBuffer[i]; ++j) {
  618. VULKAN_DestroyBuffer(rendererData, &rendererData->uploadBuffers[i][j]);
  619. }
  620. SDL_free(rendererData->uploadBuffers[i]);
  621. }
  622. SDL_free(rendererData->uploadBuffers);
  623. rendererData->uploadBuffers = NULL;
  624. SDL_free(rendererData->currentUploadBuffer);
  625. rendererData->currentUploadBuffer = NULL;
  626. }
  627. if (rendererData->constantBuffers) {
  628. SDL_assert(rendererData->numConstantBuffers);
  629. for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
  630. for (uint32_t j = 0; j < rendererData->numConstantBuffers[i]; j++) {
  631. VULKAN_DestroyBuffer(rendererData, &rendererData->constantBuffers[i][j]);
  632. }
  633. SDL_free(rendererData->constantBuffers[i]);
  634. }
  635. SDL_free(rendererData->constantBuffers);
  636. rendererData->constantBuffers = NULL;
  637. SDL_free(rendererData->numConstantBuffers);
  638. rendererData->numConstantBuffers = NULL;
  639. }
  640. if (rendererData->device != VK_NULL_HANDLE && !rendererData->device_external) {
  641. vkDestroyDevice(rendererData->device, NULL);
  642. rendererData->device = VK_NULL_HANDLE;
  643. }
  644. if (rendererData->surface != VK_NULL_HANDLE && !rendererData->surface_external) {
  645. vkDestroySurfaceKHR(rendererData->instance, rendererData->surface, NULL);
  646. rendererData->surface = VK_NULL_HANDLE;
  647. }
  648. if (rendererData->instance != VK_NULL_HANDLE && !rendererData->instance_external) {
  649. vkDestroyInstance(rendererData->instance, NULL);
  650. rendererData->instance = VK_NULL_HANDLE;
  651. }
  652. }
  653. static void VULKAN_DestroyBuffer(VULKAN_RenderData *rendererData, VULKAN_Buffer *vulkanBuffer)
  654. {
  655. if (vulkanBuffer->buffer != VK_NULL_HANDLE) {
  656. vkDestroyBuffer(rendererData->device, vulkanBuffer->buffer, NULL);
  657. vulkanBuffer->buffer = VK_NULL_HANDLE;
  658. }
  659. if (vulkanBuffer->deviceMemory != VK_NULL_HANDLE) {
  660. vkFreeMemory(rendererData->device, vulkanBuffer->deviceMemory, NULL);
  661. vulkanBuffer->deviceMemory = VK_NULL_HANDLE;
  662. }
  663. SDL_memset(vulkanBuffer, 0, sizeof(VULKAN_Buffer));
  664. }
  665. static VkResult VULKAN_AllocateBuffer(VULKAN_RenderData *rendererData, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags requiredMemoryProps, VkMemoryPropertyFlags desiredMemoryProps, VULKAN_Buffer *bufferOut)
  666. {
  667. VkResult result;
  668. VkBufferCreateInfo bufferCreateInfo = { 0 };
  669. bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  670. bufferCreateInfo.size = size;
  671. bufferCreateInfo.usage = usage;
  672. result = vkCreateBuffer(rendererData->device, &bufferCreateInfo, NULL, &bufferOut->buffer);
  673. if (result != VK_SUCCESS) {
  674. SET_ERROR_CODE("vkCreateBuffer()", result);
  675. return result;
  676. }
  677. VkMemoryRequirements memoryRequirements = { 0 };
  678. vkGetBufferMemoryRequirements(rendererData->device, bufferOut->buffer, &memoryRequirements);
  679. if (result != VK_SUCCESS) {
  680. VULKAN_DestroyBuffer(rendererData, bufferOut);
  681. SET_ERROR_CODE("vkGetBufferMemoryRequirements()", result);
  682. return result;
  683. }
  684. uint32_t memoryTypeIndex = 0;
  685. if (!VULKAN_FindMemoryTypeIndex(rendererData, memoryRequirements.memoryTypeBits, requiredMemoryProps, desiredMemoryProps, &memoryTypeIndex)) {
  686. VULKAN_DestroyBuffer(rendererData, bufferOut);
  687. return VK_ERROR_UNKNOWN;
  688. }
  689. VkMemoryAllocateInfo memoryAllocateInfo = { 0 };
  690. memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  691. memoryAllocateInfo.allocationSize = memoryRequirements.size;
  692. memoryAllocateInfo.memoryTypeIndex = memoryTypeIndex;
  693. result = vkAllocateMemory(rendererData->device, &memoryAllocateInfo, NULL, &bufferOut->deviceMemory);
  694. if (result != VK_SUCCESS) {
  695. VULKAN_DestroyBuffer(rendererData, bufferOut);
  696. SET_ERROR_CODE("vkAllocateMemory()", result);
  697. return result;
  698. }
  699. result = vkBindBufferMemory(rendererData->device, bufferOut->buffer, bufferOut->deviceMemory, 0);
  700. if (result != VK_SUCCESS) {
  701. VULKAN_DestroyBuffer(rendererData, bufferOut);
  702. SET_ERROR_CODE("vkBindBufferMemory()", result);
  703. return result;
  704. }
  705. result = vkMapMemory(rendererData->device, bufferOut->deviceMemory, 0, size, 0, &bufferOut->mappedBufferPtr);
  706. if (result != VK_SUCCESS) {
  707. VULKAN_DestroyBuffer(rendererData, bufferOut);
  708. SET_ERROR_CODE("vkMapMemory()", result);
  709. return result;
  710. }
  711. bufferOut->size = size;
  712. return result;
  713. }
  714. static void VULKAN_DestroyImage(VULKAN_RenderData *rendererData, VULKAN_Image *vulkanImage)
  715. {
  716. if (vulkanImage->imageView != VK_NULL_HANDLE) {
  717. vkDestroyImageView(rendererData->device, vulkanImage->imageView, NULL);
  718. vulkanImage->imageView = VK_NULL_HANDLE;
  719. }
  720. if (vulkanImage->image != VK_NULL_HANDLE) {
  721. if (vulkanImage->allocatedImage) {
  722. vkDestroyImage(rendererData->device, vulkanImage->image, NULL);
  723. }
  724. vulkanImage->image = VK_NULL_HANDLE;
  725. }
  726. if (vulkanImage->deviceMemory != VK_NULL_HANDLE) {
  727. if (vulkanImage->allocatedImage) {
  728. vkFreeMemory(rendererData->device, vulkanImage->deviceMemory, NULL);
  729. }
  730. vulkanImage->deviceMemory = VK_NULL_HANDLE;
  731. }
  732. SDL_memset(vulkanImage, 0, sizeof(VULKAN_Image));
  733. }
  734. static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, SDL_PropertiesID create_props, uint32_t width, uint32_t height, VkFormat format, VkImageUsageFlags imageUsage, VkComponentMapping swizzle, VkSamplerYcbcrConversionKHR samplerYcbcrConversion, VULKAN_Image *imageOut)
  735. {
  736. VkResult result;
  737. VkSamplerYcbcrConversionInfoKHR samplerYcbcrConversionInfo = { 0 };
  738. SDL_memset(imageOut, 0, sizeof(VULKAN_Image));
  739. imageOut->format = format;
  740. imageOut->image = (VkImage)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER, 0);
  741. if (imageOut->image == VK_NULL_HANDLE) {
  742. imageOut->allocatedImage = VK_TRUE;
  743. VkImageCreateInfo imageCreateInfo = { 0 };
  744. imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  745. imageCreateInfo.flags = 0;
  746. imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
  747. imageCreateInfo.format = format;
  748. imageCreateInfo.extent.width = width;
  749. imageCreateInfo.extent.height = height;
  750. imageCreateInfo.extent.depth = 1;
  751. imageCreateInfo.mipLevels = 1;
  752. imageCreateInfo.arrayLayers = 1;
  753. imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
  754. imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
  755. imageCreateInfo.usage = imageUsage;
  756. imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  757. imageCreateInfo.queueFamilyIndexCount = 0;
  758. imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  759. result = vkCreateImage(rendererData->device, &imageCreateInfo, NULL, &imageOut->image);
  760. if (result != VK_SUCCESS) {
  761. VULKAN_DestroyImage(rendererData, imageOut);
  762. SET_ERROR_CODE("vkCreateImage()", result);
  763. return result;
  764. }
  765. VkMemoryRequirements memoryRequirements = { 0 };
  766. vkGetImageMemoryRequirements(rendererData->device, imageOut->image, &memoryRequirements);
  767. if (result != VK_SUCCESS) {
  768. VULKAN_DestroyImage(rendererData, imageOut);
  769. SET_ERROR_CODE("vkGetImageMemoryRequirements()", result);
  770. return result;
  771. }
  772. uint32_t memoryTypeIndex = 0;
  773. if (!VULKAN_FindMemoryTypeIndex(rendererData, memoryRequirements.memoryTypeBits, 0, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memoryTypeIndex)) {
  774. VULKAN_DestroyImage(rendererData, imageOut);
  775. return VK_ERROR_UNKNOWN;
  776. }
  777. VkMemoryAllocateInfo memoryAllocateInfo = { 0 };
  778. memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  779. memoryAllocateInfo.allocationSize = memoryRequirements.size;
  780. memoryAllocateInfo.memoryTypeIndex = memoryTypeIndex;
  781. result = vkAllocateMemory(rendererData->device, &memoryAllocateInfo, NULL, &imageOut->deviceMemory);
  782. if (result != VK_SUCCESS) {
  783. VULKAN_DestroyImage(rendererData, imageOut);
  784. SET_ERROR_CODE("vkAllocateMemory()", result);
  785. return result;
  786. }
  787. result = vkBindImageMemory(rendererData->device, imageOut->image, imageOut->deviceMemory, 0);
  788. if (result != VK_SUCCESS) {
  789. VULKAN_DestroyImage(rendererData, imageOut);
  790. SET_ERROR_CODE("vkBindImageMemory()", result);
  791. return result;
  792. }
  793. } else {
  794. imageOut->imageLayout = (VkImageLayout)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_VULKAN_LAYOUT_NUMBER, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
  795. }
  796. if (imageOut->imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
  797. VULKAN_EnsureCommandBuffer(rendererData);
  798. VULKAN_RecordPipelineImageBarrier(rendererData,
  799. VK_ACCESS_NONE,
  800. VK_ACCESS_SHADER_READ_BIT,
  801. VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  802. VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  803. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
  804. imageOut->image,
  805. &imageOut->imageLayout);
  806. }
  807. VkImageViewCreateInfo imageViewCreateInfo = { 0 };
  808. imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  809. imageViewCreateInfo.image = imageOut->image;
  810. imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  811. imageViewCreateInfo.format = format;
  812. imageViewCreateInfo.components = swizzle;
  813. imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  814. imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
  815. imageViewCreateInfo.subresourceRange.levelCount = 1;
  816. imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
  817. imageViewCreateInfo.subresourceRange.layerCount = 1;
  818. // If it's a YCbCr image, we need to pass the conversion info to the VkImageView (and the VkSampler)
  819. if (samplerYcbcrConversion != VK_NULL_HANDLE) {
  820. samplerYcbcrConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR;
  821. samplerYcbcrConversionInfo.conversion = samplerYcbcrConversion;
  822. imageViewCreateInfo.pNext = &samplerYcbcrConversionInfo;
  823. }
  824. result = vkCreateImageView(rendererData->device, &imageViewCreateInfo, NULL, &imageOut->imageView);
  825. if (result != VK_SUCCESS) {
  826. VULKAN_DestroyImage(rendererData, imageOut);
  827. SET_ERROR_CODE("vkCreateImageView()", result);
  828. return result;
  829. }
  830. return result;
  831. }
  832. static void VULKAN_RecordPipelineImageBarrier(VULKAN_RenderData *rendererData, VkAccessFlags sourceAccessMask, VkAccessFlags destAccessMask,
  833. VkPipelineStageFlags srcStageFlags, VkPipelineStageFlags dstStageFlags, VkImageLayout destLayout, VkImage image, VkImageLayout *imageLayout)
  834. {
  835. // Stop any outstanding renderpass if open
  836. if (rendererData->currentRenderPass != VK_NULL_HANDLE) {
  837. vkCmdEndRenderPass(rendererData->currentCommandBuffer);
  838. rendererData->currentRenderPass = VK_NULL_HANDLE;
  839. }
  840. VkImageMemoryBarrier barrier = { 0 };
  841. barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  842. barrier.srcAccessMask = sourceAccessMask;
  843. barrier.dstAccessMask = destAccessMask;
  844. barrier.oldLayout = *imageLayout;
  845. barrier.newLayout = destLayout;
  846. barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  847. barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  848. barrier.image = image;
  849. barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  850. barrier.subresourceRange.baseMipLevel = 0;
  851. barrier.subresourceRange.levelCount = 1;
  852. barrier.subresourceRange.baseArrayLayer = 0;
  853. barrier.subresourceRange.layerCount = 1;
  854. vkCmdPipelineBarrier(rendererData->currentCommandBuffer, srcStageFlags, dstStageFlags, 0, 0, NULL, 0, NULL, 1, &barrier);
  855. *imageLayout = destLayout;
  856. }
  857. static VkResult VULKAN_AcquireNextSwapchainImage(SDL_Renderer *renderer)
  858. {
  859. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  860. VkResult result;
  861. rendererData->currentImageAvailableSemaphore = VK_NULL_HANDLE;
  862. result = vkAcquireNextImageKHR(rendererData->device, rendererData->swapchain, UINT64_MAX,
  863. rendererData->imageAvailableSemaphores[rendererData->currentCommandBufferIndex], VK_NULL_HANDLE, &rendererData->currentSwapchainImageIndex);
  864. if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_ERROR_SURFACE_LOST_KHR) {
  865. if (!(renderer->window->flags & SDL_WINDOW_MINIMIZED)) {
  866. result = VULKAN_CreateWindowSizeDependentResources(renderer);
  867. }
  868. return result;
  869. } else if(result == VK_SUBOPTIMAL_KHR) {
  870. // Suboptimal, but we can continue
  871. } else if (result != VK_SUCCESS) {
  872. SET_ERROR_CODE("vkAcquireNextImageKHR()", result);
  873. return result;
  874. }
  875. rendererData->currentImageAvailableSemaphore = rendererData->imageAvailableSemaphores[rendererData->currentCommandBufferIndex];
  876. return result;
  877. }
  878. static void VULKAN_BeginRenderPass(VULKAN_RenderData *rendererData, VkAttachmentLoadOp loadOp, VkClearColorValue *clearColor)
  879. {
  880. int width = rendererData->swapchainSize.width;
  881. int height = rendererData->swapchainSize.height;
  882. if (rendererData->textureRenderTarget) {
  883. width = rendererData->textureRenderTarget->width;
  884. height = rendererData->textureRenderTarget->height;
  885. }
  886. switch (loadOp) {
  887. case VK_ATTACHMENT_LOAD_OP_CLEAR:
  888. rendererData->currentRenderPass = rendererData->textureRenderTarget ?
  889. rendererData->textureRenderTarget->mainRenderpasses[VULKAN_RENDERPASS_CLEAR] :
  890. rendererData->renderPasses[VULKAN_RENDERPASS_CLEAR];
  891. break;
  892. case VK_ATTACHMENT_LOAD_OP_LOAD:
  893. default:
  894. rendererData->currentRenderPass = rendererData->textureRenderTarget ?
  895. rendererData->textureRenderTarget->mainRenderpasses[VULKAN_RENDERPASS_LOAD] :
  896. rendererData->renderPasses[VULKAN_RENDERPASS_LOAD];
  897. break;
  898. }
  899. VkFramebuffer framebuffer = rendererData->textureRenderTarget ?
  900. rendererData->textureRenderTarget->mainFramebuffer :
  901. rendererData->framebuffers[rendererData->currentSwapchainImageIndex];
  902. VkRenderPassBeginInfo renderPassBeginInfo = { 0 };
  903. renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  904. renderPassBeginInfo.pNext = NULL;
  905. renderPassBeginInfo.renderPass = rendererData->currentRenderPass;
  906. renderPassBeginInfo.framebuffer = framebuffer;
  907. renderPassBeginInfo.renderArea.offset.x = 0;
  908. renderPassBeginInfo.renderArea.offset.y = 0;
  909. renderPassBeginInfo.renderArea.extent.width = width;
  910. renderPassBeginInfo.renderArea.extent.height = height;
  911. renderPassBeginInfo.clearValueCount = (clearColor == NULL) ? 0 : 1;
  912. VkClearValue clearValue;
  913. if (clearColor != NULL) {
  914. clearValue.color = *clearColor;
  915. renderPassBeginInfo.pClearValues = &clearValue;
  916. }
  917. vkCmdBeginRenderPass(rendererData->currentCommandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
  918. }
  919. static void VULKAN_EnsureCommandBuffer(VULKAN_RenderData *rendererData)
  920. {
  921. if (rendererData->currentCommandBuffer == VK_NULL_HANDLE) {
  922. rendererData->currentCommandBuffer = rendererData->commandBuffers[rendererData->currentCommandBufferIndex];
  923. VULKAN_ResetCommandList(rendererData);
  924. // Ensure the swapchain is in the correct layout
  925. if (rendererData->swapchainImageLayouts[rendererData->currentSwapchainImageIndex] == VK_IMAGE_LAYOUT_UNDEFINED) {
  926. VULKAN_RecordPipelineImageBarrier(rendererData,
  927. 0,
  928. VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  929. VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
  930. VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  931. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  932. rendererData->swapchainImages[rendererData->currentSwapchainImageIndex],
  933. &rendererData->swapchainImageLayouts[rendererData->currentSwapchainImageIndex]);
  934. }
  935. else if (rendererData->swapchainImageLayouts[rendererData->currentCommandBufferIndex] != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
  936. VULKAN_RecordPipelineImageBarrier(rendererData,
  937. VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
  938. VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  939. VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  940. VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  941. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  942. rendererData->swapchainImages[rendererData->currentSwapchainImageIndex],
  943. &rendererData->swapchainImageLayouts[rendererData->currentSwapchainImageIndex]);
  944. }
  945. }
  946. }
  947. static bool VULKAN_ActivateCommandBuffer(SDL_Renderer *renderer, VkAttachmentLoadOp loadOp, VkClearColorValue *clearColor, VULKAN_DrawStateCache *stateCache)
  948. {
  949. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  950. VULKAN_EnsureCommandBuffer(rendererData);
  951. if (rendererData->currentRenderPass == VK_NULL_HANDLE || loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
  952. if (rendererData->currentRenderPass != VK_NULL_HANDLE) {
  953. vkCmdEndRenderPass(rendererData->currentCommandBuffer);
  954. rendererData->currentRenderPass = VK_NULL_HANDLE;
  955. }
  956. VULKAN_BeginRenderPass(rendererData, loadOp, clearColor);
  957. }
  958. // Bind cached VB now
  959. if (stateCache->vertexBuffer != VK_NULL_HANDLE) {
  960. VkDeviceSize offset = 0;
  961. vkCmdBindVertexBuffers(rendererData->currentCommandBuffer, 0, 1, &stateCache->vertexBuffer, &offset);
  962. }
  963. return true;
  964. }
  965. static void VULKAN_WaitForGPU(VULKAN_RenderData *rendererData)
  966. {
  967. vkQueueWaitIdle(rendererData->graphicsQueue);
  968. }
  969. static void VULKAN_ResetCommandList(VULKAN_RenderData *rendererData)
  970. {
  971. vkResetCommandBuffer(rendererData->currentCommandBuffer, 0);
  972. for (uint32_t i = 0; i < rendererData->numDescriptorPools[rendererData->currentCommandBufferIndex]; i++) {
  973. vkResetDescriptorPool(rendererData->device, rendererData->descriptorPools[rendererData->currentCommandBufferIndex][i], 0);
  974. }
  975. VkCommandBufferBeginInfo beginInfo = { 0 };
  976. beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  977. beginInfo.flags = 0;
  978. vkBeginCommandBuffer(rendererData->currentCommandBuffer, &beginInfo);
  979. rendererData->currentPipelineState = NULL;
  980. rendererData->currentVertexBuffer = 0;
  981. rendererData->issueBatch = false;
  982. rendererData->cliprectDirty = true;
  983. rendererData->currentDescriptorSetIndex = 0;
  984. rendererData->currentDescriptorPoolIndex = 0;
  985. rendererData->currentConstantBufferOffset = -1;
  986. rendererData->currentConstantBufferIndex = 0;
  987. // Release any upload buffers that were inflight
  988. for (int i = 0; i < rendererData->currentUploadBuffer[rendererData->currentCommandBufferIndex]; ++i) {
  989. VULKAN_DestroyBuffer(rendererData, &rendererData->uploadBuffers[rendererData->currentCommandBufferIndex][i]);
  990. }
  991. rendererData->currentUploadBuffer[rendererData->currentCommandBufferIndex] = 0;
  992. }
  993. static VkResult VULKAN_IssueBatch(VULKAN_RenderData *rendererData)
  994. {
  995. VkResult result;
  996. if (rendererData->currentCommandBuffer == VK_NULL_HANDLE) {
  997. return VK_SUCCESS;
  998. }
  999. if (rendererData->currentRenderPass) {
  1000. vkCmdEndRenderPass(rendererData->currentCommandBuffer);
  1001. rendererData->currentRenderPass = VK_NULL_HANDLE;
  1002. }
  1003. rendererData->currentPipelineState = VK_NULL_HANDLE;
  1004. rendererData->viewportDirty = true;
  1005. vkEndCommandBuffer(rendererData->currentCommandBuffer);
  1006. VkSubmitInfo submitInfo = { 0 };
  1007. VkPipelineStageFlags waitDestStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
  1008. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  1009. submitInfo.commandBufferCount = 1;
  1010. submitInfo.pCommandBuffers = &rendererData->currentCommandBuffer;
  1011. if (rendererData->waitRenderSemaphoreCount > 0) {
  1012. Uint32 additionalSemaphoreCount = (rendererData->currentImageAvailableSemaphore != VK_NULL_HANDLE) ? 1 : 0;
  1013. submitInfo.waitSemaphoreCount = rendererData->waitRenderSemaphoreCount + additionalSemaphoreCount;
  1014. if (additionalSemaphoreCount > 0) {
  1015. rendererData->waitRenderSemaphores[rendererData->waitRenderSemaphoreCount] = rendererData->currentImageAvailableSemaphore;
  1016. rendererData->waitDestStageMasks[rendererData->waitRenderSemaphoreCount] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
  1017. }
  1018. submitInfo.pWaitSemaphores = rendererData->waitRenderSemaphores;
  1019. submitInfo.pWaitDstStageMask = rendererData->waitDestStageMasks;
  1020. rendererData->waitRenderSemaphoreCount = 0;
  1021. } else if (rendererData->currentImageAvailableSemaphore != VK_NULL_HANDLE) {
  1022. submitInfo.waitSemaphoreCount = 1;
  1023. submitInfo.pWaitSemaphores = &rendererData->currentImageAvailableSemaphore;
  1024. submitInfo.pWaitDstStageMask = &waitDestStageMask;
  1025. }
  1026. result = vkQueueSubmit(rendererData->graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
  1027. rendererData->currentImageAvailableSemaphore = VK_NULL_HANDLE;
  1028. VULKAN_WaitForGPU(rendererData);
  1029. VULKAN_ResetCommandList(rendererData);
  1030. return result;
  1031. }
  1032. static void VULKAN_DestroyRenderer(SDL_Renderer *renderer)
  1033. {
  1034. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  1035. if (rendererData) {
  1036. if (rendererData->device != VK_NULL_HANDLE) {
  1037. vkDeviceWaitIdle(rendererData->device);
  1038. VULKAN_DestroyAll(renderer);
  1039. }
  1040. SDL_free(rendererData);
  1041. }
  1042. }
  1043. static VkBlendFactor GetBlendFactor(SDL_BlendFactor factor)
  1044. {
  1045. switch (factor) {
  1046. case SDL_BLENDFACTOR_ZERO:
  1047. return VK_BLEND_FACTOR_ZERO;
  1048. case SDL_BLENDFACTOR_ONE:
  1049. return VK_BLEND_FACTOR_ONE;
  1050. case SDL_BLENDFACTOR_SRC_COLOR:
  1051. return VK_BLEND_FACTOR_SRC_COLOR;
  1052. case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
  1053. return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
  1054. case SDL_BLENDFACTOR_SRC_ALPHA:
  1055. return VK_BLEND_FACTOR_SRC_ALPHA;
  1056. case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
  1057. return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
  1058. case SDL_BLENDFACTOR_DST_COLOR:
  1059. return VK_BLEND_FACTOR_DST_COLOR;
  1060. case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
  1061. return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
  1062. case SDL_BLENDFACTOR_DST_ALPHA:
  1063. return VK_BLEND_FACTOR_DST_ALPHA;
  1064. case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
  1065. return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
  1066. default:
  1067. return VK_BLEND_FACTOR_MAX_ENUM;
  1068. }
  1069. }
  1070. static VkBlendOp GetBlendOp(SDL_BlendOperation operation)
  1071. {
  1072. switch (operation) {
  1073. case SDL_BLENDOPERATION_ADD:
  1074. return VK_BLEND_OP_ADD;
  1075. case SDL_BLENDOPERATION_SUBTRACT:
  1076. return VK_BLEND_OP_SUBTRACT;
  1077. case SDL_BLENDOPERATION_REV_SUBTRACT:
  1078. return VK_BLEND_OP_REVERSE_SUBTRACT;
  1079. case SDL_BLENDOPERATION_MINIMUM:
  1080. return VK_BLEND_OP_MIN;
  1081. case SDL_BLENDOPERATION_MAXIMUM:
  1082. return VK_BLEND_OP_MAX;
  1083. default:
  1084. return VK_BLEND_OP_MAX_ENUM;
  1085. }
  1086. }
  1087. static VULKAN_PipelineState *VULKAN_CreatePipelineState(SDL_Renderer *renderer,
  1088. VULKAN_Shader shader, VkPipelineLayout pipelineLayout, VkDescriptorSetLayout descriptorSetLayout, SDL_BlendMode blendMode, VkPrimitiveTopology topology, VkFormat format)
  1089. {
  1090. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  1091. VULKAN_PipelineState *pipelineStates;
  1092. VkPipeline pipeline = VK_NULL_HANDLE;
  1093. VkResult result = VK_SUCCESS;
  1094. VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo = { 0 };
  1095. VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = { 0 };
  1096. VkVertexInputAttributeDescription attributeDescriptions[3];
  1097. VkVertexInputBindingDescription bindingDescriptions[1];
  1098. VkPipelineShaderStageCreateInfo shaderStageCreateInfo[2];
  1099. VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = { 0 };
  1100. VkPipelineViewportStateCreateInfo viewportStateCreateInfo = { 0 };
  1101. VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = { 0 };
  1102. VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = { 0 };
  1103. VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = { 0 };
  1104. VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = { 0 };
  1105. VkGraphicsPipelineCreateInfo pipelineCreateInfo = { 0 };
  1106. pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  1107. pipelineCreateInfo.flags = 0;
  1108. pipelineCreateInfo.pStages = shaderStageCreateInfo;
  1109. pipelineCreateInfo.pVertexInputState = &vertexInputCreateInfo;
  1110. pipelineCreateInfo.pInputAssemblyState = &inputAssemblyStateCreateInfo;
  1111. pipelineCreateInfo.pViewportState = &viewportStateCreateInfo;
  1112. pipelineCreateInfo.pRasterizationState = &rasterizationStateCreateInfo;
  1113. pipelineCreateInfo.pMultisampleState = &multisampleStateCreateInfo;
  1114. pipelineCreateInfo.pDepthStencilState = &depthStencilStateCreateInfo;
  1115. pipelineCreateInfo.pColorBlendState = &colorBlendStateCreateInfo;
  1116. pipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
  1117. // Shaders
  1118. const char *name = "main";
  1119. for (uint32_t i = 0; i < 2; i++) {
  1120. SDL_memset(&shaderStageCreateInfo[i], 0, sizeof(shaderStageCreateInfo[i]));
  1121. shaderStageCreateInfo[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  1122. shaderStageCreateInfo[i].module = (i == 0) ? rendererData->vertexShaderModules[shader] : rendererData->fragmentShaderModules[shader];
  1123. shaderStageCreateInfo[i].stage = (i == 0) ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
  1124. shaderStageCreateInfo[i].pName = name;
  1125. }
  1126. pipelineCreateInfo.stageCount = 2;
  1127. pipelineCreateInfo.pStages = &shaderStageCreateInfo[0];
  1128. // Vertex input
  1129. vertexInputCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  1130. vertexInputCreateInfo.vertexAttributeDescriptionCount = 3;
  1131. vertexInputCreateInfo.pVertexAttributeDescriptions = &attributeDescriptions[0];
  1132. vertexInputCreateInfo.vertexBindingDescriptionCount = 1;
  1133. vertexInputCreateInfo.pVertexBindingDescriptions = &bindingDescriptions[0];
  1134. attributeDescriptions[ 0 ].binding = 0;
  1135. attributeDescriptions[ 0 ].format = VK_FORMAT_R32G32_SFLOAT;
  1136. attributeDescriptions[ 0 ].location = 0;
  1137. attributeDescriptions[ 0 ].offset = 0;
  1138. attributeDescriptions[ 1 ].binding = 0;
  1139. attributeDescriptions[ 1 ].format = VK_FORMAT_R32G32_SFLOAT;
  1140. attributeDescriptions[ 1 ].location = 1;
  1141. attributeDescriptions[ 1 ].offset = 8;
  1142. attributeDescriptions[ 2 ].binding = 0;
  1143. attributeDescriptions[ 2 ].format = VK_FORMAT_R32G32B32A32_SFLOAT;
  1144. attributeDescriptions[ 2 ].location = 2;
  1145. attributeDescriptions[ 2 ].offset = 16;
  1146. bindingDescriptions[ 0 ].binding = 0;
  1147. bindingDescriptions[ 0 ].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
  1148. bindingDescriptions[ 0 ].stride = 32;
  1149. // Input assembly
  1150. inputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  1151. inputAssemblyStateCreateInfo.topology = topology;
  1152. inputAssemblyStateCreateInfo.primitiveRestartEnable = VK_FALSE;
  1153. viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  1154. viewportStateCreateInfo.scissorCount = 1;
  1155. viewportStateCreateInfo.viewportCount = 1;
  1156. // Dynamic states
  1157. dynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
  1158. VkDynamicState dynamicStates[2] = {
  1159. VK_DYNAMIC_STATE_VIEWPORT,
  1160. VK_DYNAMIC_STATE_SCISSOR
  1161. };
  1162. dynamicStateCreateInfo.dynamicStateCount = SDL_arraysize(dynamicStates);
  1163. dynamicStateCreateInfo.pDynamicStates = dynamicStates;
  1164. // Rasterization state
  1165. rasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  1166. rasterizationStateCreateInfo.depthClampEnable = VK_FALSE;
  1167. rasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE;
  1168. rasterizationStateCreateInfo.cullMode = VK_CULL_MODE_NONE;
  1169. rasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL;
  1170. rasterizationStateCreateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
  1171. rasterizationStateCreateInfo.depthBiasEnable = VK_FALSE;
  1172. rasterizationStateCreateInfo.depthBiasConstantFactor = 0.0f;
  1173. rasterizationStateCreateInfo.depthBiasClamp = 0.0f;
  1174. rasterizationStateCreateInfo.depthBiasSlopeFactor = 0.0f;
  1175. rasterizationStateCreateInfo.lineWidth = 1.0f;
  1176. // MSAA state
  1177. multisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  1178. VkSampleMask multiSampleMask = 0xFFFFFFFF;
  1179. multisampleStateCreateInfo.pSampleMask = &multiSampleMask;
  1180. multisampleStateCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
  1181. // Depth Stencil
  1182. depthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
  1183. // Color blend
  1184. VkPipelineColorBlendAttachmentState colorBlendAttachment = { 0 };
  1185. colorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  1186. colorBlendStateCreateInfo.attachmentCount = 1;
  1187. colorBlendStateCreateInfo.pAttachments = &colorBlendAttachment;
  1188. colorBlendAttachment.blendEnable = VK_TRUE;
  1189. colorBlendAttachment.srcColorBlendFactor = GetBlendFactor(SDL_GetBlendModeSrcColorFactor(blendMode));
  1190. colorBlendAttachment.srcAlphaBlendFactor = GetBlendFactor(SDL_GetBlendModeSrcAlphaFactor(blendMode));
  1191. colorBlendAttachment.colorBlendOp = GetBlendOp(SDL_GetBlendModeColorOperation(blendMode));
  1192. colorBlendAttachment.dstColorBlendFactor = GetBlendFactor(SDL_GetBlendModeDstColorFactor(blendMode));
  1193. colorBlendAttachment.dstAlphaBlendFactor = GetBlendFactor(SDL_GetBlendModeDstAlphaFactor(blendMode));
  1194. colorBlendAttachment.alphaBlendOp = GetBlendOp(SDL_GetBlendModeAlphaOperation(blendMode));
  1195. colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
  1196. // Renderpass / layout
  1197. pipelineCreateInfo.renderPass = rendererData->currentRenderPass;
  1198. pipelineCreateInfo.subpass = 0;
  1199. pipelineCreateInfo.layout = pipelineLayout;
  1200. result = vkCreateGraphicsPipelines(rendererData->device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, NULL, &pipeline);
  1201. if (result != VK_SUCCESS) {
  1202. SET_ERROR_CODE("vkCreateGraphicsPipelines()", result);
  1203. return NULL;
  1204. }
  1205. pipelineStates = (VULKAN_PipelineState *)SDL_realloc(rendererData->pipelineStates, (rendererData->pipelineStateCount + 1) * sizeof(*pipelineStates));
  1206. if (!pipelineStates) {
  1207. return NULL;
  1208. }
  1209. pipelineStates[rendererData->pipelineStateCount].shader = shader;
  1210. pipelineStates[rendererData->pipelineStateCount].blendMode = blendMode;
  1211. pipelineStates[rendererData->pipelineStateCount].topology = topology;
  1212. pipelineStates[rendererData->pipelineStateCount].format = format;
  1213. pipelineStates[rendererData->pipelineStateCount].pipeline = pipeline;
  1214. pipelineStates[rendererData->pipelineStateCount].descriptorSetLayout = descriptorSetLayout;
  1215. pipelineStates[rendererData->pipelineStateCount].pipelineLayout = pipelineCreateInfo.layout;
  1216. rendererData->pipelineStates = pipelineStates;
  1217. ++rendererData->pipelineStateCount;
  1218. return &pipelineStates[rendererData->pipelineStateCount - 1];
  1219. }
  1220. static bool VULKAN_FindMemoryTypeIndex(VULKAN_RenderData *rendererData, uint32_t typeBits, VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags desiredFlags, uint32_t *memoryTypeIndexOut)
  1221. {
  1222. uint32_t memoryTypeIndex = 0;
  1223. bool foundExactMatch = false;
  1224. // Desired flags must be a superset of required flags.
  1225. desiredFlags |= requiredFlags;
  1226. for (memoryTypeIndex = 0; memoryTypeIndex < rendererData->physicalDeviceMemoryProperties.memoryTypeCount; memoryTypeIndex++) {
  1227. if (typeBits & (1 << memoryTypeIndex)) {
  1228. if (rendererData->physicalDeviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags == desiredFlags) {
  1229. foundExactMatch = true;
  1230. break;
  1231. }
  1232. }
  1233. }
  1234. if (!foundExactMatch) {
  1235. for (memoryTypeIndex = 0; memoryTypeIndex < rendererData->physicalDeviceMemoryProperties.memoryTypeCount; memoryTypeIndex++) {
  1236. if (typeBits & (1 << memoryTypeIndex)) {
  1237. if ((rendererData->physicalDeviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & requiredFlags) == requiredFlags) {
  1238. break;
  1239. }
  1240. }
  1241. }
  1242. }
  1243. if (memoryTypeIndex >= rendererData->physicalDeviceMemoryProperties.memoryTypeCount) {
  1244. SET_ERROR_MESSAGE("Unable to find memory type for allocation");
  1245. return false;
  1246. }
  1247. *memoryTypeIndexOut = memoryTypeIndex;
  1248. return true;
  1249. }
  1250. static VkResult VULKAN_CreateVertexBuffer(VULKAN_RenderData *rendererData, size_t vbidx, size_t size)
  1251. {
  1252. VkResult result;
  1253. VULKAN_DestroyBuffer(rendererData, &rendererData->vertexBuffers[vbidx]);
  1254. result = VULKAN_AllocateBuffer(rendererData, size,
  1255. VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
  1256. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
  1257. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
  1258. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
  1259. &rendererData->vertexBuffers[vbidx]);
  1260. if (result != VK_SUCCESS) {
  1261. return result;
  1262. }
  1263. return result;
  1264. }
  1265. static bool VULKAN_LoadGlobalFunctions(VULKAN_RenderData *rendererData)
  1266. {
  1267. #define VULKAN_DEVICE_FUNCTION(name)
  1268. #define VULKAN_GLOBAL_FUNCTION(name) \
  1269. name = (PFN_##name)rendererData->vkGetInstanceProcAddr(VK_NULL_HANDLE, #name); \
  1270. if (!name) { \
  1271. SET_ERROR_MESSAGE("vkGetInstanceProcAddr(VK_NULL_HANDLE, \"" #name "\") failed"); \
  1272. return false; \
  1273. }
  1274. #define VULKAN_INSTANCE_FUNCTION(name)
  1275. #define VULKAN_OPTIONAL_INSTANCE_FUNCTION(name)
  1276. #define VULKAN_OPTIONAL_DEVICE_FUNCTION(name)
  1277. VULKAN_FUNCTIONS()
  1278. #undef VULKAN_DEVICE_FUNCTION
  1279. #undef VULKAN_GLOBAL_FUNCTION
  1280. #undef VULKAN_INSTANCE_FUNCTION
  1281. #undef VULKAN_OPTIONAL_INSTANCE_FUNCTION
  1282. #undef VULKAN_OPTIONAL_DEVICE_FUNCTION
  1283. return true;
  1284. }
  1285. static bool VULKAN_LoadInstanceFunctions(VULKAN_RenderData *rendererData)
  1286. {
  1287. #define VULKAN_DEVICE_FUNCTION(name)
  1288. #define VULKAN_GLOBAL_FUNCTION(name)
  1289. #define VULKAN_INSTANCE_FUNCTION(name) \
  1290. name = (PFN_##name)rendererData->vkGetInstanceProcAddr(rendererData->instance, #name); \
  1291. if (!name) { \
  1292. SET_ERROR_MESSAGE("vkGetInstanceProcAddr(instance, \"" #name "\") failed"); \
  1293. return false; \
  1294. }
  1295. #define VULKAN_OPTIONAL_INSTANCE_FUNCTION(name) \
  1296. name = (PFN_##name)rendererData->vkGetInstanceProcAddr(rendererData->instance, #name);
  1297. #define VULKAN_OPTIONAL_DEVICE_FUNCTION(name)
  1298. VULKAN_FUNCTIONS()
  1299. #undef VULKAN_DEVICE_FUNCTION
  1300. #undef VULKAN_GLOBAL_FUNCTION
  1301. #undef VULKAN_INSTANCE_FUNCTION
  1302. #undef VULKAN_OPTIONAL_INSTANCE_FUNCTION
  1303. #undef VULKAN_OPTIONAL_DEVICE_FUNCTION
  1304. return true;
  1305. }
  1306. static bool VULKAN_LoadDeviceFunctions(VULKAN_RenderData *rendererData)
  1307. {
  1308. #define VULKAN_DEVICE_FUNCTION(name) \
  1309. name = (PFN_##name)vkGetDeviceProcAddr(rendererData->device, #name); \
  1310. if (!name) { \
  1311. SET_ERROR_MESSAGE("vkGetDeviceProcAddr(device, \"" #name "\") failed"); \
  1312. return false; \
  1313. }
  1314. #define VULKAN_GLOBAL_FUNCTION(name)
  1315. #define VULKAN_OPTIONAL_DEVICE_FUNCTION(name) \
  1316. name = (PFN_##name)vkGetDeviceProcAddr(rendererData->device, #name);
  1317. #define VULKAN_INSTANCE_FUNCTION(name)
  1318. #define VULKAN_OPTIONAL_INSTANCE_FUNCTION(name)
  1319. VULKAN_FUNCTIONS()
  1320. #undef VULKAN_DEVICE_FUNCTION
  1321. #undef VULKAN_GLOBAL_FUNCTION
  1322. #undef VULKAN_INSTANCE_FUNCTION
  1323. #undef VULKAN_OPTIONAL_INSTANCE_FUNCTION
  1324. #undef VULKAN_OPTIONAL_DEVICE_FUNCTION
  1325. return true;
  1326. }
  1327. static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
  1328. {
  1329. uint32_t physicalDeviceCount = 0;
  1330. VkPhysicalDevice *physicalDevices;
  1331. VkQueueFamilyProperties *queueFamiliesProperties = NULL;
  1332. uint32_t queueFamiliesPropertiesAllocatedSize = 0;
  1333. VkExtensionProperties *deviceExtensions = NULL;
  1334. uint32_t deviceExtensionsAllocatedSize = 0;
  1335. uint32_t physicalDeviceIndex;
  1336. VkResult result;
  1337. result = vkEnumeratePhysicalDevices(rendererData->instance, &physicalDeviceCount, NULL);
  1338. if (result != VK_SUCCESS) {
  1339. SET_ERROR_CODE("vkEnumeratePhysicalDevices()", result);
  1340. return result;
  1341. }
  1342. if (physicalDeviceCount == 0) {
  1343. SET_ERROR_MESSAGE("vkEnumeratePhysicalDevices(): no physical devices");
  1344. return VK_ERROR_UNKNOWN;
  1345. }
  1346. physicalDevices = (VkPhysicalDevice *)SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
  1347. result = vkEnumeratePhysicalDevices(rendererData->instance, &physicalDeviceCount, physicalDevices);
  1348. if (result != VK_SUCCESS) {
  1349. SDL_free(physicalDevices);
  1350. SET_ERROR_CODE("vkEnumeratePhysicalDevices()", result);
  1351. return result;
  1352. }
  1353. rendererData->physicalDevice = NULL;
  1354. for (physicalDeviceIndex = 0; physicalDeviceIndex < physicalDeviceCount; physicalDeviceIndex++) {
  1355. uint32_t queueFamiliesCount = 0;
  1356. uint32_t queueFamilyIndex;
  1357. uint32_t deviceExtensionCount = 0;
  1358. bool hasSwapchainExtension = false;
  1359. uint32_t i;
  1360. VkPhysicalDevice physicalDevice = physicalDevices[physicalDeviceIndex];
  1361. vkGetPhysicalDeviceProperties(physicalDevice, &rendererData->physicalDeviceProperties);
  1362. if (VK_VERSION_MAJOR(rendererData->physicalDeviceProperties.apiVersion) < 1) {
  1363. continue;
  1364. }
  1365. vkGetPhysicalDeviceMemoryProperties(physicalDevice, &rendererData->physicalDeviceMemoryProperties);
  1366. vkGetPhysicalDeviceFeatures(physicalDevice, &rendererData->physicalDeviceFeatures);
  1367. vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamiliesCount, NULL);
  1368. if (queueFamiliesCount == 0) {
  1369. continue;
  1370. }
  1371. if (queueFamiliesPropertiesAllocatedSize < queueFamiliesCount) {
  1372. SDL_free(queueFamiliesProperties);
  1373. queueFamiliesPropertiesAllocatedSize = queueFamiliesCount;
  1374. queueFamiliesProperties = (VkQueueFamilyProperties *)SDL_malloc(sizeof(VkQueueFamilyProperties) * queueFamiliesPropertiesAllocatedSize);
  1375. if (!queueFamiliesProperties) {
  1376. SDL_free(physicalDevices);
  1377. SDL_free(deviceExtensions);
  1378. return VK_ERROR_UNKNOWN;
  1379. }
  1380. }
  1381. vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamiliesCount, queueFamiliesProperties);
  1382. rendererData->graphicsQueueFamilyIndex = queueFamiliesCount;
  1383. rendererData->presentQueueFamilyIndex = queueFamiliesCount;
  1384. for (queueFamilyIndex = 0; queueFamilyIndex < queueFamiliesCount; queueFamilyIndex++) {
  1385. VkBool32 supported = 0;
  1386. if (queueFamiliesProperties[queueFamilyIndex].queueCount == 0) {
  1387. continue;
  1388. }
  1389. if (queueFamiliesProperties[queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
  1390. rendererData->graphicsQueueFamilyIndex = queueFamilyIndex;
  1391. }
  1392. result = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, rendererData->surface, &supported);
  1393. if (result != VK_SUCCESS) {
  1394. SDL_free(physicalDevices);
  1395. SDL_free(queueFamiliesProperties);
  1396. SDL_free(deviceExtensions);
  1397. SET_ERROR_CODE("vkGetPhysicalDeviceSurfaceSupportKHR()", result);
  1398. return VK_ERROR_UNKNOWN;
  1399. }
  1400. if (supported) {
  1401. rendererData->presentQueueFamilyIndex = queueFamilyIndex;
  1402. if (queueFamiliesProperties[queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
  1403. break; // use this queue because it can present and do graphics
  1404. }
  1405. }
  1406. }
  1407. if (rendererData->graphicsQueueFamilyIndex == queueFamiliesCount) { // no good queues found
  1408. continue;
  1409. }
  1410. if (rendererData->presentQueueFamilyIndex == queueFamiliesCount) { // no good queues found
  1411. continue;
  1412. }
  1413. result = vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &deviceExtensionCount, NULL);
  1414. if (result != VK_SUCCESS) {
  1415. SDL_free(physicalDevices);
  1416. SDL_free(queueFamiliesProperties);
  1417. SDL_free(deviceExtensions);
  1418. SET_ERROR_CODE("vkEnumerateDeviceExtensionProperties()", result);
  1419. return VK_ERROR_UNKNOWN;
  1420. }
  1421. if (deviceExtensionCount == 0) {
  1422. continue;
  1423. }
  1424. if (deviceExtensionsAllocatedSize < deviceExtensionCount) {
  1425. SDL_free(deviceExtensions);
  1426. deviceExtensionsAllocatedSize = deviceExtensionCount;
  1427. deviceExtensions = (VkExtensionProperties *)SDL_malloc(sizeof(VkExtensionProperties) * deviceExtensionsAllocatedSize);
  1428. if (!deviceExtensions) {
  1429. SDL_free(physicalDevices);
  1430. SDL_free(queueFamiliesProperties);
  1431. return VK_ERROR_UNKNOWN;
  1432. }
  1433. }
  1434. result = vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &deviceExtensionCount, deviceExtensions);
  1435. if (result != VK_SUCCESS) {
  1436. SDL_free(physicalDevices);
  1437. SDL_free(queueFamiliesProperties);
  1438. SDL_free(deviceExtensions);
  1439. SET_ERROR_CODE("vkEnumerateDeviceExtensionProperties()", result);
  1440. return result;
  1441. }
  1442. for (i = 0; i < deviceExtensionCount; i++) {
  1443. if (SDL_strcmp(deviceExtensions[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
  1444. hasSwapchainExtension = true;
  1445. break;
  1446. }
  1447. }
  1448. if (!hasSwapchainExtension) {
  1449. continue;
  1450. }
  1451. rendererData->physicalDevice = physicalDevice;
  1452. break;
  1453. }
  1454. SDL_free(physicalDevices);
  1455. SDL_free(queueFamiliesProperties);
  1456. SDL_free(deviceExtensions);
  1457. if (!rendererData->physicalDevice) {
  1458. SET_ERROR_MESSAGE("No viable physical devices found");
  1459. return VK_ERROR_UNKNOWN;
  1460. }
  1461. return VK_SUCCESS;
  1462. }
  1463. static VkResult VULKAN_GetSurfaceFormats(VULKAN_RenderData *rendererData)
  1464. {
  1465. VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(rendererData->physicalDevice,
  1466. rendererData->surface,
  1467. &rendererData->surfaceFormatsCount,
  1468. NULL);
  1469. if (result != VK_SUCCESS) {
  1470. rendererData->surfaceFormatsCount = 0;
  1471. SET_ERROR_CODE("vkGetPhysicalDeviceSurfaceFormatsKHR()", result);
  1472. return result;
  1473. }
  1474. if (rendererData->surfaceFormatsCount > rendererData->surfaceFormatsAllocatedCount) {
  1475. rendererData->surfaceFormatsAllocatedCount = rendererData->surfaceFormatsCount;
  1476. SDL_free(rendererData->surfaceFormats);
  1477. rendererData->surfaceFormats = (VkSurfaceFormatKHR *)SDL_malloc(sizeof(VkSurfaceFormatKHR) * rendererData->surfaceFormatsAllocatedCount);
  1478. }
  1479. result = vkGetPhysicalDeviceSurfaceFormatsKHR(rendererData->physicalDevice,
  1480. rendererData->surface,
  1481. &rendererData->surfaceFormatsCount,
  1482. rendererData->surfaceFormats);
  1483. if (result != VK_SUCCESS) {
  1484. rendererData->surfaceFormatsCount = 0;
  1485. SET_ERROR_CODE("vkGetPhysicalDeviceSurfaceFormatsKHR()", result);
  1486. return result;
  1487. }
  1488. return VK_SUCCESS;
  1489. }
  1490. static VkSemaphore VULKAN_CreateSemaphore(VULKAN_RenderData *rendererData)
  1491. {
  1492. VkResult result;
  1493. VkSemaphore semaphore = VK_NULL_HANDLE;
  1494. VkSemaphoreCreateInfo semaphoreCreateInfo = { 0 };
  1495. semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  1496. result = vkCreateSemaphore(rendererData->device, &semaphoreCreateInfo, NULL, &semaphore);
  1497. if (result != VK_SUCCESS) {
  1498. SET_ERROR_CODE("vkCreateSemaphore()", result);
  1499. return VK_NULL_HANDLE;
  1500. }
  1501. return semaphore;
  1502. }
  1503. static bool VULKAN_DeviceExtensionsFound(VULKAN_RenderData *rendererData, int extensionsToCheck, const char * const *extNames)
  1504. {
  1505. uint32_t extensionCount;
  1506. bool foundExtensions = true;
  1507. VkResult result = vkEnumerateDeviceExtensionProperties(rendererData->physicalDevice, NULL, &extensionCount, NULL);
  1508. if (result != VK_SUCCESS ) {
  1509. SET_ERROR_CODE("vkEnumerateDeviceExtensionProperties()", result);
  1510. return false;
  1511. }
  1512. if (extensionCount > 0 ) {
  1513. VkExtensionProperties *extensionProperties = (VkExtensionProperties *)SDL_calloc(extensionCount, sizeof(VkExtensionProperties));
  1514. result = vkEnumerateDeviceExtensionProperties(rendererData->physicalDevice, NULL, &extensionCount, extensionProperties);
  1515. if (result != VK_SUCCESS ) {
  1516. SET_ERROR_CODE("vkEnumerateDeviceExtensionProperties()", result);
  1517. SDL_free(extensionProperties);
  1518. return false;
  1519. }
  1520. for (int ext = 0; ext < extensionsToCheck && foundExtensions; ext++) {
  1521. bool foundExtension = false;
  1522. for (uint32_t i = 0; i < extensionCount; i++) {
  1523. if (SDL_strcmp(extensionProperties[i].extensionName, extNames[ext]) == 0) {
  1524. foundExtension = true;
  1525. break;
  1526. }
  1527. }
  1528. foundExtensions &= foundExtension;
  1529. }
  1530. SDL_free(extensionProperties);
  1531. }
  1532. return foundExtensions;
  1533. }
  1534. static bool VULKAN_InstanceExtensionFound(VULKAN_RenderData *rendererData, const char *extName)
  1535. {
  1536. uint32_t extensionCount;
  1537. VkResult result = vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL);
  1538. if (result != VK_SUCCESS ) {
  1539. SET_ERROR_CODE("vkEnumerateInstanceExtensionProperties()", result);
  1540. return false;
  1541. }
  1542. if (extensionCount > 0 ) {
  1543. VkExtensionProperties *extensionProperties = (VkExtensionProperties *)SDL_calloc(extensionCount, sizeof(VkExtensionProperties));
  1544. result = vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensionProperties);
  1545. if (result != VK_SUCCESS ) {
  1546. SET_ERROR_CODE("vkEnumerateInstanceExtensionProperties()", result);
  1547. SDL_free(extensionProperties);
  1548. return false;
  1549. }
  1550. for (uint32_t i = 0; i< extensionCount; i++) {
  1551. if (SDL_strcmp(extensionProperties[i].extensionName, extName) == 0) {
  1552. SDL_free(extensionProperties);
  1553. return true;
  1554. }
  1555. }
  1556. SDL_free(extensionProperties);
  1557. }
  1558. return false;
  1559. }
  1560. static bool VULKAN_ValidationLayersFound(void)
  1561. {
  1562. uint32_t instanceLayerCount = 0;
  1563. uint32_t i;
  1564. bool foundValidation = false;
  1565. vkEnumerateInstanceLayerProperties(&instanceLayerCount, NULL);
  1566. if (instanceLayerCount > 0) {
  1567. VkLayerProperties *instanceLayers = (VkLayerProperties *)SDL_calloc(instanceLayerCount, sizeof(VkLayerProperties));
  1568. vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayers);
  1569. for (i = 0; i < instanceLayerCount; i++) {
  1570. if (!SDL_strcmp(SDL_VULKAN_VALIDATION_LAYER_NAME, instanceLayers[i].layerName)) {
  1571. foundValidation = true;
  1572. break;
  1573. }
  1574. }
  1575. SDL_free(instanceLayers);
  1576. }
  1577. return foundValidation;
  1578. }
  1579. // Create resources that depend on the device.
  1580. static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_PropertiesID create_props)
  1581. {
  1582. static const char *const deviceExtensionNames[] = {
  1583. VK_KHR_SWAPCHAIN_EXTENSION_NAME,
  1584. /* VK_KHR_sampler_ycbcr_conversion + dependent extensions.
  1585. Note VULKAN_DeviceExtensionsFound() call below, if these get moved in this
  1586. array, update that check too.
  1587. */
  1588. VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
  1589. VK_KHR_MAINTENANCE1_EXTENSION_NAME,
  1590. VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
  1591. VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
  1592. };
  1593. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  1594. VkResult result = VK_SUCCESS;
  1595. PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
  1596. bool createDebug = SDL_GetHintBoolean(SDL_HINT_RENDER_VULKAN_DEBUG, false);
  1597. const char *validationLayerName[] = { SDL_VULKAN_VALIDATION_LAYER_NAME };
  1598. if (!SDL_Vulkan_LoadLibrary(NULL)) {
  1599. SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "SDL_Vulkan_LoadLibrary failed" );
  1600. return VK_ERROR_UNKNOWN;
  1601. }
  1602. vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr();
  1603. if(!vkGetInstanceProcAddr) {
  1604. SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "vkGetInstanceProcAddr is NULL" );
  1605. return VK_ERROR_UNKNOWN;
  1606. }
  1607. // Load global Vulkan functions
  1608. rendererData->vkGetInstanceProcAddr = vkGetInstanceProcAddr;
  1609. if (!VULKAN_LoadGlobalFunctions(rendererData)) {
  1610. return VK_ERROR_UNKNOWN;
  1611. }
  1612. // Check for colorspace extension
  1613. rendererData->supportsEXTSwapchainColorspace = VK_FALSE;
  1614. if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR ||
  1615. renderer->output_colorspace == SDL_COLORSPACE_HDR10) {
  1616. rendererData->supportsEXTSwapchainColorspace = VULKAN_InstanceExtensionFound(rendererData, VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
  1617. if (!rendererData->supportsEXTSwapchainColorspace) {
  1618. SDL_SetError("Using HDR output but %s not supported", VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
  1619. return VK_ERROR_UNKNOWN;
  1620. }
  1621. }
  1622. // Check for VK_KHR_get_physical_device_properties2
  1623. rendererData->supportsKHRGetPhysicalDeviceProperties2 = VULKAN_InstanceExtensionFound(rendererData, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
  1624. // Create VkInstance
  1625. rendererData->instance = (VkInstance)SDL_GetPointerProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER, NULL);
  1626. if (rendererData->instance) {
  1627. rendererData->instance_external = true;
  1628. } else {
  1629. VkInstanceCreateInfo instanceCreateInfo = { 0 };
  1630. VkApplicationInfo appInfo = { 0 };
  1631. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  1632. appInfo.apiVersion = VK_API_VERSION_1_0;
  1633. instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  1634. instanceCreateInfo.pApplicationInfo = &appInfo;
  1635. char const *const *instanceExtensions = SDL_Vulkan_GetInstanceExtensions(&instanceCreateInfo.enabledExtensionCount);
  1636. const char **instanceExtensionsCopy = (const char **)SDL_calloc(instanceCreateInfo.enabledExtensionCount + 2, sizeof(const char *));
  1637. for (uint32_t i = 0; i < instanceCreateInfo.enabledExtensionCount; i++) {
  1638. instanceExtensionsCopy[i] = instanceExtensions[i];
  1639. }
  1640. if (rendererData->supportsEXTSwapchainColorspace) {
  1641. instanceExtensionsCopy[instanceCreateInfo.enabledExtensionCount] = VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME;
  1642. instanceCreateInfo.enabledExtensionCount++;
  1643. }
  1644. if (rendererData->supportsKHRGetPhysicalDeviceProperties2) {
  1645. instanceExtensionsCopy[instanceCreateInfo.enabledExtensionCount] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
  1646. instanceCreateInfo.enabledExtensionCount++;
  1647. }
  1648. instanceCreateInfo.ppEnabledExtensionNames = (const char *const *)instanceExtensionsCopy;
  1649. if (createDebug && VULKAN_ValidationLayersFound()) {
  1650. instanceCreateInfo.ppEnabledLayerNames = validationLayerName;
  1651. instanceCreateInfo.enabledLayerCount = 1;
  1652. }
  1653. result = vkCreateInstance(&instanceCreateInfo, NULL, &rendererData->instance);
  1654. SDL_free((void *)instanceExtensionsCopy);
  1655. if (result != VK_SUCCESS) {
  1656. SET_ERROR_CODE("vkCreateInstance()", result);
  1657. return result;
  1658. }
  1659. }
  1660. // Load instance Vulkan functions
  1661. if (!VULKAN_LoadInstanceFunctions(rendererData)) {
  1662. VULKAN_DestroyAll(renderer);
  1663. return VK_ERROR_UNKNOWN;
  1664. }
  1665. // Create Vulkan surface
  1666. rendererData->surface = (VkSurfaceKHR)SDL_GetNumberProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER, 0);
  1667. if (rendererData->surface) {
  1668. rendererData->surface_external = true;
  1669. } else {
  1670. if (!SDL_Vulkan_CreateSurface(renderer->window, rendererData->instance, NULL, &rendererData->surface)) {
  1671. VULKAN_DestroyAll(renderer);
  1672. return VK_ERROR_UNKNOWN;
  1673. }
  1674. }
  1675. // Choose Vulkan physical device
  1676. rendererData->physicalDevice = (VkPhysicalDevice)SDL_GetPointerProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER, NULL);
  1677. if (rendererData->physicalDevice) {
  1678. vkGetPhysicalDeviceMemoryProperties(rendererData->physicalDevice, &rendererData->physicalDeviceMemoryProperties);
  1679. vkGetPhysicalDeviceFeatures(rendererData->physicalDevice, &rendererData->physicalDeviceFeatures);
  1680. } else {
  1681. if (VULKAN_FindPhysicalDevice(rendererData) != VK_SUCCESS) {
  1682. VULKAN_DestroyAll(renderer);
  1683. return VK_ERROR_UNKNOWN;
  1684. }
  1685. }
  1686. if (SDL_HasProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER)) {
  1687. rendererData->graphicsQueueFamilyIndex = (uint32_t)SDL_GetNumberProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER, 0);
  1688. }
  1689. if (SDL_HasProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER)) {
  1690. rendererData->presentQueueFamilyIndex = (uint32_t)SDL_GetNumberProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER, 0);
  1691. }
  1692. if (rendererData->supportsKHRGetPhysicalDeviceProperties2 &&
  1693. VULKAN_DeviceExtensionsFound(rendererData, 4, &deviceExtensionNames[1])) {
  1694. rendererData->supportsKHRSamplerYCbCrConversion = true;
  1695. }
  1696. // Create Vulkan device
  1697. rendererData->device = (VkDevice)SDL_GetPointerProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_DEVICE_POINTER, NULL);
  1698. if (rendererData->device) {
  1699. rendererData->device_external = true;
  1700. } else {
  1701. VkPhysicalDeviceSamplerYcbcrConversionFeatures deviceSamplerYcbcrConversionFeatures = { 0 };
  1702. VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = { { 0 }, { 0 } };
  1703. static const float queuePriority[] = { 1.0f };
  1704. VkDeviceCreateInfo deviceCreateInfo = { 0 };
  1705. deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  1706. deviceCreateInfo.queueCreateInfoCount = 0;
  1707. deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo;
  1708. deviceCreateInfo.pEnabledFeatures = NULL;
  1709. deviceCreateInfo.enabledExtensionCount = (rendererData->supportsKHRSamplerYCbCrConversion) ? 5 : 1;
  1710. deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames;
  1711. deviceQueueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  1712. deviceQueueCreateInfo[0].queueFamilyIndex = rendererData->graphicsQueueFamilyIndex;
  1713. deviceQueueCreateInfo[0].queueCount = 1;
  1714. deviceQueueCreateInfo[0].pQueuePriorities = queuePriority;
  1715. ++deviceCreateInfo.queueCreateInfoCount;
  1716. if (rendererData->presentQueueFamilyIndex != rendererData->graphicsQueueFamilyIndex) {
  1717. deviceQueueCreateInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  1718. deviceQueueCreateInfo[1].queueFamilyIndex = rendererData->presentQueueFamilyIndex;
  1719. deviceQueueCreateInfo[1].queueCount = 1;
  1720. deviceQueueCreateInfo[1].pQueuePriorities = queuePriority;
  1721. ++deviceCreateInfo.queueCreateInfoCount;
  1722. }
  1723. if (rendererData->supportsKHRSamplerYCbCrConversion) {
  1724. deviceSamplerYcbcrConversionFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
  1725. deviceSamplerYcbcrConversionFeatures.samplerYcbcrConversion = VK_TRUE;
  1726. deviceSamplerYcbcrConversionFeatures.pNext = (void *)deviceCreateInfo.pNext;
  1727. deviceCreateInfo.pNext = &deviceSamplerYcbcrConversionFeatures;
  1728. }
  1729. result = vkCreateDevice(rendererData->physicalDevice, &deviceCreateInfo, NULL, &rendererData->device);
  1730. if (result != VK_SUCCESS) {
  1731. SET_ERROR_CODE("vkCreateDevice()", result);
  1732. VULKAN_DestroyAll(renderer);
  1733. return result;
  1734. }
  1735. }
  1736. if (!VULKAN_LoadDeviceFunctions(rendererData)) {
  1737. VULKAN_DestroyAll(renderer);
  1738. return VK_ERROR_UNKNOWN;
  1739. }
  1740. // Get graphics/present queues
  1741. vkGetDeviceQueue(rendererData->device, rendererData->graphicsQueueFamilyIndex, 0, &rendererData->graphicsQueue);
  1742. if (rendererData->graphicsQueueFamilyIndex != rendererData->presentQueueFamilyIndex) {
  1743. vkGetDeviceQueue(rendererData->device, rendererData->presentQueueFamilyIndex, 0, &rendererData->presentQueue);
  1744. } else {
  1745. rendererData->presentQueue = rendererData->graphicsQueue;
  1746. }
  1747. // Create command pool/command buffers
  1748. VkCommandPoolCreateInfo commandPoolCreateInfo = { 0 };
  1749. commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  1750. commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
  1751. commandPoolCreateInfo.queueFamilyIndex = rendererData->graphicsQueueFamilyIndex;
  1752. result = vkCreateCommandPool(rendererData->device, &commandPoolCreateInfo, NULL, &rendererData->commandPool);
  1753. if (result != VK_SUCCESS) {
  1754. VULKAN_DestroyAll(renderer);
  1755. SET_ERROR_CODE("vkCreateCommandPool()", result);
  1756. return result;
  1757. }
  1758. if (VULKAN_GetSurfaceFormats(rendererData) != VK_SUCCESS) {
  1759. VULKAN_DestroyAll(renderer);
  1760. return result;
  1761. }
  1762. // Create shaders / layouts
  1763. for (uint32_t i = 0; i < NUM_SHADERS; i++) {
  1764. VULKAN_Shader shader = (VULKAN_Shader)i;
  1765. VkShaderModuleCreateInfo shaderModuleCreateInfo = { 0 };
  1766. shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  1767. VULKAN_GetVertexShader(shader, &shaderModuleCreateInfo.pCode, &shaderModuleCreateInfo.codeSize);
  1768. result = vkCreateShaderModule(rendererData->device, &shaderModuleCreateInfo, NULL, &rendererData->vertexShaderModules[i]);
  1769. if (result != VK_SUCCESS) {
  1770. VULKAN_DestroyAll(renderer);
  1771. SET_ERROR_CODE("vkCreateShaderModule()", result);
  1772. return result;
  1773. }
  1774. VULKAN_GetPixelShader(shader, &shaderModuleCreateInfo.pCode, &shaderModuleCreateInfo.codeSize);
  1775. result = vkCreateShaderModule(rendererData->device, &shaderModuleCreateInfo, NULL, &rendererData->fragmentShaderModules[i]);
  1776. if (result != VK_SUCCESS) {
  1777. VULKAN_DestroyAll(renderer);
  1778. SET_ERROR_CODE("vkCreateShaderModule()", result);
  1779. return result;
  1780. }
  1781. }
  1782. // Descriptor set layout / pipeline layout
  1783. result = VULKAN_CreateDescriptorSetAndPipelineLayout(rendererData, VK_NULL_HANDLE, &rendererData->descriptorSetLayout, &rendererData->pipelineLayout);
  1784. if (result != VK_SUCCESS) {
  1785. VULKAN_DestroyAll(renderer);
  1786. return result;
  1787. }
  1788. // Create default vertex buffers
  1789. for (uint32_t i = 0; i < SDL_VULKAN_NUM_VERTEX_BUFFERS; ++i) {
  1790. VULKAN_CreateVertexBuffer(rendererData, i, SDL_VULKAN_VERTEX_BUFFER_DEFAULT_SIZE);
  1791. }
  1792. SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
  1793. SDL_SetPointerProperty(props, SDL_PROP_RENDERER_VULKAN_INSTANCE_POINTER, rendererData->instance);
  1794. SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_SURFACE_NUMBER, (Sint64)rendererData->surface);
  1795. SDL_SetPointerProperty(props, SDL_PROP_RENDERER_VULKAN_PHYSICAL_DEVICE_POINTER, rendererData->physicalDevice);
  1796. SDL_SetPointerProperty(props, SDL_PROP_RENDERER_VULKAN_DEVICE_POINTER, rendererData->device);
  1797. SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER, rendererData->graphicsQueueFamilyIndex);
  1798. SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER, rendererData->presentQueueFamilyIndex);
  1799. return VK_SUCCESS;
  1800. }
  1801. static VkResult VULKAN_CreateFramebuffersAndRenderPasses(SDL_Renderer *renderer, int w, int h,
  1802. VkFormat format, int imageViewCount, VkImageView *imageViews, VkFramebuffer *framebuffers, VkRenderPass renderPasses[VULKAN_RENDERPASS_COUNT])
  1803. {
  1804. VULKAN_RenderData *rendererData = (VULKAN_RenderData *) renderer->internal;
  1805. VkResult result;
  1806. VkAttachmentDescription attachmentDescription = { 0 };
  1807. attachmentDescription.format = format;
  1808. attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  1809. attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  1810. attachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  1811. attachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  1812. attachmentDescription.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  1813. attachmentDescription.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  1814. attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
  1815. attachmentDescription.flags = 0;
  1816. VkAttachmentReference colorAttachmentReference = { 0 };
  1817. colorAttachmentReference.attachment = 0;
  1818. colorAttachmentReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  1819. VkSubpassDescription subpassDescription = { 0 };
  1820. subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  1821. subpassDescription.flags = 0;
  1822. subpassDescription.inputAttachmentCount = 0;
  1823. subpassDescription.pInputAttachments = NULL;
  1824. subpassDescription.colorAttachmentCount = 1;
  1825. subpassDescription.pColorAttachments = &colorAttachmentReference;
  1826. subpassDescription.pResolveAttachments = NULL;
  1827. subpassDescription.pDepthStencilAttachment = NULL;
  1828. subpassDescription.preserveAttachmentCount = 0;
  1829. subpassDescription.pPreserveAttachments = NULL;
  1830. VkSubpassDependency subPassDependency = { 0 };
  1831. subPassDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
  1832. subPassDependency.dstSubpass = 0;
  1833. subPassDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  1834. subPassDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  1835. subPassDependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  1836. subPassDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
  1837. subPassDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
  1838. VkRenderPassCreateInfo renderPassCreateInfo = { 0 };
  1839. renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  1840. renderPassCreateInfo.flags = 0;
  1841. renderPassCreateInfo.attachmentCount = 1;
  1842. renderPassCreateInfo.pAttachments = &attachmentDescription;
  1843. renderPassCreateInfo.subpassCount = 1;
  1844. renderPassCreateInfo.pSubpasses = &subpassDescription;
  1845. renderPassCreateInfo.dependencyCount = 1;
  1846. renderPassCreateInfo.pDependencies = &subPassDependency;
  1847. result = vkCreateRenderPass(rendererData->device, &renderPassCreateInfo, NULL, &renderPasses[VULKAN_RENDERPASS_LOAD]);
  1848. if (result != VK_SUCCESS) {
  1849. SET_ERROR_CODE("vkCreateRenderPass()", result);
  1850. return result;
  1851. }
  1852. attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  1853. result = vkCreateRenderPass(rendererData->device, &renderPassCreateInfo, NULL, &renderPasses[VULKAN_RENDERPASS_CLEAR]);
  1854. if (result != VK_SUCCESS) {
  1855. SET_ERROR_CODE("vkCreateRenderPass()", result);
  1856. return result;
  1857. }
  1858. VkFramebufferCreateInfo framebufferCreateInfo = { 0 };
  1859. framebufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  1860. framebufferCreateInfo.pNext = NULL;
  1861. framebufferCreateInfo.renderPass = rendererData->renderPasses[VULKAN_RENDERPASS_LOAD];
  1862. framebufferCreateInfo.attachmentCount = 1;
  1863. framebufferCreateInfo.width = w;
  1864. framebufferCreateInfo.height = h;
  1865. framebufferCreateInfo.layers = 1;
  1866. for (int i = 0; i < imageViewCount; i++) {
  1867. framebufferCreateInfo.pAttachments = &imageViews[i];
  1868. result = vkCreateFramebuffer(rendererData->device, &framebufferCreateInfo, NULL, &framebuffers[i]);
  1869. if (result != VK_SUCCESS) {
  1870. SET_ERROR_CODE("vkCreateFramebuffer()", result);
  1871. return result;
  1872. }
  1873. }
  1874. return result;
  1875. }
  1876. static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
  1877. {
  1878. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  1879. VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(rendererData->physicalDevice, rendererData->surface, &rendererData->surfaceCapabilities);
  1880. if (result != VK_SUCCESS) {
  1881. SET_ERROR_CODE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR()", result);
  1882. return result;
  1883. }
  1884. // clean up previous swapchain resources
  1885. if (rendererData->swapchainImageViews) {
  1886. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  1887. vkDestroyImageView(rendererData->device, rendererData->swapchainImageViews[i], NULL);
  1888. }
  1889. SDL_free(rendererData->swapchainImageViews);
  1890. rendererData->swapchainImageViews = NULL;
  1891. }
  1892. if (rendererData->fences) {
  1893. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  1894. if (rendererData->fences[i] != VK_NULL_HANDLE) {
  1895. vkDestroyFence(rendererData->device, rendererData->fences[i], NULL);
  1896. }
  1897. }
  1898. SDL_free(rendererData->fences);
  1899. rendererData->fences = NULL;
  1900. }
  1901. if (rendererData->commandBuffers) {
  1902. vkResetCommandPool(rendererData->device, rendererData->commandPool, 0);
  1903. SDL_free(rendererData->commandBuffers);
  1904. rendererData->commandBuffers = NULL;
  1905. rendererData->currentCommandBuffer = VK_NULL_HANDLE;
  1906. rendererData->currentCommandBufferIndex = 0;
  1907. }
  1908. if (rendererData->framebuffers) {
  1909. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  1910. if (rendererData->framebuffers[i] != VK_NULL_HANDLE) {
  1911. vkDestroyFramebuffer(rendererData->device, rendererData->framebuffers[i], NULL);
  1912. }
  1913. }
  1914. SDL_free(rendererData->framebuffers);
  1915. rendererData->framebuffers = NULL;
  1916. }
  1917. if (rendererData->descriptorPools) {
  1918. SDL_assert(rendererData->numDescriptorPools);
  1919. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  1920. for (uint32_t j = 0; j < rendererData->numDescriptorPools[i]; j++) {
  1921. if (rendererData->descriptorPools[i][j] != VK_NULL_HANDLE) {
  1922. vkDestroyDescriptorPool(rendererData->device, rendererData->descriptorPools[i][j], NULL);
  1923. }
  1924. }
  1925. SDL_free(rendererData->descriptorPools[i]);
  1926. }
  1927. SDL_free(rendererData->descriptorPools);
  1928. rendererData->descriptorPools = NULL;
  1929. SDL_free(rendererData->numDescriptorPools);
  1930. rendererData->numDescriptorPools = NULL;
  1931. }
  1932. if (rendererData->imageAvailableSemaphores) {
  1933. for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
  1934. if (rendererData->imageAvailableSemaphores[i] != VK_NULL_HANDLE) {
  1935. vkDestroySemaphore(rendererData->device, rendererData->imageAvailableSemaphores[i], NULL);
  1936. }
  1937. }
  1938. SDL_free(rendererData->imageAvailableSemaphores);
  1939. rendererData->imageAvailableSemaphores = NULL;
  1940. }
  1941. if (rendererData->renderingFinishedSemaphores) {
  1942. for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
  1943. if (rendererData->renderingFinishedSemaphores[i] != VK_NULL_HANDLE) {
  1944. vkDestroySemaphore(rendererData->device, rendererData->renderingFinishedSemaphores[i], NULL);
  1945. }
  1946. }
  1947. SDL_free(rendererData->renderingFinishedSemaphores);
  1948. rendererData->renderingFinishedSemaphores = NULL;
  1949. }
  1950. if (rendererData->uploadBuffers) {
  1951. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  1952. for (uint32_t j = 0; j < SDL_VULKAN_NUM_UPLOAD_BUFFERS; j++) {
  1953. VULKAN_DestroyBuffer(rendererData, &rendererData->uploadBuffers[i][j]);
  1954. }
  1955. SDL_free(rendererData->uploadBuffers[i]);
  1956. }
  1957. SDL_free(rendererData->uploadBuffers);
  1958. rendererData->uploadBuffers = NULL;
  1959. }
  1960. if (rendererData->constantBuffers) {
  1961. SDL_assert(rendererData->numConstantBuffers);
  1962. for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
  1963. for (uint32_t j = 0; j < rendererData->numConstantBuffers[i]; j++) {
  1964. VULKAN_DestroyBuffer(rendererData, &rendererData->constantBuffers[i][j]);
  1965. }
  1966. SDL_free(rendererData->constantBuffers[i]);
  1967. }
  1968. SDL_free(rendererData->constantBuffers);
  1969. rendererData->constantBuffers = NULL;
  1970. SDL_free(rendererData->numConstantBuffers);
  1971. rendererData->numConstantBuffers = NULL;
  1972. }
  1973. // pick an image count
  1974. rendererData->swapchainDesiredImageCount = rendererData->surfaceCapabilities.minImageCount + SDL_VULKAN_FRAME_QUEUE_DEPTH;
  1975. if ((rendererData->swapchainDesiredImageCount > rendererData->surfaceCapabilities.maxImageCount) &&
  1976. (rendererData->surfaceCapabilities.maxImageCount > 0)) {
  1977. rendererData->swapchainDesiredImageCount = rendererData->surfaceCapabilities.maxImageCount;
  1978. }
  1979. VkFormat desiredFormat = VK_FORMAT_B8G8R8A8_UNORM;
  1980. VkColorSpaceKHR desiredColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
  1981. if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
  1982. desiredFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
  1983. desiredColorSpace = VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT;
  1984. }
  1985. else if (renderer->output_colorspace == SDL_COLORSPACE_HDR10) {
  1986. desiredFormat = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
  1987. desiredColorSpace = VK_COLOR_SPACE_HDR10_ST2084_EXT;
  1988. }
  1989. if ((rendererData->surfaceFormatsCount == 1) &&
  1990. (rendererData->surfaceFormats[0].format == VK_FORMAT_UNDEFINED)) {
  1991. // aren't any preferred formats, so we pick
  1992. rendererData->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
  1993. rendererData->surfaceFormat.format = desiredFormat;
  1994. } else {
  1995. rendererData->surfaceFormat = rendererData->surfaceFormats[0];
  1996. rendererData->surfaceFormat.colorSpace = rendererData->surfaceFormats[0].colorSpace;
  1997. for (uint32_t i = 0; i < rendererData->surfaceFormatsCount; i++) {
  1998. if (rendererData->surfaceFormats[i].format == desiredFormat &&
  1999. rendererData->surfaceFormats[i].colorSpace == desiredColorSpace) {
  2000. rendererData->surfaceFormat.colorSpace = rendererData->surfaceFormats[i].colorSpace;
  2001. rendererData->surfaceFormat = rendererData->surfaceFormats[i];
  2002. break;
  2003. }
  2004. }
  2005. }
  2006. rendererData->swapchainSize.width = SDL_clamp((uint32_t)w,
  2007. rendererData->surfaceCapabilities.minImageExtent.width,
  2008. rendererData->surfaceCapabilities.maxImageExtent.width);
  2009. rendererData->swapchainSize.height = SDL_clamp((uint32_t)h,
  2010. rendererData->surfaceCapabilities.minImageExtent.height,
  2011. rendererData->surfaceCapabilities.maxImageExtent.height);
  2012. // Handle rotation
  2013. rendererData->swapChainPreTransform = rendererData->surfaceCapabilities.currentTransform;
  2014. if (rendererData->swapChainPreTransform == VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR ||
  2015. rendererData->swapChainPreTransform == VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
  2016. uint32_t tempWidth = rendererData->swapchainSize.width;
  2017. rendererData->swapchainSize.width = rendererData->swapchainSize.height;
  2018. rendererData->swapchainSize.height = tempWidth;
  2019. }
  2020. if (rendererData->swapchainSize.width == 0 && rendererData->swapchainSize.height == 0) {
  2021. // Don't recreate the swapchain if size is (0,0), just fail and continue attempting creation
  2022. return VK_ERROR_OUT_OF_DATE_KHR;
  2023. }
  2024. // Choose a present mode. If vsync is requested, then use VK_PRESENT_MODE_FIFO_KHR which is guaranteed to be supported
  2025. VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
  2026. if (rendererData->vsync <= 0) {
  2027. uint32_t presentModeCount = 0;
  2028. result = vkGetPhysicalDeviceSurfacePresentModesKHR(rendererData->physicalDevice, rendererData->surface, &presentModeCount, NULL);
  2029. if (result != VK_SUCCESS) {
  2030. SET_ERROR_CODE("vkGetPhysicalDeviceSurfacePresentModesKHR()", result);
  2031. return result;
  2032. }
  2033. if (presentModeCount > 0) {
  2034. VkPresentModeKHR *presentModes = (VkPresentModeKHR *)SDL_calloc(presentModeCount, sizeof(VkPresentModeKHR));
  2035. result = vkGetPhysicalDeviceSurfacePresentModesKHR(rendererData->physicalDevice, rendererData->surface, &presentModeCount, presentModes);
  2036. if (result != VK_SUCCESS) {
  2037. SET_ERROR_CODE("vkGetPhysicalDeviceSurfacePresentModesKHR()", result);
  2038. SDL_free(presentModes);
  2039. return result;
  2040. }
  2041. if (rendererData->vsync == 0) {
  2042. /* If vsync is not requested, in favor these options in order:
  2043. VK_PRESENT_MODE_IMMEDIATE_KHR - no v-sync with tearing
  2044. VK_PRESENT_MODE_MAILBOX_KHR - no v-sync without tearing
  2045. VK_PRESENT_MODE_FIFO_RELAXED_KHR - no v-sync, may tear */
  2046. for (uint32_t i = 0; i < presentModeCount; i++) {
  2047. if (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) {
  2048. presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
  2049. break;
  2050. }
  2051. else if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
  2052. presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
  2053. }
  2054. else if ((presentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
  2055. (presentModes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR)) {
  2056. presentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
  2057. }
  2058. }
  2059. } else if (rendererData->vsync == -1) {
  2060. for (uint32_t i = 0; i < presentModeCount; i++) {
  2061. if (presentModes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR) {
  2062. presentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
  2063. break;
  2064. }
  2065. }
  2066. }
  2067. SDL_free(presentModes);
  2068. }
  2069. }
  2070. VkSwapchainCreateInfoKHR swapchainCreateInfo = { 0 };
  2071. swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  2072. swapchainCreateInfo.surface = rendererData->surface;
  2073. swapchainCreateInfo.minImageCount = rendererData->swapchainDesiredImageCount;
  2074. swapchainCreateInfo.imageFormat = rendererData->surfaceFormat.format;
  2075. swapchainCreateInfo.imageColorSpace = rendererData->surfaceFormat.colorSpace;
  2076. swapchainCreateInfo.imageExtent = rendererData->swapchainSize;
  2077. swapchainCreateInfo.imageArrayLayers = 1;
  2078. swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  2079. swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  2080. swapchainCreateInfo.preTransform = rendererData->swapChainPreTransform;
  2081. swapchainCreateInfo.compositeAlpha = (renderer->window->flags & SDL_WINDOW_TRANSPARENT) ? (VkCompositeAlphaFlagBitsKHR)0 : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  2082. swapchainCreateInfo.presentMode = presentMode;
  2083. swapchainCreateInfo.clipped = VK_TRUE;
  2084. swapchainCreateInfo.oldSwapchain = rendererData->swapchain;
  2085. result = vkCreateSwapchainKHR(rendererData->device, &swapchainCreateInfo, NULL, &rendererData->swapchain);
  2086. if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
  2087. vkDestroySwapchainKHR(rendererData->device, swapchainCreateInfo.oldSwapchain, NULL);
  2088. }
  2089. if (result != VK_SUCCESS) {
  2090. rendererData->swapchain = VK_NULL_HANDLE;
  2091. SET_ERROR_CODE("vkCreateSwapchainKHR()", result);
  2092. return result;
  2093. }
  2094. SDL_free(rendererData->swapchainImages);
  2095. rendererData->swapchainImages = NULL;
  2096. result = vkGetSwapchainImagesKHR(rendererData->device, rendererData->swapchain, &rendererData->swapchainImageCount, NULL);
  2097. if (result != VK_SUCCESS) {
  2098. rendererData->swapchainImageCount = 0;
  2099. SET_ERROR_CODE("vkGetSwapchainImagesKHR()", result);
  2100. return result;
  2101. }
  2102. rendererData->swapchainImages = (VkImage *)SDL_malloc(sizeof(VkImage) * rendererData->swapchainImageCount);
  2103. result = vkGetSwapchainImagesKHR(rendererData->device,
  2104. rendererData->swapchain,
  2105. &rendererData->swapchainImageCount,
  2106. rendererData->swapchainImages);
  2107. if (result != VK_SUCCESS) {
  2108. SDL_free(rendererData->swapchainImages);
  2109. rendererData->swapchainImages = NULL;
  2110. rendererData->swapchainImageCount = 0;
  2111. SET_ERROR_CODE("vkGetSwapchainImagesKHR()", result);
  2112. return result;
  2113. }
  2114. // Create VkImageView's for swapchain images
  2115. {
  2116. VkImageViewCreateInfo imageViewCreateInfo = { 0 };
  2117. imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  2118. imageViewCreateInfo.flags = 0;
  2119. imageViewCreateInfo.format = rendererData->surfaceFormat.format;
  2120. imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  2121. imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  2122. imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  2123. imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  2124. imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  2125. imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
  2126. imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
  2127. imageViewCreateInfo.subresourceRange.layerCount = 1;
  2128. imageViewCreateInfo.subresourceRange.levelCount = 1;
  2129. imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  2130. rendererData->swapchainImageViews = (VkImageView *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkImageView));
  2131. SDL_free(rendererData->swapchainImageLayouts);
  2132. rendererData->swapchainImageLayouts = (VkImageLayout *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkImageLayout));
  2133. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  2134. imageViewCreateInfo.image = rendererData->swapchainImages[i];
  2135. result = vkCreateImageView(rendererData->device, &imageViewCreateInfo, NULL, &rendererData->swapchainImageViews[i]);
  2136. if (result != VK_SUCCESS) {
  2137. VULKAN_DestroyAll(renderer);
  2138. SET_ERROR_CODE("vkCreateImageView()", result);
  2139. return result;
  2140. }
  2141. rendererData->swapchainImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
  2142. }
  2143. }
  2144. VkCommandBufferAllocateInfo commandBufferAllocateInfo = { 0 };
  2145. commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  2146. commandBufferAllocateInfo.commandPool = rendererData->commandPool;
  2147. commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  2148. commandBufferAllocateInfo.commandBufferCount = rendererData->swapchainImageCount;
  2149. rendererData->commandBuffers = (VkCommandBuffer *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkCommandBuffer));
  2150. result = vkAllocateCommandBuffers(rendererData->device, &commandBufferAllocateInfo, rendererData->commandBuffers);
  2151. if (result != VK_SUCCESS) {
  2152. VULKAN_DestroyAll(renderer);
  2153. SET_ERROR_CODE("vkAllocateCommandBuffers()", result);
  2154. return result;
  2155. }
  2156. // Create fences
  2157. rendererData->fences = (VkFence *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkFence));
  2158. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  2159. VkFenceCreateInfo fenceCreateInfo = { 0 };
  2160. fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  2161. fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
  2162. result = vkCreateFence(rendererData->device, &fenceCreateInfo, NULL, &rendererData->fences[i]);
  2163. if (result != VK_SUCCESS) {
  2164. VULKAN_DestroyAll(renderer);
  2165. SET_ERROR_CODE("vkCreateFence()", result);
  2166. return result;
  2167. }
  2168. }
  2169. // Create renderpasses and framebuffer
  2170. for (uint32_t i = 0; i < SDL_arraysize(rendererData->renderPasses); i++) {
  2171. if (rendererData->renderPasses[i] != VK_NULL_HANDLE) {
  2172. vkDestroyRenderPass(rendererData->device, rendererData->renderPasses[i], NULL);
  2173. rendererData->renderPasses[i] = VK_NULL_HANDLE;
  2174. }
  2175. }
  2176. rendererData->framebuffers = (VkFramebuffer *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkFramebuffer));
  2177. result = VULKAN_CreateFramebuffersAndRenderPasses(renderer,
  2178. rendererData->swapchainSize.width,
  2179. rendererData->swapchainSize.height,
  2180. rendererData->surfaceFormat.format,
  2181. rendererData->swapchainImageCount,
  2182. rendererData->swapchainImageViews,
  2183. rendererData->framebuffers,
  2184. rendererData->renderPasses);
  2185. if (result != VK_SUCCESS) {
  2186. VULKAN_DestroyAll(renderer);
  2187. SET_ERROR_CODE("VULKAN_CreateFramebuffersAndRenderPasses()", result);
  2188. return result;
  2189. }
  2190. // Create descriptor pools - start by allocating one per swapchain image, let it grow if more are needed
  2191. rendererData->descriptorPools = (VkDescriptorPool **)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkDescriptorPool *));
  2192. rendererData->numDescriptorPools = (uint32_t *)SDL_calloc(rendererData->swapchainImageCount, sizeof(uint32_t));
  2193. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  2194. // Start by just allocating one pool, it will grow if needed
  2195. rendererData->numDescriptorPools[i] = 1;
  2196. rendererData->descriptorPools[i] = (VkDescriptorPool *)SDL_calloc(1, sizeof(VkDescriptorPool));
  2197. rendererData->descriptorPools[i][0] = VULKAN_AllocateDescriptorPool(rendererData);
  2198. if (result != VK_SUCCESS) {
  2199. VULKAN_DestroyAll(renderer);
  2200. return result;
  2201. }
  2202. }
  2203. // Create semaphores
  2204. rendererData->imageAvailableSemaphores = (VkSemaphore *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkSemaphore));
  2205. rendererData->renderingFinishedSemaphores = (VkSemaphore *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkSemaphore));
  2206. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  2207. rendererData->imageAvailableSemaphores[i] = VULKAN_CreateSemaphore(rendererData);
  2208. if (rendererData->imageAvailableSemaphores[i] == VK_NULL_HANDLE) {
  2209. VULKAN_DestroyAll(renderer);
  2210. return VK_ERROR_UNKNOWN;
  2211. }
  2212. rendererData->renderingFinishedSemaphores[i] = VULKAN_CreateSemaphore(rendererData);
  2213. if (rendererData->renderingFinishedSemaphores[i] == VK_NULL_HANDLE) {
  2214. VULKAN_DestroyAll(renderer);
  2215. return VK_ERROR_UNKNOWN;
  2216. }
  2217. }
  2218. // Upload buffers
  2219. rendererData->uploadBuffers = (VULKAN_Buffer **)SDL_calloc(rendererData->swapchainImageCount, sizeof(VULKAN_Buffer *));
  2220. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  2221. rendererData->uploadBuffers[i] = (VULKAN_Buffer *)SDL_calloc(SDL_VULKAN_NUM_UPLOAD_BUFFERS, sizeof(VULKAN_Buffer));
  2222. }
  2223. SDL_free(rendererData->currentUploadBuffer);
  2224. rendererData->currentUploadBuffer = (int *)SDL_calloc(rendererData->swapchainImageCount, sizeof(int));
  2225. // Constant buffers
  2226. rendererData->constantBuffers = (VULKAN_Buffer **)SDL_calloc(rendererData->swapchainImageCount, sizeof(VULKAN_Buffer *));
  2227. rendererData->numConstantBuffers = (uint32_t *)SDL_calloc(rendererData->swapchainImageCount, sizeof(uint32_t));
  2228. for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
  2229. // Start with just allocating one, will grow if needed
  2230. rendererData->numConstantBuffers[i] = 1;
  2231. rendererData->constantBuffers[i] = (VULKAN_Buffer *)SDL_calloc(1, sizeof(VULKAN_Buffer));
  2232. result = VULKAN_AllocateBuffer(rendererData,
  2233. SDL_VULKAN_CONSTANT_BUFFER_DEFAULT_SIZE,
  2234. VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
  2235. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  2236. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
  2237. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
  2238. &rendererData->constantBuffers[i][0]);
  2239. if (result != VK_SUCCESS) {
  2240. VULKAN_DestroyAll(renderer);
  2241. return result;
  2242. }
  2243. }
  2244. rendererData->currentConstantBufferOffset = -1;
  2245. rendererData->currentConstantBufferIndex = 0;
  2246. VULKAN_AcquireNextSwapchainImage(renderer);
  2247. SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
  2248. SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_SWAPCHAIN_IMAGE_COUNT_NUMBER, rendererData->swapchainImageCount);
  2249. return result;
  2250. }
  2251. // Initialize all resources that change when the window's size changes.
  2252. static VkResult VULKAN_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
  2253. {
  2254. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2255. VkResult result = VK_SUCCESS;
  2256. int w, h;
  2257. // Release resources in the current command list
  2258. VULKAN_IssueBatch(rendererData);
  2259. VULKAN_WaitForGPU(rendererData);
  2260. /* The width and height of the swap chain must be based on the display's
  2261. * non-rotated size.
  2262. */
  2263. SDL_GetWindowSizeInPixels(renderer->window, &w, &h);
  2264. result = VULKAN_CreateSwapChain(renderer, w, h);
  2265. if (result != VK_SUCCESS) {
  2266. rendererData->recreateSwapchain = true;
  2267. }
  2268. rendererData->viewportDirty = true;
  2269. return result;
  2270. }
  2271. static bool VULKAN_HandleDeviceLost(SDL_Renderer *renderer)
  2272. {
  2273. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2274. bool recovered = false;
  2275. VULKAN_DestroyAll(renderer);
  2276. if (VULKAN_CreateDeviceResources(renderer, rendererData->create_props) == VK_SUCCESS &&
  2277. VULKAN_CreateWindowSizeDependentResources(renderer) == VK_SUCCESS) {
  2278. recovered = true;
  2279. } else {
  2280. SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Renderer couldn't recover from device lost: %s", SDL_GetError());
  2281. VULKAN_DestroyAll(renderer);
  2282. }
  2283. // Let the application know that the device has been reset or lost
  2284. SDL_Event event;
  2285. SDL_zero(event);
  2286. event.type = recovered ? SDL_EVENT_RENDER_DEVICE_RESET : SDL_EVENT_RENDER_DEVICE_LOST;
  2287. event.render.windowID = SDL_GetWindowID(SDL_GetRenderWindow(renderer));
  2288. SDL_PushEvent(&event);
  2289. return recovered;
  2290. }
  2291. // This method is called when the window's size changes.
  2292. static VkResult VULKAN_UpdateForWindowSizeChange(SDL_Renderer *renderer)
  2293. {
  2294. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2295. // If the GPU has previous work, wait for it to be done first
  2296. VULKAN_WaitForGPU(rendererData);
  2297. return VULKAN_CreateWindowSizeDependentResources(renderer);
  2298. }
  2299. static void VULKAN_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
  2300. {
  2301. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2302. if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
  2303. rendererData->recreateSwapchain = true;
  2304. }
  2305. #ifdef SDL_PLATFORM_ANDROID
  2306. // Prevent black screen when app returns from background
  2307. if (event->type == SDL_EVENT_WINDOW_RESTORED) {
  2308. VULKAN_HandleDeviceLost(renderer);
  2309. }
  2310. #endif
  2311. }
  2312. static bool VULKAN_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
  2313. {
  2314. SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
  2315. SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
  2316. SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
  2317. SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
  2318. SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
  2319. SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
  2320. if (GetBlendFactor(srcColorFactor) == VK_BLEND_FACTOR_MAX_ENUM ||
  2321. GetBlendFactor(srcAlphaFactor) == VK_BLEND_FACTOR_MAX_ENUM ||
  2322. GetBlendOp(colorOperation) == VK_BLEND_OP_MAX_ENUM ||
  2323. GetBlendFactor(dstColorFactor) == VK_BLEND_FACTOR_MAX_ENUM ||
  2324. GetBlendFactor(dstAlphaFactor) == VK_BLEND_FACTOR_MAX_ENUM ||
  2325. GetBlendOp(alphaOperation) == VK_BLEND_OP_MAX_ENUM) {
  2326. return false;
  2327. }
  2328. return true;
  2329. }
  2330. static bool VULKAN_CreatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
  2331. {
  2332. VULKAN_RenderData *data = (VULKAN_RenderData *)renderer->internal;
  2333. VULKAN_PaletteData *palettedata = (VULKAN_PaletteData *)SDL_calloc(1, sizeof(*palettedata));
  2334. if (!palettedata) {
  2335. return false;
  2336. }
  2337. palette->internal = palettedata;
  2338. VkFormat format = SDLPixelFormatToVkTextureFormat(SDL_PIXELFORMAT_RGBA32, renderer->output_colorspace);
  2339. VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  2340. VkComponentMapping imageViewSwizzle = data->identitySwizzle;
  2341. VkResult result = VULKAN_AllocateImage(data, 0, 256, 1, format, usage, imageViewSwizzle, VK_NULL_HANDLE, &palettedata->image);
  2342. if (result != VK_SUCCESS) {
  2343. SET_ERROR_CODE("VULKAN_AllocateImage()", result);
  2344. return false;
  2345. }
  2346. return true;
  2347. }
  2348. static bool VULKAN_UpdatePalette(SDL_Renderer *renderer, SDL_TexturePalette *palette, int ncolors, SDL_Color *colors)
  2349. {
  2350. VULKAN_RenderData *data = (VULKAN_RenderData *)renderer->internal;
  2351. VULKAN_PaletteData *palettedata = (VULKAN_PaletteData *)palette->internal;
  2352. return VULKAN_UpdateTextureInternal(data, palettedata->image.image, palettedata->image.format, 0, 0, 0, ncolors, 1, colors, ncolors * sizeof(*colors), &palettedata->image.imageLayout);
  2353. }
  2354. static void VULKAN_DestroyPalette(SDL_Renderer *renderer, SDL_TexturePalette *palette)
  2355. {
  2356. VULKAN_RenderData *data = (VULKAN_RenderData *)renderer->internal;
  2357. VULKAN_PaletteData *palettedata = (VULKAN_PaletteData *)palette->internal;
  2358. if (palettedata) {
  2359. VULKAN_DestroyImage(data, &palettedata->image);
  2360. SDL_free(palettedata);
  2361. }
  2362. }
  2363. static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
  2364. {
  2365. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2366. VULKAN_TextureData *textureData;
  2367. VkResult result;
  2368. VkFormat textureFormat = SDLPixelFormatToVkTextureFormat(texture->format, renderer->output_colorspace);
  2369. uint32_t width = texture->w;
  2370. uint32_t height = texture->h;
  2371. VkComponentMapping imageViewSwizzle = rendererData->identitySwizzle;
  2372. if (!rendererData->device) {
  2373. return SDL_SetError("Device lost and couldn't be recovered");
  2374. }
  2375. if (textureFormat == VK_FORMAT_UNDEFINED) {
  2376. return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified", __FUNCTION__, texture->format);
  2377. }
  2378. textureData = (VULKAN_TextureData *)SDL_calloc(1, sizeof(*textureData));
  2379. if (!textureData) {
  2380. return false;
  2381. }
  2382. texture->internal = textureData;
  2383. #ifdef SDL_HAVE_YUV
  2384. // YUV textures must have even width and height. Also create Ycbcr conversion
  2385. if (texture->format == SDL_PIXELFORMAT_YV12 ||
  2386. texture->format == SDL_PIXELFORMAT_IYUV ||
  2387. texture->format == SDL_PIXELFORMAT_NV12 ||
  2388. texture->format == SDL_PIXELFORMAT_NV21 ||
  2389. texture->format == SDL_PIXELFORMAT_P010) {
  2390. const uint32_t YUV_SD_THRESHOLD = 576;
  2391. // Check that we have VK_KHR_sampler_ycbcr_conversion support
  2392. if (!rendererData->supportsKHRSamplerYCbCrConversion) {
  2393. return SDL_SetError("YUV textures require a Vulkan device that supports VK_KHR_sampler_ycbcr_conversion");
  2394. }
  2395. VkSamplerYcbcrConversionCreateInfoKHR samplerYcbcrConversionCreateInfo = { 0 };
  2396. samplerYcbcrConversionCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR;
  2397. // Pad width/height to multiple of 2
  2398. width = (width + 1) & ~1;
  2399. height = (height + 1) & ~1;
  2400. // Create samplerYcbcrConversion which will be used on the VkImageView and VkSampler
  2401. samplerYcbcrConversionCreateInfo.format = textureFormat;
  2402. switch (SDL_COLORSPACEMATRIX(texture->colorspace)) {
  2403. case SDL_MATRIX_COEFFICIENTS_BT470BG:
  2404. case SDL_MATRIX_COEFFICIENTS_BT601:
  2405. samplerYcbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR;
  2406. break;
  2407. case SDL_MATRIX_COEFFICIENTS_BT709:
  2408. samplerYcbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR;
  2409. break;
  2410. case SDL_MATRIX_COEFFICIENTS_BT2020_NCL:
  2411. samplerYcbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR;
  2412. break;
  2413. case SDL_MATRIX_COEFFICIENTS_UNSPECIFIED:
  2414. if (texture->format == SDL_PIXELFORMAT_P010) {
  2415. samplerYcbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR;
  2416. } else if (height > YUV_SD_THRESHOLD) {
  2417. samplerYcbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR;
  2418. } else {
  2419. samplerYcbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR;
  2420. }
  2421. break;
  2422. default:
  2423. return SDL_SetError("Unsupported Ycbcr colorspace: %d", SDL_COLORSPACEMATRIX(texture->colorspace));
  2424. }
  2425. samplerYcbcrConversionCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  2426. samplerYcbcrConversionCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  2427. samplerYcbcrConversionCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  2428. samplerYcbcrConversionCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  2429. if (texture->format == SDL_PIXELFORMAT_YV12 ||
  2430. texture->format == SDL_PIXELFORMAT_NV21) {
  2431. samplerYcbcrConversionCreateInfo.components.r = VK_COMPONENT_SWIZZLE_B;
  2432. samplerYcbcrConversionCreateInfo.components.b = VK_COMPONENT_SWIZZLE_R;
  2433. }
  2434. switch (SDL_COLORSPACERANGE(texture->colorspace)) {
  2435. case SDL_COLOR_RANGE_LIMITED:
  2436. samplerYcbcrConversionCreateInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR;
  2437. break;
  2438. case SDL_COLOR_RANGE_FULL:
  2439. default:
  2440. samplerYcbcrConversionCreateInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR;
  2441. break;
  2442. }
  2443. switch (SDL_COLORSPACECHROMA(texture->colorspace)) {
  2444. case SDL_CHROMA_LOCATION_LEFT:
  2445. samplerYcbcrConversionCreateInfo.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN_KHR;
  2446. samplerYcbcrConversionCreateInfo.yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT_KHR;
  2447. break;
  2448. case SDL_CHROMA_LOCATION_TOPLEFT:
  2449. samplerYcbcrConversionCreateInfo.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN_KHR;
  2450. samplerYcbcrConversionCreateInfo.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN_KHR;
  2451. break;
  2452. case SDL_CHROMA_LOCATION_NONE:
  2453. case SDL_CHROMA_LOCATION_CENTER:
  2454. default:
  2455. samplerYcbcrConversionCreateInfo.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT_KHR;
  2456. samplerYcbcrConversionCreateInfo.yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT_KHR;
  2457. break;
  2458. }
  2459. samplerYcbcrConversionCreateInfo.chromaFilter = VK_FILTER_LINEAR;
  2460. samplerYcbcrConversionCreateInfo.forceExplicitReconstruction = VK_FALSE;
  2461. result = vkCreateSamplerYcbcrConversionKHR(rendererData->device, &samplerYcbcrConversionCreateInfo, NULL, &textureData->samplerYcbcrConversion);
  2462. if (result != VK_SUCCESS) {
  2463. SET_ERROR_CODE("vkCreateSamplerYcbcrConversionKHR()", result);
  2464. return false;
  2465. }
  2466. // Also create VkSampler object which we will need to pass to the PSO as an immutable sampler
  2467. VkSamplerCreateInfo samplerCreateInfo = { 0 };
  2468. samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
  2469. samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
  2470. samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
  2471. samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
  2472. samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  2473. samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  2474. samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  2475. samplerCreateInfo.mipLodBias = 0.0f;
  2476. samplerCreateInfo.anisotropyEnable = VK_FALSE;
  2477. samplerCreateInfo.maxAnisotropy = 1.0f;
  2478. samplerCreateInfo.minLod = 0.0f;
  2479. samplerCreateInfo.maxLod = 1000.0f;
  2480. VkSamplerYcbcrConversionInfoKHR samplerYcbcrConversionInfo = { 0 };
  2481. samplerYcbcrConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR;
  2482. samplerYcbcrConversionInfo.conversion = textureData->samplerYcbcrConversion;
  2483. samplerCreateInfo.pNext = &samplerYcbcrConversionInfo;
  2484. result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &textureData->samplerYcbcr);
  2485. if (result != VK_SUCCESS) {
  2486. SET_ERROR_CODE("vkCreateSampler()", result);
  2487. return false;
  2488. }
  2489. // Allocate special descriptor set layout with samplerYcbcr baked as an immutable sampler
  2490. result = VULKAN_CreateDescriptorSetAndPipelineLayout(rendererData, textureData->samplerYcbcr, &textureData->descriptorSetLayoutYcbcr, &textureData->pipelineLayoutYcbcr);
  2491. if (result != VK_SUCCESS) {
  2492. return false;
  2493. }
  2494. }
  2495. #endif
  2496. textureData->width = width;
  2497. textureData->height = height;
  2498. VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  2499. if (texture->access == SDL_TEXTUREACCESS_TARGET) {
  2500. usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  2501. }
  2502. result = VULKAN_AllocateImage(rendererData, create_props, width, height, textureFormat, usage, imageViewSwizzle, textureData->samplerYcbcrConversion, &textureData->mainImage);
  2503. if (result != VK_SUCCESS) {
  2504. SET_ERROR_CODE("VULKAN_AllocateImage()", result);
  2505. return false;
  2506. }
  2507. SDL_PropertiesID props = SDL_GetTextureProperties(texture);
  2508. SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_VULKAN_TEXTURE_NUMBER, (Sint64)textureData->mainImage.image);
  2509. if (texture->access == SDL_TEXTUREACCESS_TARGET) {
  2510. result = VULKAN_CreateFramebuffersAndRenderPasses(renderer,
  2511. texture->w,
  2512. texture->h,
  2513. textureFormat,
  2514. 1,
  2515. &textureData->mainImage.imageView,
  2516. &textureData->mainFramebuffer,
  2517. textureData->mainRenderpasses);
  2518. if (result != VK_SUCCESS) {
  2519. SET_ERROR_CODE("VULKAN_CreateFramebuffersAndRenderPasses()", result);
  2520. return false;
  2521. }
  2522. }
  2523. return true;
  2524. }
  2525. static void VULKAN_DestroyTexture(SDL_Renderer *renderer,
  2526. SDL_Texture *texture)
  2527. {
  2528. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2529. VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
  2530. if (!textureData) {
  2531. return;
  2532. }
  2533. /* Because SDL_DestroyTexture might be called while the data is in-flight, we need to issue the batch first
  2534. Unfortunately, this means that deleting a lot of textures mid-frame will have poor performance. */
  2535. VULKAN_IssueBatch(rendererData);
  2536. VULKAN_WaitForGPU(rendererData);
  2537. VULKAN_DestroyImage(rendererData, &textureData->mainImage);
  2538. #ifdef SDL_HAVE_YUV
  2539. if (textureData->samplerYcbcrConversion != VK_NULL_HANDLE) {
  2540. vkDestroySamplerYcbcrConversionKHR(rendererData->device, textureData->samplerYcbcrConversion, NULL);
  2541. textureData->samplerYcbcrConversion = VK_NULL_HANDLE;
  2542. }
  2543. if (textureData->samplerYcbcr != VK_NULL_HANDLE) {
  2544. vkDestroySampler(rendererData->device, textureData->samplerYcbcr, NULL);
  2545. textureData->samplerYcbcr = VK_NULL_HANDLE;
  2546. }
  2547. if (textureData->pipelineLayoutYcbcr != VK_NULL_HANDLE) {
  2548. vkDestroyPipelineLayout(rendererData->device, textureData->pipelineLayoutYcbcr, NULL);
  2549. textureData->pipelineLayoutYcbcr = VK_NULL_HANDLE;
  2550. }
  2551. if (textureData->descriptorSetLayoutYcbcr != VK_NULL_HANDLE) {
  2552. vkDestroyDescriptorSetLayout(rendererData->device, textureData->descriptorSetLayoutYcbcr, NULL);
  2553. textureData->descriptorSetLayoutYcbcr = VK_NULL_HANDLE;
  2554. }
  2555. #endif
  2556. VULKAN_DestroyBuffer(rendererData, &textureData->stagingBuffer);
  2557. if (textureData->mainFramebuffer != VK_NULL_HANDLE) {
  2558. vkDestroyFramebuffer(rendererData->device, textureData->mainFramebuffer, NULL);
  2559. textureData->mainFramebuffer = VK_NULL_HANDLE;
  2560. }
  2561. for (uint32_t i = 0; i < SDL_arraysize(textureData->mainRenderpasses); i++) {
  2562. if (textureData->mainRenderpasses[i] != VK_NULL_HANDLE) {
  2563. vkDestroyRenderPass(rendererData->device, textureData->mainRenderpasses[i], NULL);
  2564. textureData->mainRenderpasses[i] = VK_NULL_HANDLE;
  2565. }
  2566. }
  2567. SDL_free(textureData);
  2568. texture->internal = NULL;
  2569. }
  2570. static bool VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, VkImage image, VkFormat format, int plane, int x, int y, int w, int h, const void *pixels, int pitch, VkImageLayout *imageLayout)
  2571. {
  2572. VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(format, plane);
  2573. VkDeviceSize length = w * pixelSize;
  2574. VkDeviceSize uploadBufferSize = length * h;
  2575. const Uint8 *src;
  2576. Uint8 *dst;
  2577. VkResult rc;
  2578. int planeCount = VULKAN_VkFormatGetNumPlanes(format);
  2579. VULKAN_EnsureCommandBuffer(rendererData);
  2580. int currentUploadBufferIndex = rendererData->currentUploadBuffer[rendererData->currentCommandBufferIndex];
  2581. VULKAN_Buffer *uploadBuffer = &rendererData->uploadBuffers[rendererData->currentCommandBufferIndex][currentUploadBufferIndex];
  2582. rc = VULKAN_AllocateBuffer(rendererData, uploadBufferSize,
  2583. VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
  2584. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  2585. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
  2586. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
  2587. uploadBuffer);
  2588. if (rc != VK_SUCCESS) {
  2589. return false;
  2590. }
  2591. src = (const Uint8 *)pixels;
  2592. dst = (Uint8 *)uploadBuffer->mappedBufferPtr;
  2593. if (length == (VkDeviceSize)pitch) {
  2594. SDL_memcpy(dst, src, (size_t)length * h);
  2595. } else {
  2596. if (length > (VkDeviceSize)pitch) {
  2597. length = pitch;
  2598. }
  2599. for (VkDeviceSize row = h; row--; ) {
  2600. SDL_memcpy(dst, src, (size_t)length);
  2601. src += pitch;
  2602. dst += length;
  2603. }
  2604. }
  2605. // Make sure the destination is in the correct resource state
  2606. VULKAN_RecordPipelineImageBarrier(rendererData,
  2607. VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
  2608. VK_ACCESS_TRANSFER_WRITE_BIT,
  2609. VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  2610. VK_PIPELINE_STAGE_TRANSFER_BIT,
  2611. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  2612. image,
  2613. imageLayout);
  2614. VkBufferImageCopy region;
  2615. region.bufferOffset = 0;
  2616. region.bufferRowLength = 0;
  2617. region.bufferImageHeight = 0;
  2618. region.imageSubresource.baseArrayLayer = 0;
  2619. region.imageSubresource.layerCount = 1;
  2620. region.imageSubresource.mipLevel = 0;
  2621. if (planeCount <= 1) {
  2622. region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  2623. } else {
  2624. region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << plane;
  2625. }
  2626. region.imageOffset.x = x;
  2627. region.imageOffset.y = y;
  2628. region.imageOffset.z = 0;
  2629. region.imageExtent.width = w;
  2630. region.imageExtent.height = h;
  2631. region.imageExtent.depth = 1;
  2632. vkCmdCopyBufferToImage(rendererData->currentCommandBuffer, uploadBuffer->buffer, image, *imageLayout, 1, &region);
  2633. // Transition the texture to be shader accessible
  2634. VULKAN_RecordPipelineImageBarrier(rendererData,
  2635. VK_ACCESS_TRANSFER_WRITE_BIT,
  2636. VK_ACCESS_SHADER_READ_BIT,
  2637. VK_PIPELINE_STAGE_TRANSFER_BIT,
  2638. VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  2639. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
  2640. image,
  2641. imageLayout);
  2642. rendererData->currentUploadBuffer[rendererData->currentCommandBufferIndex]++;
  2643. // If we've used up all the upload buffers, we need to issue the batch
  2644. if (rendererData->currentUploadBuffer[rendererData->currentCommandBufferIndex] == SDL_VULKAN_NUM_UPLOAD_BUFFERS) {
  2645. VULKAN_IssueBatch(rendererData);
  2646. }
  2647. return true;
  2648. }
  2649. #ifdef SDL_HAVE_YUV
  2650. static bool VULKAN_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
  2651. const SDL_Rect *rect,
  2652. const Uint8 *Yplane, int Ypitch,
  2653. const Uint8 *UVplane, int UVpitch);
  2654. static bool VULKAN_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
  2655. const SDL_Rect *rect,
  2656. const Uint8 *Yplane, int Ypitch,
  2657. const Uint8 *Uplane, int Upitch,
  2658. const Uint8 *Vplane, int Vpitch);
  2659. #endif
  2660. static bool VULKAN_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
  2661. const SDL_Rect *rect, const void *srcPixels,
  2662. int srcPitch)
  2663. {
  2664. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2665. VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
  2666. if (!textureData) {
  2667. return SDL_SetError("Texture is not currently available");
  2668. }
  2669. #ifdef SDL_HAVE_YUV
  2670. Uint32 numPlanes = VULKAN_VkFormatGetNumPlanes(textureData->mainImage.format);
  2671. if (numPlanes == 2) {
  2672. // NV12/NV21 data
  2673. int UVbpp = (int)VULKAN_GetBytesPerPixel(textureData->mainImage.format, 1);
  2674. int Ypitch = srcPitch;
  2675. int UVpitch = (srcPitch + (UVbpp - 1)) & ~(UVbpp - 1);
  2676. const Uint8 *plane0 = (const Uint8 *)srcPixels;
  2677. const Uint8 *plane1 = plane0 + rect->h * srcPitch;
  2678. return VULKAN_UpdateTextureNV(renderer, texture, rect, plane0, Ypitch, plane1, UVpitch);
  2679. } else if (numPlanes == 3) {
  2680. // YUV data
  2681. int Ypitch = srcPitch;
  2682. int UVpitch = ((Ypitch + 1) / 2);
  2683. const Uint8 *plane0 = (const Uint8 *)srcPixels;
  2684. const Uint8 *plane1 = plane0 + rect->h * Ypitch;
  2685. const Uint8 *plane2 = plane1 + ((rect->h + 1) / 2) * UVpitch;
  2686. if (texture->format == SDL_PIXELFORMAT_YV12) {
  2687. return VULKAN_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane2, UVpitch, plane1, UVpitch);
  2688. } else {
  2689. return VULKAN_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane1, UVpitch, plane2, UVpitch);
  2690. }
  2691. }
  2692. #endif
  2693. if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 0, rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainImage.imageLayout)) {
  2694. return false;
  2695. }
  2696. return true;
  2697. }
  2698. #ifdef SDL_HAVE_YUV
  2699. static bool VULKAN_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
  2700. const SDL_Rect *rect,
  2701. const Uint8 *Yplane, int Ypitch,
  2702. const Uint8 *Uplane, int Upitch,
  2703. const Uint8 *Vplane, int Vpitch)
  2704. {
  2705. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2706. VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
  2707. if (!textureData) {
  2708. return SDL_SetError("Texture is not currently available");
  2709. }
  2710. if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainImage.imageLayout)) {
  2711. return false;
  2712. }
  2713. if (texture->format == SDL_PIXELFORMAT_YV12) {
  2714. if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 1, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch, &textureData->mainImage.imageLayout)) {
  2715. return false;
  2716. }
  2717. if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 2, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch, &textureData->mainImage.imageLayout)) {
  2718. return false;
  2719. }
  2720. } else {
  2721. if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 1, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch, &textureData->mainImage.imageLayout)) {
  2722. return false;
  2723. }
  2724. if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 2, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch, &textureData->mainImage.imageLayout)) {
  2725. return false;
  2726. }
  2727. }
  2728. return true;
  2729. }
  2730. static bool VULKAN_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
  2731. const SDL_Rect *rect,
  2732. const Uint8 *Yplane, int Ypitch,
  2733. const Uint8 *UVplane, int UVpitch)
  2734. {
  2735. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2736. VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
  2737. if (!textureData) {
  2738. return SDL_SetError("Texture is not currently available");
  2739. }
  2740. if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainImage.imageLayout)) {
  2741. return false;
  2742. }
  2743. if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 1, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, UVplane, UVpitch, &textureData->mainImage.imageLayout)) {
  2744. return false;
  2745. }
  2746. return true;
  2747. }
  2748. #endif
  2749. static bool VULKAN_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
  2750. const SDL_Rect *rect, void **pixels, int *pitch)
  2751. {
  2752. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2753. VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
  2754. VkResult rc;
  2755. if (!textureData) {
  2756. return SDL_SetError("Texture is not currently available");
  2757. }
  2758. if (textureData->stagingBuffer.buffer != VK_NULL_HANDLE) {
  2759. return SDL_SetError("texture is already locked");
  2760. }
  2761. VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(textureData->mainImage.format, 0);
  2762. VkDeviceSize length = rect->w * pixelSize;
  2763. VkDeviceSize stagingBufferSize = length * rect->h;
  2764. rc = VULKAN_AllocateBuffer(rendererData,
  2765. stagingBufferSize,
  2766. VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
  2767. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
  2768. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
  2769. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
  2770. &textureData->stagingBuffer);
  2771. if (rc != VK_SUCCESS) {
  2772. return false;
  2773. }
  2774. /* Make note of where the staging texture will be written to
  2775. * (on a call to SDL_UnlockTexture):
  2776. */
  2777. textureData->lockedRect = *rect;
  2778. /* Make sure the caller has information on the texture's pixel buffer,
  2779. * then return:
  2780. */
  2781. *pixels = textureData->stagingBuffer.mappedBufferPtr;
  2782. *pitch = (int)length;
  2783. return true;
  2784. }
  2785. static void VULKAN_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  2786. {
  2787. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2788. VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
  2789. if (!textureData) {
  2790. return;
  2791. }
  2792. VULKAN_EnsureCommandBuffer(rendererData);
  2793. // Make sure the destination is in the correct resource state
  2794. VULKAN_RecordPipelineImageBarrier(rendererData,
  2795. VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
  2796. VK_ACCESS_TRANSFER_WRITE_BIT,
  2797. VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  2798. VK_PIPELINE_STAGE_TRANSFER_BIT,
  2799. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  2800. textureData->mainImage.image,
  2801. &textureData->mainImage.imageLayout);
  2802. VkBufferImageCopy region;
  2803. region.bufferOffset = 0;
  2804. region.bufferRowLength = 0;
  2805. region.bufferImageHeight = 0;
  2806. region.imageSubresource.baseArrayLayer = 0;
  2807. region.imageSubresource.layerCount = 1;
  2808. region.imageSubresource.mipLevel = 0;
  2809. region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  2810. region.imageOffset.x = textureData->lockedRect.x;
  2811. region.imageOffset.y = textureData->lockedRect.y;
  2812. region.imageOffset.z = 0;
  2813. region.imageExtent.width = textureData->lockedRect.w;
  2814. region.imageExtent.height = textureData->lockedRect.h;
  2815. region.imageExtent.depth = 1;
  2816. vkCmdCopyBufferToImage(rendererData->currentCommandBuffer, textureData->stagingBuffer.buffer, textureData->mainImage.image, textureData->mainImage.imageLayout, 1, &region);
  2817. // Transition the texture to be shader accessible
  2818. VULKAN_RecordPipelineImageBarrier(rendererData,
  2819. VK_ACCESS_TRANSFER_WRITE_BIT,
  2820. VK_ACCESS_SHADER_READ_BIT,
  2821. VK_PIPELINE_STAGE_TRANSFER_BIT,
  2822. VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  2823. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
  2824. textureData->mainImage.image,
  2825. &textureData->mainImage.imageLayout);
  2826. // Execute the command list before releasing the staging buffer
  2827. VULKAN_IssueBatch(rendererData);
  2828. VULKAN_DestroyBuffer(rendererData, &textureData->stagingBuffer);
  2829. }
  2830. static bool VULKAN_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
  2831. {
  2832. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2833. VULKAN_TextureData *textureData = NULL;
  2834. VULKAN_EnsureCommandBuffer(rendererData);
  2835. if (!texture) {
  2836. if (rendererData->textureRenderTarget) {
  2837. VULKAN_RecordPipelineImageBarrier(rendererData,
  2838. VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  2839. VK_ACCESS_SHADER_READ_BIT,
  2840. VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  2841. VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  2842. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
  2843. rendererData->textureRenderTarget->mainImage.image,
  2844. &rendererData->textureRenderTarget->mainImage.imageLayout);
  2845. }
  2846. rendererData->textureRenderTarget = NULL;
  2847. return true;
  2848. }
  2849. textureData = (VULKAN_TextureData *)texture->internal;
  2850. if (textureData->mainImage.imageView == VK_NULL_HANDLE) {
  2851. return SDL_SetError("specified texture is not a render target");
  2852. }
  2853. rendererData->textureRenderTarget = textureData;
  2854. VULKAN_RecordPipelineImageBarrier(rendererData,
  2855. VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  2856. VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  2857. VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  2858. VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  2859. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  2860. rendererData->textureRenderTarget->mainImage.image,
  2861. &rendererData->textureRenderTarget->mainImage.imageLayout);
  2862. return true;
  2863. }
  2864. static bool VULKAN_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
  2865. {
  2866. return true; // nothing to do in this backend.
  2867. }
  2868. static bool VULKAN_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
  2869. {
  2870. VULKAN_VertexPositionColor *verts = (VULKAN_VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VULKAN_VertexPositionColor), 0, &cmd->data.draw.first);
  2871. int i;
  2872. SDL_FColor color = cmd->data.draw.color;
  2873. bool convert_color = SDL_RenderingLinearSpace(renderer);
  2874. if (!verts) {
  2875. return false;
  2876. }
  2877. cmd->data.draw.count = count;
  2878. if (convert_color) {
  2879. SDL_ConvertToLinear(&color);
  2880. }
  2881. for (i = 0; i < count; i++) {
  2882. verts->pos[0] = points[i].x + 0.5f;
  2883. verts->pos[1] = points[i].y + 0.5f;
  2884. verts->tex[0] = 0.0f;
  2885. verts->tex[1] = 0.0f;
  2886. verts->color = color;
  2887. verts++;
  2888. }
  2889. return true;
  2890. }
  2891. static bool VULKAN_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
  2892. const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride,
  2893. int num_vertices, const void *indices, int num_indices, int size_indices,
  2894. float scale_x, float scale_y)
  2895. {
  2896. int i;
  2897. int count = indices ? num_indices : num_vertices;
  2898. VULKAN_VertexPositionColor *verts = (VULKAN_VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VULKAN_VertexPositionColor), 0, &cmd->data.draw.first);
  2899. bool convert_color = SDL_RenderingLinearSpace(renderer);
  2900. VULKAN_TextureData *textureData = texture ? (VULKAN_TextureData *)texture->internal : NULL;
  2901. float u_scale = textureData ? (float)texture->w / textureData->width : 0.0f;
  2902. float v_scale = textureData ? (float)texture->h / textureData->height : 0.0f;
  2903. if (!verts) {
  2904. return false;
  2905. }
  2906. cmd->data.draw.count = count;
  2907. size_indices = indices ? size_indices : 0;
  2908. for (i = 0; i < count; i++) {
  2909. int j;
  2910. float *xy_;
  2911. if (size_indices == 4) {
  2912. j = ((const Uint32 *)indices)[i];
  2913. } else if (size_indices == 2) {
  2914. j = ((const Uint16 *)indices)[i];
  2915. } else if (size_indices == 1) {
  2916. j = ((const Uint8 *)indices)[i];
  2917. } else {
  2918. j = i;
  2919. }
  2920. xy_ = (float *)((char *)xy + j * xy_stride);
  2921. verts->pos[0] = xy_[0] * scale_x;
  2922. verts->pos[1] = xy_[1] * scale_y;
  2923. verts->color = *(SDL_FColor *)((char *)color + j * color_stride);
  2924. if (convert_color) {
  2925. SDL_ConvertToLinear(&verts->color);
  2926. }
  2927. if (texture) {
  2928. float *uv_ = (float *)((char *)uv + j * uv_stride);
  2929. verts->tex[0] = uv_[0] * u_scale;
  2930. verts->tex[1] = uv_[1] * v_scale;
  2931. } else {
  2932. verts->tex[0] = 0.0f;
  2933. verts->tex[1] = 0.0f;
  2934. }
  2935. verts += 1;
  2936. }
  2937. return true;
  2938. }
  2939. static bool VULKAN_UpdateVertexBuffer(SDL_Renderer *renderer,
  2940. const void *vertexData, size_t dataSizeInBytes, VULKAN_DrawStateCache *stateCache)
  2941. {
  2942. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2943. const int vbidx = rendererData->currentVertexBuffer;
  2944. VULKAN_Buffer *vertexBuffer;
  2945. if (dataSizeInBytes == 0) {
  2946. return true; // nothing to do.
  2947. }
  2948. if (rendererData->issueBatch) {
  2949. if (VULKAN_IssueBatch(rendererData) != VK_SUCCESS) {
  2950. return SDL_SetError("Failed to issue intermediate batch");
  2951. }
  2952. }
  2953. // If the existing vertex buffer isn't big enough, we need to recreate a big enough one
  2954. if (dataSizeInBytes > rendererData->vertexBuffers[vbidx].size) {
  2955. VULKAN_IssueBatch(rendererData);
  2956. VULKAN_WaitForGPU(rendererData);
  2957. VULKAN_CreateVertexBuffer(rendererData, vbidx, dataSizeInBytes);
  2958. }
  2959. vertexBuffer = &rendererData->vertexBuffers[vbidx];
  2960. SDL_memcpy(vertexBuffer->mappedBufferPtr, vertexData, dataSizeInBytes);
  2961. stateCache->vertexBuffer = vertexBuffer->buffer;
  2962. rendererData->currentVertexBuffer = vbidx + 1;
  2963. if (rendererData->currentVertexBuffer >= SDL_VULKAN_NUM_VERTEX_BUFFERS) {
  2964. rendererData->currentVertexBuffer = 0;
  2965. rendererData->issueBatch = true;
  2966. }
  2967. return true;
  2968. }
  2969. static VkSurfaceTransformFlagBitsKHR VULKAN_GetRotationForCurrentRenderTarget(VULKAN_RenderData *rendererData)
  2970. {
  2971. if (rendererData->textureRenderTarget) {
  2972. return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
  2973. } else {
  2974. return rendererData->swapChainPreTransform;
  2975. }
  2976. }
  2977. static bool VULKAN_IsDisplayRotated90Degrees(VkSurfaceTransformFlagBitsKHR rotation)
  2978. {
  2979. switch (rotation) {
  2980. case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
  2981. case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
  2982. return true;
  2983. default:
  2984. return false;
  2985. }
  2986. }
  2987. static bool VULKAN_UpdateViewport(SDL_Renderer *renderer)
  2988. {
  2989. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  2990. const SDL_Rect *viewport = &rendererData->currentViewport;
  2991. Float4X4 projection;
  2992. Float4X4 view;
  2993. VkSurfaceTransformFlagBitsKHR rotation = VULKAN_GetRotationForCurrentRenderTarget(rendererData);
  2994. bool swapDimensions;
  2995. if (viewport->w == 0 || viewport->h == 0) {
  2996. /* If the viewport is empty, assume that it is because
  2997. * SDL_CreateRenderer is calling it, and will call it again later
  2998. * with a non-empty viewport.
  2999. */
  3000. // SDL_Log("%s, no viewport was set!", __FUNCTION__);
  3001. return false;
  3002. }
  3003. switch (rotation) {
  3004. case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
  3005. projection = MatrixRotationZ(SDL_PI_F * 0.5f);
  3006. break;
  3007. case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
  3008. projection = MatrixRotationZ(SDL_PI_F);
  3009. break;
  3010. case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
  3011. projection = MatrixRotationZ(-SDL_PI_F * 0.5f);
  3012. break;
  3013. case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
  3014. default:
  3015. projection = MatrixIdentity();
  3016. break;
  3017. }
  3018. // Update the view matrix
  3019. SDL_zero(view);
  3020. view.m[0][0] = 2.0f / viewport->w;
  3021. view.m[1][1] = -2.0f / viewport->h;
  3022. view.m[2][2] = 1.0f;
  3023. view.m[3][0] = -1.0f;
  3024. view.m[3][1] = 1.0f;
  3025. view.m[3][3] = 1.0f;
  3026. rendererData->vertexShaderConstantsData.projectionAndView = MatrixMultiply(
  3027. view,
  3028. projection);
  3029. VkViewport vkViewport;
  3030. swapDimensions = VULKAN_IsDisplayRotated90Degrees(rotation);
  3031. if (swapDimensions) {
  3032. vkViewport.x = viewport->y;
  3033. vkViewport.y = viewport->x;
  3034. vkViewport.width = viewport->h;
  3035. vkViewport.height = viewport->w;
  3036. }
  3037. else {
  3038. vkViewport.x = viewport->x;
  3039. vkViewport.y = viewport->y;
  3040. vkViewport.width = viewport->w;
  3041. vkViewport.height = viewport->h;
  3042. }
  3043. vkViewport.minDepth = 0.0f;
  3044. vkViewport.maxDepth = 1.0f;
  3045. vkCmdSetViewport(rendererData->currentCommandBuffer, 0, 1, &vkViewport);
  3046. rendererData->viewportDirty = false;
  3047. return true;
  3048. }
  3049. static bool VULKAN_UpdateClipRect(SDL_Renderer *renderer)
  3050. {
  3051. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3052. const SDL_Rect *viewport = &rendererData->currentViewport;
  3053. VkSurfaceTransformFlagBitsKHR rotation = VULKAN_GetRotationForCurrentRenderTarget(rendererData);
  3054. bool swapDimensions = VULKAN_IsDisplayRotated90Degrees(rotation);
  3055. VkRect2D scissor;
  3056. if (rendererData->currentCliprectEnabled) {
  3057. scissor.offset.x = viewport->x + rendererData->currentCliprect.x;
  3058. scissor.offset.y = viewport->y + rendererData->currentCliprect.y;
  3059. scissor.extent.width = rendererData->currentCliprect.w;
  3060. scissor.extent.height = rendererData->currentCliprect.h;
  3061. } else {
  3062. scissor.offset.x = viewport->x;
  3063. scissor.offset.y = viewport->y;
  3064. scissor.extent.width = viewport->w;
  3065. scissor.extent.height = viewport->h;
  3066. }
  3067. if (swapDimensions) {
  3068. VkRect2D scissorTemp = scissor;
  3069. scissor.offset.x = scissorTemp.offset.y;
  3070. scissor.offset.y = scissorTemp.offset.x;
  3071. scissor.extent.width = scissorTemp.extent.height;
  3072. scissor.extent.height = scissorTemp.extent.width;
  3073. }
  3074. vkCmdSetScissor(rendererData->currentCommandBuffer, 0, 1, &scissor);
  3075. rendererData->cliprectDirty = false;
  3076. return true;
  3077. }
  3078. static void VULKAN_SetupShaderConstants(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Texture *texture, VULKAN_PixelShaderConstants *constants)
  3079. {
  3080. float output_headroom;
  3081. SDL_zerop(constants);
  3082. constants->scRGB_output = (float)SDL_RenderingLinearSpace(renderer);
  3083. constants->color_scale = cmd->data.draw.color_scale;
  3084. if (texture) {
  3085. switch (texture->format) {
  3086. case SDL_PIXELFORMAT_YV12:
  3087. case SDL_PIXELFORMAT_IYUV:
  3088. case SDL_PIXELFORMAT_NV12:
  3089. case SDL_PIXELFORMAT_NV21:
  3090. constants->input_type = INPUTTYPE_SRGB;
  3091. break;
  3092. case SDL_PIXELFORMAT_P010:
  3093. constants->input_type = INPUTTYPE_HDR10;
  3094. break;
  3095. default:
  3096. if (texture->colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
  3097. constants->input_type = INPUTTYPE_SCRGB;
  3098. } else if (SDL_COLORSPACEPRIMARIES(texture->colorspace) == SDL_COLOR_PRIMARIES_BT2020 &&
  3099. SDL_COLORSPACETRANSFER(texture->colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ) {
  3100. constants->input_type = INPUTTYPE_HDR10;
  3101. } else {
  3102. // The sampler will convert from sRGB to linear on load if working in linear colorspace
  3103. constants->input_type = INPUTTYPE_UNSPECIFIED;
  3104. }
  3105. break;
  3106. }
  3107. if (texture->format == SDL_PIXELFORMAT_INDEX8) {
  3108. switch (cmd->data.draw.texture_scale_mode) {
  3109. case SDL_SCALEMODE_NEAREST:
  3110. constants->texture_type = TEXTURETYPE_PALETTE_NEAREST;
  3111. break;
  3112. case SDL_SCALEMODE_LINEAR:
  3113. constants->texture_type = TEXTURETYPE_PALETTE_LINEAR;
  3114. break;
  3115. case SDL_SCALEMODE_PIXELART:
  3116. constants->texture_type = TEXTURETYPE_PALETTE_PIXELART;
  3117. break;
  3118. default:
  3119. SDL_assert(!"Unknown scale mode");
  3120. break;
  3121. }
  3122. } else {
  3123. if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_PIXELART) {
  3124. constants->texture_type = TEXTURETYPE_RGB_PIXELART;
  3125. } else {
  3126. constants->texture_type = TEXTURETYPE_RGB;
  3127. }
  3128. }
  3129. if (constants->texture_type == TEXTURETYPE_PALETTE_LINEAR ||
  3130. constants->texture_type == TEXTURETYPE_PALETTE_PIXELART ||
  3131. constants->texture_type == TEXTURETYPE_RGB_PIXELART) {
  3132. constants->texture_width = texture->w;
  3133. constants->texture_height = texture->h;
  3134. constants->texel_width = 1.0f / constants->texture_width;
  3135. constants->texel_height = 1.0f / constants->texture_height;
  3136. }
  3137. constants->sdr_white_point = texture->SDR_white_point;
  3138. if (renderer->target) {
  3139. output_headroom = renderer->target->HDR_headroom;
  3140. } else {
  3141. output_headroom = renderer->HDR_headroom;
  3142. }
  3143. if (texture->HDR_headroom > output_headroom && output_headroom > 0.0f) {
  3144. constants->tonemap_method = TONEMAP_CHROME;
  3145. constants->tonemap_factor1 = (output_headroom / (texture->HDR_headroom * texture->HDR_headroom));
  3146. constants->tonemap_factor2 = (1.0f / output_headroom);
  3147. }
  3148. }
  3149. }
  3150. static VULKAN_Shader SelectShader(const VULKAN_PixelShaderConstants *shader_constants)
  3151. {
  3152. if (!shader_constants) {
  3153. return SHADER_SOLID;
  3154. }
  3155. if (shader_constants->texture_type == TEXTURETYPE_RGB &&
  3156. shader_constants->input_type == INPUTTYPE_UNSPECIFIED &&
  3157. shader_constants->tonemap_method == TONEMAP_NONE) {
  3158. return SHADER_RGB;
  3159. }
  3160. return SHADER_ADVANCED;
  3161. }
  3162. static VkDescriptorPool VULKAN_AllocateDescriptorPool(VULKAN_RenderData *rendererData)
  3163. {
  3164. VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
  3165. VkDescriptorPoolSize descriptorPoolSizes[3];
  3166. VkResult result;
  3167. descriptorPoolSizes[0].descriptorCount = SDL_VULKAN_MAX_DESCRIPTOR_SETS;
  3168. descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLER;
  3169. descriptorPoolSizes[1].descriptorCount = SDL_VULKAN_MAX_DESCRIPTOR_SETS;
  3170. descriptorPoolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  3171. descriptorPoolSizes[2].descriptorCount = SDL_VULKAN_MAX_DESCRIPTOR_SETS;
  3172. descriptorPoolSizes[2].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  3173. VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = { 0 };
  3174. descriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  3175. descriptorPoolCreateInfo.poolSizeCount = SDL_arraysize(descriptorPoolSizes);
  3176. descriptorPoolCreateInfo.pPoolSizes = descriptorPoolSizes;
  3177. descriptorPoolCreateInfo.maxSets = SDL_VULKAN_MAX_DESCRIPTOR_SETS;
  3178. result = vkCreateDescriptorPool(rendererData->device, &descriptorPoolCreateInfo, NULL, &descriptorPool);
  3179. if (result != VK_SUCCESS) {
  3180. SET_ERROR_CODE("vkCreateDescrptorPool()", result);
  3181. return VK_NULL_HANDLE;
  3182. }
  3183. return descriptorPool;
  3184. }
  3185. static VkResult VULKAN_CreateDescriptorSetAndPipelineLayout(VULKAN_RenderData *rendererData, VkSampler samplerYcbcr, VkDescriptorSetLayout *descriptorSetLayoutOut,
  3186. VkPipelineLayout *pipelineLayoutOut)
  3187. {
  3188. VkResult result;
  3189. // Descriptor set layout
  3190. VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = { 0 };
  3191. descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  3192. descriptorSetLayoutCreateInfo.flags = 0;
  3193. VkDescriptorSetLayoutBinding layoutBindings[3];
  3194. // PixelShaderConstants
  3195. layoutBindings[0].binding = 0;
  3196. layoutBindings[0].descriptorCount = 1;
  3197. layoutBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  3198. layoutBindings[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  3199. layoutBindings[0].pImmutableSamplers = NULL;
  3200. // Combined image/sampler
  3201. layoutBindings[1].binding = 1;
  3202. layoutBindings[1].descriptorCount = 1;
  3203. layoutBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  3204. layoutBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  3205. layoutBindings[1].pImmutableSamplers = (samplerYcbcr != VK_NULL_HANDLE) ? &samplerYcbcr : NULL;
  3206. // Combined image/sampler
  3207. layoutBindings[2].binding = 2;
  3208. layoutBindings[2].descriptorCount = 1;
  3209. layoutBindings[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  3210. layoutBindings[2].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  3211. layoutBindings[2].pImmutableSamplers = (samplerYcbcr != VK_NULL_HANDLE) ? &samplerYcbcr : NULL;
  3212. descriptorSetLayoutCreateInfo.bindingCount = 3;
  3213. descriptorSetLayoutCreateInfo.pBindings = layoutBindings;
  3214. result = vkCreateDescriptorSetLayout(rendererData->device, &descriptorSetLayoutCreateInfo, NULL, descriptorSetLayoutOut);
  3215. if (result != VK_SUCCESS) {
  3216. SET_ERROR_CODE("vkCreateDescriptorSetLayout()", result);
  3217. return result;
  3218. }
  3219. // Pipeline layout
  3220. VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = { 0 };
  3221. VkPushConstantRange pushConstantRange;
  3222. pushConstantRange.size = sizeof( VULKAN_VertexShaderConstants );
  3223. pushConstantRange.offset = 0;
  3224. pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
  3225. pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  3226. pipelineLayoutCreateInfo.setLayoutCount = 1;
  3227. pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayoutOut;
  3228. pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
  3229. pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
  3230. result = vkCreatePipelineLayout(rendererData->device, &pipelineLayoutCreateInfo, NULL, pipelineLayoutOut);
  3231. if (result != VK_SUCCESS) {
  3232. SET_ERROR_CODE("vkCreatePipelineLayout()", result);
  3233. return result;
  3234. }
  3235. return result;
  3236. }
  3237. static VkDescriptorSet VULKAN_AllocateDescriptorSet(SDL_Renderer *renderer, VULKAN_Shader shader, VkDescriptorSetLayout descriptorSetLayout,
  3238. VkBuffer constantBuffer, VkDeviceSize constantBufferOffset, int numImages, VkImageView *imageViews, int numSamplers, VkSampler *samplers)
  3239. {
  3240. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3241. uint32_t currentDescriptorPoolIndex = rendererData->currentDescriptorPoolIndex;
  3242. VkDescriptorPool descriptorPool = rendererData->descriptorPools[rendererData->currentCommandBufferIndex][currentDescriptorPoolIndex];
  3243. VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = { 0 };
  3244. descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  3245. descriptorSetAllocateInfo.descriptorSetCount = 1;
  3246. descriptorSetAllocateInfo.descriptorPool = descriptorPool;
  3247. descriptorSetAllocateInfo.pSetLayouts = &descriptorSetLayout;
  3248. VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
  3249. VkResult result = (rendererData->currentDescriptorSetIndex >= SDL_VULKAN_MAX_DESCRIPTOR_SETS) ? VK_ERROR_OUT_OF_DEVICE_MEMORY : VK_SUCCESS;
  3250. if (result == VK_SUCCESS) {
  3251. result = vkAllocateDescriptorSets(rendererData->device, &descriptorSetAllocateInfo, &descriptorSet);
  3252. }
  3253. if (result != VK_SUCCESS) {
  3254. // Out of descriptor sets in this pool - see if we have more pools allocated
  3255. currentDescriptorPoolIndex++;
  3256. if (currentDescriptorPoolIndex < rendererData->numDescriptorPools[rendererData->currentCommandBufferIndex]) {
  3257. descriptorPool = rendererData->descriptorPools[rendererData->currentCommandBufferIndex][currentDescriptorPoolIndex];
  3258. descriptorSetAllocateInfo.descriptorPool = descriptorPool;
  3259. result = vkAllocateDescriptorSets(rendererData->device, &descriptorSetAllocateInfo, &descriptorSet);
  3260. if (result != VK_SUCCESS) {
  3261. // This should not fail - we are allocating from the front of the descriptor set
  3262. SDL_SetError("Unable to allocate descriptor set");
  3263. return VK_NULL_HANDLE;
  3264. }
  3265. rendererData->currentDescriptorPoolIndex = currentDescriptorPoolIndex;
  3266. rendererData->currentDescriptorSetIndex = 0;
  3267. }
  3268. // We are out of pools, create a new one
  3269. else {
  3270. descriptorPool = VULKAN_AllocateDescriptorPool(rendererData);
  3271. if (descriptorPool == VK_NULL_HANDLE) {
  3272. // SDL_SetError called in VULKAN_AllocateDescriptorPool if we failed to allocate a new pool
  3273. return VK_NULL_HANDLE;
  3274. }
  3275. rendererData->numDescriptorPools[rendererData->currentCommandBufferIndex]++;
  3276. VkDescriptorPool *descriptorPools = (VkDescriptorPool *)SDL_realloc(rendererData->descriptorPools[rendererData->currentCommandBufferIndex],
  3277. sizeof(VkDescriptorPool) * rendererData->numDescriptorPools[rendererData->currentCommandBufferIndex]);
  3278. descriptorPools[rendererData->numDescriptorPools[rendererData->currentCommandBufferIndex] - 1] = descriptorPool;
  3279. rendererData->descriptorPools[rendererData->currentCommandBufferIndex] = descriptorPools;
  3280. rendererData->currentDescriptorPoolIndex = currentDescriptorPoolIndex;
  3281. rendererData->currentDescriptorSetIndex = 0;
  3282. // Call recursively to allocate from the new pool
  3283. return VULKAN_AllocateDescriptorSet(renderer, shader, descriptorSetLayout, constantBuffer, constantBufferOffset, numImages, imageViews, numSamplers, samplers);
  3284. }
  3285. }
  3286. rendererData->currentDescriptorSetIndex++;
  3287. VkDescriptorImageInfo combinedImageSamplerDescriptor[2];
  3288. VkDescriptorBufferInfo bufferDescriptor = { 0 };
  3289. bufferDescriptor.buffer = constantBuffer;
  3290. bufferDescriptor.offset = constantBufferOffset;
  3291. bufferDescriptor.range = sizeof(VULKAN_PixelShaderConstants);
  3292. VkWriteDescriptorSet descriptorWrites[3];
  3293. SDL_zero(descriptorWrites);
  3294. uint32_t descriptorCount = 1; // Always have the uniform buffer
  3295. descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  3296. descriptorWrites[0].dstSet = descriptorSet;
  3297. descriptorWrites[0].dstBinding = 0;
  3298. descriptorWrites[0].dstArrayElement = 0;
  3299. descriptorWrites[0].descriptorCount = 1;
  3300. descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  3301. descriptorWrites[0].pBufferInfo = &bufferDescriptor;
  3302. SDL_assert(numSamplers == numImages);
  3303. for (int i = 0; i < numImages; ++i) {
  3304. SDL_assert(i < SDL_arraysize(combinedImageSamplerDescriptor));
  3305. VkDescriptorImageInfo *pImageInfo = &combinedImageSamplerDescriptor[i];
  3306. SDL_zerop(pImageInfo);
  3307. if (descriptorSetLayout == rendererData->descriptorSetLayout) {
  3308. pImageInfo->sampler = samplers[i];
  3309. } else {
  3310. // Ignore the sampler if we're using YcBcCr data since it will be baked in the descriptor set layout
  3311. }
  3312. pImageInfo->imageView = imageViews[i];
  3313. pImageInfo->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  3314. SDL_assert(descriptorCount < SDL_arraysize(descriptorWrites));
  3315. VkWriteDescriptorSet *pDescriptorSet = &descriptorWrites[descriptorCount++];
  3316. pDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  3317. pDescriptorSet->dstSet = descriptorSet;
  3318. pDescriptorSet->dstBinding = 1 + i;
  3319. pDescriptorSet->dstArrayElement = 0;
  3320. pDescriptorSet->descriptorCount = 1;
  3321. pDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  3322. pDescriptorSet->pImageInfo = pImageInfo;
  3323. }
  3324. vkUpdateDescriptorSets(rendererData->device, descriptorCount, descriptorWrites, 0, NULL);
  3325. return descriptorSet;
  3326. }
  3327. static bool VULKAN_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, VkPipelineLayout pipelineLayout, VkDescriptorSetLayout descriptorSetLayout,
  3328. const VULKAN_PixelShaderConstants *shader_constants, VkPrimitiveTopology topology, int numImages, VkImageView *imageViews, int numSamplers, VkSampler *samplers, const Float4X4 *matrix, VULKAN_DrawStateCache *stateCache)
  3329. {
  3330. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3331. const SDL_BlendMode blendMode = cmd->data.draw.blend;
  3332. VkFormat format = rendererData->surfaceFormat.format;
  3333. const Float4X4 *newmatrix = matrix ? matrix : &rendererData->identity;
  3334. bool updateConstants = false;
  3335. VULKAN_Shader shader = SelectShader(shader_constants);
  3336. VULKAN_PixelShaderConstants solid_constants;
  3337. VkDescriptorSet descriptorSet;
  3338. VkBuffer constantBuffer;
  3339. VkDeviceSize constantBufferOffset;
  3340. int i;
  3341. if (!VULKAN_ActivateCommandBuffer(renderer, VK_ATTACHMENT_LOAD_OP_LOAD, NULL, stateCache)) {
  3342. return false;
  3343. }
  3344. // See if we need to change the pipeline state
  3345. if (!rendererData->currentPipelineState ||
  3346. rendererData->currentPipelineState->shader != shader ||
  3347. rendererData->currentPipelineState->blendMode != blendMode ||
  3348. rendererData->currentPipelineState->topology != topology ||
  3349. rendererData->currentPipelineState->format != format ||
  3350. rendererData->currentPipelineState->pipelineLayout != pipelineLayout ||
  3351. rendererData->currentPipelineState->descriptorSetLayout != descriptorSetLayout) {
  3352. rendererData->currentPipelineState = NULL;
  3353. for (i = 0; i < rendererData->pipelineStateCount; ++i) {
  3354. VULKAN_PipelineState *candidatePiplineState = &rendererData->pipelineStates[i];
  3355. if (candidatePiplineState->shader == shader &&
  3356. candidatePiplineState->blendMode == blendMode &&
  3357. candidatePiplineState->topology == topology &&
  3358. candidatePiplineState->format == format &&
  3359. candidatePiplineState->pipelineLayout == pipelineLayout &&
  3360. candidatePiplineState->descriptorSetLayout == descriptorSetLayout) {
  3361. rendererData->currentPipelineState = candidatePiplineState;
  3362. break;
  3363. }
  3364. }
  3365. // If we didn't find a match, create a new one -- it must mean the blend mode is non-standard
  3366. if (!rendererData->currentPipelineState) {
  3367. rendererData->currentPipelineState = VULKAN_CreatePipelineState(renderer, shader, pipelineLayout, descriptorSetLayout, blendMode, topology, format);
  3368. }
  3369. if (!rendererData->currentPipelineState) {
  3370. return SDL_SetError("Unable to create required pipeline state");
  3371. }
  3372. vkCmdBindPipeline(rendererData->currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, rendererData->currentPipelineState->pipeline);
  3373. updateConstants = true;
  3374. }
  3375. if (rendererData->viewportDirty) {
  3376. if (VULKAN_UpdateViewport(renderer)) {
  3377. // vertexShaderConstantsData.projectionAndView has changed
  3378. updateConstants = true;
  3379. }
  3380. }
  3381. if (rendererData->cliprectDirty) {
  3382. VULKAN_UpdateClipRect(renderer);
  3383. }
  3384. if (updateConstants == true || SDL_memcmp(&rendererData->vertexShaderConstantsData.model, newmatrix, sizeof(*newmatrix)) != 0) {
  3385. SDL_memcpy(&rendererData->vertexShaderConstantsData.model, newmatrix, sizeof(*newmatrix));
  3386. vkCmdPushConstants(rendererData->currentCommandBuffer, rendererData->currentPipelineState->pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0,
  3387. sizeof(rendererData->vertexShaderConstantsData),
  3388. &rendererData->vertexShaderConstantsData);
  3389. }
  3390. if (!shader_constants) {
  3391. VULKAN_SetupShaderConstants(renderer, cmd, NULL, &solid_constants);
  3392. shader_constants = &solid_constants;
  3393. }
  3394. constantBuffer = rendererData->constantBuffers[rendererData->currentCommandBufferIndex][rendererData->currentConstantBufferIndex].buffer;
  3395. constantBufferOffset = (rendererData->currentConstantBufferOffset < 0) ? 0 : rendererData->currentConstantBufferOffset;
  3396. if (updateConstants ||
  3397. SDL_memcmp(shader_constants, &rendererData->currentPipelineState->shader_constants, sizeof(*shader_constants)) != 0) {
  3398. if (rendererData->currentConstantBufferOffset == -1) {
  3399. // First time, grab offset 0
  3400. rendererData->currentConstantBufferOffset = 0;
  3401. constantBufferOffset = 0;
  3402. }
  3403. else {
  3404. // Align the next address to the minUniformBufferOffsetAlignment
  3405. VkDeviceSize alignment = rendererData->physicalDeviceProperties.limits.minUniformBufferOffsetAlignment;
  3406. SDL_assert(rendererData->currentConstantBufferOffset >= 0 );
  3407. rendererData->currentConstantBufferOffset += (int32_t)(sizeof(VULKAN_PixelShaderConstants) + alignment - 1) & ~(alignment - 1);
  3408. constantBufferOffset = rendererData->currentConstantBufferOffset;
  3409. }
  3410. // If we have run out of size in this constant buffer, create another if needed
  3411. if (rendererData->currentConstantBufferOffset >= SDL_VULKAN_CONSTANT_BUFFER_DEFAULT_SIZE) {
  3412. uint32_t newConstantBufferIndex = (rendererData->currentConstantBufferIndex + 1);
  3413. // We need a new constant buffer
  3414. if (newConstantBufferIndex >= rendererData->numConstantBuffers[rendererData->currentCommandBufferIndex]) {
  3415. VULKAN_Buffer newConstantBuffer;
  3416. VkResult result = VULKAN_AllocateBuffer(rendererData,
  3417. SDL_VULKAN_CONSTANT_BUFFER_DEFAULT_SIZE,
  3418. VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
  3419. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  3420. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
  3421. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
  3422. &newConstantBuffer);
  3423. if (result != VK_SUCCESS) {
  3424. return false;
  3425. }
  3426. rendererData->numConstantBuffers[rendererData->currentCommandBufferIndex]++;
  3427. VULKAN_Buffer *newConstantBuffers = (VULKAN_Buffer *)SDL_realloc(rendererData->constantBuffers[rendererData->currentCommandBufferIndex],
  3428. sizeof(VULKAN_Buffer) * rendererData->numConstantBuffers[rendererData->currentCommandBufferIndex]);
  3429. newConstantBuffers[rendererData->numConstantBuffers[rendererData->currentCommandBufferIndex] - 1] = newConstantBuffer;
  3430. rendererData->constantBuffers[rendererData->currentCommandBufferIndex] = newConstantBuffers;
  3431. }
  3432. rendererData->currentConstantBufferIndex = newConstantBufferIndex;
  3433. rendererData->currentConstantBufferOffset = 0;
  3434. constantBufferOffset = 0;
  3435. constantBuffer = rendererData->constantBuffers[rendererData->currentCommandBufferIndex][rendererData->currentConstantBufferIndex].buffer;
  3436. }
  3437. SDL_memcpy(&rendererData->currentPipelineState->shader_constants, shader_constants, sizeof(*shader_constants));
  3438. // Upload constants to persistently mapped buffer
  3439. uint8_t *dst = (uint8_t *)rendererData->constantBuffers[rendererData->currentCommandBufferIndex][rendererData->currentConstantBufferIndex].mappedBufferPtr;
  3440. dst += constantBufferOffset;
  3441. SDL_memcpy(dst, &rendererData->currentPipelineState->shader_constants, sizeof(VULKAN_PixelShaderConstants));
  3442. }
  3443. // Allocate/update descriptor set with the bindings
  3444. descriptorSet = VULKAN_AllocateDescriptorSet(renderer, shader, descriptorSetLayout, constantBuffer, constantBufferOffset, numImages, imageViews, numSamplers, samplers);
  3445. if (descriptorSet == VK_NULL_HANDLE) {
  3446. return false;
  3447. }
  3448. // Bind the descriptor set with the sampler/UBO/image views
  3449. vkCmdBindDescriptorSets(rendererData->currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, rendererData->currentPipelineState->pipelineLayout,
  3450. 0, 1, &descriptorSet, 0, NULL);
  3451. return true;
  3452. }
  3453. static VkSampler VULKAN_GetSampler(VULKAN_RenderData *data, SDL_PixelFormat format, SDL_ScaleMode scale_mode, SDL_TextureAddressMode address_u, SDL_TextureAddressMode address_v)
  3454. {
  3455. Uint32 key = RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v);
  3456. SDL_assert(key < SDL_arraysize(data->samplers));
  3457. if (!data->samplers[key]) {
  3458. VkSamplerCreateInfo samplerCreateInfo = { 0 };
  3459. samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
  3460. samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
  3461. samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  3462. samplerCreateInfo.mipLodBias = 0.0f;
  3463. samplerCreateInfo.anisotropyEnable = VK_FALSE;
  3464. samplerCreateInfo.maxAnisotropy = 1.0f;
  3465. samplerCreateInfo.minLod = 0.0f;
  3466. samplerCreateInfo.maxLod = 1000.0f;
  3467. switch (scale_mode) {
  3468. case SDL_SCALEMODE_NEAREST:
  3469. samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
  3470. samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
  3471. break;
  3472. case SDL_SCALEMODE_PIXELART: // Uses linear sampling
  3473. case SDL_SCALEMODE_LINEAR:
  3474. if (format == SDL_PIXELFORMAT_INDEX8) {
  3475. // We'll do linear sampling in the shader
  3476. samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
  3477. samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
  3478. } else {
  3479. samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
  3480. samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
  3481. }
  3482. break;
  3483. default:
  3484. SDL_SetError("Unknown scale mode: %d", scale_mode);
  3485. return VK_NULL_HANDLE;
  3486. }
  3487. switch (address_u) {
  3488. case SDL_TEXTURE_ADDRESS_CLAMP:
  3489. samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  3490. break;
  3491. case SDL_TEXTURE_ADDRESS_WRAP:
  3492. samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  3493. break;
  3494. default:
  3495. SDL_SetError("Unknown texture address mode: %d", address_u);
  3496. return VK_NULL_HANDLE;
  3497. }
  3498. switch (address_v) {
  3499. case SDL_TEXTURE_ADDRESS_CLAMP:
  3500. samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  3501. break;
  3502. case SDL_TEXTURE_ADDRESS_WRAP:
  3503. samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  3504. break;
  3505. default:
  3506. SDL_SetError("Unknown texture address mode: %d", address_v);
  3507. return VK_NULL_HANDLE;
  3508. }
  3509. VkResult result = vkCreateSampler(data->device, &samplerCreateInfo, NULL, &data->samplers[key]);
  3510. if (result != VK_SUCCESS) {
  3511. SET_ERROR_CODE("vkCreateSampler()", result);
  3512. return VK_NULL_HANDLE;
  3513. }
  3514. }
  3515. return data->samplers[key];
  3516. }
  3517. static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix, VULKAN_DrawStateCache *stateCache)
  3518. {
  3519. SDL_Texture *texture = cmd->data.draw.texture;
  3520. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3521. VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
  3522. int numImageViews = 0;
  3523. VkImageView imageViews[2];
  3524. int numSamplers = 0;
  3525. VkSampler samplers[2];
  3526. VULKAN_PixelShaderConstants constants;
  3527. VkDescriptorSetLayout descriptorSetLayout = (textureData->descriptorSetLayoutYcbcr != VK_NULL_HANDLE) ? textureData->descriptorSetLayoutYcbcr : rendererData->descriptorSetLayout;
  3528. VkPipelineLayout pipelineLayout = (textureData->pipelineLayoutYcbcr != VK_NULL_HANDLE) ? textureData->pipelineLayoutYcbcr : rendererData->pipelineLayout;
  3529. VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants);
  3530. if (textureData->mainImage.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
  3531. bool stoppedRenderPass = false;
  3532. if (rendererData->currentRenderPass != VK_NULL_HANDLE) {
  3533. vkCmdEndRenderPass(rendererData->currentCommandBuffer);
  3534. rendererData->currentRenderPass = VK_NULL_HANDLE;
  3535. stoppedRenderPass = true;
  3536. }
  3537. VULKAN_RecordPipelineImageBarrier(rendererData,
  3538. VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  3539. VK_ACCESS_SHADER_READ_BIT,
  3540. VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  3541. VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  3542. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
  3543. textureData->mainImage.image,
  3544. &textureData->mainImage.imageLayout);
  3545. if (stoppedRenderPass) {
  3546. VULKAN_BeginRenderPass(rendererData, VK_ATTACHMENT_LOAD_OP_LOAD, NULL);
  3547. }
  3548. }
  3549. imageViews[numImageViews++] = textureData->mainImage.imageView;
  3550. samplers[numSamplers] = VULKAN_GetSampler(rendererData, texture->format, cmd->data.draw.texture_scale_mode, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
  3551. if (samplers[numSamplers] == VK_NULL_HANDLE) {
  3552. return false;
  3553. }
  3554. ++numSamplers;
  3555. if (texture->palette) {
  3556. VULKAN_PaletteData *palette = (VULKAN_PaletteData *)texture->palette->internal;
  3557. if (palette->image.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
  3558. bool stoppedRenderPass = false;
  3559. if (rendererData->currentRenderPass != VK_NULL_HANDLE) {
  3560. vkCmdEndRenderPass(rendererData->currentCommandBuffer);
  3561. rendererData->currentRenderPass = VK_NULL_HANDLE;
  3562. stoppedRenderPass = true;
  3563. }
  3564. VULKAN_RecordPipelineImageBarrier(rendererData,
  3565. VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  3566. VK_ACCESS_SHADER_READ_BIT,
  3567. VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  3568. VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  3569. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
  3570. palette->image.image,
  3571. &palette->image.imageLayout);
  3572. if (stoppedRenderPass) {
  3573. VULKAN_BeginRenderPass(rendererData, VK_ATTACHMENT_LOAD_OP_LOAD, NULL);
  3574. }
  3575. }
  3576. imageViews[numImageViews++] = palette->image.imageView;
  3577. samplers[numSamplers] = VULKAN_GetSampler(rendererData, SDL_PIXELFORMAT_UNKNOWN, SDL_SCALEMODE_NEAREST, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
  3578. if (samplers[numSamplers] == VK_NULL_HANDLE) {
  3579. return false;
  3580. }
  3581. ++numSamplers;
  3582. } else {
  3583. // We need a valid image view and sampler, but we know we're not going to reference them in the shader
  3584. imageViews[numImageViews++] = imageViews[0];
  3585. samplers[numSamplers++] = samplers[0];
  3586. }
  3587. return VULKAN_SetDrawState(renderer, cmd, pipelineLayout, descriptorSetLayout, &constants, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, numImageViews, imageViews, numSamplers, samplers, matrix, stateCache);
  3588. }
  3589. static void VULKAN_DrawPrimitives(SDL_Renderer *renderer, VkPrimitiveTopology primitiveTopology, const size_t vertexStart, const size_t vertexCount)
  3590. {
  3591. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3592. vkCmdDraw(rendererData->currentCommandBuffer, (uint32_t)vertexCount, 1, (uint32_t)vertexStart, 0);
  3593. }
  3594. static void VULKAN_InvalidateCachedState(SDL_Renderer *renderer)
  3595. {
  3596. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3597. rendererData->currentPipelineState = NULL;
  3598. rendererData->cliprectDirty = true;
  3599. }
  3600. static bool VULKAN_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
  3601. {
  3602. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3603. VkSurfaceTransformFlagBitsKHR currentRotation = VULKAN_GetRotationForCurrentRenderTarget(rendererData);
  3604. VULKAN_DrawStateCache stateCache;
  3605. SDL_memset(&stateCache, 0, sizeof(stateCache));
  3606. if (!rendererData->device) {
  3607. return SDL_SetError("Device lost and couldn't be recovered");
  3608. }
  3609. if(rendererData->currentViewportRotation != currentRotation) {
  3610. rendererData->currentViewportRotation = currentRotation;
  3611. rendererData->viewportDirty = true;
  3612. rendererData->cliprectDirty = true;
  3613. }
  3614. if (rendererData->recreateSwapchain) {
  3615. if (VULKAN_UpdateForWindowSizeChange(renderer) != VK_SUCCESS) {
  3616. return false;
  3617. }
  3618. rendererData->recreateSwapchain = false;
  3619. }
  3620. if (!VULKAN_UpdateVertexBuffer(renderer, vertices, vertsize, &stateCache)) {
  3621. return false;
  3622. }
  3623. while (cmd) {
  3624. switch (cmd->command) {
  3625. case SDL_RENDERCMD_SETDRAWCOLOR:
  3626. {
  3627. break; // this isn't currently used in this render backend.
  3628. }
  3629. case SDL_RENDERCMD_SETVIEWPORT:
  3630. {
  3631. SDL_Rect *viewport = &rendererData->currentViewport;
  3632. if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) {
  3633. SDL_copyp(viewport, &cmd->data.viewport.rect);
  3634. rendererData->viewportDirty = true;
  3635. rendererData->cliprectDirty = true;
  3636. }
  3637. break;
  3638. }
  3639. case SDL_RENDERCMD_SETCLIPRECT:
  3640. {
  3641. const SDL_Rect *rect = &cmd->data.cliprect.rect;
  3642. if (rendererData->currentCliprectEnabled != cmd->data.cliprect.enabled) {
  3643. rendererData->currentCliprectEnabled = cmd->data.cliprect.enabled;
  3644. rendererData->cliprectDirty = true;
  3645. }
  3646. if (SDL_memcmp(&rendererData->currentCliprect, rect, sizeof(*rect)) != 0) {
  3647. SDL_copyp(&rendererData->currentCliprect, rect);
  3648. rendererData->cliprectDirty = true;
  3649. }
  3650. break;
  3651. }
  3652. case SDL_RENDERCMD_CLEAR:
  3653. {
  3654. bool convert_color = SDL_RenderingLinearSpace(renderer);
  3655. SDL_FColor color = cmd->data.color.color;
  3656. if (convert_color) {
  3657. SDL_ConvertToLinear(&color);
  3658. }
  3659. color.r *= cmd->data.color.color_scale;
  3660. color.g *= cmd->data.color.color_scale;
  3661. color.b *= cmd->data.color.color_scale;
  3662. VkClearColorValue clearColor;
  3663. clearColor.float32[0] = color.r;
  3664. clearColor.float32[1] = color.g;
  3665. clearColor.float32[2] = color.b;
  3666. clearColor.float32[3] = color.a;
  3667. VULKAN_ActivateCommandBuffer(renderer, VK_ATTACHMENT_LOAD_OP_CLEAR, &clearColor, &stateCache);
  3668. break;
  3669. }
  3670. case SDL_RENDERCMD_DRAW_LINES:
  3671. {
  3672. size_t count = cmd->data.draw.count;
  3673. const size_t first = cmd->data.draw.first;
  3674. const size_t start = first / sizeof(VULKAN_VertexPositionColor);
  3675. const VULKAN_VertexPositionColor *verts = (VULKAN_VertexPositionColor *)(((Uint8 *)vertices) + first);
  3676. bool have_point_draw_state = false;
  3677. // Add the final point in the line
  3678. size_t line_start = 0;
  3679. size_t line_end = line_start + count - 1;
  3680. if (verts[line_start].pos[0] != verts[line_end].pos[0] || verts[line_start].pos[1] != verts[line_end].pos[1]) {
  3681. VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
  3682. VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, start + line_end, 1);
  3683. have_point_draw_state = true;
  3684. }
  3685. if (count > 2) {
  3686. // joined lines cannot be grouped
  3687. VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, NULL, 0, NULL, NULL, &stateCache);
  3688. VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, start, count);
  3689. } else {
  3690. // let's group non joined lines
  3691. SDL_RenderCommand *finalcmd = cmd;
  3692. SDL_RenderCommand *nextcmd;
  3693. float thiscolorscale = cmd->data.draw.color_scale;
  3694. SDL_BlendMode thisblend = cmd->data.draw.blend;
  3695. for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
  3696. const SDL_RenderCommandType nextcmdtype = nextcmd->command;
  3697. if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
  3698. if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
  3699. // The vertex data has the draw color built in, ignore this
  3700. continue;
  3701. }
  3702. break; // can't go any further on this draw call, different render command up next.
  3703. } else if (nextcmd->data.draw.count != 2) {
  3704. break; // can't go any further on this draw call, those are joined lines
  3705. } else if (nextcmd->data.draw.blend != thisblend ||
  3706. nextcmd->data.draw.color_scale != thiscolorscale) {
  3707. break; // can't go any further on this draw call, different blendmode copy up next.
  3708. } else {
  3709. finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
  3710. // Add the final point in the line
  3711. line_start = count;
  3712. line_end = line_start + nextcmd->data.draw.count - 1;
  3713. if (verts[line_start].pos[0] != verts[line_end].pos[0] || verts[line_start].pos[1] != verts[line_end].pos[1]) {
  3714. if (!have_point_draw_state) {
  3715. VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
  3716. have_point_draw_state = true;
  3717. }
  3718. VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, start + line_end, 1);
  3719. }
  3720. count += nextcmd->data.draw.count;
  3721. }
  3722. }
  3723. VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
  3724. VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, start, count);
  3725. cmd = finalcmd; // skip any copy commands we just combined in here.
  3726. }
  3727. break;
  3728. }
  3729. case SDL_RENDERCMD_FILL_RECTS: // unused
  3730. break;
  3731. case SDL_RENDERCMD_COPY: // unused
  3732. break;
  3733. case SDL_RENDERCMD_COPY_EX: // unused
  3734. break;
  3735. case SDL_RENDERCMD_DRAW_POINTS:
  3736. case SDL_RENDERCMD_GEOMETRY:
  3737. {
  3738. /* as long as we have the same copy command in a row, with the
  3739. same texture, we can combine them all into a single draw call. */
  3740. float thiscolorscale = cmd->data.draw.color_scale;
  3741. SDL_Texture *thistexture = cmd->data.draw.texture;
  3742. SDL_BlendMode thisblend = cmd->data.draw.blend;
  3743. SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
  3744. SDL_TextureAddressMode thisaddressmode_u = cmd->data.draw.texture_address_mode_u;
  3745. SDL_TextureAddressMode thisaddressmode_v = cmd->data.draw.texture_address_mode_v;
  3746. const SDL_RenderCommandType thiscmdtype = cmd->command;
  3747. SDL_RenderCommand *finalcmd = cmd;
  3748. SDL_RenderCommand *nextcmd;
  3749. size_t count = cmd->data.draw.count;
  3750. const size_t first = cmd->data.draw.first;
  3751. const size_t start = first / sizeof(VULKAN_VertexPositionColor);
  3752. for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
  3753. const SDL_RenderCommandType nextcmdtype = nextcmd->command;
  3754. if (nextcmdtype != thiscmdtype) {
  3755. if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
  3756. // The vertex data has the draw color built in, ignore this
  3757. continue;
  3758. }
  3759. break; // can't go any further on this draw call, different render command up next.
  3760. } else if (nextcmd->data.draw.texture != thistexture ||
  3761. nextcmd->data.draw.texture_scale_mode != thisscalemode ||
  3762. nextcmd->data.draw.texture_address_mode_u != thisaddressmode_u ||
  3763. nextcmd->data.draw.texture_address_mode_v != thisaddressmode_v ||
  3764. nextcmd->data.draw.blend != thisblend ||
  3765. nextcmd->data.draw.color_scale != thiscolorscale) {
  3766. break; // can't go any further on this draw call, different texture/blendmode copy up next.
  3767. } else {
  3768. finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
  3769. count += nextcmd->data.draw.count;
  3770. }
  3771. }
  3772. if (thiscmdtype == SDL_RENDERCMD_GEOMETRY) {
  3773. if (thistexture) {
  3774. VULKAN_SetCopyState(renderer, cmd, NULL, &stateCache);
  3775. } else {
  3776. VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
  3777. }
  3778. VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, start, count);
  3779. } else {
  3780. VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
  3781. VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, start, count);
  3782. }
  3783. cmd = finalcmd; // skip any copy commands we just combined in here.
  3784. break;
  3785. }
  3786. case SDL_RENDERCMD_NO_OP:
  3787. break;
  3788. }
  3789. cmd = cmd->next;
  3790. }
  3791. return true;
  3792. }
  3793. static SDL_Surface *VULKAN_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
  3794. {
  3795. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3796. VkImage backBuffer;
  3797. VkImageLayout *imageLayout;
  3798. VULKAN_Buffer readbackBuffer;
  3799. VkDeviceSize pixelSize;
  3800. VkDeviceSize length;
  3801. VkDeviceSize readbackBufferSize;
  3802. VkFormat vkFormat;
  3803. SDL_Surface *output;
  3804. VULKAN_EnsureCommandBuffer(rendererData);
  3805. // Stop any outstanding renderpass if open
  3806. if (rendererData->currentRenderPass != VK_NULL_HANDLE) {
  3807. vkCmdEndRenderPass(rendererData->currentCommandBuffer);
  3808. rendererData->currentRenderPass = VK_NULL_HANDLE;
  3809. }
  3810. if (rendererData->textureRenderTarget) {
  3811. backBuffer = rendererData->textureRenderTarget->mainImage.image;
  3812. imageLayout = &rendererData->textureRenderTarget->mainImage.imageLayout;
  3813. vkFormat = rendererData->textureRenderTarget->mainImage.format;
  3814. } else {
  3815. backBuffer = rendererData->swapchainImages[rendererData->currentSwapchainImageIndex];
  3816. imageLayout = &rendererData->swapchainImageLayouts[rendererData->currentSwapchainImageIndex];
  3817. vkFormat = rendererData->surfaceFormat.format;
  3818. }
  3819. pixelSize = VULKAN_GetBytesPerPixel(vkFormat, 0);
  3820. length = rect->w * pixelSize;
  3821. readbackBufferSize = length * rect->h;
  3822. if (VULKAN_AllocateBuffer(rendererData, readbackBufferSize,
  3823. VK_BUFFER_USAGE_TRANSFER_DST_BIT,
  3824. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
  3825. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
  3826. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
  3827. &readbackBuffer) != VK_SUCCESS) {
  3828. return NULL;
  3829. }
  3830. // Make sure the source is in the correct resource state
  3831. VULKAN_RecordPipelineImageBarrier(rendererData,
  3832. VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
  3833. VK_ACCESS_TRANSFER_READ_BIT,
  3834. VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  3835. VK_PIPELINE_STAGE_TRANSFER_BIT,
  3836. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  3837. backBuffer,
  3838. imageLayout);
  3839. // Copy the image to the readback buffer
  3840. VkBufferImageCopy region;
  3841. region.bufferOffset = 0;
  3842. region.bufferRowLength = 0;
  3843. region.bufferImageHeight = 0;
  3844. region.imageSubresource.baseArrayLayer = 0;
  3845. region.imageSubresource.layerCount = 1;
  3846. region.imageSubresource.mipLevel = 0;
  3847. region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  3848. region.imageOffset.x = rect->x;
  3849. region.imageOffset.y = rect->y;
  3850. region.imageOffset.z = 0;
  3851. region.imageExtent.width = rect->w;
  3852. region.imageExtent.height = rect->h;
  3853. region.imageExtent.depth = 1;
  3854. vkCmdCopyImageToBuffer(rendererData->currentCommandBuffer, backBuffer, *imageLayout, readbackBuffer.buffer, 1, &region);
  3855. // We need to issue the command list for the copy to finish
  3856. VULKAN_IssueBatch(rendererData);
  3857. // Transition the render target back to a render target
  3858. VULKAN_RecordPipelineImageBarrier(rendererData,
  3859. VK_ACCESS_TRANSFER_WRITE_BIT,
  3860. VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
  3861. VK_PIPELINE_STAGE_TRANSFER_BIT,
  3862. VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
  3863. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  3864. backBuffer,
  3865. imageLayout);
  3866. output = SDL_DuplicatePixels(
  3867. rect->w, rect->h,
  3868. VULKAN_VkFormatToSDLPixelFormat(vkFormat),
  3869. renderer->target ? renderer->target->colorspace : renderer->output_colorspace,
  3870. readbackBuffer.mappedBufferPtr,
  3871. (int)length);
  3872. VULKAN_DestroyBuffer(rendererData, &readbackBuffer);
  3873. return output;
  3874. }
  3875. static bool VULKAN_AddVulkanRenderSemaphores(SDL_Renderer *renderer, Uint32 wait_stage_mask, Sint64 wait_semaphore, Sint64 signal_semaphore)
  3876. {
  3877. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3878. if (wait_semaphore) {
  3879. if (rendererData->waitRenderSemaphoreCount == rendererData->waitRenderSemaphoreMax) {
  3880. // Allocate an additional one at the end for the normal present wait
  3881. VkPipelineStageFlags *waitDestStageMasks = (VkPipelineStageFlags *)SDL_realloc(rendererData->waitDestStageMasks, (rendererData->waitRenderSemaphoreMax + 2) * sizeof(*waitDestStageMasks));
  3882. if (!waitDestStageMasks) {
  3883. return false;
  3884. }
  3885. rendererData->waitDestStageMasks = waitDestStageMasks;
  3886. VkSemaphore *semaphores = (VkSemaphore *)SDL_realloc(rendererData->waitRenderSemaphores, (rendererData->waitRenderSemaphoreMax + 2) * sizeof(*semaphores));
  3887. if (!semaphores) {
  3888. return false;
  3889. }
  3890. rendererData->waitRenderSemaphores = semaphores;
  3891. ++rendererData->waitRenderSemaphoreMax;
  3892. }
  3893. rendererData->waitDestStageMasks[rendererData->waitRenderSemaphoreCount] = wait_stage_mask;
  3894. rendererData->waitRenderSemaphores[rendererData->waitRenderSemaphoreCount] = (VkSemaphore)wait_semaphore;
  3895. ++rendererData->waitRenderSemaphoreCount;
  3896. }
  3897. if (signal_semaphore) {
  3898. if (rendererData->signalRenderSemaphoreCount == rendererData->signalRenderSemaphoreMax) {
  3899. // Allocate an additional one at the end for the normal present signal
  3900. VkSemaphore *semaphores = (VkSemaphore *)SDL_realloc(rendererData->signalRenderSemaphores, (rendererData->signalRenderSemaphoreMax + 2) * sizeof(*semaphores));
  3901. if (!semaphores) {
  3902. return false;
  3903. }
  3904. rendererData->signalRenderSemaphores = semaphores;
  3905. ++rendererData->signalRenderSemaphoreMax;
  3906. }
  3907. rendererData->signalRenderSemaphores[rendererData->signalRenderSemaphoreCount] = (VkSemaphore)signal_semaphore;
  3908. ++rendererData->signalRenderSemaphoreCount;
  3909. }
  3910. return true;
  3911. }
  3912. static bool VULKAN_RenderPresent(SDL_Renderer *renderer)
  3913. {
  3914. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  3915. VkResult result = VK_SUCCESS;
  3916. if (!rendererData->device) {
  3917. return SDL_SetError("Device lost and couldn't be recovered");
  3918. }
  3919. if (rendererData->currentCommandBuffer) {
  3920. rendererData->currentPipelineState = VK_NULL_HANDLE;
  3921. rendererData->viewportDirty = true;
  3922. VULKAN_RecordPipelineImageBarrier(rendererData,
  3923. VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  3924. VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
  3925. VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  3926. VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  3927. VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
  3928. rendererData->swapchainImages[rendererData->currentSwapchainImageIndex],
  3929. &rendererData->swapchainImageLayouts[rendererData->currentSwapchainImageIndex]);
  3930. vkEndCommandBuffer(rendererData->currentCommandBuffer);
  3931. result = vkResetFences(rendererData->device, 1, &rendererData->fences[rendererData->currentCommandBufferIndex]);
  3932. if (result != VK_SUCCESS) {
  3933. SET_ERROR_CODE("vkResetFences()", result);
  3934. return false;
  3935. }
  3936. VkPipelineStageFlags waitDestStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
  3937. VkSubmitInfo submitInfo = { 0 };
  3938. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  3939. if (rendererData->waitRenderSemaphoreCount > 0) {
  3940. Uint32 additionalSemaphoreCount = (rendererData->currentImageAvailableSemaphore != VK_NULL_HANDLE) ? 1 : 0;
  3941. submitInfo.waitSemaphoreCount = rendererData->waitRenderSemaphoreCount + additionalSemaphoreCount;
  3942. if (additionalSemaphoreCount > 0) {
  3943. rendererData->waitRenderSemaphores[rendererData->waitRenderSemaphoreCount] = rendererData->currentImageAvailableSemaphore;
  3944. rendererData->waitDestStageMasks[rendererData->waitRenderSemaphoreCount] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
  3945. }
  3946. submitInfo.pWaitSemaphores = rendererData->waitRenderSemaphores;
  3947. submitInfo.pWaitDstStageMask = rendererData->waitDestStageMasks;
  3948. rendererData->waitRenderSemaphoreCount = 0;
  3949. } else if (rendererData->currentImageAvailableSemaphore != VK_NULL_HANDLE) {
  3950. submitInfo.waitSemaphoreCount = 1;
  3951. submitInfo.pWaitSemaphores = &rendererData->currentImageAvailableSemaphore;
  3952. submitInfo.pWaitDstStageMask = &waitDestStageMask;
  3953. }
  3954. submitInfo.commandBufferCount = 1;
  3955. submitInfo.pCommandBuffers = &rendererData->currentCommandBuffer;
  3956. if (rendererData->signalRenderSemaphoreCount > 0) {
  3957. submitInfo.signalSemaphoreCount = rendererData->signalRenderSemaphoreCount + 1;
  3958. rendererData->signalRenderSemaphores[rendererData->signalRenderSemaphoreCount] = rendererData->renderingFinishedSemaphores[rendererData->currentCommandBufferIndex];
  3959. submitInfo.pSignalSemaphores = rendererData->signalRenderSemaphores;
  3960. rendererData->signalRenderSemaphoreCount = 0;
  3961. } else {
  3962. submitInfo.signalSemaphoreCount = 1;
  3963. submitInfo.pSignalSemaphores = &rendererData->renderingFinishedSemaphores[rendererData->currentCommandBufferIndex];
  3964. }
  3965. result = vkQueueSubmit(rendererData->graphicsQueue, 1, &submitInfo, rendererData->fences[rendererData->currentCommandBufferIndex]);
  3966. if (result != VK_SUCCESS) {
  3967. if (result == VK_ERROR_DEVICE_LOST) {
  3968. if (VULKAN_HandleDeviceLost(renderer)) {
  3969. SDL_SetError("Present failed, device lost");
  3970. } else {
  3971. // Recovering from device lost failed, error is already set
  3972. }
  3973. } else {
  3974. SET_ERROR_CODE("vkQueueSubmit()", result);
  3975. }
  3976. return false;
  3977. }
  3978. rendererData->currentCommandBuffer = VK_NULL_HANDLE;
  3979. rendererData->currentImageAvailableSemaphore = VK_NULL_HANDLE;
  3980. VkPresentInfoKHR presentInfo = { 0 };
  3981. presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  3982. presentInfo.waitSemaphoreCount = 1;
  3983. presentInfo.pWaitSemaphores = &rendererData->renderingFinishedSemaphores[rendererData->currentCommandBufferIndex];
  3984. presentInfo.swapchainCount = 1;
  3985. presentInfo.pSwapchains = &rendererData->swapchain;
  3986. presentInfo.pImageIndices = &rendererData->currentSwapchainImageIndex;
  3987. result = vkQueuePresentKHR(rendererData->presentQueue, &presentInfo);
  3988. if ((result != VK_SUCCESS) && (result != VK_ERROR_OUT_OF_DATE_KHR) && (result != VK_ERROR_SURFACE_LOST_KHR) && (result != VK_SUBOPTIMAL_KHR )) {
  3989. SET_ERROR_CODE("vkQueuePresentKHR()", result);
  3990. return false;
  3991. }
  3992. rendererData->currentCommandBufferIndex = ( rendererData->currentCommandBufferIndex + 1 ) % rendererData->swapchainImageCount;
  3993. // Wait for previous time this command buffer was submitted, will be N frames ago
  3994. result = vkWaitForFences(rendererData->device, 1, &rendererData->fences[rendererData->currentCommandBufferIndex], VK_TRUE, UINT64_MAX);
  3995. if (result != VK_SUCCESS) {
  3996. if (result == VK_ERROR_DEVICE_LOST) {
  3997. if (VULKAN_HandleDeviceLost(renderer)) {
  3998. SDL_SetError("Present failed, device lost");
  3999. } else {
  4000. // Recovering from device lost failed, error is already set
  4001. }
  4002. } else {
  4003. SET_ERROR_CODE("vkWaitForFences()", result);
  4004. }
  4005. return false;
  4006. }
  4007. VULKAN_AcquireNextSwapchainImage(renderer);
  4008. }
  4009. return true;
  4010. }
  4011. static bool VULKAN_SetVSync(SDL_Renderer *renderer, const int vsync)
  4012. {
  4013. VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
  4014. switch (vsync) {
  4015. case -1:
  4016. case 0:
  4017. case 1:
  4018. // Supported
  4019. break;
  4020. default:
  4021. return SDL_Unsupported();
  4022. }
  4023. if (vsync != rendererData->vsync) {
  4024. rendererData->vsync = vsync;
  4025. rendererData->recreateSwapchain = true;
  4026. }
  4027. return true;
  4028. }
  4029. static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
  4030. {
  4031. VULKAN_RenderData *rendererData;
  4032. SDL_SetupRendererColorspace(renderer, create_props);
  4033. if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
  4034. renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR
  4035. /*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) {
  4036. return SDL_SetError("Unsupported output colorspace");
  4037. }
  4038. rendererData = (VULKAN_RenderData *)SDL_calloc(1, sizeof(*rendererData));
  4039. if (!rendererData) {
  4040. return false;
  4041. }
  4042. rendererData->identity = MatrixIdentity();
  4043. rendererData->identitySwizzle.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  4044. rendererData->identitySwizzle.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  4045. rendererData->identitySwizzle.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  4046. rendererData->identitySwizzle.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  4047. // Save the create props in case we need to recreate on device lost
  4048. rendererData->create_props = SDL_CreateProperties();
  4049. if (!SDL_CopyProperties(create_props, rendererData->create_props)) {
  4050. SDL_free(rendererData);
  4051. return false;
  4052. }
  4053. renderer->WindowEvent = VULKAN_WindowEvent;
  4054. renderer->SupportsBlendMode = VULKAN_SupportsBlendMode;
  4055. renderer->CreatePalette = VULKAN_CreatePalette;
  4056. renderer->UpdatePalette = VULKAN_UpdatePalette;
  4057. renderer->DestroyPalette = VULKAN_DestroyPalette;
  4058. renderer->CreateTexture = VULKAN_CreateTexture;
  4059. renderer->UpdateTexture = VULKAN_UpdateTexture;
  4060. #ifdef SDL_HAVE_YUV
  4061. renderer->UpdateTextureYUV = VULKAN_UpdateTextureYUV;
  4062. renderer->UpdateTextureNV = VULKAN_UpdateTextureNV;
  4063. #endif
  4064. renderer->LockTexture = VULKAN_LockTexture;
  4065. renderer->UnlockTexture = VULKAN_UnlockTexture;
  4066. renderer->SetRenderTarget = VULKAN_SetRenderTarget;
  4067. renderer->QueueSetViewport = VULKAN_QueueNoOp;
  4068. renderer->QueueSetDrawColor = VULKAN_QueueNoOp;
  4069. renderer->QueueDrawPoints = VULKAN_QueueDrawPoints;
  4070. renderer->QueueDrawLines = VULKAN_QueueDrawPoints; // lines and points queue vertices the same way.
  4071. renderer->QueueGeometry = VULKAN_QueueGeometry;
  4072. renderer->InvalidateCachedState = VULKAN_InvalidateCachedState;
  4073. renderer->RunCommandQueue = VULKAN_RunCommandQueue;
  4074. renderer->RenderReadPixels = VULKAN_RenderReadPixels;
  4075. renderer->AddVulkanRenderSemaphores = VULKAN_AddVulkanRenderSemaphores;
  4076. renderer->RenderPresent = VULKAN_RenderPresent;
  4077. renderer->DestroyTexture = VULKAN_DestroyTexture;
  4078. renderer->DestroyRenderer = VULKAN_DestroyRenderer;
  4079. renderer->SetVSync = VULKAN_SetVSync;
  4080. renderer->internal = rendererData;
  4081. VULKAN_InvalidateCachedState(renderer);
  4082. renderer->name = VULKAN_RenderDriver.name;
  4083. SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 16384);
  4084. /* HACK: make sure the SDL_Renderer references the SDL_Window data now, in
  4085. * order to give init functions access to the underlying window handle:
  4086. */
  4087. renderer->window = window;
  4088. // Initialize Vulkan resources
  4089. if (VULKAN_CreateDeviceResources(renderer, create_props) != VK_SUCCESS) {
  4090. return false;
  4091. }
  4092. if (VULKAN_CreateWindowSizeDependentResources(renderer) != VK_SUCCESS) {
  4093. return false;
  4094. }
  4095. for (int i = 0; i < SDL_arraysize(vk_format_map); i++) {
  4096. VkImageFormatProperties properties;
  4097. if (vkGetPhysicalDeviceImageFormatProperties(rendererData->physicalDevice,
  4098. vk_format_map[i].unorm,
  4099. VK_IMAGE_TYPE_2D,
  4100. VK_IMAGE_TILING_OPTIMAL,
  4101. VK_IMAGE_USAGE_SAMPLED_BIT,
  4102. 0,
  4103. &properties) != VK_SUCCESS) {
  4104. continue;
  4105. }
  4106. if (vkGetPhysicalDeviceImageFormatProperties(rendererData->physicalDevice,
  4107. vk_format_map[i].srgb,
  4108. VK_IMAGE_TYPE_2D,
  4109. VK_IMAGE_TILING_OPTIMAL,
  4110. VK_IMAGE_USAGE_SAMPLED_BIT,
  4111. 0,
  4112. &properties) != VK_SUCCESS) {
  4113. continue;
  4114. }
  4115. SDL_AddSupportedTextureFormat(renderer, vk_format_map[i].sdl);
  4116. }
  4117. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
  4118. #ifdef SDL_HAVE_YUV
  4119. if (rendererData->supportsKHRSamplerYCbCrConversion) {
  4120. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
  4121. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
  4122. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
  4123. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
  4124. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);
  4125. }
  4126. #endif
  4127. return true;
  4128. }
  4129. SDL_RenderDriver VULKAN_RenderDriver = {
  4130. VULKAN_CreateRenderer, "vulkan"
  4131. };
  4132. #endif // SDL_VIDEO_RENDER_VULKAN