SDL_gpu_vulkan.c 444 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2025 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_GPU_VULKAN
  20. // Needed for VK_KHR_portability_subset
  21. #define VK_ENABLE_BETA_EXTENSIONS
  22. #define VK_NO_PROTOTYPES
  23. #include "../../video/khronos/vulkan/vulkan.h"
  24. #include <SDL3/SDL_vulkan.h>
  25. #include "../SDL_sysgpu.h"
  26. #define VULKAN_INTERNAL_clamp(val, min, max) SDL_max(min, SDL_min(val, max))
  27. // Global Vulkan Loader Entry Points
  28. static PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
  29. #define VULKAN_GLOBAL_FUNCTION(name) \
  30. static PFN_##name name = NULL;
  31. #include "SDL_gpu_vulkan_vkfuncs.h"
  32. typedef struct VulkanExtensions
  33. {
  34. // These extensions are required!
  35. // Globally supported
  36. Uint8 KHR_swapchain;
  37. // Core since 1.1, needed for negative VkViewport::height
  38. Uint8 KHR_maintenance1;
  39. // These extensions are optional!
  40. // Core since 1.2, but requires annoying paperwork to implement
  41. Uint8 KHR_driver_properties;
  42. // Only required for special implementations (i.e. MoltenVK)
  43. Uint8 KHR_portability_subset;
  44. // Only required for decoding HDR ASTC textures
  45. Uint8 EXT_texture_compression_astc_hdr;
  46. } VulkanExtensions;
  47. // Defines
  48. #define SMALL_ALLOCATION_THRESHOLD 2097152 // 2 MiB
  49. #define SMALL_ALLOCATION_SIZE 16777216 // 16 MiB
  50. #define LARGE_ALLOCATION_INCREMENT 67108864 // 64 MiB
  51. #define MAX_UBO_SECTION_SIZE 4096 // 4 KiB
  52. #define DESCRIPTOR_POOL_SIZE 128
  53. #define WINDOW_PROPERTY_DATA "SDL_GPUVulkanWindowPropertyData"
  54. #define IDENTITY_SWIZZLE \
  55. { \
  56. VK_COMPONENT_SWIZZLE_IDENTITY, \
  57. VK_COMPONENT_SWIZZLE_IDENTITY, \
  58. VK_COMPONENT_SWIZZLE_IDENTITY, \
  59. VK_COMPONENT_SWIZZLE_IDENTITY \
  60. }
  61. #define NULL_DESC_LAYOUT (VkDescriptorSetLayout)0
  62. #define NULL_PIPELINE_LAYOUT (VkPipelineLayout)0
  63. #define NULL_RENDER_PASS (SDL_GPURenderPass *)0
  64. #define EXPAND_ELEMENTS_IF_NEEDED(arr, initialValue, type) \
  65. do { \
  66. if (arr->count == arr->capacity) { \
  67. if (arr->capacity == 0) { \
  68. arr->capacity = initialValue; \
  69. } else { \
  70. arr->capacity *= 2; \
  71. } \
  72. arr->elements = (type *)SDL_realloc( \
  73. arr->elements, \
  74. arr->capacity * sizeof(type)); \
  75. } \
  76. } while (0)
  77. #define MOVE_ARRAY_CONTENTS_AND_RESET(i, dstArr, dstCount, srcArr, srcCount) \
  78. do { \
  79. for ((i) = 0; (i) < (srcCount); (i) += 1) { \
  80. (dstArr)[i] = (srcArr)[i]; \
  81. } \
  82. (dstCount) = (srcCount); \
  83. (srcCount) = 0; \
  84. while (0)
  85. // Conversions
  86. static const Uint8 DEVICE_PRIORITY_HIGHPERFORMANCE[] = {
  87. 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
  88. 3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
  89. 4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
  90. 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
  91. 1 // VK_PHYSICAL_DEVICE_TYPE_CPU
  92. };
  93. static const Uint8 DEVICE_PRIORITY_LOWPOWER[] = {
  94. 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
  95. 4, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
  96. 3, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
  97. 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
  98. 1 // VK_PHYSICAL_DEVICE_TYPE_CPU
  99. };
  100. static VkPresentModeKHR SDLToVK_PresentMode[] = {
  101. VK_PRESENT_MODE_FIFO_KHR,
  102. VK_PRESENT_MODE_IMMEDIATE_KHR,
  103. VK_PRESENT_MODE_MAILBOX_KHR
  104. };
  105. static VkFormat SDLToVK_TextureFormat[] = {
  106. VK_FORMAT_UNDEFINED, // INVALID
  107. VK_FORMAT_R8_UNORM, // A8_UNORM
  108. VK_FORMAT_R8_UNORM, // R8_UNORM
  109. VK_FORMAT_R8G8_UNORM, // R8G8_UNORM
  110. VK_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
  111. VK_FORMAT_R16_UNORM, // R16_UNORM
  112. VK_FORMAT_R16G16_UNORM, // R16G16_UNORM
  113. VK_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
  114. VK_FORMAT_A2B10G10R10_UNORM_PACK32, // R10G10B10A2_UNORM
  115. VK_FORMAT_R5G6B5_UNORM_PACK16, // B5G6R5_UNORM
  116. VK_FORMAT_A1R5G5B5_UNORM_PACK16, // B5G5R5A1_UNORM
  117. VK_FORMAT_B4G4R4A4_UNORM_PACK16, // B4G4R4A4_UNORM
  118. VK_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
  119. VK_FORMAT_BC1_RGBA_UNORM_BLOCK, // BC1_UNORM
  120. VK_FORMAT_BC2_UNORM_BLOCK, // BC2_UNORM
  121. VK_FORMAT_BC3_UNORM_BLOCK, // BC3_UNORM
  122. VK_FORMAT_BC4_UNORM_BLOCK, // BC4_UNORM
  123. VK_FORMAT_BC5_UNORM_BLOCK, // BC5_UNORM
  124. VK_FORMAT_BC7_UNORM_BLOCK, // BC7_UNORM
  125. VK_FORMAT_BC6H_SFLOAT_BLOCK, // BC6H_FLOAT
  126. VK_FORMAT_BC6H_UFLOAT_BLOCK, // BC6H_UFLOAT
  127. VK_FORMAT_R8_SNORM, // R8_SNORM
  128. VK_FORMAT_R8G8_SNORM, // R8G8_SNORM
  129. VK_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
  130. VK_FORMAT_R16_SNORM, // R16_SNORM
  131. VK_FORMAT_R16G16_SNORM, // R16G16_SNORM
  132. VK_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
  133. VK_FORMAT_R16_SFLOAT, // R16_FLOAT
  134. VK_FORMAT_R16G16_SFLOAT, // R16G16_FLOAT
  135. VK_FORMAT_R16G16B16A16_SFLOAT, // R16G16B16A16_FLOAT
  136. VK_FORMAT_R32_SFLOAT, // R32_FLOAT
  137. VK_FORMAT_R32G32_SFLOAT, // R32G32_FLOAT
  138. VK_FORMAT_R32G32B32A32_SFLOAT, // R32G32B32A32_FLOAT
  139. VK_FORMAT_B10G11R11_UFLOAT_PACK32, // R11G11B10_UFLOAT
  140. VK_FORMAT_R8_UINT, // R8_UINT
  141. VK_FORMAT_R8G8_UINT, // R8G8_UINT
  142. VK_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
  143. VK_FORMAT_R16_UINT, // R16_UINT
  144. VK_FORMAT_R16G16_UINT, // R16G16_UINT
  145. VK_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
  146. VK_FORMAT_R32_UINT, // R32_UINT
  147. VK_FORMAT_R32G32_UINT, // R32G32_UINT
  148. VK_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
  149. VK_FORMAT_R8_SINT, // R8_INT
  150. VK_FORMAT_R8G8_SINT, // R8G8_INT
  151. VK_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
  152. VK_FORMAT_R16_SINT, // R16_INT
  153. VK_FORMAT_R16G16_SINT, // R16G16_INT
  154. VK_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
  155. VK_FORMAT_R32_SINT, // R32_INT
  156. VK_FORMAT_R32G32_SINT, // R32G32_INT
  157. VK_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
  158. VK_FORMAT_R8G8B8A8_SRGB, // R8G8B8A8_UNORM_SRGB
  159. VK_FORMAT_B8G8R8A8_SRGB, // B8G8R8A8_UNORM_SRGB
  160. VK_FORMAT_BC1_RGBA_SRGB_BLOCK, // BC1_UNORM_SRGB
  161. VK_FORMAT_BC2_SRGB_BLOCK, // BC3_UNORM_SRGB
  162. VK_FORMAT_BC3_SRGB_BLOCK, // BC3_UNORM_SRGB
  163. VK_FORMAT_BC7_SRGB_BLOCK, // BC7_UNORM_SRGB
  164. VK_FORMAT_D16_UNORM, // D16_UNORM
  165. VK_FORMAT_X8_D24_UNORM_PACK32, // D24_UNORM
  166. VK_FORMAT_D32_SFLOAT, // D32_FLOAT
  167. VK_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT
  168. VK_FORMAT_D32_SFLOAT_S8_UINT, // D32_FLOAT_S8_UINT
  169. VK_FORMAT_ASTC_4x4_UNORM_BLOCK, // ASTC_4x4_UNORM
  170. VK_FORMAT_ASTC_5x4_UNORM_BLOCK, // ASTC_5x4_UNORM
  171. VK_FORMAT_ASTC_5x5_UNORM_BLOCK, // ASTC_5x5_UNORM
  172. VK_FORMAT_ASTC_6x5_UNORM_BLOCK, // ASTC_6x5_UNORM
  173. VK_FORMAT_ASTC_6x6_UNORM_BLOCK, // ASTC_6x6_UNORM
  174. VK_FORMAT_ASTC_8x5_UNORM_BLOCK, // ASTC_8x5_UNORM
  175. VK_FORMAT_ASTC_8x6_UNORM_BLOCK, // ASTC_8x6_UNORM
  176. VK_FORMAT_ASTC_8x8_UNORM_BLOCK, // ASTC_8x8_UNORM
  177. VK_FORMAT_ASTC_10x5_UNORM_BLOCK, // ASTC_10x5_UNORM
  178. VK_FORMAT_ASTC_10x6_UNORM_BLOCK, // ASTC_10x6_UNORM
  179. VK_FORMAT_ASTC_10x8_UNORM_BLOCK, // ASTC_10x8_UNORM
  180. VK_FORMAT_ASTC_10x10_UNORM_BLOCK, // ASTC_10x10_UNORM
  181. VK_FORMAT_ASTC_12x10_UNORM_BLOCK, // ASTC_12x10_UNORM
  182. VK_FORMAT_ASTC_12x12_UNORM_BLOCK, // ASTC_12x12_UNORM
  183. VK_FORMAT_ASTC_4x4_SRGB_BLOCK, // ASTC_4x4_UNORM_SRGB
  184. VK_FORMAT_ASTC_5x4_SRGB_BLOCK, // ASTC_5x4_UNORM_SRGB
  185. VK_FORMAT_ASTC_5x5_SRGB_BLOCK, // ASTC_5x5_UNORM_SRGB
  186. VK_FORMAT_ASTC_6x5_SRGB_BLOCK, // ASTC_6x5_UNORM_SRGB
  187. VK_FORMAT_ASTC_6x6_SRGB_BLOCK, // ASTC_6x6_UNORM_SRGB
  188. VK_FORMAT_ASTC_8x5_SRGB_BLOCK, // ASTC_8x5_UNORM_SRGB
  189. VK_FORMAT_ASTC_8x6_SRGB_BLOCK, // ASTC_8x6_UNORM_SRGB
  190. VK_FORMAT_ASTC_8x8_SRGB_BLOCK, // ASTC_8x8_UNORM_SRGB
  191. VK_FORMAT_ASTC_10x5_SRGB_BLOCK, // ASTC_10x5_UNORM_SRGB
  192. VK_FORMAT_ASTC_10x6_SRGB_BLOCK, // ASTC_10x6_UNORM_SRGB
  193. VK_FORMAT_ASTC_10x8_SRGB_BLOCK, // ASTC_10x8_UNORM_SRGB
  194. VK_FORMAT_ASTC_10x10_SRGB_BLOCK, // ASTC_10x10_UNORM_SRGB
  195. VK_FORMAT_ASTC_12x10_SRGB_BLOCK, // ASTC_12x10_UNORM_SRGB
  196. VK_FORMAT_ASTC_12x12_SRGB_BLOCK, // ASTC_12x12_UNORM_SRGB
  197. VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, // ASTC_4x4_FLOAT
  198. VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT, // ASTC_5x4_FLOAT
  199. VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT, // ASTC_5x5_FLOAT
  200. VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT, // ASTC_6x5_FLOAT
  201. VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT, // ASTC_6x6_FLOAT
  202. VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT, // ASTC_8x5_FLOAT
  203. VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT, // ASTC_8x6_FLOAT
  204. VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT, // ASTC_8x8_FLOAT
  205. VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT, // ASTC_10x5_FLOAT
  206. VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT, // ASTC_10x6_FLOAT
  207. VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT, // ASTC_10x8_FLOAT
  208. VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT, // ASTC_10x10_FLOAT
  209. VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT, // ASTC_12x10_FLOAT
  210. VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK // ASTC_12x12_FLOAT
  211. };
  212. SDL_COMPILE_TIME_ASSERT(SDLToVK_TextureFormat, SDL_arraysize(SDLToVK_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
  213. static VkComponentMapping SwizzleForSDLFormat(SDL_GPUTextureFormat format)
  214. {
  215. if (format == SDL_GPU_TEXTUREFORMAT_A8_UNORM) {
  216. // TODO: use VK_FORMAT_A8_UNORM_KHR from VK_KHR_maintenance5 when available
  217. return (VkComponentMapping){
  218. VK_COMPONENT_SWIZZLE_ZERO,
  219. VK_COMPONENT_SWIZZLE_ZERO,
  220. VK_COMPONENT_SWIZZLE_ZERO,
  221. VK_COMPONENT_SWIZZLE_R,
  222. };
  223. }
  224. if (format == SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM) {
  225. // ARGB -> BGRA
  226. // TODO: use VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT from VK_EXT_4444_formats when available
  227. return (VkComponentMapping){
  228. VK_COMPONENT_SWIZZLE_G,
  229. VK_COMPONENT_SWIZZLE_R,
  230. VK_COMPONENT_SWIZZLE_A,
  231. VK_COMPONENT_SWIZZLE_B,
  232. };
  233. }
  234. return (VkComponentMapping)IDENTITY_SWIZZLE;
  235. }
  236. static VkFormat SwapchainCompositionToFormat[] = {
  237. VK_FORMAT_B8G8R8A8_UNORM, // SDR
  238. VK_FORMAT_B8G8R8A8_SRGB, // SDR_LINEAR
  239. VK_FORMAT_R16G16B16A16_SFLOAT, // HDR_EXTENDED_LINEAR
  240. VK_FORMAT_A2B10G10R10_UNORM_PACK32 // HDR10_ST2084
  241. };
  242. static VkFormat SwapchainCompositionToFallbackFormat[] = {
  243. VK_FORMAT_R8G8B8A8_UNORM, // SDR
  244. VK_FORMAT_R8G8B8A8_SRGB, // SDR_LINEAR
  245. VK_FORMAT_UNDEFINED, // HDR_EXTENDED_LINEAR (no fallback)
  246. VK_FORMAT_UNDEFINED // HDR10_ST2084 (no fallback)
  247. };
  248. static SDL_GPUTextureFormat SwapchainCompositionToSDLFormat(
  249. SDL_GPUSwapchainComposition composition,
  250. bool usingFallback)
  251. {
  252. switch (composition) {
  253. case SDL_GPU_SWAPCHAINCOMPOSITION_SDR:
  254. return usingFallback ? SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM : SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM;
  255. case SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR:
  256. return usingFallback ? SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB : SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB;
  257. case SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR:
  258. return SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT;
  259. case SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2084:
  260. return SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM;
  261. default:
  262. return SDL_GPU_TEXTUREFORMAT_INVALID;
  263. }
  264. }
  265. static VkColorSpaceKHR SwapchainCompositionToColorSpace[] = {
  266. VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, // SDR
  267. VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, // SDR_LINEAR
  268. VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT, // HDR_EXTENDED_LINEAR
  269. VK_COLOR_SPACE_HDR10_ST2084_EXT // HDR10_ST2084
  270. };
  271. static VkComponentMapping SwapchainCompositionSwizzle[] = {
  272. IDENTITY_SWIZZLE, // SDR
  273. IDENTITY_SWIZZLE, // SDR_LINEAR
  274. IDENTITY_SWIZZLE, // HDR_EXTENDED_LINEAR
  275. {
  276. // HDR10_ST2084
  277. VK_COMPONENT_SWIZZLE_R,
  278. VK_COMPONENT_SWIZZLE_G,
  279. VK_COMPONENT_SWIZZLE_B,
  280. VK_COMPONENT_SWIZZLE_A,
  281. }
  282. };
  283. static VkFormat SDLToVK_VertexFormat[] = {
  284. VK_FORMAT_UNDEFINED, // INVALID
  285. VK_FORMAT_R32_SINT, // INT
  286. VK_FORMAT_R32G32_SINT, // INT2
  287. VK_FORMAT_R32G32B32_SINT, // INT3
  288. VK_FORMAT_R32G32B32A32_SINT, // INT4
  289. VK_FORMAT_R32_UINT, // UINT
  290. VK_FORMAT_R32G32_UINT, // UINT2
  291. VK_FORMAT_R32G32B32_UINT, // UINT3
  292. VK_FORMAT_R32G32B32A32_UINT, // UINT4
  293. VK_FORMAT_R32_SFLOAT, // FLOAT
  294. VK_FORMAT_R32G32_SFLOAT, // FLOAT2
  295. VK_FORMAT_R32G32B32_SFLOAT, // FLOAT3
  296. VK_FORMAT_R32G32B32A32_SFLOAT, // FLOAT4
  297. VK_FORMAT_R8G8_SINT, // BYTE2
  298. VK_FORMAT_R8G8B8A8_SINT, // BYTE4
  299. VK_FORMAT_R8G8_UINT, // UBYTE2
  300. VK_FORMAT_R8G8B8A8_UINT, // UBYTE4
  301. VK_FORMAT_R8G8_SNORM, // BYTE2_NORM
  302. VK_FORMAT_R8G8B8A8_SNORM, // BYTE4_NORM
  303. VK_FORMAT_R8G8_UNORM, // UBYTE2_NORM
  304. VK_FORMAT_R8G8B8A8_UNORM, // UBYTE4_NORM
  305. VK_FORMAT_R16G16_SINT, // SHORT2
  306. VK_FORMAT_R16G16B16A16_SINT, // SHORT4
  307. VK_FORMAT_R16G16_UINT, // USHORT2
  308. VK_FORMAT_R16G16B16A16_UINT, // USHORT4
  309. VK_FORMAT_R16G16_SNORM, // SHORT2_NORM
  310. VK_FORMAT_R16G16B16A16_SNORM, // SHORT4_NORM
  311. VK_FORMAT_R16G16_UNORM, // USHORT2_NORM
  312. VK_FORMAT_R16G16B16A16_UNORM, // USHORT4_NORM
  313. VK_FORMAT_R16G16_SFLOAT, // HALF2
  314. VK_FORMAT_R16G16B16A16_SFLOAT // HALF4
  315. };
  316. SDL_COMPILE_TIME_ASSERT(SDLToVK_VertexFormat, SDL_arraysize(SDLToVK_VertexFormat) == SDL_GPU_VERTEXELEMENTFORMAT_MAX_ENUM_VALUE);
  317. static VkIndexType SDLToVK_IndexType[] = {
  318. VK_INDEX_TYPE_UINT16,
  319. VK_INDEX_TYPE_UINT32
  320. };
  321. static VkPrimitiveTopology SDLToVK_PrimitiveType[] = {
  322. VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
  323. VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
  324. VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
  325. VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
  326. VK_PRIMITIVE_TOPOLOGY_POINT_LIST
  327. };
  328. static VkCullModeFlags SDLToVK_CullMode[] = {
  329. VK_CULL_MODE_NONE,
  330. VK_CULL_MODE_FRONT_BIT,
  331. VK_CULL_MODE_BACK_BIT,
  332. VK_CULL_MODE_FRONT_AND_BACK
  333. };
  334. static VkFrontFace SDLToVK_FrontFace[] = {
  335. VK_FRONT_FACE_COUNTER_CLOCKWISE,
  336. VK_FRONT_FACE_CLOCKWISE
  337. };
  338. static VkBlendFactor SDLToVK_BlendFactor[] = {
  339. VK_BLEND_FACTOR_ZERO, // INVALID
  340. VK_BLEND_FACTOR_ZERO,
  341. VK_BLEND_FACTOR_ONE,
  342. VK_BLEND_FACTOR_SRC_COLOR,
  343. VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
  344. VK_BLEND_FACTOR_DST_COLOR,
  345. VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
  346. VK_BLEND_FACTOR_SRC_ALPHA,
  347. VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
  348. VK_BLEND_FACTOR_DST_ALPHA,
  349. VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
  350. VK_BLEND_FACTOR_CONSTANT_COLOR,
  351. VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
  352. VK_BLEND_FACTOR_SRC_ALPHA_SATURATE
  353. };
  354. SDL_COMPILE_TIME_ASSERT(SDLToVK_BlendFactor, SDL_arraysize(SDLToVK_BlendFactor) == SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE);
  355. static VkBlendOp SDLToVK_BlendOp[] = {
  356. VK_BLEND_OP_ADD, // INVALID
  357. VK_BLEND_OP_ADD,
  358. VK_BLEND_OP_SUBTRACT,
  359. VK_BLEND_OP_REVERSE_SUBTRACT,
  360. VK_BLEND_OP_MIN,
  361. VK_BLEND_OP_MAX
  362. };
  363. SDL_COMPILE_TIME_ASSERT(SDLToVK_BlendOp, SDL_arraysize(SDLToVK_BlendOp) == SDL_GPU_BLENDOP_MAX_ENUM_VALUE);
  364. static VkCompareOp SDLToVK_CompareOp[] = {
  365. VK_COMPARE_OP_NEVER, // INVALID
  366. VK_COMPARE_OP_NEVER,
  367. VK_COMPARE_OP_LESS,
  368. VK_COMPARE_OP_EQUAL,
  369. VK_COMPARE_OP_LESS_OR_EQUAL,
  370. VK_COMPARE_OP_GREATER,
  371. VK_COMPARE_OP_NOT_EQUAL,
  372. VK_COMPARE_OP_GREATER_OR_EQUAL,
  373. VK_COMPARE_OP_ALWAYS
  374. };
  375. SDL_COMPILE_TIME_ASSERT(SDLToVK_CompareOp, SDL_arraysize(SDLToVK_CompareOp) == SDL_GPU_COMPAREOP_MAX_ENUM_VALUE);
  376. static VkStencilOp SDLToVK_StencilOp[] = {
  377. VK_STENCIL_OP_KEEP, // INVALID
  378. VK_STENCIL_OP_KEEP,
  379. VK_STENCIL_OP_ZERO,
  380. VK_STENCIL_OP_REPLACE,
  381. VK_STENCIL_OP_INCREMENT_AND_CLAMP,
  382. VK_STENCIL_OP_DECREMENT_AND_CLAMP,
  383. VK_STENCIL_OP_INVERT,
  384. VK_STENCIL_OP_INCREMENT_AND_WRAP,
  385. VK_STENCIL_OP_DECREMENT_AND_WRAP
  386. };
  387. SDL_COMPILE_TIME_ASSERT(SDLToVK_StencilOp, SDL_arraysize(SDLToVK_StencilOp) == SDL_GPU_STENCILOP_MAX_ENUM_VALUE);
  388. static VkAttachmentLoadOp SDLToVK_LoadOp[] = {
  389. VK_ATTACHMENT_LOAD_OP_LOAD,
  390. VK_ATTACHMENT_LOAD_OP_CLEAR,
  391. VK_ATTACHMENT_LOAD_OP_DONT_CARE
  392. };
  393. static VkAttachmentStoreOp SDLToVK_StoreOp[] = {
  394. VK_ATTACHMENT_STORE_OP_STORE,
  395. VK_ATTACHMENT_STORE_OP_DONT_CARE,
  396. VK_ATTACHMENT_STORE_OP_DONT_CARE,
  397. VK_ATTACHMENT_STORE_OP_STORE
  398. };
  399. static VkSampleCountFlagBits SDLToVK_SampleCount[] = {
  400. VK_SAMPLE_COUNT_1_BIT,
  401. VK_SAMPLE_COUNT_2_BIT,
  402. VK_SAMPLE_COUNT_4_BIT,
  403. VK_SAMPLE_COUNT_8_BIT
  404. };
  405. static VkVertexInputRate SDLToVK_VertexInputRate[] = {
  406. VK_VERTEX_INPUT_RATE_VERTEX,
  407. VK_VERTEX_INPUT_RATE_INSTANCE
  408. };
  409. static VkFilter SDLToVK_Filter[] = {
  410. VK_FILTER_NEAREST,
  411. VK_FILTER_LINEAR
  412. };
  413. static VkSamplerMipmapMode SDLToVK_SamplerMipmapMode[] = {
  414. VK_SAMPLER_MIPMAP_MODE_NEAREST,
  415. VK_SAMPLER_MIPMAP_MODE_LINEAR
  416. };
  417. static VkSamplerAddressMode SDLToVK_SamplerAddressMode[] = {
  418. VK_SAMPLER_ADDRESS_MODE_REPEAT,
  419. VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
  420. VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
  421. };
  422. // Structures
  423. typedef struct VulkanMemoryAllocation VulkanMemoryAllocation;
  424. typedef struct VulkanBuffer VulkanBuffer;
  425. typedef struct VulkanBufferContainer VulkanBufferContainer;
  426. typedef struct VulkanUniformBuffer VulkanUniformBuffer;
  427. typedef struct VulkanTexture VulkanTexture;
  428. typedef struct VulkanTextureContainer VulkanTextureContainer;
  429. typedef struct VulkanFenceHandle
  430. {
  431. VkFence fence;
  432. SDL_AtomicInt referenceCount;
  433. } VulkanFenceHandle;
  434. // Memory Allocation
  435. typedef struct VulkanMemoryFreeRegion
  436. {
  437. VulkanMemoryAllocation *allocation;
  438. VkDeviceSize offset;
  439. VkDeviceSize size;
  440. Uint32 allocationIndex;
  441. Uint32 sortedIndex;
  442. } VulkanMemoryFreeRegion;
  443. typedef struct VulkanMemoryUsedRegion
  444. {
  445. VulkanMemoryAllocation *allocation;
  446. VkDeviceSize offset;
  447. VkDeviceSize size;
  448. VkDeviceSize resourceOffset; // differs from offset based on alignment
  449. VkDeviceSize resourceSize; // differs from size based on alignment
  450. VkDeviceSize alignment;
  451. Uint8 isBuffer;
  452. union
  453. {
  454. VulkanBuffer *vulkanBuffer;
  455. VulkanTexture *vulkanTexture;
  456. };
  457. } VulkanMemoryUsedRegion;
  458. typedef struct VulkanMemorySubAllocator
  459. {
  460. Uint32 memoryTypeIndex;
  461. VulkanMemoryAllocation **allocations;
  462. Uint32 allocationCount;
  463. VulkanMemoryFreeRegion **sortedFreeRegions;
  464. Uint32 sortedFreeRegionCount;
  465. Uint32 sortedFreeRegionCapacity;
  466. } VulkanMemorySubAllocator;
  467. struct VulkanMemoryAllocation
  468. {
  469. VulkanMemorySubAllocator *allocator;
  470. VkDeviceMemory memory;
  471. VkDeviceSize size;
  472. VulkanMemoryUsedRegion **usedRegions;
  473. Uint32 usedRegionCount;
  474. Uint32 usedRegionCapacity;
  475. VulkanMemoryFreeRegion **freeRegions;
  476. Uint32 freeRegionCount;
  477. Uint32 freeRegionCapacity;
  478. Uint8 availableForAllocation;
  479. VkDeviceSize freeSpace;
  480. VkDeviceSize usedSpace;
  481. Uint8 *mapPointer;
  482. SDL_Mutex *memoryLock;
  483. };
  484. typedef struct VulkanMemoryAllocator
  485. {
  486. VulkanMemorySubAllocator subAllocators[VK_MAX_MEMORY_TYPES];
  487. } VulkanMemoryAllocator;
  488. // Memory structures
  489. typedef enum VulkanBufferType
  490. {
  491. VULKAN_BUFFER_TYPE_GPU,
  492. VULKAN_BUFFER_TYPE_UNIFORM,
  493. VULKAN_BUFFER_TYPE_TRANSFER
  494. } VulkanBufferType;
  495. struct VulkanBuffer
  496. {
  497. VulkanBufferContainer *container;
  498. Uint32 containerIndex;
  499. VkBuffer buffer;
  500. VulkanMemoryUsedRegion *usedRegion;
  501. // Needed for uniforms and defrag
  502. VulkanBufferType type;
  503. SDL_GPUBufferUsageFlags usage;
  504. VkDeviceSize size;
  505. SDL_AtomicInt referenceCount;
  506. bool transitioned;
  507. bool markedForDestroy; // so that defrag doesn't double-free
  508. VulkanUniformBuffer *uniformBufferForDefrag;
  509. };
  510. struct VulkanBufferContainer
  511. {
  512. VulkanBuffer *activeBuffer;
  513. VulkanBuffer **buffers;
  514. Uint32 bufferCapacity;
  515. Uint32 bufferCount;
  516. bool dedicated;
  517. char *debugName;
  518. };
  519. // Renderer Structure
  520. typedef struct QueueFamilyIndices
  521. {
  522. Uint32 graphicsFamily;
  523. Uint32 presentFamily;
  524. Uint32 computeFamily;
  525. Uint32 transferFamily;
  526. } QueueFamilyIndices;
  527. typedef struct VulkanSampler
  528. {
  529. VkSampler sampler;
  530. SDL_AtomicInt referenceCount;
  531. } VulkanSampler;
  532. typedef struct VulkanShader
  533. {
  534. VkShaderModule shaderModule;
  535. char *entrypointName;
  536. SDL_GPUShaderStage stage;
  537. Uint32 numSamplers;
  538. Uint32 numStorageTextures;
  539. Uint32 numStorageBuffers;
  540. Uint32 numUniformBuffers;
  541. SDL_AtomicInt referenceCount;
  542. } VulkanShader;
  543. /* Textures are made up of individual subresources.
  544. * This helps us barrier the resource efficiently.
  545. */
  546. typedef struct VulkanTextureSubresource
  547. {
  548. VulkanTexture *parent;
  549. Uint32 layer;
  550. Uint32 level;
  551. VkImageView *renderTargetViews; // One render target view per depth slice
  552. VkImageView computeWriteView;
  553. VkImageView depthStencilView;
  554. } VulkanTextureSubresource;
  555. struct VulkanTexture
  556. {
  557. VulkanTextureContainer *container;
  558. Uint32 containerIndex;
  559. VulkanMemoryUsedRegion *usedRegion;
  560. VkImage image;
  561. VkImageView fullView; // used for samplers and storage reads
  562. VkComponentMapping swizzle;
  563. VkImageAspectFlags aspectFlags;
  564. Uint32 depth; // used for cleanup only
  565. // FIXME: It'd be nice if we didn't have to have this on the texture...
  566. SDL_GPUTextureUsageFlags usage; // used for defrag transitions only.
  567. Uint32 subresourceCount;
  568. VulkanTextureSubresource *subresources;
  569. bool markedForDestroy; // so that defrag doesn't double-free
  570. SDL_AtomicInt referenceCount;
  571. };
  572. struct VulkanTextureContainer
  573. {
  574. TextureCommonHeader header;
  575. VulkanTexture *activeTexture;
  576. Uint32 textureCapacity;
  577. Uint32 textureCount;
  578. VulkanTexture **textures;
  579. char *debugName;
  580. bool canBeCycled;
  581. };
  582. typedef enum VulkanBufferUsageMode
  583. {
  584. VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
  585. VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
  586. VULKAN_BUFFER_USAGE_MODE_VERTEX_READ,
  587. VULKAN_BUFFER_USAGE_MODE_INDEX_READ,
  588. VULKAN_BUFFER_USAGE_MODE_INDIRECT,
  589. VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ,
  590. VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
  591. VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
  592. } VulkanBufferUsageMode;
  593. typedef enum VulkanTextureUsageMode
  594. {
  595. VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
  596. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  597. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
  598. VULKAN_TEXTURE_USAGE_MODE_SAMPLER,
  599. VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ,
  600. VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
  601. VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
  602. VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT,
  603. VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT,
  604. VULKAN_TEXTURE_USAGE_MODE_PRESENT
  605. } VulkanTextureUsageMode;
  606. typedef enum VulkanUniformBufferStage
  607. {
  608. VULKAN_UNIFORM_BUFFER_STAGE_VERTEX,
  609. VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT,
  610. VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE
  611. } VulkanUniformBufferStage;
  612. typedef struct VulkanFramebuffer
  613. {
  614. VkFramebuffer framebuffer;
  615. SDL_AtomicInt referenceCount;
  616. } VulkanFramebuffer;
  617. typedef struct WindowData
  618. {
  619. SDL_Window *window;
  620. SDL_GPUSwapchainComposition swapchainComposition;
  621. SDL_GPUPresentMode presentMode;
  622. bool needsSwapchainRecreate;
  623. Uint32 swapchainCreateWidth;
  624. Uint32 swapchainCreateHeight;
  625. // Window surface
  626. VkSurfaceKHR surface;
  627. // Swapchain for window surface
  628. VkSwapchainKHR swapchain;
  629. VkFormat format;
  630. VkColorSpaceKHR colorSpace;
  631. VkComponentMapping swapchainSwizzle;
  632. bool usingFallbackFormat;
  633. // Swapchain images
  634. VulkanTextureContainer *textureContainers; // use containers so that swapchain textures can use the same API as other textures
  635. Uint32 imageCount;
  636. Uint32 width;
  637. Uint32 height;
  638. // Synchronization primitives
  639. VkSemaphore imageAvailableSemaphore[MAX_FRAMES_IN_FLIGHT];
  640. VkSemaphore *renderFinishedSemaphore;
  641. SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
  642. Uint32 frameCounter;
  643. } WindowData;
  644. typedef struct SwapchainSupportDetails
  645. {
  646. VkSurfaceCapabilitiesKHR capabilities;
  647. VkSurfaceFormatKHR *formats;
  648. Uint32 formatsLength;
  649. VkPresentModeKHR *presentModes;
  650. Uint32 presentModesLength;
  651. } SwapchainSupportDetails;
  652. typedef struct VulkanPresentData
  653. {
  654. WindowData *windowData;
  655. Uint32 swapchainImageIndex;
  656. } VulkanPresentData;
  657. struct VulkanUniformBuffer
  658. {
  659. VulkanBuffer *buffer;
  660. Uint32 drawOffset;
  661. Uint32 writeOffset;
  662. };
  663. typedef struct VulkanDescriptorInfo
  664. {
  665. VkDescriptorType descriptorType;
  666. VkShaderStageFlagBits stageFlag;
  667. } VulkanDescriptorInfo;
  668. typedef struct DescriptorSetPool
  669. {
  670. // It's a pool... of pools!!!
  671. Uint32 poolCount;
  672. VkDescriptorPool *descriptorPools;
  673. // We'll just manage the descriptor sets ourselves instead of freeing the sets
  674. VkDescriptorSet *descriptorSets;
  675. Uint32 descriptorSetCount;
  676. Uint32 descriptorSetIndex;
  677. } DescriptorSetPool;
  678. // A command buffer acquires a cache at command buffer acquisition time
  679. typedef struct DescriptorSetCache
  680. {
  681. // Pools are indexed by DescriptorSetLayoutID which increases monotonically
  682. // There's only a certain number of maximum layouts possible since we de-duplicate them.
  683. DescriptorSetPool *pools;
  684. Uint32 poolCount;
  685. } DescriptorSetCache;
  686. typedef struct DescriptorSetLayoutHashTableKey
  687. {
  688. VkShaderStageFlagBits shaderStage;
  689. // Category 1: read resources
  690. Uint32 samplerCount;
  691. Uint32 storageBufferCount;
  692. Uint32 storageTextureCount;
  693. // Category 2: write resources
  694. Uint32 writeStorageBufferCount;
  695. Uint32 writeStorageTextureCount;
  696. // Category 3: uniform buffers
  697. Uint32 uniformBufferCount;
  698. } DescriptorSetLayoutHashTableKey;
  699. typedef uint32_t DescriptorSetLayoutID;
  700. typedef struct DescriptorSetLayout
  701. {
  702. DescriptorSetLayoutID ID;
  703. VkDescriptorSetLayout descriptorSetLayout;
  704. // Category 1: read resources
  705. Uint32 samplerCount;
  706. Uint32 storageBufferCount;
  707. Uint32 storageTextureCount;
  708. // Category 2: write resources
  709. Uint32 writeStorageBufferCount;
  710. Uint32 writeStorageTextureCount;
  711. // Category 3: uniform buffers
  712. Uint32 uniformBufferCount;
  713. } DescriptorSetLayout;
  714. typedef struct GraphicsPipelineResourceLayoutHashTableKey
  715. {
  716. Uint32 vertexSamplerCount;
  717. Uint32 vertexStorageTextureCount;
  718. Uint32 vertexStorageBufferCount;
  719. Uint32 vertexUniformBufferCount;
  720. Uint32 fragmentSamplerCount;
  721. Uint32 fragmentStorageTextureCount;
  722. Uint32 fragmentStorageBufferCount;
  723. Uint32 fragmentUniformBufferCount;
  724. } GraphicsPipelineResourceLayoutHashTableKey;
  725. typedef struct VulkanGraphicsPipelineResourceLayout
  726. {
  727. VkPipelineLayout pipelineLayout;
  728. /*
  729. * Descriptor set layout is as follows:
  730. * 0: vertex resources
  731. * 1: vertex uniform buffers
  732. * 2: fragment resources
  733. * 3: fragment uniform buffers
  734. */
  735. DescriptorSetLayout *descriptorSetLayouts[4];
  736. Uint32 vertexSamplerCount;
  737. Uint32 vertexStorageTextureCount;
  738. Uint32 vertexStorageBufferCount;
  739. Uint32 vertexUniformBufferCount;
  740. Uint32 fragmentSamplerCount;
  741. Uint32 fragmentStorageTextureCount;
  742. Uint32 fragmentStorageBufferCount;
  743. Uint32 fragmentUniformBufferCount;
  744. } VulkanGraphicsPipelineResourceLayout;
  745. typedef struct VulkanGraphicsPipeline
  746. {
  747. GraphicsPipelineCommonHeader header;
  748. VkPipeline pipeline;
  749. SDL_GPUPrimitiveType primitiveType;
  750. VulkanGraphicsPipelineResourceLayout *resourceLayout;
  751. VulkanShader *vertexShader;
  752. VulkanShader *fragmentShader;
  753. SDL_AtomicInt referenceCount;
  754. } VulkanGraphicsPipeline;
  755. typedef struct ComputePipelineResourceLayoutHashTableKey
  756. {
  757. Uint32 samplerCount;
  758. Uint32 readonlyStorageTextureCount;
  759. Uint32 readonlyStorageBufferCount;
  760. Uint32 readWriteStorageTextureCount;
  761. Uint32 readWriteStorageBufferCount;
  762. Uint32 uniformBufferCount;
  763. } ComputePipelineResourceLayoutHashTableKey;
  764. typedef struct VulkanComputePipelineResourceLayout
  765. {
  766. VkPipelineLayout pipelineLayout;
  767. /*
  768. * Descriptor set layout is as follows:
  769. * 0: samplers, then read-only textures, then read-only buffers
  770. * 1: write-only textures, then write-only buffers
  771. * 2: uniform buffers
  772. */
  773. DescriptorSetLayout *descriptorSetLayouts[3];
  774. Uint32 numSamplers;
  775. Uint32 numReadonlyStorageTextures;
  776. Uint32 numReadonlyStorageBuffers;
  777. Uint32 numReadWriteStorageTextures;
  778. Uint32 numReadWriteStorageBuffers;
  779. Uint32 numUniformBuffers;
  780. } VulkanComputePipelineResourceLayout;
  781. typedef struct VulkanComputePipeline
  782. {
  783. ComputePipelineCommonHeader header;
  784. VkShaderModule shaderModule;
  785. VkPipeline pipeline;
  786. VulkanComputePipelineResourceLayout *resourceLayout;
  787. SDL_AtomicInt referenceCount;
  788. } VulkanComputePipeline;
  789. typedef struct RenderPassColorTargetDescription
  790. {
  791. VkFormat format;
  792. SDL_GPULoadOp loadOp;
  793. SDL_GPUStoreOp storeOp;
  794. } RenderPassColorTargetDescription;
  795. typedef struct RenderPassDepthStencilTargetDescription
  796. {
  797. VkFormat format;
  798. SDL_GPULoadOp loadOp;
  799. SDL_GPUStoreOp storeOp;
  800. SDL_GPULoadOp stencilLoadOp;
  801. SDL_GPUStoreOp stencilStoreOp;
  802. } RenderPassDepthStencilTargetDescription;
  803. typedef struct CommandPoolHashTableKey
  804. {
  805. SDL_ThreadID threadID;
  806. } CommandPoolHashTableKey;
  807. typedef struct RenderPassHashTableKey
  808. {
  809. RenderPassColorTargetDescription colorTargetDescriptions[MAX_COLOR_TARGET_BINDINGS];
  810. Uint32 numColorTargets;
  811. VkFormat resolveTargetFormats[MAX_COLOR_TARGET_BINDINGS];
  812. Uint32 numResolveTargets;
  813. RenderPassDepthStencilTargetDescription depthStencilTargetDescription;
  814. VkSampleCountFlagBits sampleCount;
  815. } RenderPassHashTableKey;
  816. typedef struct VulkanRenderPassHashTableValue
  817. {
  818. VkRenderPass handle;
  819. } VulkanRenderPassHashTableValue;
  820. typedef struct FramebufferHashTableKey
  821. {
  822. VkImageView colorAttachmentViews[MAX_COLOR_TARGET_BINDINGS];
  823. Uint32 numColorTargets;
  824. VkImageView resolveAttachmentViews[MAX_COLOR_TARGET_BINDINGS];
  825. Uint32 numResolveAttachments;
  826. VkImageView depthStencilAttachmentView;
  827. Uint32 width;
  828. Uint32 height;
  829. } FramebufferHashTableKey;
  830. // Command structures
  831. typedef struct VulkanFencePool
  832. {
  833. SDL_Mutex *lock;
  834. VulkanFenceHandle **availableFences;
  835. Uint32 availableFenceCount;
  836. Uint32 availableFenceCapacity;
  837. } VulkanFencePool;
  838. typedef struct VulkanCommandPool VulkanCommandPool;
  839. typedef struct VulkanRenderer VulkanRenderer;
  840. typedef struct VulkanCommandBuffer
  841. {
  842. CommandBufferCommonHeader common;
  843. VulkanRenderer *renderer;
  844. VkCommandBuffer commandBuffer;
  845. VulkanCommandPool *commandPool;
  846. VulkanPresentData *presentDatas;
  847. Uint32 presentDataCount;
  848. Uint32 presentDataCapacity;
  849. VkSemaphore *waitSemaphores;
  850. Uint32 waitSemaphoreCount;
  851. Uint32 waitSemaphoreCapacity;
  852. VkSemaphore *signalSemaphores;
  853. Uint32 signalSemaphoreCount;
  854. Uint32 signalSemaphoreCapacity;
  855. VulkanComputePipeline *currentComputePipeline;
  856. VulkanGraphicsPipeline *currentGraphicsPipeline;
  857. // Keep track of resources transitioned away from their default state to barrier them on pass end
  858. VulkanTextureSubresource *colorAttachmentSubresources[MAX_COLOR_TARGET_BINDINGS];
  859. Uint32 colorAttachmentSubresourceCount;
  860. VulkanTextureSubresource *resolveAttachmentSubresources[MAX_COLOR_TARGET_BINDINGS];
  861. Uint32 resolveAttachmentSubresourceCount;
  862. VulkanTextureSubresource *depthStencilAttachmentSubresource; // may be NULL
  863. // Dynamic state
  864. VkViewport currentViewport;
  865. VkRect2D currentScissor;
  866. float blendConstants[4];
  867. Uint8 stencilRef;
  868. // Resource bind state
  869. DescriptorSetCache *descriptorSetCache; // acquired when command buffer is acquired
  870. bool needNewVertexResourceDescriptorSet;
  871. bool needNewVertexUniformDescriptorSet;
  872. bool needNewVertexUniformOffsets;
  873. bool needNewFragmentResourceDescriptorSet;
  874. bool needNewFragmentUniformDescriptorSet;
  875. bool needNewFragmentUniformOffsets;
  876. bool needNewComputeReadOnlyDescriptorSet;
  877. bool needNewComputeReadWriteDescriptorSet;
  878. bool needNewComputeUniformDescriptorSet;
  879. bool needNewComputeUniformOffsets;
  880. VkDescriptorSet vertexResourceDescriptorSet;
  881. VkDescriptorSet vertexUniformDescriptorSet;
  882. VkDescriptorSet fragmentResourceDescriptorSet;
  883. VkDescriptorSet fragmentUniformDescriptorSet;
  884. VkDescriptorSet computeReadOnlyDescriptorSet;
  885. VkDescriptorSet computeReadWriteDescriptorSet;
  886. VkDescriptorSet computeUniformDescriptorSet;
  887. VkBuffer vertexBuffers[MAX_VERTEX_BUFFERS];
  888. VkDeviceSize vertexBufferOffsets[MAX_VERTEX_BUFFERS];
  889. Uint32 vertexBufferCount;
  890. bool needVertexBufferBind;
  891. VkImageView vertexSamplerTextureViewBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  892. VkSampler vertexSamplerBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  893. VkImageView vertexStorageTextureViewBindings[MAX_STORAGE_TEXTURES_PER_STAGE];
  894. VkBuffer vertexStorageBufferBindings[MAX_STORAGE_BUFFERS_PER_STAGE];
  895. VkImageView fragmentSamplerTextureViewBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  896. VkSampler fragmentSamplerBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  897. VkImageView fragmentStorageTextureViewBindings[MAX_STORAGE_TEXTURES_PER_STAGE];
  898. VkBuffer fragmentStorageBufferBindings[MAX_STORAGE_BUFFERS_PER_STAGE];
  899. VkImageView computeSamplerTextureViewBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  900. VkSampler computeSamplerBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  901. VkImageView readOnlyComputeStorageTextureViewBindings[MAX_STORAGE_TEXTURES_PER_STAGE];
  902. VkBuffer readOnlyComputeStorageBufferBindings[MAX_STORAGE_BUFFERS_PER_STAGE];
  903. // Track these separately because barriers can happen mid compute pass
  904. VulkanTexture *readOnlyComputeStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
  905. VulkanBuffer *readOnlyComputeStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
  906. VkImageView readWriteComputeStorageTextureViewBindings[MAX_COMPUTE_WRITE_TEXTURES];
  907. VkBuffer readWriteComputeStorageBufferBindings[MAX_COMPUTE_WRITE_BUFFERS];
  908. // Track these separately because they are barriered when the compute pass begins
  909. VulkanTextureSubresource *readWriteComputeStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
  910. Uint32 readWriteComputeStorageTextureSubresourceCount;
  911. VulkanBuffer *readWriteComputeStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
  912. // Uniform buffers
  913. VulkanUniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
  914. VulkanUniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
  915. VulkanUniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
  916. // Track used resources
  917. VulkanBuffer **usedBuffers;
  918. Sint32 usedBufferCount;
  919. Sint32 usedBufferCapacity;
  920. VulkanTexture **usedTextures;
  921. Sint32 usedTextureCount;
  922. Sint32 usedTextureCapacity;
  923. VulkanSampler **usedSamplers;
  924. Sint32 usedSamplerCount;
  925. Sint32 usedSamplerCapacity;
  926. VulkanGraphicsPipeline **usedGraphicsPipelines;
  927. Sint32 usedGraphicsPipelineCount;
  928. Sint32 usedGraphicsPipelineCapacity;
  929. VulkanComputePipeline **usedComputePipelines;
  930. Sint32 usedComputePipelineCount;
  931. Sint32 usedComputePipelineCapacity;
  932. VulkanFramebuffer **usedFramebuffers;
  933. Sint32 usedFramebufferCount;
  934. Sint32 usedFramebufferCapacity;
  935. VulkanUniformBuffer **usedUniformBuffers;
  936. Sint32 usedUniformBufferCount;
  937. Sint32 usedUniformBufferCapacity;
  938. VulkanFenceHandle *inFlightFence;
  939. bool autoReleaseFence;
  940. bool swapchainRequested;
  941. bool isDefrag; // Whether this CB was created for defragging
  942. } VulkanCommandBuffer;
  943. struct VulkanCommandPool
  944. {
  945. SDL_ThreadID threadID;
  946. VkCommandPool commandPool;
  947. VulkanCommandBuffer **inactiveCommandBuffers;
  948. Uint32 inactiveCommandBufferCapacity;
  949. Uint32 inactiveCommandBufferCount;
  950. };
  951. // Context
  952. struct VulkanRenderer
  953. {
  954. VkInstance instance;
  955. VkPhysicalDevice physicalDevice;
  956. VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
  957. VkPhysicalDeviceDriverPropertiesKHR physicalDeviceDriverProperties;
  958. VkDevice logicalDevice;
  959. Uint8 integratedMemoryNotification;
  960. Uint8 outOfDeviceLocalMemoryWarning;
  961. Uint8 outofBARMemoryWarning;
  962. Uint8 fillModeOnlyWarning;
  963. bool debugMode;
  964. bool preferLowPower;
  965. Uint32 allowedFramesInFlight;
  966. VulkanExtensions supports;
  967. bool supportsDebugUtils;
  968. bool supportsColorspace;
  969. bool supportsPhysicalDeviceProperties2;
  970. bool supportsFillModeNonSolid;
  971. bool supportsMultiDrawIndirect;
  972. VulkanMemoryAllocator *memoryAllocator;
  973. VkPhysicalDeviceMemoryProperties memoryProperties;
  974. bool checkEmptyAllocations;
  975. WindowData **claimedWindows;
  976. Uint32 claimedWindowCount;
  977. Uint32 claimedWindowCapacity;
  978. Uint32 queueFamilyIndex;
  979. VkQueue unifiedQueue;
  980. VulkanCommandBuffer **submittedCommandBuffers;
  981. Uint32 submittedCommandBufferCount;
  982. Uint32 submittedCommandBufferCapacity;
  983. VulkanFencePool fencePool;
  984. SDL_HashTable *commandPoolHashTable;
  985. SDL_HashTable *renderPassHashTable;
  986. SDL_HashTable *framebufferHashTable;
  987. SDL_HashTable *graphicsPipelineResourceLayoutHashTable;
  988. SDL_HashTable *computePipelineResourceLayoutHashTable;
  989. SDL_HashTable *descriptorSetLayoutHashTable;
  990. VulkanUniformBuffer **uniformBufferPool;
  991. Uint32 uniformBufferPoolCount;
  992. Uint32 uniformBufferPoolCapacity;
  993. DescriptorSetCache **descriptorSetCachePool;
  994. Uint32 descriptorSetCachePoolCount;
  995. Uint32 descriptorSetCachePoolCapacity;
  996. SDL_AtomicInt layoutResourceID;
  997. Uint32 minUBOAlignment;
  998. // Deferred resource destruction
  999. VulkanTexture **texturesToDestroy;
  1000. Uint32 texturesToDestroyCount;
  1001. Uint32 texturesToDestroyCapacity;
  1002. VulkanBuffer **buffersToDestroy;
  1003. Uint32 buffersToDestroyCount;
  1004. Uint32 buffersToDestroyCapacity;
  1005. VulkanSampler **samplersToDestroy;
  1006. Uint32 samplersToDestroyCount;
  1007. Uint32 samplersToDestroyCapacity;
  1008. VulkanGraphicsPipeline **graphicsPipelinesToDestroy;
  1009. Uint32 graphicsPipelinesToDestroyCount;
  1010. Uint32 graphicsPipelinesToDestroyCapacity;
  1011. VulkanComputePipeline **computePipelinesToDestroy;
  1012. Uint32 computePipelinesToDestroyCount;
  1013. Uint32 computePipelinesToDestroyCapacity;
  1014. VulkanShader **shadersToDestroy;
  1015. Uint32 shadersToDestroyCount;
  1016. Uint32 shadersToDestroyCapacity;
  1017. VulkanFramebuffer **framebuffersToDestroy;
  1018. Uint32 framebuffersToDestroyCount;
  1019. Uint32 framebuffersToDestroyCapacity;
  1020. SDL_Mutex *allocatorLock;
  1021. SDL_Mutex *disposeLock;
  1022. SDL_Mutex *submitLock;
  1023. SDL_Mutex *acquireCommandBufferLock;
  1024. SDL_Mutex *acquireUniformBufferLock;
  1025. SDL_Mutex *renderPassFetchLock;
  1026. SDL_Mutex *framebufferFetchLock;
  1027. SDL_Mutex *graphicsPipelineLayoutFetchLock;
  1028. SDL_Mutex *computePipelineLayoutFetchLock;
  1029. SDL_Mutex *descriptorSetLayoutFetchLock;
  1030. SDL_Mutex *windowLock;
  1031. Uint8 defragInProgress;
  1032. VulkanMemoryAllocation **allocationsToDefrag;
  1033. Uint32 allocationsToDefragCount;
  1034. Uint32 allocationsToDefragCapacity;
  1035. #define VULKAN_INSTANCE_FUNCTION(func) \
  1036. PFN_##func func;
  1037. #define VULKAN_DEVICE_FUNCTION(func) \
  1038. PFN_##func func;
  1039. #include "SDL_gpu_vulkan_vkfuncs.h"
  1040. };
  1041. // Forward declarations
  1042. static bool VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
  1043. static bool VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
  1044. static void VULKAN_ReleaseWindow(SDL_GPURenderer *driverData, SDL_Window *window);
  1045. static bool VULKAN_Wait(SDL_GPURenderer *driverData);
  1046. static bool VULKAN_WaitForFences(SDL_GPURenderer *driverData, bool waitAll, SDL_GPUFence *const *fences, Uint32 numFences);
  1047. static bool VULKAN_Submit(SDL_GPUCommandBuffer *commandBuffer);
  1048. static SDL_GPUCommandBuffer *VULKAN_AcquireCommandBuffer(SDL_GPURenderer *driverData);
  1049. // Error Handling
  1050. static inline const char *VkErrorMessages(VkResult code)
  1051. {
  1052. #define ERR_TO_STR(e) \
  1053. case e: \
  1054. return #e;
  1055. switch (code) {
  1056. ERR_TO_STR(VK_ERROR_OUT_OF_HOST_MEMORY)
  1057. ERR_TO_STR(VK_ERROR_OUT_OF_DEVICE_MEMORY)
  1058. ERR_TO_STR(VK_ERROR_FRAGMENTED_POOL)
  1059. ERR_TO_STR(VK_ERROR_OUT_OF_POOL_MEMORY)
  1060. ERR_TO_STR(VK_ERROR_INITIALIZATION_FAILED)
  1061. ERR_TO_STR(VK_ERROR_LAYER_NOT_PRESENT)
  1062. ERR_TO_STR(VK_ERROR_EXTENSION_NOT_PRESENT)
  1063. ERR_TO_STR(VK_ERROR_FEATURE_NOT_PRESENT)
  1064. ERR_TO_STR(VK_ERROR_TOO_MANY_OBJECTS)
  1065. ERR_TO_STR(VK_ERROR_DEVICE_LOST)
  1066. ERR_TO_STR(VK_ERROR_INCOMPATIBLE_DRIVER)
  1067. ERR_TO_STR(VK_ERROR_OUT_OF_DATE_KHR)
  1068. ERR_TO_STR(VK_ERROR_SURFACE_LOST_KHR)
  1069. ERR_TO_STR(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
  1070. ERR_TO_STR(VK_SUBOPTIMAL_KHR)
  1071. ERR_TO_STR(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR)
  1072. ERR_TO_STR(VK_ERROR_INVALID_SHADER_NV)
  1073. default:
  1074. return "Unhandled VkResult!";
  1075. }
  1076. #undef ERR_TO_STR
  1077. }
  1078. #define SET_ERROR(fmt, msg) \
  1079. do { \
  1080. if (renderer->debugMode) { \
  1081. SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
  1082. } \
  1083. SDL_SetError((fmt), (msg)); \
  1084. } while (0)
  1085. #define SET_STRING_ERROR(msg) SET_ERROR("%s", msg)
  1086. #define SET_ERROR_AND_RETURN(fmt, msg, ret) \
  1087. do { \
  1088. SET_ERROR(fmt, msg); \
  1089. return ret; \
  1090. } while (0)
  1091. #define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
  1092. #define CHECK_VULKAN_ERROR_AND_RETURN(res, fn, ret) \
  1093. do { \
  1094. if ((res) != VK_SUCCESS) { \
  1095. if (renderer->debugMode) { \
  1096. SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s %s", #fn, VkErrorMessages(res)); \
  1097. } \
  1098. SDL_SetError("%s %s", #fn, VkErrorMessages(res)); \
  1099. return (ret); \
  1100. } \
  1101. } while (0)
  1102. // Utility
  1103. static inline VkPolygonMode SDLToVK_PolygonMode(
  1104. VulkanRenderer *renderer,
  1105. SDL_GPUFillMode mode)
  1106. {
  1107. if (mode == SDL_GPU_FILLMODE_FILL) {
  1108. return VK_POLYGON_MODE_FILL; // always available!
  1109. }
  1110. if (renderer->supportsFillModeNonSolid && mode == SDL_GPU_FILLMODE_LINE) {
  1111. return VK_POLYGON_MODE_LINE;
  1112. }
  1113. if (!renderer->fillModeOnlyWarning) {
  1114. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Unsupported fill mode requested, using FILL!");
  1115. renderer->fillModeOnlyWarning = 1;
  1116. }
  1117. return VK_POLYGON_MODE_FILL;
  1118. }
  1119. // Memory Management
  1120. // Vulkan: Memory Allocation
  1121. static inline VkDeviceSize VULKAN_INTERNAL_NextHighestAlignment(
  1122. VkDeviceSize n,
  1123. VkDeviceSize align)
  1124. {
  1125. return align * ((n + align - 1) / align);
  1126. }
  1127. static inline Uint32 VULKAN_INTERNAL_NextHighestAlignment32(
  1128. Uint32 n,
  1129. Uint32 align)
  1130. {
  1131. return align * ((n + align - 1) / align);
  1132. }
  1133. static void VULKAN_INTERNAL_MakeMemoryUnavailable(
  1134. VulkanRenderer *renderer,
  1135. VulkanMemoryAllocation *allocation)
  1136. {
  1137. Uint32 i, j;
  1138. VulkanMemoryFreeRegion *freeRegion;
  1139. allocation->availableForAllocation = 0;
  1140. for (i = 0; i < allocation->freeRegionCount; i += 1) {
  1141. freeRegion = allocation->freeRegions[i];
  1142. // close the gap in the sorted list
  1143. if (allocation->allocator->sortedFreeRegionCount > 1) {
  1144. for (j = freeRegion->sortedIndex; j < allocation->allocator->sortedFreeRegionCount - 1; j += 1) {
  1145. allocation->allocator->sortedFreeRegions[j] =
  1146. allocation->allocator->sortedFreeRegions[j + 1];
  1147. allocation->allocator->sortedFreeRegions[j]->sortedIndex = j;
  1148. }
  1149. }
  1150. allocation->allocator->sortedFreeRegionCount -= 1;
  1151. }
  1152. }
  1153. static void VULKAN_INTERNAL_MarkAllocationsForDefrag(
  1154. VulkanRenderer *renderer)
  1155. {
  1156. Uint32 memoryType, allocationIndex;
  1157. VulkanMemorySubAllocator *currentAllocator;
  1158. for (memoryType = 0; memoryType < VK_MAX_MEMORY_TYPES; memoryType += 1) {
  1159. currentAllocator = &renderer->memoryAllocator->subAllocators[memoryType];
  1160. for (allocationIndex = 0; allocationIndex < currentAllocator->allocationCount; allocationIndex += 1) {
  1161. if (currentAllocator->allocations[allocationIndex]->availableForAllocation == 1) {
  1162. if (currentAllocator->allocations[allocationIndex]->freeRegionCount > 1) {
  1163. EXPAND_ARRAY_IF_NEEDED(
  1164. renderer->allocationsToDefrag,
  1165. VulkanMemoryAllocation *,
  1166. renderer->allocationsToDefragCount + 1,
  1167. renderer->allocationsToDefragCapacity,
  1168. renderer->allocationsToDefragCapacity * 2);
  1169. renderer->allocationsToDefrag[renderer->allocationsToDefragCount] =
  1170. currentAllocator->allocations[allocationIndex];
  1171. renderer->allocationsToDefragCount += 1;
  1172. VULKAN_INTERNAL_MakeMemoryUnavailable(
  1173. renderer,
  1174. currentAllocator->allocations[allocationIndex]);
  1175. }
  1176. }
  1177. }
  1178. }
  1179. }
  1180. static void VULKAN_INTERNAL_RemoveMemoryFreeRegion(
  1181. VulkanRenderer *renderer,
  1182. VulkanMemoryFreeRegion *freeRegion)
  1183. {
  1184. Uint32 i;
  1185. SDL_LockMutex(renderer->allocatorLock);
  1186. if (freeRegion->allocation->availableForAllocation) {
  1187. // close the gap in the sorted list
  1188. if (freeRegion->allocation->allocator->sortedFreeRegionCount > 1) {
  1189. for (i = freeRegion->sortedIndex; i < freeRegion->allocation->allocator->sortedFreeRegionCount - 1; i += 1) {
  1190. freeRegion->allocation->allocator->sortedFreeRegions[i] =
  1191. freeRegion->allocation->allocator->sortedFreeRegions[i + 1];
  1192. freeRegion->allocation->allocator->sortedFreeRegions[i]->sortedIndex = i;
  1193. }
  1194. }
  1195. freeRegion->allocation->allocator->sortedFreeRegionCount -= 1;
  1196. }
  1197. // close the gap in the buffer list
  1198. if (freeRegion->allocation->freeRegionCount > 1 && freeRegion->allocationIndex != freeRegion->allocation->freeRegionCount - 1) {
  1199. freeRegion->allocation->freeRegions[freeRegion->allocationIndex] =
  1200. freeRegion->allocation->freeRegions[freeRegion->allocation->freeRegionCount - 1];
  1201. freeRegion->allocation->freeRegions[freeRegion->allocationIndex]->allocationIndex =
  1202. freeRegion->allocationIndex;
  1203. }
  1204. freeRegion->allocation->freeRegionCount -= 1;
  1205. freeRegion->allocation->freeSpace -= freeRegion->size;
  1206. SDL_free(freeRegion);
  1207. SDL_UnlockMutex(renderer->allocatorLock);
  1208. }
  1209. static void VULKAN_INTERNAL_NewMemoryFreeRegion(
  1210. VulkanRenderer *renderer,
  1211. VulkanMemoryAllocation *allocation,
  1212. VkDeviceSize offset,
  1213. VkDeviceSize size)
  1214. {
  1215. VulkanMemoryFreeRegion *newFreeRegion;
  1216. VkDeviceSize newOffset, newSize;
  1217. Sint32 insertionIndex = 0;
  1218. SDL_LockMutex(renderer->allocatorLock);
  1219. // look for an adjacent region to merge
  1220. for (Sint32 i = allocation->freeRegionCount - 1; i >= 0; i -= 1) {
  1221. // check left side
  1222. if (allocation->freeRegions[i]->offset + allocation->freeRegions[i]->size == offset) {
  1223. newOffset = allocation->freeRegions[i]->offset;
  1224. newSize = allocation->freeRegions[i]->size + size;
  1225. VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, allocation->freeRegions[i]);
  1226. VULKAN_INTERNAL_NewMemoryFreeRegion(renderer, allocation, newOffset, newSize);
  1227. SDL_UnlockMutex(renderer->allocatorLock);
  1228. return;
  1229. }
  1230. // check right side
  1231. if (allocation->freeRegions[i]->offset == offset + size) {
  1232. newOffset = offset;
  1233. newSize = allocation->freeRegions[i]->size + size;
  1234. VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, allocation->freeRegions[i]);
  1235. VULKAN_INTERNAL_NewMemoryFreeRegion(renderer, allocation, newOffset, newSize);
  1236. SDL_UnlockMutex(renderer->allocatorLock);
  1237. return;
  1238. }
  1239. }
  1240. // region is not contiguous with another free region, make a new one
  1241. allocation->freeRegionCount += 1;
  1242. if (allocation->freeRegionCount > allocation->freeRegionCapacity) {
  1243. allocation->freeRegionCapacity *= 2;
  1244. allocation->freeRegions = SDL_realloc(
  1245. allocation->freeRegions,
  1246. sizeof(VulkanMemoryFreeRegion *) * allocation->freeRegionCapacity);
  1247. }
  1248. newFreeRegion = SDL_malloc(sizeof(VulkanMemoryFreeRegion));
  1249. newFreeRegion->offset = offset;
  1250. newFreeRegion->size = size;
  1251. newFreeRegion->allocation = allocation;
  1252. allocation->freeSpace += size;
  1253. allocation->freeRegions[allocation->freeRegionCount - 1] = newFreeRegion;
  1254. newFreeRegion->allocationIndex = allocation->freeRegionCount - 1;
  1255. if (allocation->availableForAllocation) {
  1256. for (Uint32 i = 0; i < allocation->allocator->sortedFreeRegionCount; i += 1) {
  1257. if (allocation->allocator->sortedFreeRegions[i]->size < size) {
  1258. // this is where the new region should go
  1259. break;
  1260. }
  1261. insertionIndex += 1;
  1262. }
  1263. if (allocation->allocator->sortedFreeRegionCount + 1 > allocation->allocator->sortedFreeRegionCapacity) {
  1264. allocation->allocator->sortedFreeRegionCapacity *= 2;
  1265. allocation->allocator->sortedFreeRegions = SDL_realloc(
  1266. allocation->allocator->sortedFreeRegions,
  1267. sizeof(VulkanMemoryFreeRegion *) * allocation->allocator->sortedFreeRegionCapacity);
  1268. }
  1269. // perform insertion sort
  1270. if (allocation->allocator->sortedFreeRegionCount > 0 && (Uint32)insertionIndex != allocation->allocator->sortedFreeRegionCount) {
  1271. for (Sint32 i = allocation->allocator->sortedFreeRegionCount; i > insertionIndex && i > 0; i -= 1) {
  1272. allocation->allocator->sortedFreeRegions[i] = allocation->allocator->sortedFreeRegions[i - 1];
  1273. allocation->allocator->sortedFreeRegions[i]->sortedIndex = i;
  1274. }
  1275. }
  1276. allocation->allocator->sortedFreeRegionCount += 1;
  1277. allocation->allocator->sortedFreeRegions[insertionIndex] = newFreeRegion;
  1278. newFreeRegion->sortedIndex = insertionIndex;
  1279. }
  1280. SDL_UnlockMutex(renderer->allocatorLock);
  1281. }
  1282. static VulkanMemoryUsedRegion *VULKAN_INTERNAL_NewMemoryUsedRegion(
  1283. VulkanRenderer *renderer,
  1284. VulkanMemoryAllocation *allocation,
  1285. VkDeviceSize offset,
  1286. VkDeviceSize size,
  1287. VkDeviceSize resourceOffset,
  1288. VkDeviceSize resourceSize,
  1289. VkDeviceSize alignment)
  1290. {
  1291. VulkanMemoryUsedRegion *memoryUsedRegion;
  1292. SDL_LockMutex(renderer->allocatorLock);
  1293. if (allocation->usedRegionCount == allocation->usedRegionCapacity) {
  1294. allocation->usedRegionCapacity *= 2;
  1295. allocation->usedRegions = SDL_realloc(
  1296. allocation->usedRegions,
  1297. allocation->usedRegionCapacity * sizeof(VulkanMemoryUsedRegion *));
  1298. }
  1299. memoryUsedRegion = SDL_malloc(sizeof(VulkanMemoryUsedRegion));
  1300. memoryUsedRegion->allocation = allocation;
  1301. memoryUsedRegion->offset = offset;
  1302. memoryUsedRegion->size = size;
  1303. memoryUsedRegion->resourceOffset = resourceOffset;
  1304. memoryUsedRegion->resourceSize = resourceSize;
  1305. memoryUsedRegion->alignment = alignment;
  1306. allocation->usedSpace += size;
  1307. allocation->usedRegions[allocation->usedRegionCount] = memoryUsedRegion;
  1308. allocation->usedRegionCount += 1;
  1309. SDL_UnlockMutex(renderer->allocatorLock);
  1310. return memoryUsedRegion;
  1311. }
  1312. static void VULKAN_INTERNAL_RemoveMemoryUsedRegion(
  1313. VulkanRenderer *renderer,
  1314. VulkanMemoryUsedRegion *usedRegion)
  1315. {
  1316. Uint32 i;
  1317. SDL_LockMutex(renderer->allocatorLock);
  1318. for (i = 0; i < usedRegion->allocation->usedRegionCount; i += 1) {
  1319. if (usedRegion->allocation->usedRegions[i] == usedRegion) {
  1320. // plug the hole
  1321. if (i != usedRegion->allocation->usedRegionCount - 1) {
  1322. usedRegion->allocation->usedRegions[i] = usedRegion->allocation->usedRegions[usedRegion->allocation->usedRegionCount - 1];
  1323. }
  1324. break;
  1325. }
  1326. }
  1327. usedRegion->allocation->usedSpace -= usedRegion->size;
  1328. usedRegion->allocation->usedRegionCount -= 1;
  1329. VULKAN_INTERNAL_NewMemoryFreeRegion(
  1330. renderer,
  1331. usedRegion->allocation,
  1332. usedRegion->offset,
  1333. usedRegion->size);
  1334. if (usedRegion->allocation->usedRegionCount == 0) {
  1335. renderer->checkEmptyAllocations = true;
  1336. }
  1337. SDL_free(usedRegion);
  1338. SDL_UnlockMutex(renderer->allocatorLock);
  1339. }
  1340. static bool VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
  1341. Uint32 memoryTypeIndex,
  1342. const Uint32 *memoryTypeIndexArray,
  1343. Uint32 count)
  1344. {
  1345. Uint32 i = 0;
  1346. for (i = 0; i < count; i += 1) {
  1347. if (memoryTypeIndexArray[i] == memoryTypeIndex) {
  1348. return false;
  1349. }
  1350. }
  1351. return true;
  1352. }
  1353. /* Returns an array of memory type indices in order of preference.
  1354. * Memory types are requested with the following three guidelines:
  1355. *
  1356. * Required: Absolutely necessary
  1357. * Preferred: Nice to have, but not necessary
  1358. * Tolerable: Can be allowed if there are no other options
  1359. *
  1360. * We return memory types in this order:
  1361. * 1. Required and preferred. This is the best category.
  1362. * 2. Required only.
  1363. * 3. Required, preferred, and tolerable.
  1364. * 4. Required and tolerable. This is the worst category.
  1365. */
  1366. static Uint32 *VULKAN_INTERNAL_FindBestMemoryTypes(
  1367. VulkanRenderer *renderer,
  1368. Uint32 typeFilter,
  1369. VkMemoryPropertyFlags requiredProperties,
  1370. VkMemoryPropertyFlags preferredProperties,
  1371. VkMemoryPropertyFlags tolerableProperties,
  1372. Uint32 *pCount)
  1373. {
  1374. Uint32 i;
  1375. Uint32 index = 0;
  1376. Uint32 *result = SDL_malloc(sizeof(Uint32) * renderer->memoryProperties.memoryTypeCount);
  1377. // required + preferred + !tolerable
  1378. for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
  1379. if ((typeFilter & (1 << i)) &&
  1380. (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
  1381. (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == preferredProperties &&
  1382. (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == 0) {
  1383. if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
  1384. i,
  1385. result,
  1386. index)) {
  1387. result[index] = i;
  1388. index += 1;
  1389. }
  1390. }
  1391. }
  1392. // required + !preferred + !tolerable
  1393. for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
  1394. if ((typeFilter & (1 << i)) &&
  1395. (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
  1396. (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == 0 &&
  1397. (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == 0) {
  1398. if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
  1399. i,
  1400. result,
  1401. index)) {
  1402. result[index] = i;
  1403. index += 1;
  1404. }
  1405. }
  1406. }
  1407. // required + preferred + tolerable
  1408. for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
  1409. if ((typeFilter & (1 << i)) &&
  1410. (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
  1411. (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == preferredProperties &&
  1412. (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == tolerableProperties) {
  1413. if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
  1414. i,
  1415. result,
  1416. index)) {
  1417. result[index] = i;
  1418. index += 1;
  1419. }
  1420. }
  1421. }
  1422. // required + !preferred + tolerable
  1423. for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
  1424. if ((typeFilter & (1 << i)) &&
  1425. (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
  1426. (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == 0 &&
  1427. (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == tolerableProperties) {
  1428. if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
  1429. i,
  1430. result,
  1431. index)) {
  1432. result[index] = i;
  1433. index += 1;
  1434. }
  1435. }
  1436. }
  1437. *pCount = index;
  1438. return result;
  1439. }
  1440. static Uint32 *VULKAN_INTERNAL_FindBestBufferMemoryTypes(
  1441. VulkanRenderer *renderer,
  1442. VkBuffer buffer,
  1443. VkMemoryPropertyFlags requiredMemoryProperties,
  1444. VkMemoryPropertyFlags preferredMemoryProperties,
  1445. VkMemoryPropertyFlags tolerableMemoryProperties,
  1446. VkMemoryRequirements *pMemoryRequirements,
  1447. Uint32 *pCount)
  1448. {
  1449. renderer->vkGetBufferMemoryRequirements(
  1450. renderer->logicalDevice,
  1451. buffer,
  1452. pMemoryRequirements);
  1453. return VULKAN_INTERNAL_FindBestMemoryTypes(
  1454. renderer,
  1455. pMemoryRequirements->memoryTypeBits,
  1456. requiredMemoryProperties,
  1457. preferredMemoryProperties,
  1458. tolerableMemoryProperties,
  1459. pCount);
  1460. }
  1461. static Uint32 *VULKAN_INTERNAL_FindBestImageMemoryTypes(
  1462. VulkanRenderer *renderer,
  1463. VkImage image,
  1464. VkMemoryPropertyFlags preferredMemoryPropertyFlags,
  1465. VkMemoryRequirements *pMemoryRequirements,
  1466. Uint32 *pCount)
  1467. {
  1468. renderer->vkGetImageMemoryRequirements(
  1469. renderer->logicalDevice,
  1470. image,
  1471. pMemoryRequirements);
  1472. return VULKAN_INTERNAL_FindBestMemoryTypes(
  1473. renderer,
  1474. pMemoryRequirements->memoryTypeBits,
  1475. 0,
  1476. preferredMemoryPropertyFlags,
  1477. 0,
  1478. pCount);
  1479. }
  1480. static void VULKAN_INTERNAL_DeallocateMemory(
  1481. VulkanRenderer *renderer,
  1482. VulkanMemorySubAllocator *allocator,
  1483. Uint32 allocationIndex)
  1484. {
  1485. Uint32 i;
  1486. VulkanMemoryAllocation *allocation = allocator->allocations[allocationIndex];
  1487. SDL_LockMutex(renderer->allocatorLock);
  1488. // If this allocation was marked for defrag, cancel that
  1489. for (i = 0; i < renderer->allocationsToDefragCount; i += 1) {
  1490. if (allocation == renderer->allocationsToDefrag[i]) {
  1491. renderer->allocationsToDefrag[i] = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
  1492. renderer->allocationsToDefragCount -= 1;
  1493. break;
  1494. }
  1495. }
  1496. for (i = 0; i < allocation->freeRegionCount; i += 1) {
  1497. VULKAN_INTERNAL_RemoveMemoryFreeRegion(
  1498. renderer,
  1499. allocation->freeRegions[i]);
  1500. }
  1501. SDL_free(allocation->freeRegions);
  1502. /* no need to iterate used regions because deallocate
  1503. * only happens when there are 0 used regions
  1504. */
  1505. SDL_free(allocation->usedRegions);
  1506. renderer->vkFreeMemory(
  1507. renderer->logicalDevice,
  1508. allocation->memory,
  1509. NULL);
  1510. SDL_DestroyMutex(allocation->memoryLock);
  1511. SDL_free(allocation);
  1512. if (allocationIndex != allocator->allocationCount - 1) {
  1513. allocator->allocations[allocationIndex] = allocator->allocations[allocator->allocationCount - 1];
  1514. }
  1515. allocator->allocationCount -= 1;
  1516. SDL_UnlockMutex(renderer->allocatorLock);
  1517. }
  1518. static Uint8 VULKAN_INTERNAL_AllocateMemory(
  1519. VulkanRenderer *renderer,
  1520. VkBuffer buffer,
  1521. VkImage image,
  1522. Uint32 memoryTypeIndex,
  1523. VkDeviceSize allocationSize,
  1524. Uint8 isHostVisible,
  1525. VulkanMemoryAllocation **pMemoryAllocation)
  1526. {
  1527. VulkanMemoryAllocation *allocation;
  1528. VulkanMemorySubAllocator *allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex];
  1529. VkMemoryAllocateInfo allocInfo;
  1530. VkResult result;
  1531. allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  1532. allocInfo.pNext = NULL;
  1533. allocInfo.memoryTypeIndex = memoryTypeIndex;
  1534. allocInfo.allocationSize = allocationSize;
  1535. allocation = SDL_malloc(sizeof(VulkanMemoryAllocation));
  1536. allocation->size = allocationSize;
  1537. allocation->freeSpace = 0; // added by FreeRegions
  1538. allocation->usedSpace = 0; // added by UsedRegions
  1539. allocation->memoryLock = SDL_CreateMutex();
  1540. allocator->allocationCount += 1;
  1541. allocator->allocations = SDL_realloc(
  1542. allocator->allocations,
  1543. sizeof(VulkanMemoryAllocation *) * allocator->allocationCount);
  1544. allocator->allocations[allocator->allocationCount - 1] = allocation;
  1545. allocInfo.pNext = NULL;
  1546. allocation->availableForAllocation = 1;
  1547. allocation->usedRegions = SDL_malloc(sizeof(VulkanMemoryUsedRegion *));
  1548. allocation->usedRegionCount = 0;
  1549. allocation->usedRegionCapacity = 1;
  1550. allocation->freeRegions = SDL_malloc(sizeof(VulkanMemoryFreeRegion *));
  1551. allocation->freeRegionCount = 0;
  1552. allocation->freeRegionCapacity = 1;
  1553. allocation->allocator = allocator;
  1554. result = renderer->vkAllocateMemory(
  1555. renderer->logicalDevice,
  1556. &allocInfo,
  1557. NULL,
  1558. &allocation->memory);
  1559. if (result != VK_SUCCESS) {
  1560. // Uh oh, we couldn't allocate, time to clean up
  1561. SDL_free(allocation->freeRegions);
  1562. allocator->allocationCount -= 1;
  1563. allocator->allocations = SDL_realloc(
  1564. allocator->allocations,
  1565. sizeof(VulkanMemoryAllocation *) * allocator->allocationCount);
  1566. SDL_free(allocation);
  1567. return 0;
  1568. }
  1569. // Persistent mapping for host-visible memory
  1570. if (isHostVisible) {
  1571. result = renderer->vkMapMemory(
  1572. renderer->logicalDevice,
  1573. allocation->memory,
  1574. 0,
  1575. VK_WHOLE_SIZE,
  1576. 0,
  1577. (void **)&allocation->mapPointer);
  1578. CHECK_VULKAN_ERROR_AND_RETURN(result, vkMapMemory, 0);
  1579. } else {
  1580. allocation->mapPointer = NULL;
  1581. }
  1582. VULKAN_INTERNAL_NewMemoryFreeRegion(
  1583. renderer,
  1584. allocation,
  1585. 0,
  1586. allocation->size);
  1587. *pMemoryAllocation = allocation;
  1588. return 1;
  1589. }
  1590. static Uint8 VULKAN_INTERNAL_BindBufferMemory(
  1591. VulkanRenderer *renderer,
  1592. VulkanMemoryUsedRegion *usedRegion,
  1593. VkDeviceSize alignedOffset,
  1594. VkBuffer buffer)
  1595. {
  1596. VkResult vulkanResult;
  1597. SDL_LockMutex(usedRegion->allocation->memoryLock);
  1598. vulkanResult = renderer->vkBindBufferMemory(
  1599. renderer->logicalDevice,
  1600. buffer,
  1601. usedRegion->allocation->memory,
  1602. alignedOffset);
  1603. SDL_UnlockMutex(usedRegion->allocation->memoryLock);
  1604. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkBindBufferMemory, 0);
  1605. return 1;
  1606. }
  1607. static Uint8 VULKAN_INTERNAL_BindImageMemory(
  1608. VulkanRenderer *renderer,
  1609. VulkanMemoryUsedRegion *usedRegion,
  1610. VkDeviceSize alignedOffset,
  1611. VkImage image)
  1612. {
  1613. VkResult vulkanResult;
  1614. SDL_LockMutex(usedRegion->allocation->memoryLock);
  1615. vulkanResult = renderer->vkBindImageMemory(
  1616. renderer->logicalDevice,
  1617. image,
  1618. usedRegion->allocation->memory,
  1619. alignedOffset);
  1620. SDL_UnlockMutex(usedRegion->allocation->memoryLock);
  1621. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkBindImageMemory, 0);
  1622. return 1;
  1623. }
  1624. static Uint8 VULKAN_INTERNAL_BindResourceMemory(
  1625. VulkanRenderer *renderer,
  1626. Uint32 memoryTypeIndex,
  1627. VkMemoryRequirements *memoryRequirements,
  1628. VkDeviceSize resourceSize, // may be different from requirements size!
  1629. bool dedicated, // the entire memory allocation should be used for this resource
  1630. VkBuffer buffer, // may be VK_NULL_HANDLE
  1631. VkImage image, // may be VK_NULL_HANDLE
  1632. VulkanMemoryUsedRegion **pMemoryUsedRegion)
  1633. {
  1634. VulkanMemoryAllocation *allocation;
  1635. VulkanMemorySubAllocator *allocator;
  1636. VulkanMemoryFreeRegion *region;
  1637. VulkanMemoryFreeRegion *selectedRegion;
  1638. VulkanMemoryUsedRegion *usedRegion;
  1639. VkDeviceSize requiredSize, allocationSize;
  1640. VkDeviceSize alignedOffset = 0;
  1641. VkDeviceSize newRegionSize, newRegionOffset;
  1642. Uint8 isHostVisible, smallAllocation, allocationResult;
  1643. Sint32 i;
  1644. isHostVisible =
  1645. (renderer->memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags &
  1646. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
  1647. allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex];
  1648. requiredSize = memoryRequirements->size;
  1649. smallAllocation = requiredSize <= SMALL_ALLOCATION_THRESHOLD;
  1650. if ((buffer == VK_NULL_HANDLE && image == VK_NULL_HANDLE) ||
  1651. (buffer != VK_NULL_HANDLE && image != VK_NULL_HANDLE)) {
  1652. SDL_LogError(SDL_LOG_CATEGORY_GPU, "BindResourceMemory must be given either a VulkanBuffer or a VulkanTexture");
  1653. return 0;
  1654. }
  1655. SDL_LockMutex(renderer->allocatorLock);
  1656. selectedRegion = NULL;
  1657. if (dedicated) {
  1658. // Force an allocation
  1659. allocationSize = requiredSize;
  1660. } else {
  1661. // Search for a suitable existing free region
  1662. for (i = allocator->sortedFreeRegionCount - 1; i >= 0; i -= 1) {
  1663. region = allocator->sortedFreeRegions[i];
  1664. if (smallAllocation && region->allocation->size != SMALL_ALLOCATION_SIZE) {
  1665. // region is not in a small allocation
  1666. continue;
  1667. }
  1668. if (!smallAllocation && region->allocation->size == SMALL_ALLOCATION_SIZE) {
  1669. // allocation is not small and current region is in a small allocation
  1670. continue;
  1671. }
  1672. alignedOffset = VULKAN_INTERNAL_NextHighestAlignment(
  1673. region->offset,
  1674. memoryRequirements->alignment);
  1675. if (alignedOffset + requiredSize <= region->offset + region->size) {
  1676. selectedRegion = region;
  1677. break;
  1678. }
  1679. }
  1680. if (selectedRegion != NULL) {
  1681. region = selectedRegion;
  1682. allocation = region->allocation;
  1683. usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion(
  1684. renderer,
  1685. allocation,
  1686. region->offset,
  1687. requiredSize + (alignedOffset - region->offset),
  1688. alignedOffset,
  1689. resourceSize,
  1690. memoryRequirements->alignment);
  1691. usedRegion->isBuffer = buffer != VK_NULL_HANDLE;
  1692. newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize);
  1693. newRegionOffset = alignedOffset + requiredSize;
  1694. // remove and add modified region to re-sort
  1695. VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region);
  1696. // if size is 0, no need to re-insert
  1697. if (newRegionSize != 0) {
  1698. VULKAN_INTERNAL_NewMemoryFreeRegion(
  1699. renderer,
  1700. allocation,
  1701. newRegionOffset,
  1702. newRegionSize);
  1703. }
  1704. SDL_UnlockMutex(renderer->allocatorLock);
  1705. if (buffer != VK_NULL_HANDLE) {
  1706. if (!VULKAN_INTERNAL_BindBufferMemory(
  1707. renderer,
  1708. usedRegion,
  1709. alignedOffset,
  1710. buffer)) {
  1711. VULKAN_INTERNAL_RemoveMemoryUsedRegion(
  1712. renderer,
  1713. usedRegion);
  1714. return 0;
  1715. }
  1716. } else if (image != VK_NULL_HANDLE) {
  1717. if (!VULKAN_INTERNAL_BindImageMemory(
  1718. renderer,
  1719. usedRegion,
  1720. alignedOffset,
  1721. image)) {
  1722. VULKAN_INTERNAL_RemoveMemoryUsedRegion(
  1723. renderer,
  1724. usedRegion);
  1725. return 0;
  1726. }
  1727. }
  1728. *pMemoryUsedRegion = usedRegion;
  1729. return 1;
  1730. }
  1731. // No suitable free regions exist, allocate a new memory region
  1732. if (
  1733. renderer->allocationsToDefragCount == 0 &&
  1734. !renderer->defragInProgress) {
  1735. // Mark currently fragmented allocations for defrag
  1736. VULKAN_INTERNAL_MarkAllocationsForDefrag(renderer);
  1737. }
  1738. if (requiredSize > SMALL_ALLOCATION_THRESHOLD) {
  1739. // allocate a page of required size aligned to LARGE_ALLOCATION_INCREMENT increments
  1740. allocationSize =
  1741. VULKAN_INTERNAL_NextHighestAlignment(requiredSize, LARGE_ALLOCATION_INCREMENT);
  1742. } else {
  1743. allocationSize = SMALL_ALLOCATION_SIZE;
  1744. }
  1745. }
  1746. allocationResult = VULKAN_INTERNAL_AllocateMemory(
  1747. renderer,
  1748. buffer,
  1749. image,
  1750. memoryTypeIndex,
  1751. allocationSize,
  1752. isHostVisible,
  1753. &allocation);
  1754. // Uh oh, we're out of memory
  1755. if (allocationResult == 0) {
  1756. SDL_UnlockMutex(renderer->allocatorLock);
  1757. // Responsibility of the caller to handle being out of memory
  1758. return 2;
  1759. }
  1760. usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion(
  1761. renderer,
  1762. allocation,
  1763. 0,
  1764. requiredSize,
  1765. 0,
  1766. resourceSize,
  1767. memoryRequirements->alignment);
  1768. usedRegion->isBuffer = buffer != VK_NULL_HANDLE;
  1769. region = allocation->freeRegions[0];
  1770. newRegionOffset = region->offset + requiredSize;
  1771. newRegionSize = region->size - requiredSize;
  1772. VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region);
  1773. if (newRegionSize != 0) {
  1774. VULKAN_INTERNAL_NewMemoryFreeRegion(
  1775. renderer,
  1776. allocation,
  1777. newRegionOffset,
  1778. newRegionSize);
  1779. }
  1780. SDL_UnlockMutex(renderer->allocatorLock);
  1781. if (buffer != VK_NULL_HANDLE) {
  1782. if (!VULKAN_INTERNAL_BindBufferMemory(
  1783. renderer,
  1784. usedRegion,
  1785. 0,
  1786. buffer)) {
  1787. VULKAN_INTERNAL_RemoveMemoryUsedRegion(
  1788. renderer,
  1789. usedRegion);
  1790. return 0;
  1791. }
  1792. } else if (image != VK_NULL_HANDLE) {
  1793. if (!VULKAN_INTERNAL_BindImageMemory(
  1794. renderer,
  1795. usedRegion,
  1796. 0,
  1797. image)) {
  1798. VULKAN_INTERNAL_RemoveMemoryUsedRegion(
  1799. renderer,
  1800. usedRegion);
  1801. return 0;
  1802. }
  1803. }
  1804. *pMemoryUsedRegion = usedRegion;
  1805. return 1;
  1806. }
  1807. static Uint8 VULKAN_INTERNAL_BindMemoryForImage(
  1808. VulkanRenderer *renderer,
  1809. VkImage image,
  1810. VulkanMemoryUsedRegion **usedRegion)
  1811. {
  1812. Uint8 bindResult = 0;
  1813. Uint32 memoryTypeCount = 0;
  1814. Uint32 *memoryTypesToTry = NULL;
  1815. Uint32 selectedMemoryTypeIndex = 0;
  1816. Uint32 i;
  1817. VkMemoryPropertyFlags preferredMemoryPropertyFlags;
  1818. VkMemoryRequirements memoryRequirements;
  1819. /* Vulkan memory types have several memory properties.
  1820. *
  1821. * Unlike buffers, images are always optimally stored device-local,
  1822. * so that is the only property we prefer here.
  1823. *
  1824. * If memory is constrained, it is fine for the texture to not
  1825. * be device-local.
  1826. */
  1827. preferredMemoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
  1828. memoryTypesToTry = VULKAN_INTERNAL_FindBestImageMemoryTypes(
  1829. renderer,
  1830. image,
  1831. preferredMemoryPropertyFlags,
  1832. &memoryRequirements,
  1833. &memoryTypeCount);
  1834. for (i = 0; i < memoryTypeCount; i += 1) {
  1835. bindResult = VULKAN_INTERNAL_BindResourceMemory(
  1836. renderer,
  1837. memoryTypesToTry[i],
  1838. &memoryRequirements,
  1839. memoryRequirements.size,
  1840. false,
  1841. VK_NULL_HANDLE,
  1842. image,
  1843. usedRegion);
  1844. if (bindResult == 1) {
  1845. selectedMemoryTypeIndex = memoryTypesToTry[i];
  1846. break;
  1847. }
  1848. }
  1849. SDL_free(memoryTypesToTry);
  1850. // Check for warnings on success
  1851. if (bindResult == 1) {
  1852. if (!renderer->outOfDeviceLocalMemoryWarning) {
  1853. if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) {
  1854. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Out of device-local memory, allocating textures on host-local memory!");
  1855. renderer->outOfDeviceLocalMemoryWarning = 1;
  1856. }
  1857. }
  1858. }
  1859. return bindResult;
  1860. }
  1861. static Uint8 VULKAN_INTERNAL_BindMemoryForBuffer(
  1862. VulkanRenderer *renderer,
  1863. VkBuffer buffer,
  1864. VkDeviceSize size,
  1865. VulkanBufferType type,
  1866. bool dedicated,
  1867. VulkanMemoryUsedRegion **usedRegion)
  1868. {
  1869. Uint8 bindResult = 0;
  1870. Uint32 memoryTypeCount = 0;
  1871. Uint32 *memoryTypesToTry = NULL;
  1872. Uint32 selectedMemoryTypeIndex = 0;
  1873. Uint32 i;
  1874. VkMemoryPropertyFlags requiredMemoryPropertyFlags = 0;
  1875. VkMemoryPropertyFlags preferredMemoryPropertyFlags = 0;
  1876. VkMemoryPropertyFlags tolerableMemoryPropertyFlags = 0;
  1877. VkMemoryRequirements memoryRequirements;
  1878. /* Buffers need to be optimally bound to a memory type
  1879. * based on their use case and the architecture of the system.
  1880. *
  1881. * It is important to understand the distinction between device and host.
  1882. *
  1883. * On a traditional high-performance desktop computer,
  1884. * the "device" would be the GPU, and the "host" would be the CPU.
  1885. * Memory being copied between these two must cross the PCI bus.
  1886. * On these systems we have to be concerned about bandwidth limitations
  1887. * and causing memory stalls, so we have taken a great deal of care
  1888. * to structure this API to guide the client towards optimal usage.
  1889. *
  1890. * Other kinds of devices do not necessarily have this distinction.
  1891. * On an iPhone or Nintendo Switch, all memory is accessible both to the
  1892. * GPU and the CPU at all times. These kinds of systems are known as
  1893. * UMA, or Unified Memory Architecture. A desktop computer using the
  1894. * CPU's integrated graphics can also be thought of as UMA.
  1895. *
  1896. * Vulkan memory types have several memory properties.
  1897. * The relevant memory properties are as follows:
  1898. *
  1899. * DEVICE_LOCAL:
  1900. * This memory is on-device and most efficient for device access.
  1901. * On UMA systems all memory is device-local.
  1902. * If memory is not device-local, then it is host-local.
  1903. *
  1904. * HOST_VISIBLE:
  1905. * This memory can be mapped for host access, meaning we can obtain
  1906. * a pointer to directly access the memory.
  1907. *
  1908. * HOST_COHERENT:
  1909. * Host-coherent memory does not require cache management operations
  1910. * when mapped, so we always set this alongside HOST_VISIBLE
  1911. * to avoid extra record keeping.
  1912. *
  1913. * HOST_CACHED:
  1914. * Host-cached memory is faster to access than uncached memory
  1915. * but memory of this type might not always be available.
  1916. *
  1917. * GPU buffers, like vertex buffers, indirect buffers, etc
  1918. * are optimally stored in device-local memory.
  1919. * However, if device-local memory is low, these buffers
  1920. * can be accessed from host-local memory with a performance penalty.
  1921. *
  1922. * Uniform buffers must be host-visible and coherent because
  1923. * the client uses them to quickly push small amounts of data.
  1924. * We prefer uniform buffers to also be device-local because
  1925. * they are accessed by shaders, but the amount of memory
  1926. * that is both device-local and host-visible
  1927. * is often constrained, particularly on low-end devices.
  1928. *
  1929. * Transfer buffers must be host-visible and coherent because
  1930. * the client uses them to stage data to be transferred
  1931. * to device-local memory, or to read back data transferred
  1932. * from the device. We prefer the cache bit for performance
  1933. * but it isn't strictly necessary. We tolerate device-local
  1934. * memory in this situation because, as mentioned above,
  1935. * on certain devices all memory is device-local, and even
  1936. * though the transfer isn't strictly necessary it is still
  1937. * useful for correctly timelining data.
  1938. */
  1939. if (type == VULKAN_BUFFER_TYPE_GPU) {
  1940. preferredMemoryPropertyFlags |=
  1941. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
  1942. } else if (type == VULKAN_BUFFER_TYPE_UNIFORM) {
  1943. requiredMemoryPropertyFlags |=
  1944. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  1945. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
  1946. preferredMemoryPropertyFlags |=
  1947. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
  1948. } else if (type == VULKAN_BUFFER_TYPE_TRANSFER) {
  1949. requiredMemoryPropertyFlags |=
  1950. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  1951. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
  1952. preferredMemoryPropertyFlags |=
  1953. VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
  1954. tolerableMemoryPropertyFlags |=
  1955. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
  1956. } else {
  1957. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer type!");
  1958. return 0;
  1959. }
  1960. memoryTypesToTry = VULKAN_INTERNAL_FindBestBufferMemoryTypes(
  1961. renderer,
  1962. buffer,
  1963. requiredMemoryPropertyFlags,
  1964. preferredMemoryPropertyFlags,
  1965. tolerableMemoryPropertyFlags,
  1966. &memoryRequirements,
  1967. &memoryTypeCount);
  1968. for (i = 0; i < memoryTypeCount; i += 1) {
  1969. bindResult = VULKAN_INTERNAL_BindResourceMemory(
  1970. renderer,
  1971. memoryTypesToTry[i],
  1972. &memoryRequirements,
  1973. size,
  1974. dedicated,
  1975. buffer,
  1976. VK_NULL_HANDLE,
  1977. usedRegion);
  1978. if (bindResult == 1) {
  1979. selectedMemoryTypeIndex = memoryTypesToTry[i];
  1980. break;
  1981. }
  1982. }
  1983. SDL_free(memoryTypesToTry);
  1984. // Check for warnings on success
  1985. if (bindResult == 1) {
  1986. if (type == VULKAN_BUFFER_TYPE_GPU) {
  1987. if (!renderer->outOfDeviceLocalMemoryWarning) {
  1988. if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) {
  1989. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Out of device-local memory, allocating buffers on host-local memory, expect degraded performance!");
  1990. renderer->outOfDeviceLocalMemoryWarning = 1;
  1991. }
  1992. }
  1993. } else if (type == VULKAN_BUFFER_TYPE_UNIFORM) {
  1994. if (!renderer->outofBARMemoryWarning) {
  1995. if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) {
  1996. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Out of BAR memory, allocating uniform buffers on host-local memory, expect degraded performance!");
  1997. renderer->outofBARMemoryWarning = 1;
  1998. }
  1999. }
  2000. } else if (type == VULKAN_BUFFER_TYPE_TRANSFER) {
  2001. if (!renderer->integratedMemoryNotification) {
  2002. if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
  2003. SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Integrated memory detected, allocating TransferBuffers on device-local memory!");
  2004. renderer->integratedMemoryNotification = 1;
  2005. }
  2006. }
  2007. }
  2008. }
  2009. return bindResult;
  2010. }
  2011. // Resource tracking
  2012. #define ADD_TO_ARRAY_UNIQUE(resource, type, array, count, capacity) \
  2013. Uint32 i; \
  2014. \
  2015. for (i = 0; i < commandBuffer->count; i += 1) { \
  2016. if (commandBuffer->array[i] == resource) { \
  2017. return; \
  2018. } \
  2019. } \
  2020. \
  2021. if (commandBuffer->count == commandBuffer->capacity) { \
  2022. commandBuffer->capacity += 1; \
  2023. commandBuffer->array = SDL_realloc( \
  2024. commandBuffer->array, \
  2025. commandBuffer->capacity * sizeof(type)); \
  2026. } \
  2027. commandBuffer->array[commandBuffer->count] = resource; \
  2028. commandBuffer->count += 1;
  2029. #define TRACK_RESOURCE(resource, type, array, count, capacity) \
  2030. for (Sint32 i = commandBuffer->count - 1; i >= 0; i -= 1) { \
  2031. if (commandBuffer->array[i] == resource) { \
  2032. return; \
  2033. } \
  2034. } \
  2035. \
  2036. if (commandBuffer->count == commandBuffer->capacity) { \
  2037. commandBuffer->capacity += 1; \
  2038. commandBuffer->array = SDL_realloc( \
  2039. commandBuffer->array, \
  2040. commandBuffer->capacity * sizeof(type)); \
  2041. } \
  2042. commandBuffer->array[commandBuffer->count] = resource; \
  2043. commandBuffer->count += 1; \
  2044. SDL_AtomicIncRef(&resource->referenceCount);
  2045. static void VULKAN_INTERNAL_TrackBuffer(
  2046. VulkanCommandBuffer *commandBuffer,
  2047. VulkanBuffer *buffer)
  2048. {
  2049. TRACK_RESOURCE(
  2050. buffer,
  2051. VulkanBuffer *,
  2052. usedBuffers,
  2053. usedBufferCount,
  2054. usedBufferCapacity)
  2055. }
  2056. static void VULKAN_INTERNAL_TrackTexture(
  2057. VulkanCommandBuffer *commandBuffer,
  2058. VulkanTexture *texture)
  2059. {
  2060. TRACK_RESOURCE(
  2061. texture,
  2062. VulkanTexture *,
  2063. usedTextures,
  2064. usedTextureCount,
  2065. usedTextureCapacity)
  2066. }
  2067. static void VULKAN_INTERNAL_TrackSampler(
  2068. VulkanCommandBuffer *commandBuffer,
  2069. VulkanSampler *sampler)
  2070. {
  2071. TRACK_RESOURCE(
  2072. sampler,
  2073. VulkanSampler *,
  2074. usedSamplers,
  2075. usedSamplerCount,
  2076. usedSamplerCapacity)
  2077. }
  2078. static void VULKAN_INTERNAL_TrackGraphicsPipeline(
  2079. VulkanCommandBuffer *commandBuffer,
  2080. VulkanGraphicsPipeline *graphicsPipeline)
  2081. {
  2082. TRACK_RESOURCE(
  2083. graphicsPipeline,
  2084. VulkanGraphicsPipeline *,
  2085. usedGraphicsPipelines,
  2086. usedGraphicsPipelineCount,
  2087. usedGraphicsPipelineCapacity)
  2088. }
  2089. static void VULKAN_INTERNAL_TrackComputePipeline(
  2090. VulkanCommandBuffer *commandBuffer,
  2091. VulkanComputePipeline *computePipeline)
  2092. {
  2093. TRACK_RESOURCE(
  2094. computePipeline,
  2095. VulkanComputePipeline *,
  2096. usedComputePipelines,
  2097. usedComputePipelineCount,
  2098. usedComputePipelineCapacity)
  2099. }
  2100. static void VULKAN_INTERNAL_TrackFramebuffer(
  2101. VulkanRenderer *renderer,
  2102. VulkanCommandBuffer *commandBuffer,
  2103. VulkanFramebuffer *framebuffer)
  2104. {
  2105. TRACK_RESOURCE(
  2106. framebuffer,
  2107. VulkanFramebuffer *,
  2108. usedFramebuffers,
  2109. usedFramebufferCount,
  2110. usedFramebufferCapacity);
  2111. }
  2112. static void VULKAN_INTERNAL_TrackUniformBuffer(
  2113. VulkanCommandBuffer *commandBuffer,
  2114. VulkanUniformBuffer *uniformBuffer)
  2115. {
  2116. for (Sint32 i = commandBuffer->usedUniformBufferCount - 1; i >= 0; i -= 1) {
  2117. if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) {
  2118. return;
  2119. }
  2120. }
  2121. if (commandBuffer->usedUniformBufferCount == commandBuffer->usedUniformBufferCapacity) {
  2122. commandBuffer->usedUniformBufferCapacity += 1;
  2123. commandBuffer->usedUniformBuffers = SDL_realloc(
  2124. commandBuffer->usedUniformBuffers,
  2125. commandBuffer->usedUniformBufferCapacity * sizeof(VulkanUniformBuffer *));
  2126. }
  2127. commandBuffer->usedUniformBuffers[commandBuffer->usedUniformBufferCount] = uniformBuffer;
  2128. commandBuffer->usedUniformBufferCount += 1;
  2129. VULKAN_INTERNAL_TrackBuffer(
  2130. commandBuffer,
  2131. uniformBuffer->buffer);
  2132. }
  2133. #undef TRACK_RESOURCE
  2134. // Memory Barriers
  2135. /*
  2136. * In Vulkan, we must manually synchronize operations that write to resources on the GPU
  2137. * so that read-after-write, write-after-read, and write-after-write hazards do not occur.
  2138. * Additionally, textures are required to be in specific layouts for specific use cases.
  2139. * Both of these tasks are accomplished with vkCmdPipelineBarrier.
  2140. *
  2141. * To insert the correct barriers, we keep track of "usage modes" for buffers and textures.
  2142. * These indicate the current usage of that resource on the command buffer.
  2143. * The transition from one usage mode to another indicates how the barrier should be constructed.
  2144. *
  2145. * Pipeline barriers cannot be inserted during a render pass, but they can be inserted
  2146. * during a compute or copy pass.
  2147. *
  2148. * This means that the "default" usage mode of any given resource should be that it should be
  2149. * ready for a graphics-read operation, because we cannot barrier during a render pass.
  2150. * In the case where a resource is only used in compute, its default usage mode can be compute-read.
  2151. * This strategy allows us to avoid expensive record keeping of command buffer/resource usage mode pairs,
  2152. * and it fully covers synchronization between all combinations of stages.
  2153. *
  2154. * In Upload and Copy functions, we transition the resource immediately before and after the copy command.
  2155. *
  2156. * When binding a resource for compute, we transition when the Bind functions are called.
  2157. * If a bind slot containing a resource is overwritten, we transition the resource in that slot back to its default.
  2158. * When EndComputePass is called we transition all bound resources back to their default state.
  2159. *
  2160. * When binding a texture as a render pass attachment, we transition the resource on BeginRenderPass
  2161. * and transition it back to its default on EndRenderPass.
  2162. *
  2163. * This strategy imposes certain limitations on resource usage flags.
  2164. * For example, a texture cannot have both the SAMPLER and GRAPHICS_STORAGE usage flags,
  2165. * because then it is impossible for the backend to infer which default usage mode the texture should use.
  2166. *
  2167. * Sync hazards can be detected by setting VK_KHRONOS_VALIDATION_VALIDATE_SYNC=1 when using validation layers.
  2168. */
  2169. static void VULKAN_INTERNAL_BufferMemoryBarrier(
  2170. VulkanRenderer *renderer,
  2171. VulkanCommandBuffer *commandBuffer,
  2172. VulkanBufferUsageMode sourceUsageMode,
  2173. VulkanBufferUsageMode destinationUsageMode,
  2174. VulkanBuffer *buffer)
  2175. {
  2176. VkPipelineStageFlags srcStages = 0;
  2177. VkPipelineStageFlags dstStages = 0;
  2178. VkBufferMemoryBarrier memoryBarrier;
  2179. memoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
  2180. memoryBarrier.pNext = NULL;
  2181. memoryBarrier.srcAccessMask = 0;
  2182. memoryBarrier.dstAccessMask = 0;
  2183. memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  2184. memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  2185. memoryBarrier.buffer = buffer->buffer;
  2186. memoryBarrier.offset = 0;
  2187. memoryBarrier.size = buffer->size;
  2188. if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE) {
  2189. srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
  2190. memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
  2191. } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION) {
  2192. srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
  2193. memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  2194. } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_VERTEX_READ) {
  2195. srcStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
  2196. memoryBarrier.srcAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
  2197. } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_INDEX_READ) {
  2198. srcStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
  2199. memoryBarrier.srcAccessMask = VK_ACCESS_INDEX_READ_BIT;
  2200. } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_INDIRECT) {
  2201. srcStages = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
  2202. memoryBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
  2203. } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ) {
  2204. srcStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  2205. memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2206. } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ) {
  2207. srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  2208. memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2209. } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
  2210. srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  2211. memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
  2212. } else {
  2213. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer source barrier type!");
  2214. return;
  2215. }
  2216. if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE) {
  2217. dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
  2218. memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
  2219. } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION) {
  2220. dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
  2221. memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  2222. } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_VERTEX_READ) {
  2223. dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
  2224. memoryBarrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
  2225. } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_INDEX_READ) {
  2226. dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
  2227. memoryBarrier.dstAccessMask = VK_ACCESS_INDEX_READ_BIT;
  2228. } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_INDIRECT) {
  2229. dstStages = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
  2230. memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
  2231. } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ) {
  2232. dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  2233. memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2234. } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ) {
  2235. dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  2236. memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2237. } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
  2238. dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  2239. memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
  2240. } else {
  2241. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer destination barrier type!");
  2242. return;
  2243. }
  2244. renderer->vkCmdPipelineBarrier(
  2245. commandBuffer->commandBuffer,
  2246. srcStages,
  2247. dstStages,
  2248. 0,
  2249. 0,
  2250. NULL,
  2251. 1,
  2252. &memoryBarrier,
  2253. 0,
  2254. NULL);
  2255. buffer->transitioned = true;
  2256. }
  2257. static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
  2258. VulkanRenderer *renderer,
  2259. VulkanCommandBuffer *commandBuffer,
  2260. VulkanTextureUsageMode sourceUsageMode,
  2261. VulkanTextureUsageMode destinationUsageMode,
  2262. VulkanTextureSubresource *textureSubresource)
  2263. {
  2264. VkPipelineStageFlags srcStages = 0;
  2265. VkPipelineStageFlags dstStages = 0;
  2266. VkImageMemoryBarrier memoryBarrier;
  2267. memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  2268. memoryBarrier.pNext = NULL;
  2269. memoryBarrier.srcAccessMask = 0;
  2270. memoryBarrier.dstAccessMask = 0;
  2271. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  2272. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  2273. memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  2274. memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  2275. memoryBarrier.image = textureSubresource->parent->image;
  2276. memoryBarrier.subresourceRange.aspectMask = textureSubresource->parent->aspectFlags;
  2277. memoryBarrier.subresourceRange.baseArrayLayer = textureSubresource->layer;
  2278. memoryBarrier.subresourceRange.layerCount = 1;
  2279. memoryBarrier.subresourceRange.baseMipLevel = textureSubresource->level;
  2280. memoryBarrier.subresourceRange.levelCount = 1;
  2281. if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED) {
  2282. srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  2283. memoryBarrier.srcAccessMask = 0;
  2284. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  2285. } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE) {
  2286. srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
  2287. memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
  2288. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  2289. } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION) {
  2290. srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
  2291. memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  2292. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  2293. } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_SAMPLER) {
  2294. srcStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  2295. memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2296. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  2297. } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ) {
  2298. srcStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  2299. memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2300. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
  2301. } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ) {
  2302. srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  2303. memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2304. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
  2305. } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
  2306. srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  2307. memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
  2308. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
  2309. } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT) {
  2310. srcStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  2311. memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  2312. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  2313. } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT) {
  2314. srcStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  2315. memoryBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  2316. memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  2317. } else {
  2318. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized texture source barrier type!");
  2319. return;
  2320. }
  2321. if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE) {
  2322. dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
  2323. memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
  2324. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  2325. } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION) {
  2326. dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
  2327. memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  2328. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  2329. } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_SAMPLER) {
  2330. dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  2331. memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2332. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  2333. } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ) {
  2334. dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  2335. memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2336. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
  2337. } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ) {
  2338. dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  2339. memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  2340. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
  2341. } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
  2342. dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
  2343. memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
  2344. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
  2345. } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT) {
  2346. dstStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  2347. memoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  2348. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  2349. } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT) {
  2350. dstStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  2351. memoryBarrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  2352. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  2353. } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_PRESENT) {
  2354. dstStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  2355. memoryBarrier.dstAccessMask = 0;
  2356. memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  2357. } else {
  2358. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized texture destination barrier type!");
  2359. return;
  2360. }
  2361. renderer->vkCmdPipelineBarrier(
  2362. commandBuffer->commandBuffer,
  2363. srcStages,
  2364. dstStages,
  2365. 0,
  2366. 0,
  2367. NULL,
  2368. 0,
  2369. NULL,
  2370. 1,
  2371. &memoryBarrier);
  2372. }
  2373. static VulkanBufferUsageMode VULKAN_INTERNAL_DefaultBufferUsageMode(
  2374. VulkanBuffer *buffer)
  2375. {
  2376. // NOTE: order matters here!
  2377. if (buffer->usage & SDL_GPU_BUFFERUSAGE_VERTEX) {
  2378. return VULKAN_BUFFER_USAGE_MODE_VERTEX_READ;
  2379. } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_INDEX) {
  2380. return VULKAN_BUFFER_USAGE_MODE_INDEX_READ;
  2381. } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_INDIRECT) {
  2382. return VULKAN_BUFFER_USAGE_MODE_INDIRECT;
  2383. } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ) {
  2384. return VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ;
  2385. } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ) {
  2386. return VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ;
  2387. } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE) {
  2388. return VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE;
  2389. } else {
  2390. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Buffer has no default usage mode!");
  2391. return VULKAN_BUFFER_USAGE_MODE_VERTEX_READ;
  2392. }
  2393. }
  2394. static VulkanTextureUsageMode VULKAN_INTERNAL_DefaultTextureUsageMode(
  2395. VulkanTexture *texture)
  2396. {
  2397. // NOTE: order matters here!
  2398. // NOTE: graphics storage bits and sampler bit are mutually exclusive!
  2399. if (texture->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) {
  2400. return VULKAN_TEXTURE_USAGE_MODE_SAMPLER;
  2401. } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) {
  2402. return VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ;
  2403. } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
  2404. return VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT;
  2405. } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
  2406. return VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT;
  2407. } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ) {
  2408. return VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ;
  2409. } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) {
  2410. return VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE;
  2411. } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE) {
  2412. return VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE;
  2413. } else {
  2414. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Texture has no default usage mode!");
  2415. return VULKAN_TEXTURE_USAGE_MODE_SAMPLER;
  2416. }
  2417. }
  2418. static void VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
  2419. VulkanRenderer *renderer,
  2420. VulkanCommandBuffer *commandBuffer,
  2421. VulkanBufferUsageMode destinationUsageMode,
  2422. VulkanBuffer *buffer)
  2423. {
  2424. VULKAN_INTERNAL_BufferMemoryBarrier(
  2425. renderer,
  2426. commandBuffer,
  2427. VULKAN_INTERNAL_DefaultBufferUsageMode(buffer),
  2428. destinationUsageMode,
  2429. buffer);
  2430. }
  2431. static void VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
  2432. VulkanRenderer *renderer,
  2433. VulkanCommandBuffer *commandBuffer,
  2434. VulkanBufferUsageMode sourceUsageMode,
  2435. VulkanBuffer *buffer)
  2436. {
  2437. VULKAN_INTERNAL_BufferMemoryBarrier(
  2438. renderer,
  2439. commandBuffer,
  2440. sourceUsageMode,
  2441. VULKAN_INTERNAL_DefaultBufferUsageMode(buffer),
  2442. buffer);
  2443. }
  2444. static void VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  2445. VulkanRenderer *renderer,
  2446. VulkanCommandBuffer *commandBuffer,
  2447. VulkanTextureUsageMode destinationUsageMode,
  2448. VulkanTextureSubresource *textureSubresource)
  2449. {
  2450. VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
  2451. renderer,
  2452. commandBuffer,
  2453. VULKAN_INTERNAL_DefaultTextureUsageMode(textureSubresource->parent),
  2454. destinationUsageMode,
  2455. textureSubresource);
  2456. }
  2457. static void VULKAN_INTERNAL_TextureTransitionFromDefaultUsage(
  2458. VulkanRenderer *renderer,
  2459. VulkanCommandBuffer *commandBuffer,
  2460. VulkanTextureUsageMode destinationUsageMode,
  2461. VulkanTexture *texture)
  2462. {
  2463. for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
  2464. VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  2465. renderer,
  2466. commandBuffer,
  2467. destinationUsageMode,
  2468. &texture->subresources[i]);
  2469. }
  2470. }
  2471. static void VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  2472. VulkanRenderer *renderer,
  2473. VulkanCommandBuffer *commandBuffer,
  2474. VulkanTextureUsageMode sourceUsageMode,
  2475. VulkanTextureSubresource *textureSubresource)
  2476. {
  2477. VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
  2478. renderer,
  2479. commandBuffer,
  2480. sourceUsageMode,
  2481. VULKAN_INTERNAL_DefaultTextureUsageMode(textureSubresource->parent),
  2482. textureSubresource);
  2483. }
  2484. static void VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
  2485. VulkanRenderer *renderer,
  2486. VulkanCommandBuffer *commandBuffer,
  2487. VulkanTextureUsageMode sourceUsageMode,
  2488. VulkanTexture *texture)
  2489. {
  2490. // FIXME: could optimize this barrier
  2491. for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
  2492. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  2493. renderer,
  2494. commandBuffer,
  2495. sourceUsageMode,
  2496. &texture->subresources[i]);
  2497. }
  2498. }
  2499. // Resource Disposal
  2500. static void VULKAN_INTERNAL_ReleaseFramebuffer(
  2501. VulkanRenderer *renderer,
  2502. VulkanFramebuffer *framebuffer)
  2503. {
  2504. SDL_LockMutex(renderer->disposeLock);
  2505. EXPAND_ARRAY_IF_NEEDED(
  2506. renderer->framebuffersToDestroy,
  2507. VulkanFramebuffer *,
  2508. renderer->framebuffersToDestroyCount + 1,
  2509. renderer->framebuffersToDestroyCapacity,
  2510. renderer->framebuffersToDestroyCapacity * 2);
  2511. renderer->framebuffersToDestroy[renderer->framebuffersToDestroyCount] = framebuffer;
  2512. renderer->framebuffersToDestroyCount += 1;
  2513. SDL_UnlockMutex(renderer->disposeLock);
  2514. }
  2515. static void VULKAN_INTERNAL_DestroyFramebuffer(
  2516. VulkanRenderer *renderer,
  2517. VulkanFramebuffer *framebuffer)
  2518. {
  2519. renderer->vkDestroyFramebuffer(
  2520. renderer->logicalDevice,
  2521. framebuffer->framebuffer,
  2522. NULL);
  2523. SDL_free(framebuffer);
  2524. }
  2525. typedef struct CheckOneFramebufferForRemovalData
  2526. {
  2527. Uint32 keysToRemoveCapacity;
  2528. Uint32 keysToRemoveCount;
  2529. FramebufferHashTableKey **keysToRemove;
  2530. VkImageView view;
  2531. } CheckOneFramebufferForRemovalData;
  2532. static bool SDLCALL CheckOneFramebufferForRemoval(void *userdata, const SDL_HashTable *table, const void *vkey, const void *vvalue)
  2533. {
  2534. CheckOneFramebufferForRemovalData *data = (CheckOneFramebufferForRemovalData *) userdata;
  2535. FramebufferHashTableKey *key = (FramebufferHashTableKey *) vkey;
  2536. VkImageView view = data->view;
  2537. bool remove = false;
  2538. for (Uint32 i = 0; i < key->numColorTargets; i += 1) {
  2539. if (key->colorAttachmentViews[i] == view) {
  2540. remove = true;
  2541. }
  2542. }
  2543. for (Uint32 i = 0; i < key->numResolveAttachments; i += 1) {
  2544. if (key->resolveAttachmentViews[i] == view) {
  2545. remove = true;
  2546. }
  2547. }
  2548. if (key->depthStencilAttachmentView == view) {
  2549. remove = true;
  2550. }
  2551. if (remove) {
  2552. if (data->keysToRemoveCount == data->keysToRemoveCapacity) {
  2553. data->keysToRemoveCapacity *= 2;
  2554. void *ptr = SDL_realloc(data->keysToRemove, data->keysToRemoveCapacity * sizeof(FramebufferHashTableKey *));
  2555. if (!ptr) {
  2556. return false; // ugh, stop iterating. We're in trouble.
  2557. }
  2558. data->keysToRemove = (FramebufferHashTableKey **) ptr;
  2559. }
  2560. data->keysToRemove[data->keysToRemoveCount] = key;
  2561. data->keysToRemoveCount++;
  2562. }
  2563. return true; // keep iterating.
  2564. }
  2565. static void VULKAN_INTERNAL_RemoveFramebuffersContainingView(
  2566. VulkanRenderer *renderer,
  2567. VkImageView view)
  2568. {
  2569. // Can't remove while iterating!
  2570. CheckOneFramebufferForRemovalData data = { 8, 0, NULL, view };
  2571. data.keysToRemove = (FramebufferHashTableKey **) SDL_malloc(data.keysToRemoveCapacity * sizeof(FramebufferHashTableKey *));
  2572. if (!data.keysToRemove) {
  2573. return; // uhoh.
  2574. }
  2575. SDL_LockMutex(renderer->framebufferFetchLock);
  2576. SDL_IterateHashTable(renderer->framebufferHashTable, CheckOneFramebufferForRemoval, &data);
  2577. for (Uint32 i = 0; i < data.keysToRemoveCount; i += 1) {
  2578. SDL_RemoveFromHashTable(renderer->framebufferHashTable, (void *)data.keysToRemove[i]);
  2579. }
  2580. SDL_UnlockMutex(renderer->framebufferFetchLock);
  2581. SDL_free(data.keysToRemove);
  2582. }
  2583. static void VULKAN_INTERNAL_DestroyTexture(
  2584. VulkanRenderer *renderer,
  2585. VulkanTexture *texture)
  2586. {
  2587. // Clean up subresources
  2588. for (Uint32 subresourceIndex = 0; subresourceIndex < texture->subresourceCount; subresourceIndex += 1) {
  2589. if (texture->subresources[subresourceIndex].renderTargetViews != NULL) {
  2590. for (Uint32 depthIndex = 0; depthIndex < texture->depth; depthIndex += 1) {
  2591. VULKAN_INTERNAL_RemoveFramebuffersContainingView(
  2592. renderer,
  2593. texture->subresources[subresourceIndex].renderTargetViews[depthIndex]);
  2594. }
  2595. for (Uint32 depthIndex = 0; depthIndex < texture->depth; depthIndex += 1) {
  2596. renderer->vkDestroyImageView(
  2597. renderer->logicalDevice,
  2598. texture->subresources[subresourceIndex].renderTargetViews[depthIndex],
  2599. NULL);
  2600. }
  2601. SDL_free(texture->subresources[subresourceIndex].renderTargetViews);
  2602. }
  2603. if (texture->subresources[subresourceIndex].computeWriteView != VK_NULL_HANDLE) {
  2604. renderer->vkDestroyImageView(
  2605. renderer->logicalDevice,
  2606. texture->subresources[subresourceIndex].computeWriteView,
  2607. NULL);
  2608. }
  2609. if (texture->subresources[subresourceIndex].depthStencilView != VK_NULL_HANDLE) {
  2610. VULKAN_INTERNAL_RemoveFramebuffersContainingView(
  2611. renderer,
  2612. texture->subresources[subresourceIndex].depthStencilView);
  2613. renderer->vkDestroyImageView(
  2614. renderer->logicalDevice,
  2615. texture->subresources[subresourceIndex].depthStencilView,
  2616. NULL);
  2617. }
  2618. }
  2619. SDL_free(texture->subresources);
  2620. if (texture->fullView) {
  2621. renderer->vkDestroyImageView(
  2622. renderer->logicalDevice,
  2623. texture->fullView,
  2624. NULL);
  2625. }
  2626. if (texture->image) {
  2627. renderer->vkDestroyImage(
  2628. renderer->logicalDevice,
  2629. texture->image,
  2630. NULL);
  2631. }
  2632. if (texture->usedRegion) {
  2633. VULKAN_INTERNAL_RemoveMemoryUsedRegion(
  2634. renderer,
  2635. texture->usedRegion);
  2636. }
  2637. SDL_free(texture);
  2638. }
  2639. static void VULKAN_INTERNAL_DestroyBuffer(
  2640. VulkanRenderer *renderer,
  2641. VulkanBuffer *buffer)
  2642. {
  2643. renderer->vkDestroyBuffer(
  2644. renderer->logicalDevice,
  2645. buffer->buffer,
  2646. NULL);
  2647. VULKAN_INTERNAL_RemoveMemoryUsedRegion(
  2648. renderer,
  2649. buffer->usedRegion);
  2650. SDL_free(buffer);
  2651. }
  2652. static void VULKAN_INTERNAL_DestroyCommandPool(
  2653. VulkanRenderer *renderer,
  2654. VulkanCommandPool *commandPool)
  2655. {
  2656. Uint32 i;
  2657. VulkanCommandBuffer *commandBuffer;
  2658. renderer->vkDestroyCommandPool(
  2659. renderer->logicalDevice,
  2660. commandPool->commandPool,
  2661. NULL);
  2662. for (i = 0; i < commandPool->inactiveCommandBufferCount; i += 1) {
  2663. commandBuffer = commandPool->inactiveCommandBuffers[i];
  2664. SDL_free(commandBuffer->presentDatas);
  2665. SDL_free(commandBuffer->waitSemaphores);
  2666. SDL_free(commandBuffer->signalSemaphores);
  2667. SDL_free(commandBuffer->usedBuffers);
  2668. SDL_free(commandBuffer->usedTextures);
  2669. SDL_free(commandBuffer->usedSamplers);
  2670. SDL_free(commandBuffer->usedGraphicsPipelines);
  2671. SDL_free(commandBuffer->usedComputePipelines);
  2672. SDL_free(commandBuffer->usedFramebuffers);
  2673. SDL_free(commandBuffer->usedUniformBuffers);
  2674. SDL_free(commandBuffer);
  2675. }
  2676. SDL_free(commandPool->inactiveCommandBuffers);
  2677. SDL_free(commandPool);
  2678. }
  2679. static void VULKAN_INTERNAL_DestroyDescriptorSetLayout(
  2680. VulkanRenderer *renderer,
  2681. DescriptorSetLayout *layout)
  2682. {
  2683. if (layout == NULL) {
  2684. return;
  2685. }
  2686. if (layout->descriptorSetLayout != VK_NULL_HANDLE) {
  2687. renderer->vkDestroyDescriptorSetLayout(
  2688. renderer->logicalDevice,
  2689. layout->descriptorSetLayout,
  2690. NULL);
  2691. }
  2692. SDL_free(layout);
  2693. }
  2694. static void VULKAN_INTERNAL_DestroyGraphicsPipeline(
  2695. VulkanRenderer *renderer,
  2696. VulkanGraphicsPipeline *graphicsPipeline)
  2697. {
  2698. renderer->vkDestroyPipeline(
  2699. renderer->logicalDevice,
  2700. graphicsPipeline->pipeline,
  2701. NULL);
  2702. (void)SDL_AtomicDecRef(&graphicsPipeline->vertexShader->referenceCount);
  2703. (void)SDL_AtomicDecRef(&graphicsPipeline->fragmentShader->referenceCount);
  2704. SDL_free(graphicsPipeline);
  2705. }
  2706. static void VULKAN_INTERNAL_DestroyComputePipeline(
  2707. VulkanRenderer *renderer,
  2708. VulkanComputePipeline *computePipeline)
  2709. {
  2710. if (computePipeline->pipeline != VK_NULL_HANDLE) {
  2711. renderer->vkDestroyPipeline(
  2712. renderer->logicalDevice,
  2713. computePipeline->pipeline,
  2714. NULL);
  2715. }
  2716. if (computePipeline->shaderModule != VK_NULL_HANDLE) {
  2717. renderer->vkDestroyShaderModule(
  2718. renderer->logicalDevice,
  2719. computePipeline->shaderModule,
  2720. NULL);
  2721. }
  2722. SDL_free(computePipeline);
  2723. }
  2724. static void VULKAN_INTERNAL_DestroyShader(
  2725. VulkanRenderer *renderer,
  2726. VulkanShader *vulkanShader)
  2727. {
  2728. renderer->vkDestroyShaderModule(
  2729. renderer->logicalDevice,
  2730. vulkanShader->shaderModule,
  2731. NULL);
  2732. SDL_free(vulkanShader->entrypointName);
  2733. SDL_free(vulkanShader);
  2734. }
  2735. static void VULKAN_INTERNAL_DestroySampler(
  2736. VulkanRenderer *renderer,
  2737. VulkanSampler *vulkanSampler)
  2738. {
  2739. renderer->vkDestroySampler(
  2740. renderer->logicalDevice,
  2741. vulkanSampler->sampler,
  2742. NULL);
  2743. SDL_free(vulkanSampler);
  2744. }
  2745. static void VULKAN_INTERNAL_DestroySwapchain(
  2746. VulkanRenderer *renderer,
  2747. WindowData *windowData)
  2748. {
  2749. Uint32 i;
  2750. if (windowData == NULL) {
  2751. return;
  2752. }
  2753. for (i = 0; i < windowData->imageCount; i += 1) {
  2754. VULKAN_INTERNAL_RemoveFramebuffersContainingView(
  2755. renderer,
  2756. windowData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0]);
  2757. renderer->vkDestroyImageView(
  2758. renderer->logicalDevice,
  2759. windowData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0],
  2760. NULL);
  2761. SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].renderTargetViews);
  2762. SDL_free(windowData->textureContainers[i].activeTexture->subresources);
  2763. SDL_free(windowData->textureContainers[i].activeTexture);
  2764. }
  2765. SDL_free(windowData->textureContainers);
  2766. windowData->textureContainers = NULL;
  2767. if (windowData->swapchain) {
  2768. renderer->vkDestroySwapchainKHR(
  2769. renderer->logicalDevice,
  2770. windowData->swapchain,
  2771. NULL);
  2772. windowData->swapchain = VK_NULL_HANDLE;
  2773. }
  2774. if (windowData->surface) {
  2775. renderer->vkDestroySurfaceKHR(
  2776. renderer->instance,
  2777. windowData->surface,
  2778. NULL);
  2779. windowData->surface = VK_NULL_HANDLE;
  2780. }
  2781. for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
  2782. if (windowData->imageAvailableSemaphore[i]) {
  2783. renderer->vkDestroySemaphore(
  2784. renderer->logicalDevice,
  2785. windowData->imageAvailableSemaphore[i],
  2786. NULL);
  2787. windowData->imageAvailableSemaphore[i] = VK_NULL_HANDLE;
  2788. }
  2789. }
  2790. for (i = 0; i < windowData->imageCount; i += 1) {
  2791. if (windowData->renderFinishedSemaphore[i]) {
  2792. renderer->vkDestroySemaphore(
  2793. renderer->logicalDevice,
  2794. windowData->renderFinishedSemaphore[i],
  2795. NULL);
  2796. windowData->renderFinishedSemaphore[i] = VK_NULL_HANDLE;
  2797. }
  2798. }
  2799. SDL_free(windowData->renderFinishedSemaphore);
  2800. windowData->renderFinishedSemaphore = NULL;
  2801. windowData->imageCount = 0;
  2802. }
  2803. static void VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(
  2804. VulkanRenderer *renderer,
  2805. VulkanGraphicsPipelineResourceLayout *resourceLayout)
  2806. {
  2807. if (resourceLayout->pipelineLayout != VK_NULL_HANDLE) {
  2808. renderer->vkDestroyPipelineLayout(
  2809. renderer->logicalDevice,
  2810. resourceLayout->pipelineLayout,
  2811. NULL);
  2812. }
  2813. SDL_free(resourceLayout);
  2814. }
  2815. static void VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(
  2816. VulkanRenderer *renderer,
  2817. VulkanComputePipelineResourceLayout *resourceLayout)
  2818. {
  2819. if (resourceLayout->pipelineLayout != VK_NULL_HANDLE) {
  2820. renderer->vkDestroyPipelineLayout(
  2821. renderer->logicalDevice,
  2822. resourceLayout->pipelineLayout,
  2823. NULL);
  2824. }
  2825. SDL_free(resourceLayout);
  2826. }
  2827. static void VULKAN_INTERNAL_DestroyDescriptorSetCache(
  2828. VulkanRenderer *renderer,
  2829. DescriptorSetCache *descriptorSetCache)
  2830. {
  2831. for (Uint32 i = 0; i < descriptorSetCache->poolCount; i += 1) {
  2832. for (Uint32 j = 0; j < descriptorSetCache->pools[i].poolCount; j += 1) {
  2833. renderer->vkDestroyDescriptorPool(
  2834. renderer->logicalDevice,
  2835. descriptorSetCache->pools[i].descriptorPools[j],
  2836. NULL);
  2837. }
  2838. SDL_free(descriptorSetCache->pools[i].descriptorSets);
  2839. SDL_free(descriptorSetCache->pools[i].descriptorPools);
  2840. }
  2841. SDL_free(descriptorSetCache->pools);
  2842. SDL_free(descriptorSetCache);
  2843. }
  2844. // Hashtable functions
  2845. static Uint32 SDLCALL VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashFunction(void *userdata, const void *key)
  2846. {
  2847. GraphicsPipelineResourceLayoutHashTableKey *hashTableKey = (GraphicsPipelineResourceLayoutHashTableKey *)key;
  2848. /* The algorithm for this hashing function
  2849. * is taken from Josh Bloch's "Effective Java".
  2850. * (https://stackoverflow.com/a/113600/12492383)
  2851. */
  2852. const Uint32 hashFactor = 31;
  2853. Uint32 result = 1;
  2854. result = result * hashFactor + hashTableKey->vertexSamplerCount;
  2855. result = result * hashFactor + hashTableKey->vertexStorageBufferCount;
  2856. result = result * hashFactor + hashTableKey->vertexStorageTextureCount;
  2857. result = result * hashFactor + hashTableKey->vertexUniformBufferCount;
  2858. result = result * hashFactor + hashTableKey->fragmentSamplerCount;
  2859. result = result * hashFactor + hashTableKey->fragmentStorageBufferCount;
  2860. result = result * hashFactor + hashTableKey->fragmentStorageTextureCount;
  2861. result = result * hashFactor + hashTableKey->fragmentUniformBufferCount;
  2862. return result;
  2863. }
  2864. static bool SDLCALL VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashKeyMatch(void *userdata, const void *aKey, const void *bKey)
  2865. {
  2866. return SDL_memcmp(aKey, bKey, sizeof(GraphicsPipelineResourceLayoutHashTableKey)) == 0;
  2867. }
  2868. static void SDLCALL VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashDestroy(void *userdata, const void *key, const void *value)
  2869. {
  2870. VulkanRenderer *renderer = (VulkanRenderer *)userdata;
  2871. VulkanGraphicsPipelineResourceLayout *resourceLayout = (VulkanGraphicsPipelineResourceLayout *)value;
  2872. VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(renderer, resourceLayout);
  2873. SDL_free((void*)key);
  2874. }
  2875. static Uint32 SDLCALL VULKAN_INTERNAL_ComputePipelineResourceLayoutHashFunction(void *userdata, const void *key)
  2876. {
  2877. ComputePipelineResourceLayoutHashTableKey *hashTableKey = (ComputePipelineResourceLayoutHashTableKey *)key;
  2878. /* The algorithm for this hashing function
  2879. * is taken from Josh Bloch's "Effective Java".
  2880. * (https://stackoverflow.com/a/113600/12492383)
  2881. */
  2882. const Uint32 hashFactor = 31;
  2883. Uint32 result = 1;
  2884. result = result * hashFactor + hashTableKey->samplerCount;
  2885. result = result * hashFactor + hashTableKey->readonlyStorageTextureCount;
  2886. result = result * hashFactor + hashTableKey->readonlyStorageBufferCount;
  2887. result = result * hashFactor + hashTableKey->readWriteStorageTextureCount;
  2888. result = result * hashFactor + hashTableKey->readWriteStorageBufferCount;
  2889. result = result * hashFactor + hashTableKey->uniformBufferCount;
  2890. return result;
  2891. }
  2892. static bool SDLCALL VULKAN_INTERNAL_ComputePipelineResourceLayoutHashKeyMatch(void *userdata, const void *aKey, const void *bKey)
  2893. {
  2894. return SDL_memcmp(aKey, bKey, sizeof(ComputePipelineResourceLayoutHashTableKey)) == 0;
  2895. }
  2896. static void SDLCALL VULKAN_INTERNAL_ComputePipelineResourceLayoutHashDestroy(void *userdata, const void *key, const void *value)
  2897. {
  2898. VulkanRenderer *renderer = (VulkanRenderer *)userdata;
  2899. VulkanComputePipelineResourceLayout *resourceLayout = (VulkanComputePipelineResourceLayout *)value;
  2900. VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(renderer, resourceLayout);
  2901. SDL_free((void*)key);
  2902. }
  2903. static Uint32 SDLCALL VULKAN_INTERNAL_DescriptorSetLayoutHashFunction(void *userdata, const void *key)
  2904. {
  2905. DescriptorSetLayoutHashTableKey *hashTableKey = (DescriptorSetLayoutHashTableKey *)key;
  2906. /* The algorithm for this hashing function
  2907. * is taken from Josh Bloch's "Effective Java".
  2908. * (https://stackoverflow.com/a/113600/12492383)
  2909. */
  2910. const Uint32 hashFactor = 31;
  2911. Uint32 result = 1;
  2912. result = result * hashFactor + hashTableKey->shaderStage;
  2913. result = result * hashFactor + hashTableKey->samplerCount;
  2914. result = result * hashFactor + hashTableKey->storageTextureCount;
  2915. result = result * hashFactor + hashTableKey->storageBufferCount;
  2916. result = result * hashFactor + hashTableKey->writeStorageTextureCount;
  2917. result = result * hashFactor + hashTableKey->writeStorageBufferCount;
  2918. result = result * hashFactor + hashTableKey->uniformBufferCount;
  2919. return result;
  2920. }
  2921. static bool SDLCALL VULKAN_INTERNAL_DescriptorSetLayoutHashKeyMatch(void *userdata, const void *aKey, const void *bKey)
  2922. {
  2923. return SDL_memcmp(aKey, bKey, sizeof(DescriptorSetLayoutHashTableKey)) == 0;
  2924. }
  2925. static void SDLCALL VULKAN_INTERNAL_DescriptorSetLayoutHashDestroy(void *userdata, const void *key, const void *value)
  2926. {
  2927. VulkanRenderer *renderer = (VulkanRenderer *)userdata;
  2928. DescriptorSetLayout *layout = (DescriptorSetLayout *)value;
  2929. VULKAN_INTERNAL_DestroyDescriptorSetLayout(renderer, layout);
  2930. SDL_free((void*)key);
  2931. }
  2932. static Uint32 SDLCALL VULKAN_INTERNAL_CommandPoolHashFunction(void *userdata, const void *key)
  2933. {
  2934. return (Uint32)((CommandPoolHashTableKey *)key)->threadID;
  2935. }
  2936. static bool SDLCALL VULKAN_INTERNAL_CommandPoolHashKeyMatch(void *userdata, const void *aKey, const void *bKey)
  2937. {
  2938. CommandPoolHashTableKey *a = (CommandPoolHashTableKey *)aKey;
  2939. CommandPoolHashTableKey *b = (CommandPoolHashTableKey *)bKey;
  2940. return a->threadID == b->threadID;
  2941. }
  2942. static void SDLCALL VULKAN_INTERNAL_CommandPoolHashDestroy(void *userdata, const void *key, const void *value)
  2943. {
  2944. VulkanRenderer *renderer = (VulkanRenderer *)userdata;
  2945. VulkanCommandPool *pool = (VulkanCommandPool *)value;
  2946. VULKAN_INTERNAL_DestroyCommandPool(renderer, pool);
  2947. SDL_free((void *)key);
  2948. }
  2949. static Uint32 SDLCALL VULKAN_INTERNAL_RenderPassHashFunction(void *userdata, const void *key)
  2950. {
  2951. RenderPassHashTableKey *hashTableKey = (RenderPassHashTableKey *)key;
  2952. /* The algorithm for this hashing function
  2953. * is taken from Josh Bloch's "Effective Java".
  2954. * (https://stackoverflow.com/a/113600/12492383)
  2955. */
  2956. const Uint32 hashFactor = 31;
  2957. Uint32 result = 1;
  2958. for (Uint32 i = 0; i < hashTableKey->numColorTargets; i += 1) {
  2959. result = result * hashFactor + hashTableKey->colorTargetDescriptions[i].loadOp;
  2960. result = result * hashFactor + hashTableKey->colorTargetDescriptions[i].storeOp;
  2961. result = result * hashFactor + hashTableKey->colorTargetDescriptions[i].format;
  2962. }
  2963. for (Uint32 i = 0; i < hashTableKey->numResolveTargets; i += 1) {
  2964. result = result * hashFactor + hashTableKey->resolveTargetFormats[i];
  2965. }
  2966. result = result * hashFactor + hashTableKey->depthStencilTargetDescription.loadOp;
  2967. result = result * hashFactor + hashTableKey->depthStencilTargetDescription.storeOp;
  2968. result = result * hashFactor + hashTableKey->depthStencilTargetDescription.stencilLoadOp;
  2969. result = result * hashFactor + hashTableKey->depthStencilTargetDescription.stencilStoreOp;
  2970. result = result * hashFactor + hashTableKey->depthStencilTargetDescription.format;
  2971. result = result * hashFactor + hashTableKey->sampleCount;
  2972. return result;
  2973. }
  2974. static bool SDLCALL VULKAN_INTERNAL_RenderPassHashKeyMatch(void *userdata, const void *aKey, const void *bKey)
  2975. {
  2976. RenderPassHashTableKey *a = (RenderPassHashTableKey *)aKey;
  2977. RenderPassHashTableKey *b = (RenderPassHashTableKey *)bKey;
  2978. if (a->numColorTargets != b->numColorTargets) {
  2979. return 0;
  2980. }
  2981. if (a->numResolveTargets != b->numResolveTargets) {
  2982. return 0;
  2983. }
  2984. if (a->sampleCount != b->sampleCount) {
  2985. return 0;
  2986. }
  2987. for (Uint32 i = 0; i < a->numColorTargets; i += 1) {
  2988. if (a->colorTargetDescriptions[i].format != b->colorTargetDescriptions[i].format) {
  2989. return 0;
  2990. }
  2991. if (a->colorTargetDescriptions[i].loadOp != b->colorTargetDescriptions[i].loadOp) {
  2992. return 0;
  2993. }
  2994. if (a->colorTargetDescriptions[i].storeOp != b->colorTargetDescriptions[i].storeOp) {
  2995. return 0;
  2996. }
  2997. }
  2998. for (Uint32 i = 0; i < a->numResolveTargets; i += 1) {
  2999. if (a->resolveTargetFormats[i] != b->resolveTargetFormats[i]) {
  3000. return 0;
  3001. }
  3002. }
  3003. if (a->depthStencilTargetDescription.format != b->depthStencilTargetDescription.format) {
  3004. return 0;
  3005. }
  3006. if (a->depthStencilTargetDescription.loadOp != b->depthStencilTargetDescription.loadOp) {
  3007. return 0;
  3008. }
  3009. if (a->depthStencilTargetDescription.storeOp != b->depthStencilTargetDescription.storeOp) {
  3010. return 0;
  3011. }
  3012. if (a->depthStencilTargetDescription.stencilLoadOp != b->depthStencilTargetDescription.stencilLoadOp) {
  3013. return 0;
  3014. }
  3015. if (a->depthStencilTargetDescription.stencilStoreOp != b->depthStencilTargetDescription.stencilStoreOp) {
  3016. return 0;
  3017. }
  3018. return 1;
  3019. }
  3020. static void SDLCALL VULKAN_INTERNAL_RenderPassHashDestroy(void *userdata, const void *key, const void *value)
  3021. {
  3022. VulkanRenderer *renderer = (VulkanRenderer *)userdata;
  3023. VulkanRenderPassHashTableValue *renderPassWrapper = (VulkanRenderPassHashTableValue *)value;
  3024. renderer->vkDestroyRenderPass(
  3025. renderer->logicalDevice,
  3026. renderPassWrapper->handle,
  3027. NULL);
  3028. SDL_free(renderPassWrapper);
  3029. SDL_free((void *)key);
  3030. }
  3031. static Uint32 SDLCALL VULKAN_INTERNAL_FramebufferHashFunction(void *userdata, const void *key)
  3032. {
  3033. FramebufferHashTableKey *hashTableKey = (FramebufferHashTableKey *)key;
  3034. /* The algorithm for this hashing function
  3035. * is taken from Josh Bloch's "Effective Java".
  3036. * (https://stackoverflow.com/a/113600/12492383)
  3037. */
  3038. const Uint32 hashFactor = 31;
  3039. Uint32 result = 1;
  3040. for (Uint32 i = 0; i < hashTableKey->numColorTargets; i += 1) {
  3041. result = result * hashFactor + (Uint32)(uintptr_t)hashTableKey->colorAttachmentViews[i];
  3042. }
  3043. for (Uint32 i = 0; i < hashTableKey->numResolveAttachments; i += 1) {
  3044. result = result * hashFactor + (Uint32)(uintptr_t)hashTableKey->resolveAttachmentViews[i];
  3045. }
  3046. result = result * hashFactor + (Uint32)(uintptr_t)hashTableKey->depthStencilAttachmentView;
  3047. result = result * hashFactor + hashTableKey->width;
  3048. result = result * hashFactor + hashTableKey->height;
  3049. return result;
  3050. }
  3051. static bool SDLCALL VULKAN_INTERNAL_FramebufferHashKeyMatch(void *userdata, const void *aKey, const void *bKey)
  3052. {
  3053. FramebufferHashTableKey *a = (FramebufferHashTableKey *)aKey;
  3054. FramebufferHashTableKey *b = (FramebufferHashTableKey *)bKey;
  3055. if (a->numColorTargets != b->numColorTargets) {
  3056. return 0;
  3057. }
  3058. if (a->numResolveAttachments != b->numResolveAttachments) {
  3059. return 0;
  3060. }
  3061. for (Uint32 i = 0; i < a->numColorTargets; i += 1) {
  3062. if (a->colorAttachmentViews[i] != b->colorAttachmentViews[i]) {
  3063. return 0;
  3064. }
  3065. }
  3066. for (Uint32 i = 0; i < a->numResolveAttachments; i += 1) {
  3067. if (a->resolveAttachmentViews[i] != b->resolveAttachmentViews[i]) {
  3068. return 0;
  3069. }
  3070. }
  3071. if (a->depthStencilAttachmentView != b->depthStencilAttachmentView) {
  3072. return 0;
  3073. }
  3074. if (a->width != b->width) {
  3075. return 0;
  3076. }
  3077. if (a->height != b->height) {
  3078. return 0;
  3079. }
  3080. return 1;
  3081. }
  3082. static void SDLCALL VULKAN_INTERNAL_FramebufferHashDestroy(void *userdata, const void *key, const void *value)
  3083. {
  3084. VulkanRenderer *renderer = (VulkanRenderer *)userdata;
  3085. VulkanFramebuffer *framebuffer = (VulkanFramebuffer *)value;
  3086. VULKAN_INTERNAL_ReleaseFramebuffer(renderer, framebuffer);
  3087. SDL_free((void *)key);
  3088. }
  3089. // Descriptor pools
  3090. static bool VULKAN_INTERNAL_AllocateDescriptorSets(
  3091. VulkanRenderer *renderer,
  3092. VkDescriptorPool descriptorPool,
  3093. VkDescriptorSetLayout descriptorSetLayout,
  3094. Uint32 descriptorSetCount,
  3095. VkDescriptorSet *descriptorSetArray)
  3096. {
  3097. VkDescriptorSetAllocateInfo descriptorSetAllocateInfo;
  3098. VkDescriptorSetLayout *descriptorSetLayouts = SDL_stack_alloc(VkDescriptorSetLayout, descriptorSetCount);
  3099. VkResult vulkanResult;
  3100. Uint32 i;
  3101. for (i = 0; i < descriptorSetCount; i += 1) {
  3102. descriptorSetLayouts[i] = descriptorSetLayout;
  3103. }
  3104. descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  3105. descriptorSetAllocateInfo.pNext = NULL;
  3106. descriptorSetAllocateInfo.descriptorPool = descriptorPool;
  3107. descriptorSetAllocateInfo.descriptorSetCount = descriptorSetCount;
  3108. descriptorSetAllocateInfo.pSetLayouts = descriptorSetLayouts;
  3109. vulkanResult = renderer->vkAllocateDescriptorSets(
  3110. renderer->logicalDevice,
  3111. &descriptorSetAllocateInfo,
  3112. descriptorSetArray);
  3113. SDL_stack_free(descriptorSetLayouts);
  3114. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkAllocateDescriptorSets, false);
  3115. return true;
  3116. }
  3117. static bool VULKAN_INTERNAL_AllocateDescriptorsFromPool(
  3118. VulkanRenderer *renderer,
  3119. DescriptorSetLayout *descriptorSetLayout,
  3120. DescriptorSetPool *descriptorSetPool)
  3121. {
  3122. VkDescriptorPoolSize descriptorPoolSizes[
  3123. MAX_TEXTURE_SAMPLERS_PER_STAGE +
  3124. MAX_STORAGE_TEXTURES_PER_STAGE +
  3125. MAX_STORAGE_BUFFERS_PER_STAGE +
  3126. MAX_COMPUTE_WRITE_TEXTURES +
  3127. MAX_COMPUTE_WRITE_BUFFERS +
  3128. MAX_UNIFORM_BUFFERS_PER_STAGE];
  3129. VkDescriptorPoolCreateInfo descriptorPoolInfo;
  3130. VkDescriptorPool pool;
  3131. VkResult vulkanResult;
  3132. // Category 1
  3133. for (Uint32 i = 0; i < descriptorSetLayout->samplerCount; i += 1) {
  3134. descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  3135. descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
  3136. }
  3137. for (Uint32 i = descriptorSetLayout->samplerCount; i < descriptorSetLayout->samplerCount + descriptorSetLayout->storageTextureCount; i += 1) {
  3138. descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; // Yes, we are declaring the storage image as a sampled image, because shaders are stupid.
  3139. descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
  3140. }
  3141. for (Uint32 i = descriptorSetLayout->samplerCount + descriptorSetLayout->storageTextureCount; i < descriptorSetLayout->samplerCount + descriptorSetLayout->storageTextureCount + descriptorSetLayout->storageBufferCount; i += 1) {
  3142. descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  3143. descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
  3144. }
  3145. // Category 2
  3146. for (Uint32 i = 0; i < descriptorSetLayout->writeStorageTextureCount; i += 1) {
  3147. descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
  3148. descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
  3149. }
  3150. for (Uint32 i = descriptorSetLayout->writeStorageTextureCount; i < descriptorSetLayout->writeStorageTextureCount + descriptorSetLayout->writeStorageBufferCount; i += 1) {
  3151. descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  3152. descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
  3153. }
  3154. // Category 3
  3155. for (Uint32 i = 0; i < descriptorSetLayout->uniformBufferCount; i += 1) {
  3156. descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
  3157. descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
  3158. }
  3159. descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  3160. descriptorPoolInfo.pNext = NULL;
  3161. descriptorPoolInfo.flags = 0;
  3162. descriptorPoolInfo.maxSets = DESCRIPTOR_POOL_SIZE;
  3163. descriptorPoolInfo.poolSizeCount =
  3164. descriptorSetLayout->samplerCount +
  3165. descriptorSetLayout->storageTextureCount +
  3166. descriptorSetLayout->storageBufferCount +
  3167. descriptorSetLayout->writeStorageTextureCount +
  3168. descriptorSetLayout->writeStorageBufferCount +
  3169. descriptorSetLayout->uniformBufferCount;
  3170. descriptorPoolInfo.pPoolSizes = descriptorPoolSizes;
  3171. vulkanResult = renderer->vkCreateDescriptorPool(
  3172. renderer->logicalDevice,
  3173. &descriptorPoolInfo,
  3174. NULL,
  3175. &pool);
  3176. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDescriptorPool, false);
  3177. descriptorSetPool->poolCount += 1;
  3178. descriptorSetPool->descriptorPools = SDL_realloc(
  3179. descriptorSetPool->descriptorPools,
  3180. sizeof(VkDescriptorPool) * descriptorSetPool->poolCount);
  3181. descriptorSetPool->descriptorPools[descriptorSetPool->poolCount - 1] = pool;
  3182. descriptorSetPool->descriptorSets = SDL_realloc(
  3183. descriptorSetPool->descriptorSets,
  3184. sizeof(VkDescriptorSet) * descriptorSetPool->poolCount * DESCRIPTOR_POOL_SIZE);
  3185. if (!VULKAN_INTERNAL_AllocateDescriptorSets(
  3186. renderer,
  3187. pool,
  3188. descriptorSetLayout->descriptorSetLayout,
  3189. DESCRIPTOR_POOL_SIZE,
  3190. &descriptorSetPool->descriptorSets[descriptorSetPool->descriptorSetCount])) {
  3191. return false;
  3192. }
  3193. descriptorSetPool->descriptorSetCount += DESCRIPTOR_POOL_SIZE;
  3194. return true;
  3195. }
  3196. // NOTE: these categories should be mutually exclusive
  3197. static DescriptorSetLayout *VULKAN_INTERNAL_FetchDescriptorSetLayout(
  3198. VulkanRenderer *renderer,
  3199. VkShaderStageFlagBits shaderStage,
  3200. // Category 1: read resources
  3201. Uint32 samplerCount,
  3202. Uint32 storageTextureCount,
  3203. Uint32 storageBufferCount,
  3204. // Category 2: write resources
  3205. Uint32 writeStorageTextureCount,
  3206. Uint32 writeStorageBufferCount,
  3207. // Category 3: uniform buffers
  3208. Uint32 uniformBufferCount)
  3209. {
  3210. DescriptorSetLayoutHashTableKey key;
  3211. SDL_zero(key);
  3212. DescriptorSetLayout *layout = NULL;
  3213. key.shaderStage = shaderStage;
  3214. key.samplerCount = samplerCount;
  3215. key.storageTextureCount = storageTextureCount;
  3216. key.storageBufferCount = storageBufferCount;
  3217. key.writeStorageTextureCount = writeStorageTextureCount;
  3218. key.writeStorageBufferCount = writeStorageBufferCount;
  3219. key.uniformBufferCount = uniformBufferCount;
  3220. SDL_LockMutex(renderer->descriptorSetLayoutFetchLock);
  3221. if (SDL_FindInHashTable(
  3222. renderer->descriptorSetLayoutHashTable,
  3223. (const void *)&key,
  3224. (const void **)&layout)) {
  3225. SDL_UnlockMutex(renderer->descriptorSetLayoutFetchLock);
  3226. return layout;
  3227. }
  3228. VkDescriptorSetLayout descriptorSetLayout;
  3229. VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[
  3230. MAX_TEXTURE_SAMPLERS_PER_STAGE +
  3231. MAX_STORAGE_TEXTURES_PER_STAGE +
  3232. MAX_STORAGE_BUFFERS_PER_STAGE +
  3233. MAX_COMPUTE_WRITE_TEXTURES +
  3234. MAX_COMPUTE_WRITE_BUFFERS];
  3235. VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo;
  3236. descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  3237. descriptorSetLayoutCreateInfo.pNext = NULL;
  3238. descriptorSetLayoutCreateInfo.flags = 0;
  3239. // Category 1
  3240. for (Uint32 i = 0; i < samplerCount; i += 1) {
  3241. descriptorSetLayoutBindings[i].binding = i;
  3242. descriptorSetLayoutBindings[i].descriptorCount = 1;
  3243. descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  3244. descriptorSetLayoutBindings[i].stageFlags = shaderStage;
  3245. descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
  3246. }
  3247. for (Uint32 i = samplerCount; i < samplerCount + storageTextureCount; i += 1) {
  3248. descriptorSetLayoutBindings[i].binding = i;
  3249. descriptorSetLayoutBindings[i].descriptorCount = 1;
  3250. descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; // Yes, we are declaring the storage image as a sampled image, because shaders are stupid.
  3251. descriptorSetLayoutBindings[i].stageFlags = shaderStage;
  3252. descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
  3253. }
  3254. for (Uint32 i = samplerCount + storageTextureCount; i < samplerCount + storageTextureCount + storageBufferCount; i += 1) {
  3255. descriptorSetLayoutBindings[i].binding = i;
  3256. descriptorSetLayoutBindings[i].descriptorCount = 1;
  3257. descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  3258. descriptorSetLayoutBindings[i].stageFlags = shaderStage;
  3259. descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
  3260. }
  3261. // Category 2
  3262. for (Uint32 i = 0; i < writeStorageTextureCount; i += 1) {
  3263. descriptorSetLayoutBindings[i].binding = i;
  3264. descriptorSetLayoutBindings[i].descriptorCount = 1;
  3265. descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
  3266. descriptorSetLayoutBindings[i].stageFlags = shaderStage;
  3267. descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
  3268. }
  3269. for (Uint32 i = writeStorageTextureCount; i < writeStorageTextureCount + writeStorageBufferCount; i += 1) {
  3270. descriptorSetLayoutBindings[i].binding = i;
  3271. descriptorSetLayoutBindings[i].descriptorCount = 1;
  3272. descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  3273. descriptorSetLayoutBindings[i].stageFlags = shaderStage;
  3274. descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
  3275. }
  3276. // Category 3
  3277. for (Uint32 i = 0; i < uniformBufferCount; i += 1) {
  3278. descriptorSetLayoutBindings[i].binding = i;
  3279. descriptorSetLayoutBindings[i].descriptorCount = 1;
  3280. descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
  3281. descriptorSetLayoutBindings[i].stageFlags = shaderStage;
  3282. descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
  3283. }
  3284. descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
  3285. descriptorSetLayoutCreateInfo.bindingCount =
  3286. samplerCount +
  3287. storageTextureCount +
  3288. storageBufferCount +
  3289. writeStorageTextureCount +
  3290. writeStorageBufferCount +
  3291. uniformBufferCount;
  3292. VkResult vulkanResult = renderer->vkCreateDescriptorSetLayout(
  3293. renderer->logicalDevice,
  3294. &descriptorSetLayoutCreateInfo,
  3295. NULL,
  3296. &descriptorSetLayout);
  3297. if (vulkanResult != VK_SUCCESS) {
  3298. SDL_UnlockMutex(renderer->descriptorSetLayoutFetchLock);
  3299. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDescriptorSetLayout, NULL);
  3300. }
  3301. layout = SDL_malloc(sizeof(DescriptorSetLayout));
  3302. layout->descriptorSetLayout = descriptorSetLayout;
  3303. layout->samplerCount = samplerCount;
  3304. layout->storageBufferCount = storageBufferCount;
  3305. layout->storageTextureCount = storageTextureCount;
  3306. layout->writeStorageBufferCount = writeStorageBufferCount;
  3307. layout->writeStorageTextureCount = writeStorageTextureCount;
  3308. layout->uniformBufferCount = uniformBufferCount;
  3309. layout->ID = SDL_AtomicIncRef(&renderer->layoutResourceID);
  3310. DescriptorSetLayoutHashTableKey *allocedKey = SDL_malloc(sizeof(DescriptorSetLayoutHashTableKey));
  3311. SDL_memcpy(allocedKey, &key, sizeof(DescriptorSetLayoutHashTableKey));
  3312. SDL_InsertIntoHashTable(
  3313. renderer->descriptorSetLayoutHashTable,
  3314. (const void *)allocedKey,
  3315. (const void *)layout, true);
  3316. SDL_UnlockMutex(renderer->descriptorSetLayoutFetchLock);
  3317. return layout;
  3318. }
  3319. static VulkanGraphicsPipelineResourceLayout *VULKAN_INTERNAL_FetchGraphicsPipelineResourceLayout(
  3320. VulkanRenderer *renderer,
  3321. VulkanShader *vertexShader,
  3322. VulkanShader *fragmentShader)
  3323. {
  3324. GraphicsPipelineResourceLayoutHashTableKey key;
  3325. SDL_zero(key);
  3326. VulkanGraphicsPipelineResourceLayout *pipelineResourceLayout = NULL;
  3327. key.vertexSamplerCount = vertexShader->numSamplers;
  3328. key.vertexStorageTextureCount = vertexShader->numStorageTextures;
  3329. key.vertexStorageBufferCount = vertexShader->numStorageBuffers;
  3330. key.vertexUniformBufferCount = vertexShader->numUniformBuffers;
  3331. key.fragmentSamplerCount = fragmentShader->numSamplers;
  3332. key.fragmentStorageTextureCount = fragmentShader->numStorageTextures;
  3333. key.fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
  3334. key.fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
  3335. SDL_LockMutex(renderer->graphicsPipelineLayoutFetchLock);
  3336. if (SDL_FindInHashTable(
  3337. renderer->graphicsPipelineResourceLayoutHashTable,
  3338. (const void *)&key,
  3339. (const void **)&pipelineResourceLayout)) {
  3340. SDL_UnlockMutex(renderer->graphicsPipelineLayoutFetchLock);
  3341. return pipelineResourceLayout;
  3342. }
  3343. VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
  3344. VkDescriptorSetLayout descriptorSetLayouts[4];
  3345. VkResult vulkanResult;
  3346. pipelineResourceLayout = SDL_calloc(1, sizeof(VulkanGraphicsPipelineResourceLayout));
  3347. pipelineResourceLayout->descriptorSetLayouts[0] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
  3348. renderer,
  3349. VK_SHADER_STAGE_VERTEX_BIT,
  3350. vertexShader->numSamplers,
  3351. vertexShader->numStorageTextures,
  3352. vertexShader->numStorageBuffers,
  3353. 0,
  3354. 0,
  3355. 0);
  3356. pipelineResourceLayout->descriptorSetLayouts[1] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
  3357. renderer,
  3358. VK_SHADER_STAGE_VERTEX_BIT,
  3359. 0,
  3360. 0,
  3361. 0,
  3362. 0,
  3363. 0,
  3364. vertexShader->numUniformBuffers);
  3365. pipelineResourceLayout->descriptorSetLayouts[2] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
  3366. renderer,
  3367. VK_SHADER_STAGE_FRAGMENT_BIT,
  3368. fragmentShader->numSamplers,
  3369. fragmentShader->numStorageTextures,
  3370. fragmentShader->numStorageBuffers,
  3371. 0,
  3372. 0,
  3373. 0);
  3374. pipelineResourceLayout->descriptorSetLayouts[3] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
  3375. renderer,
  3376. VK_SHADER_STAGE_FRAGMENT_BIT,
  3377. 0,
  3378. 0,
  3379. 0,
  3380. 0,
  3381. 0,
  3382. fragmentShader->numUniformBuffers);
  3383. descriptorSetLayouts[0] = pipelineResourceLayout->descriptorSetLayouts[0]->descriptorSetLayout;
  3384. descriptorSetLayouts[1] = pipelineResourceLayout->descriptorSetLayouts[1]->descriptorSetLayout;
  3385. descriptorSetLayouts[2] = pipelineResourceLayout->descriptorSetLayouts[2]->descriptorSetLayout;
  3386. descriptorSetLayouts[3] = pipelineResourceLayout->descriptorSetLayouts[3]->descriptorSetLayout;
  3387. pipelineResourceLayout->vertexSamplerCount = vertexShader->numSamplers;
  3388. pipelineResourceLayout->vertexStorageTextureCount = vertexShader->numStorageTextures;
  3389. pipelineResourceLayout->vertexStorageBufferCount = vertexShader->numStorageBuffers;
  3390. pipelineResourceLayout->vertexUniformBufferCount = vertexShader->numUniformBuffers;
  3391. pipelineResourceLayout->fragmentSamplerCount = fragmentShader->numSamplers;
  3392. pipelineResourceLayout->fragmentStorageTextureCount = fragmentShader->numStorageTextures;
  3393. pipelineResourceLayout->fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
  3394. pipelineResourceLayout->fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
  3395. // Create the pipeline layout
  3396. pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  3397. pipelineLayoutCreateInfo.pNext = NULL;
  3398. pipelineLayoutCreateInfo.flags = 0;
  3399. pipelineLayoutCreateInfo.setLayoutCount = 4;
  3400. pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts;
  3401. pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
  3402. pipelineLayoutCreateInfo.pPushConstantRanges = NULL;
  3403. vulkanResult = renderer->vkCreatePipelineLayout(
  3404. renderer->logicalDevice,
  3405. &pipelineLayoutCreateInfo,
  3406. NULL,
  3407. &pipelineResourceLayout->pipelineLayout);
  3408. if (vulkanResult != VK_SUCCESS) {
  3409. VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(renderer, pipelineResourceLayout);
  3410. SDL_UnlockMutex(renderer->graphicsPipelineLayoutFetchLock);
  3411. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL);
  3412. }
  3413. GraphicsPipelineResourceLayoutHashTableKey *allocedKey = SDL_malloc(sizeof(GraphicsPipelineResourceLayoutHashTableKey));
  3414. SDL_memcpy(allocedKey, &key, sizeof(GraphicsPipelineResourceLayoutHashTableKey));
  3415. SDL_InsertIntoHashTable(
  3416. renderer->graphicsPipelineResourceLayoutHashTable,
  3417. (const void *)allocedKey,
  3418. (const void *)pipelineResourceLayout, true);
  3419. SDL_UnlockMutex(renderer->graphicsPipelineLayoutFetchLock);
  3420. return pipelineResourceLayout;
  3421. }
  3422. static VulkanComputePipelineResourceLayout *VULKAN_INTERNAL_FetchComputePipelineResourceLayout(
  3423. VulkanRenderer *renderer,
  3424. const SDL_GPUComputePipelineCreateInfo *createinfo)
  3425. {
  3426. ComputePipelineResourceLayoutHashTableKey key;
  3427. SDL_zero(key);
  3428. VulkanComputePipelineResourceLayout *pipelineResourceLayout = NULL;
  3429. key.samplerCount = createinfo->num_samplers;
  3430. key.readonlyStorageTextureCount = createinfo->num_readonly_storage_textures;
  3431. key.readonlyStorageBufferCount = createinfo->num_readonly_storage_buffers;
  3432. key.readWriteStorageTextureCount = createinfo->num_readwrite_storage_textures;
  3433. key.readWriteStorageBufferCount = createinfo->num_readwrite_storage_buffers;
  3434. key.uniformBufferCount = createinfo->num_uniform_buffers;
  3435. SDL_LockMutex(renderer->computePipelineLayoutFetchLock);
  3436. if (SDL_FindInHashTable(
  3437. renderer->computePipelineResourceLayoutHashTable,
  3438. (const void *)&key,
  3439. (const void **)&pipelineResourceLayout)) {
  3440. SDL_UnlockMutex(renderer->computePipelineLayoutFetchLock);
  3441. return pipelineResourceLayout;
  3442. }
  3443. VkDescriptorSetLayout descriptorSetLayouts[3];
  3444. VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
  3445. VkResult vulkanResult;
  3446. pipelineResourceLayout = SDL_calloc(1, sizeof(VulkanComputePipelineResourceLayout));
  3447. pipelineResourceLayout->descriptorSetLayouts[0] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
  3448. renderer,
  3449. VK_SHADER_STAGE_COMPUTE_BIT,
  3450. createinfo->num_samplers,
  3451. createinfo->num_readonly_storage_textures,
  3452. createinfo->num_readonly_storage_buffers,
  3453. 0,
  3454. 0,
  3455. 0);
  3456. pipelineResourceLayout->descriptorSetLayouts[1] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
  3457. renderer,
  3458. VK_SHADER_STAGE_COMPUTE_BIT,
  3459. 0,
  3460. 0,
  3461. 0,
  3462. createinfo->num_readwrite_storage_textures,
  3463. createinfo->num_readwrite_storage_buffers,
  3464. 0);
  3465. pipelineResourceLayout->descriptorSetLayouts[2] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
  3466. renderer,
  3467. VK_SHADER_STAGE_COMPUTE_BIT,
  3468. 0,
  3469. 0,
  3470. 0,
  3471. 0,
  3472. 0,
  3473. createinfo->num_uniform_buffers);
  3474. descriptorSetLayouts[0] = pipelineResourceLayout->descriptorSetLayouts[0]->descriptorSetLayout;
  3475. descriptorSetLayouts[1] = pipelineResourceLayout->descriptorSetLayouts[1]->descriptorSetLayout;
  3476. descriptorSetLayouts[2] = pipelineResourceLayout->descriptorSetLayouts[2]->descriptorSetLayout;
  3477. pipelineResourceLayout->numSamplers = createinfo->num_samplers;
  3478. pipelineResourceLayout->numReadonlyStorageTextures = createinfo->num_readonly_storage_textures;
  3479. pipelineResourceLayout->numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers;
  3480. pipelineResourceLayout->numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
  3481. pipelineResourceLayout->numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
  3482. pipelineResourceLayout->numUniformBuffers = createinfo->num_uniform_buffers;
  3483. // Create the pipeline layout
  3484. pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  3485. pipelineLayoutCreateInfo.pNext = NULL;
  3486. pipelineLayoutCreateInfo.flags = 0;
  3487. pipelineLayoutCreateInfo.setLayoutCount = 3;
  3488. pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts;
  3489. pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
  3490. pipelineLayoutCreateInfo.pPushConstantRanges = NULL;
  3491. vulkanResult = renderer->vkCreatePipelineLayout(
  3492. renderer->logicalDevice,
  3493. &pipelineLayoutCreateInfo,
  3494. NULL,
  3495. &pipelineResourceLayout->pipelineLayout);
  3496. if (vulkanResult != VK_SUCCESS) {
  3497. VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(renderer, pipelineResourceLayout);
  3498. SDL_UnlockMutex(renderer->computePipelineLayoutFetchLock);
  3499. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL);
  3500. }
  3501. ComputePipelineResourceLayoutHashTableKey *allocedKey = SDL_malloc(sizeof(ComputePipelineResourceLayoutHashTableKey));
  3502. SDL_memcpy(allocedKey, &key, sizeof(ComputePipelineResourceLayoutHashTableKey));
  3503. SDL_InsertIntoHashTable(
  3504. renderer->computePipelineResourceLayoutHashTable,
  3505. (const void *)allocedKey,
  3506. (const void *)pipelineResourceLayout, true);
  3507. SDL_UnlockMutex(renderer->computePipelineLayoutFetchLock);
  3508. return pipelineResourceLayout;
  3509. }
  3510. // Data Buffer
  3511. static VulkanBuffer *VULKAN_INTERNAL_CreateBuffer(
  3512. VulkanRenderer *renderer,
  3513. VkDeviceSize size,
  3514. SDL_GPUBufferUsageFlags usageFlags,
  3515. VulkanBufferType type,
  3516. bool dedicated,
  3517. const char *debugName)
  3518. {
  3519. VulkanBuffer *buffer;
  3520. VkResult vulkanResult;
  3521. VkBufferCreateInfo createinfo;
  3522. VkBufferUsageFlags vulkanUsageFlags = 0;
  3523. Uint8 bindResult;
  3524. if (usageFlags & SDL_GPU_BUFFERUSAGE_VERTEX) {
  3525. vulkanUsageFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
  3526. }
  3527. if (usageFlags & SDL_GPU_BUFFERUSAGE_INDEX) {
  3528. vulkanUsageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
  3529. }
  3530. if (usageFlags & (SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ |
  3531. SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ |
  3532. SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE)) {
  3533. vulkanUsageFlags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
  3534. }
  3535. if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT) {
  3536. vulkanUsageFlags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
  3537. }
  3538. if (type == VULKAN_BUFFER_TYPE_UNIFORM) {
  3539. vulkanUsageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
  3540. } else {
  3541. // GPU buffers need transfer bits for defrag, transfer buffers need them for transfers
  3542. vulkanUsageFlags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
  3543. }
  3544. buffer = SDL_calloc(1, sizeof(VulkanBuffer));
  3545. buffer->size = size;
  3546. buffer->usage = usageFlags;
  3547. buffer->type = type;
  3548. buffer->markedForDestroy = false;
  3549. buffer->transitioned = false;
  3550. createinfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  3551. createinfo.pNext = NULL;
  3552. createinfo.flags = 0;
  3553. createinfo.size = size;
  3554. createinfo.usage = vulkanUsageFlags;
  3555. createinfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  3556. createinfo.queueFamilyIndexCount = 1;
  3557. createinfo.pQueueFamilyIndices = &renderer->queueFamilyIndex;
  3558. // Set transfer bits so we can defrag
  3559. createinfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
  3560. vulkanResult = renderer->vkCreateBuffer(
  3561. renderer->logicalDevice,
  3562. &createinfo,
  3563. NULL,
  3564. &buffer->buffer);
  3565. if (vulkanResult != VK_SUCCESS) {
  3566. SDL_free(buffer);
  3567. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateBuffer, NULL);
  3568. }
  3569. bindResult = VULKAN_INTERNAL_BindMemoryForBuffer(
  3570. renderer,
  3571. buffer->buffer,
  3572. buffer->size,
  3573. buffer->type,
  3574. dedicated,
  3575. &buffer->usedRegion);
  3576. if (bindResult != 1) {
  3577. renderer->vkDestroyBuffer(
  3578. renderer->logicalDevice,
  3579. buffer->buffer,
  3580. NULL);
  3581. SDL_free(buffer);
  3582. return NULL;
  3583. }
  3584. buffer->usedRegion->vulkanBuffer = buffer; // lol
  3585. SDL_SetAtomicInt(&buffer->referenceCount, 0);
  3586. if (renderer->debugMode && renderer->supportsDebugUtils && debugName != NULL) {
  3587. VkDebugUtilsObjectNameInfoEXT nameInfo;
  3588. nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  3589. nameInfo.pNext = NULL;
  3590. nameInfo.pObjectName = debugName;
  3591. nameInfo.objectType = VK_OBJECT_TYPE_BUFFER;
  3592. nameInfo.objectHandle = (uint64_t)buffer->buffer;
  3593. renderer->vkSetDebugUtilsObjectNameEXT(
  3594. renderer->logicalDevice,
  3595. &nameInfo);
  3596. }
  3597. return buffer;
  3598. }
  3599. static VulkanBufferContainer *VULKAN_INTERNAL_CreateBufferContainer(
  3600. VulkanRenderer *renderer,
  3601. VkDeviceSize size,
  3602. SDL_GPUBufferUsageFlags usageFlags,
  3603. VulkanBufferType type,
  3604. bool dedicated,
  3605. const char *debugName)
  3606. {
  3607. VulkanBufferContainer *bufferContainer;
  3608. VulkanBuffer *buffer;
  3609. buffer = VULKAN_INTERNAL_CreateBuffer(
  3610. renderer,
  3611. size,
  3612. usageFlags,
  3613. type,
  3614. dedicated,
  3615. debugName);
  3616. if (buffer == NULL) {
  3617. return NULL;
  3618. }
  3619. bufferContainer = SDL_calloc(1, sizeof(VulkanBufferContainer));
  3620. bufferContainer->activeBuffer = buffer;
  3621. buffer->container = bufferContainer;
  3622. buffer->containerIndex = 0;
  3623. bufferContainer->bufferCapacity = 1;
  3624. bufferContainer->bufferCount = 1;
  3625. bufferContainer->buffers = SDL_calloc(bufferContainer->bufferCapacity, sizeof(VulkanBuffer *));
  3626. bufferContainer->buffers[0] = bufferContainer->activeBuffer;
  3627. bufferContainer->dedicated = dedicated;
  3628. bufferContainer->debugName = NULL;
  3629. if (debugName != NULL) {
  3630. bufferContainer->debugName = SDL_strdup(debugName);
  3631. }
  3632. return bufferContainer;
  3633. }
  3634. // Texture Subresource Utilities
  3635. static Uint32 VULKAN_INTERNAL_GetTextureSubresourceIndex(
  3636. Uint32 mipLevel,
  3637. Uint32 layer,
  3638. Uint32 numLevels)
  3639. {
  3640. return mipLevel + (layer * numLevels);
  3641. }
  3642. static VulkanTextureSubresource *VULKAN_INTERNAL_FetchTextureSubresource(
  3643. VulkanTextureContainer *textureContainer,
  3644. Uint32 layer,
  3645. Uint32 level)
  3646. {
  3647. Uint32 index = VULKAN_INTERNAL_GetTextureSubresourceIndex(
  3648. level,
  3649. layer,
  3650. textureContainer->header.info.num_levels);
  3651. return &textureContainer->activeTexture->subresources[index];
  3652. }
  3653. static bool VULKAN_INTERNAL_CreateRenderTargetView(
  3654. VulkanRenderer *renderer,
  3655. VulkanTexture *texture,
  3656. Uint32 layerOrDepth,
  3657. Uint32 level,
  3658. VkFormat format,
  3659. VkComponentMapping swizzle,
  3660. VkImageView *pView)
  3661. {
  3662. VkResult vulkanResult;
  3663. VkImageViewCreateInfo imageViewCreateInfo;
  3664. // create framebuffer compatible views for RenderTarget
  3665. imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  3666. imageViewCreateInfo.pNext = NULL;
  3667. imageViewCreateInfo.flags = 0;
  3668. imageViewCreateInfo.image = texture->image;
  3669. imageViewCreateInfo.format = format;
  3670. imageViewCreateInfo.components = swizzle;
  3671. imageViewCreateInfo.subresourceRange.aspectMask = texture->aspectFlags;
  3672. imageViewCreateInfo.subresourceRange.baseMipLevel = level;
  3673. imageViewCreateInfo.subresourceRange.levelCount = 1;
  3674. imageViewCreateInfo.subresourceRange.baseArrayLayer = layerOrDepth;
  3675. imageViewCreateInfo.subresourceRange.layerCount = 1;
  3676. imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  3677. vulkanResult = renderer->vkCreateImageView(
  3678. renderer->logicalDevice,
  3679. &imageViewCreateInfo,
  3680. NULL,
  3681. pView);
  3682. if (vulkanResult != VK_SUCCESS) {
  3683. *pView = (VkImageView)VK_NULL_HANDLE;
  3684. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateImageView, false);
  3685. }
  3686. return true;
  3687. }
  3688. static bool VULKAN_INTERNAL_CreateSubresourceView(
  3689. VulkanRenderer *renderer,
  3690. const SDL_GPUTextureCreateInfo *createinfo,
  3691. VulkanTexture *texture,
  3692. Uint32 layer,
  3693. Uint32 level,
  3694. VkComponentMapping swizzle,
  3695. VkImageView *pView)
  3696. {
  3697. VkResult vulkanResult;
  3698. VkImageViewCreateInfo imageViewCreateInfo;
  3699. // create framebuffer compatible views for RenderTarget
  3700. imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  3701. imageViewCreateInfo.pNext = NULL;
  3702. imageViewCreateInfo.flags = 0;
  3703. imageViewCreateInfo.image = texture->image;
  3704. imageViewCreateInfo.format = SDLToVK_TextureFormat[createinfo->format];
  3705. imageViewCreateInfo.components = swizzle;
  3706. imageViewCreateInfo.subresourceRange.aspectMask = texture->aspectFlags;
  3707. imageViewCreateInfo.subresourceRange.baseMipLevel = level;
  3708. imageViewCreateInfo.subresourceRange.levelCount = 1;
  3709. imageViewCreateInfo.subresourceRange.baseArrayLayer = layer;
  3710. imageViewCreateInfo.subresourceRange.layerCount = 1;
  3711. imageViewCreateInfo.viewType = (createinfo->type == SDL_GPU_TEXTURETYPE_3D) ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D;
  3712. vulkanResult = renderer->vkCreateImageView(
  3713. renderer->logicalDevice,
  3714. &imageViewCreateInfo,
  3715. NULL,
  3716. pView);
  3717. if (vulkanResult != VK_SUCCESS) {
  3718. *pView = (VkImageView)VK_NULL_HANDLE;
  3719. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateImageView, false);
  3720. }
  3721. return true;
  3722. }
  3723. // Swapchain
  3724. static bool VULKAN_INTERNAL_QuerySwapchainSupport(
  3725. VulkanRenderer *renderer,
  3726. VkPhysicalDevice physicalDevice,
  3727. VkSurfaceKHR surface,
  3728. SwapchainSupportDetails *outputDetails)
  3729. {
  3730. VkResult result;
  3731. VkBool32 supportsPresent;
  3732. renderer->vkGetPhysicalDeviceSurfaceSupportKHR(
  3733. physicalDevice,
  3734. renderer->queueFamilyIndex,
  3735. surface,
  3736. &supportsPresent);
  3737. // Initialize these in case anything fails
  3738. outputDetails->formatsLength = 0;
  3739. outputDetails->presentModesLength = 0;
  3740. if (!supportsPresent) {
  3741. SET_STRING_ERROR_AND_RETURN("This surface does not support presenting!", false);
  3742. }
  3743. // Run the device surface queries
  3744. result = renderer->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
  3745. physicalDevice,
  3746. surface,
  3747. &outputDetails->capabilities);
  3748. CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfaceCapabilitiesKHR, false);
  3749. if (!(outputDetails->capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)) {
  3750. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Opaque presentation unsupported! Expect weird transparency bugs!");
  3751. }
  3752. result = renderer->vkGetPhysicalDeviceSurfaceFormatsKHR(
  3753. physicalDevice,
  3754. surface,
  3755. &outputDetails->formatsLength,
  3756. NULL);
  3757. CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfaceFormatsKHR, false);
  3758. result = renderer->vkGetPhysicalDeviceSurfacePresentModesKHR(
  3759. physicalDevice,
  3760. surface,
  3761. &outputDetails->presentModesLength,
  3762. NULL);
  3763. CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfacePresentModesKHR, false);
  3764. // Generate the arrays, if applicable
  3765. outputDetails->formats = NULL;
  3766. if (outputDetails->formatsLength != 0) {
  3767. outputDetails->formats = (VkSurfaceFormatKHR *)SDL_malloc(
  3768. sizeof(VkSurfaceFormatKHR) * outputDetails->formatsLength);
  3769. if (!outputDetails->formats) { // OOM
  3770. return false;
  3771. }
  3772. result = renderer->vkGetPhysicalDeviceSurfaceFormatsKHR(
  3773. physicalDevice,
  3774. surface,
  3775. &outputDetails->formatsLength,
  3776. outputDetails->formats);
  3777. if (result != VK_SUCCESS) {
  3778. SDL_free(outputDetails->formats);
  3779. CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfaceFormatsKHR, false);
  3780. }
  3781. }
  3782. outputDetails->presentModes = NULL;
  3783. if (outputDetails->presentModesLength != 0) {
  3784. outputDetails->presentModes = (VkPresentModeKHR *)SDL_malloc(
  3785. sizeof(VkPresentModeKHR) * outputDetails->presentModesLength);
  3786. if (!outputDetails->presentModes) { // OOM
  3787. SDL_free(outputDetails->formats);
  3788. return false;
  3789. }
  3790. result = renderer->vkGetPhysicalDeviceSurfacePresentModesKHR(
  3791. physicalDevice,
  3792. surface,
  3793. &outputDetails->presentModesLength,
  3794. outputDetails->presentModes);
  3795. if (result != VK_SUCCESS) {
  3796. SDL_free(outputDetails->formats);
  3797. SDL_free(outputDetails->presentModes);
  3798. CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfacePresentModesKHR, false);
  3799. }
  3800. }
  3801. /* If we made it here, all the queries were successful. This does NOT
  3802. * necessarily mean there are any supported formats or present modes!
  3803. */
  3804. return true;
  3805. }
  3806. static bool VULKAN_INTERNAL_VerifySwapSurfaceFormat(
  3807. VkFormat desiredFormat,
  3808. VkColorSpaceKHR desiredColorSpace,
  3809. VkSurfaceFormatKHR *availableFormats,
  3810. Uint32 availableFormatsLength)
  3811. {
  3812. Uint32 i;
  3813. for (i = 0; i < availableFormatsLength; i += 1) {
  3814. if (availableFormats[i].format == desiredFormat &&
  3815. availableFormats[i].colorSpace == desiredColorSpace) {
  3816. return true;
  3817. }
  3818. }
  3819. return false;
  3820. }
  3821. static bool VULKAN_INTERNAL_VerifySwapPresentMode(
  3822. VkPresentModeKHR presentMode,
  3823. const VkPresentModeKHR *availablePresentModes,
  3824. Uint32 availablePresentModesLength)
  3825. {
  3826. Uint32 i;
  3827. for (i = 0; i < availablePresentModesLength; i += 1) {
  3828. if (availablePresentModes[i] == presentMode) {
  3829. return true;
  3830. }
  3831. }
  3832. return false;
  3833. }
  3834. /* It would be nice if VULKAN_INTERNAL_CreateSwapchain could return a bool.
  3835. * Unfortunately, some Win32 NVIDIA drivers are stupid
  3836. * and will return surface extents of (0, 0)
  3837. * in certain edge cases, and the swapchain extents are not allowed to be 0.
  3838. * In this case, the client probably still wants to claim the window
  3839. * or recreate the swapchain, so we should return 2 to indicate retry.
  3840. * -cosmonaut
  3841. */
  3842. #define VULKAN_INTERNAL_TRY_AGAIN 2
  3843. static Uint32 VULKAN_INTERNAL_CreateSwapchain(
  3844. VulkanRenderer *renderer,
  3845. WindowData *windowData)
  3846. {
  3847. VkResult vulkanResult;
  3848. VkSwapchainCreateInfoKHR swapchainCreateInfo;
  3849. VkImage *swapchainImages;
  3850. VkSemaphoreCreateInfo semaphoreCreateInfo;
  3851. SwapchainSupportDetails swapchainSupportDetails;
  3852. bool hasValidSwapchainComposition, hasValidPresentMode;
  3853. Uint32 i;
  3854. windowData->frameCounter = 0;
  3855. SDL_VideoDevice *_this = SDL_GetVideoDevice();
  3856. SDL_assert(_this && _this->Vulkan_CreateSurface);
  3857. // Each swapchain must have its own surface.
  3858. if (!_this->Vulkan_CreateSurface(
  3859. _this,
  3860. windowData->window,
  3861. renderer->instance,
  3862. NULL, // FIXME: VAllocationCallbacks
  3863. &windowData->surface)) {
  3864. return false;
  3865. }
  3866. SDL_assert(windowData->surface);
  3867. if (!VULKAN_INTERNAL_QuerySwapchainSupport(
  3868. renderer,
  3869. renderer->physicalDevice,
  3870. windowData->surface,
  3871. &swapchainSupportDetails)) {
  3872. renderer->vkDestroySurfaceKHR(
  3873. renderer->instance,
  3874. windowData->surface,
  3875. NULL);
  3876. windowData->surface = VK_NULL_HANDLE;
  3877. if (swapchainSupportDetails.formatsLength > 0) {
  3878. SDL_free(swapchainSupportDetails.formats);
  3879. }
  3880. if (swapchainSupportDetails.presentModesLength > 0) {
  3881. SDL_free(swapchainSupportDetails.presentModes);
  3882. }
  3883. return false;
  3884. }
  3885. // Verify that we can use the requested composition and present mode
  3886. windowData->format = SwapchainCompositionToFormat[windowData->swapchainComposition];
  3887. windowData->colorSpace = SwapchainCompositionToColorSpace[windowData->swapchainComposition];
  3888. windowData->swapchainSwizzle = SwapchainCompositionSwizzle[windowData->swapchainComposition];
  3889. windowData->usingFallbackFormat = false;
  3890. hasValidSwapchainComposition = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
  3891. windowData->format,
  3892. windowData->colorSpace,
  3893. swapchainSupportDetails.formats,
  3894. swapchainSupportDetails.formatsLength);
  3895. if (!hasValidSwapchainComposition) {
  3896. // Let's try again with the fallback format...
  3897. windowData->format = SwapchainCompositionToFallbackFormat[windowData->swapchainComposition];
  3898. windowData->usingFallbackFormat = true;
  3899. hasValidSwapchainComposition = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
  3900. windowData->format,
  3901. windowData->colorSpace,
  3902. swapchainSupportDetails.formats,
  3903. swapchainSupportDetails.formatsLength);
  3904. }
  3905. hasValidPresentMode = VULKAN_INTERNAL_VerifySwapPresentMode(
  3906. SDLToVK_PresentMode[windowData->presentMode],
  3907. swapchainSupportDetails.presentModes,
  3908. swapchainSupportDetails.presentModesLength);
  3909. if (!hasValidSwapchainComposition || !hasValidPresentMode) {
  3910. renderer->vkDestroySurfaceKHR(
  3911. renderer->instance,
  3912. windowData->surface,
  3913. NULL);
  3914. windowData->surface = VK_NULL_HANDLE;
  3915. if (swapchainSupportDetails.formatsLength > 0) {
  3916. SDL_free(swapchainSupportDetails.formats);
  3917. }
  3918. if (swapchainSupportDetails.presentModesLength > 0) {
  3919. SDL_free(swapchainSupportDetails.presentModes);
  3920. }
  3921. if (!hasValidSwapchainComposition) {
  3922. SET_STRING_ERROR_AND_RETURN("Device does not support requested swapchain composition!", false);
  3923. }
  3924. if (!hasValidPresentMode) {
  3925. SET_STRING_ERROR_AND_RETURN("Device does not support requested present_mode!", false);
  3926. }
  3927. return false;
  3928. }
  3929. // NVIDIA + Win32 can return 0 extent when the window is minimized. Try again!
  3930. if (swapchainSupportDetails.capabilities.currentExtent.width == 0 ||
  3931. swapchainSupportDetails.capabilities.currentExtent.height == 0) {
  3932. renderer->vkDestroySurfaceKHR(
  3933. renderer->instance,
  3934. windowData->surface,
  3935. NULL);
  3936. windowData->surface = VK_NULL_HANDLE;
  3937. if (swapchainSupportDetails.formatsLength > 0) {
  3938. SDL_free(swapchainSupportDetails.formats);
  3939. }
  3940. if (swapchainSupportDetails.presentModesLength > 0) {
  3941. SDL_free(swapchainSupportDetails.presentModes);
  3942. }
  3943. return VULKAN_INTERNAL_TRY_AGAIN;
  3944. }
  3945. Uint32 requestedImageCount = renderer->allowedFramesInFlight;
  3946. #ifdef SDL_PLATFORM_APPLE
  3947. windowData->width = swapchainSupportDetails.capabilities.currentExtent.width;
  3948. windowData->height = swapchainSupportDetails.capabilities.currentExtent.height;
  3949. #else
  3950. windowData->width = SDL_clamp(
  3951. windowData->swapchainCreateWidth,
  3952. swapchainSupportDetails.capabilities.minImageExtent.width,
  3953. swapchainSupportDetails.capabilities.maxImageExtent.width);
  3954. windowData->height = SDL_clamp(windowData->swapchainCreateHeight,
  3955. swapchainSupportDetails.capabilities.minImageExtent.height,
  3956. swapchainSupportDetails.capabilities.maxImageExtent.height);
  3957. #endif
  3958. if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
  3959. requestedImageCount > swapchainSupportDetails.capabilities.maxImageCount) {
  3960. requestedImageCount = swapchainSupportDetails.capabilities.maxImageCount;
  3961. }
  3962. if (requestedImageCount < swapchainSupportDetails.capabilities.minImageCount) {
  3963. requestedImageCount = swapchainSupportDetails.capabilities.minImageCount;
  3964. }
  3965. if (windowData->presentMode == SDL_GPU_PRESENTMODE_MAILBOX) {
  3966. /* Required for proper triple-buffering.
  3967. * Note that this is below the above maxImageCount check!
  3968. * If the driver advertises MAILBOX but does not support 3 swap
  3969. * images, it's not real mailbox support, so let it fail hard.
  3970. * -flibit
  3971. */
  3972. requestedImageCount = SDL_max(requestedImageCount, 3);
  3973. }
  3974. swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  3975. swapchainCreateInfo.pNext = NULL;
  3976. swapchainCreateInfo.flags = 0;
  3977. swapchainCreateInfo.surface = windowData->surface;
  3978. swapchainCreateInfo.minImageCount = requestedImageCount;
  3979. swapchainCreateInfo.imageFormat = windowData->format;
  3980. swapchainCreateInfo.imageColorSpace = windowData->colorSpace;
  3981. swapchainCreateInfo.imageExtent.width = windowData->width;
  3982. swapchainCreateInfo.imageExtent.height = windowData->height;
  3983. swapchainCreateInfo.imageArrayLayers = 1;
  3984. swapchainCreateInfo.imageUsage =
  3985. VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
  3986. VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  3987. swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  3988. swapchainCreateInfo.queueFamilyIndexCount = 0;
  3989. swapchainCreateInfo.pQueueFamilyIndices = NULL;
  3990. #ifdef SDL_PLATFORM_ANDROID
  3991. swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
  3992. #else
  3993. swapchainCreateInfo.preTransform = swapchainSupportDetails.capabilities.currentTransform;
  3994. #endif
  3995. swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  3996. swapchainCreateInfo.presentMode = SDLToVK_PresentMode[windowData->presentMode];
  3997. swapchainCreateInfo.clipped = VK_TRUE;
  3998. swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
  3999. vulkanResult = renderer->vkCreateSwapchainKHR(
  4000. renderer->logicalDevice,
  4001. &swapchainCreateInfo,
  4002. NULL,
  4003. &windowData->swapchain);
  4004. if (swapchainSupportDetails.formatsLength > 0) {
  4005. SDL_free(swapchainSupportDetails.formats);
  4006. }
  4007. if (swapchainSupportDetails.presentModesLength > 0) {
  4008. SDL_free(swapchainSupportDetails.presentModes);
  4009. }
  4010. if (vulkanResult != VK_SUCCESS) {
  4011. renderer->vkDestroySurfaceKHR(
  4012. renderer->instance,
  4013. windowData->surface,
  4014. NULL);
  4015. windowData->surface = VK_NULL_HANDLE;
  4016. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSwapchainKHR, false);
  4017. }
  4018. vulkanResult = renderer->vkGetSwapchainImagesKHR(
  4019. renderer->logicalDevice,
  4020. windowData->swapchain,
  4021. &windowData->imageCount,
  4022. NULL);
  4023. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkGetSwapchainImagesKHR, false);
  4024. windowData->textureContainers = SDL_malloc(
  4025. sizeof(VulkanTextureContainer) * windowData->imageCount);
  4026. if (!windowData->textureContainers) { // OOM
  4027. renderer->vkDestroySurfaceKHR(
  4028. renderer->instance,
  4029. windowData->surface,
  4030. NULL);
  4031. renderer->vkDestroySwapchainKHR(
  4032. renderer->logicalDevice,
  4033. windowData->swapchain,
  4034. NULL);
  4035. windowData->surface = VK_NULL_HANDLE;
  4036. windowData->swapchain = VK_NULL_HANDLE;
  4037. return false;
  4038. }
  4039. swapchainImages = SDL_stack_alloc(VkImage, windowData->imageCount);
  4040. vulkanResult = renderer->vkGetSwapchainImagesKHR(
  4041. renderer->logicalDevice,
  4042. windowData->swapchain,
  4043. &windowData->imageCount,
  4044. swapchainImages);
  4045. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkGetSwapchainImagesKHR, false);
  4046. for (i = 0; i < windowData->imageCount; i += 1) {
  4047. // Initialize dummy container
  4048. SDL_zero(windowData->textureContainers[i]);
  4049. windowData->textureContainers[i].canBeCycled = false;
  4050. windowData->textureContainers[i].header.info.width = windowData->width;
  4051. windowData->textureContainers[i].header.info.height = windowData->height;
  4052. windowData->textureContainers[i].header.info.layer_count_or_depth = 1;
  4053. windowData->textureContainers[i].header.info.format = SwapchainCompositionToSDLFormat(
  4054. windowData->swapchainComposition,
  4055. windowData->usingFallbackFormat);
  4056. windowData->textureContainers[i].header.info.type = SDL_GPU_TEXTURETYPE_2D;
  4057. windowData->textureContainers[i].header.info.num_levels = 1;
  4058. windowData->textureContainers[i].header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
  4059. windowData->textureContainers[i].header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
  4060. windowData->textureContainers[i].activeTexture = SDL_malloc(sizeof(VulkanTexture));
  4061. windowData->textureContainers[i].activeTexture->image = swapchainImages[i];
  4062. // Swapchain memory is managed by the driver
  4063. windowData->textureContainers[i].activeTexture->usedRegion = NULL;
  4064. windowData->textureContainers[i].activeTexture->swizzle = windowData->swapchainSwizzle;
  4065. windowData->textureContainers[i].activeTexture->aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
  4066. windowData->textureContainers[i].activeTexture->depth = 1;
  4067. windowData->textureContainers[i].activeTexture->usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
  4068. windowData->textureContainers[i].activeTexture->container = &windowData->textureContainers[i];
  4069. SDL_SetAtomicInt(&windowData->textureContainers[i].activeTexture->referenceCount, 0);
  4070. // Create slice
  4071. windowData->textureContainers[i].activeTexture->subresourceCount = 1;
  4072. windowData->textureContainers[i].activeTexture->subresources = SDL_malloc(sizeof(VulkanTextureSubresource));
  4073. windowData->textureContainers[i].activeTexture->subresources[0].parent = windowData->textureContainers[i].activeTexture;
  4074. windowData->textureContainers[i].activeTexture->subresources[0].layer = 0;
  4075. windowData->textureContainers[i].activeTexture->subresources[0].level = 0;
  4076. windowData->textureContainers[i].activeTexture->subresources[0].renderTargetViews = SDL_malloc(sizeof(VkImageView));
  4077. if (!VULKAN_INTERNAL_CreateRenderTargetView(
  4078. renderer,
  4079. windowData->textureContainers[i].activeTexture,
  4080. 0,
  4081. 0,
  4082. windowData->format,
  4083. windowData->swapchainSwizzle,
  4084. &windowData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0])) {
  4085. renderer->vkDestroySurfaceKHR(
  4086. renderer->instance,
  4087. windowData->surface,
  4088. NULL);
  4089. renderer->vkDestroySwapchainKHR(
  4090. renderer->logicalDevice,
  4091. windowData->swapchain,
  4092. NULL);
  4093. windowData->surface = VK_NULL_HANDLE;
  4094. windowData->swapchain = VK_NULL_HANDLE;
  4095. return false;
  4096. }
  4097. }
  4098. SDL_stack_free(swapchainImages);
  4099. semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  4100. semaphoreCreateInfo.pNext = NULL;
  4101. semaphoreCreateInfo.flags = 0;
  4102. for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
  4103. vulkanResult = renderer->vkCreateSemaphore(
  4104. renderer->logicalDevice,
  4105. &semaphoreCreateInfo,
  4106. NULL,
  4107. &windowData->imageAvailableSemaphore[i]);
  4108. if (vulkanResult != VK_SUCCESS) {
  4109. renderer->vkDestroySurfaceKHR(
  4110. renderer->instance,
  4111. windowData->surface,
  4112. NULL);
  4113. renderer->vkDestroySwapchainKHR(
  4114. renderer->logicalDevice,
  4115. windowData->swapchain,
  4116. NULL);
  4117. windowData->surface = VK_NULL_HANDLE;
  4118. windowData->swapchain = VK_NULL_HANDLE;
  4119. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
  4120. }
  4121. windowData->inFlightFences[i] = NULL;
  4122. }
  4123. windowData->renderFinishedSemaphore = SDL_malloc(
  4124. sizeof(VkSemaphore) * windowData->imageCount);
  4125. for (i = 0; i < windowData->imageCount; i += 1) {
  4126. vulkanResult = renderer->vkCreateSemaphore(
  4127. renderer->logicalDevice,
  4128. &semaphoreCreateInfo,
  4129. NULL,
  4130. &windowData->renderFinishedSemaphore[i]);
  4131. if (vulkanResult != VK_SUCCESS) {
  4132. renderer->vkDestroySurfaceKHR(
  4133. renderer->instance,
  4134. windowData->surface,
  4135. NULL);
  4136. renderer->vkDestroySwapchainKHR(
  4137. renderer->logicalDevice,
  4138. windowData->swapchain,
  4139. NULL);
  4140. windowData->surface = VK_NULL_HANDLE;
  4141. windowData->swapchain = VK_NULL_HANDLE;
  4142. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false);
  4143. }
  4144. }
  4145. windowData->needsSwapchainRecreate = false;
  4146. return true;
  4147. }
  4148. // Command Buffers
  4149. static bool VULKAN_INTERNAL_BeginCommandBuffer(
  4150. VulkanRenderer *renderer,
  4151. VulkanCommandBuffer *commandBuffer)
  4152. {
  4153. VkCommandBufferBeginInfo beginInfo;
  4154. VkResult result;
  4155. beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  4156. beginInfo.pNext = NULL;
  4157. beginInfo.flags = 0;
  4158. beginInfo.pInheritanceInfo = NULL;
  4159. beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  4160. result = renderer->vkBeginCommandBuffer(
  4161. commandBuffer->commandBuffer,
  4162. &beginInfo);
  4163. CHECK_VULKAN_ERROR_AND_RETURN(result, vkBeginCommandBuffer, false);
  4164. return true;
  4165. }
  4166. static bool VULKAN_INTERNAL_EndCommandBuffer(
  4167. VulkanRenderer *renderer,
  4168. VulkanCommandBuffer *commandBuffer)
  4169. {
  4170. VkResult result = renderer->vkEndCommandBuffer(
  4171. commandBuffer->commandBuffer);
  4172. CHECK_VULKAN_ERROR_AND_RETURN(result, vkEndCommandBuffer, false);
  4173. return true;
  4174. }
  4175. static void VULKAN_DestroyDevice(
  4176. SDL_GPUDevice *device)
  4177. {
  4178. VulkanRenderer *renderer = (VulkanRenderer *)device->driverData;
  4179. VulkanMemorySubAllocator *allocator;
  4180. VULKAN_Wait(device->driverData);
  4181. for (Sint32 i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) {
  4182. VULKAN_ReleaseWindow(device->driverData, renderer->claimedWindows[i]->window);
  4183. }
  4184. SDL_free(renderer->claimedWindows);
  4185. VULKAN_Wait(device->driverData);
  4186. SDL_free(renderer->submittedCommandBuffers);
  4187. for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
  4188. VULKAN_INTERNAL_DestroyBuffer(
  4189. renderer,
  4190. renderer->uniformBufferPool[i]->buffer);
  4191. SDL_free(renderer->uniformBufferPool[i]);
  4192. }
  4193. SDL_free(renderer->uniformBufferPool);
  4194. for (Uint32 i = 0; i < renderer->descriptorSetCachePoolCount; i += 1) {
  4195. VULKAN_INTERNAL_DestroyDescriptorSetCache(
  4196. renderer,
  4197. renderer->descriptorSetCachePool[i]);
  4198. }
  4199. SDL_free(renderer->descriptorSetCachePool);
  4200. for (Uint32 i = 0; i < renderer->fencePool.availableFenceCount; i += 1) {
  4201. renderer->vkDestroyFence(
  4202. renderer->logicalDevice,
  4203. renderer->fencePool.availableFences[i]->fence,
  4204. NULL);
  4205. SDL_free(renderer->fencePool.availableFences[i]);
  4206. }
  4207. SDL_free(renderer->fencePool.availableFences);
  4208. SDL_DestroyMutex(renderer->fencePool.lock);
  4209. SDL_DestroyHashTable(renderer->commandPoolHashTable);
  4210. SDL_DestroyHashTable(renderer->renderPassHashTable);
  4211. SDL_DestroyHashTable(renderer->framebufferHashTable);
  4212. SDL_DestroyHashTable(renderer->graphicsPipelineResourceLayoutHashTable);
  4213. SDL_DestroyHashTable(renderer->computePipelineResourceLayoutHashTable);
  4214. SDL_DestroyHashTable(renderer->descriptorSetLayoutHashTable);
  4215. for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
  4216. allocator = &renderer->memoryAllocator->subAllocators[i];
  4217. for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
  4218. for (Sint32 k = allocator->allocations[j]->usedRegionCount - 1; k >= 0; k -= 1) {
  4219. VULKAN_INTERNAL_RemoveMemoryUsedRegion(
  4220. renderer,
  4221. allocator->allocations[j]->usedRegions[k]);
  4222. }
  4223. VULKAN_INTERNAL_DeallocateMemory(
  4224. renderer,
  4225. allocator,
  4226. j);
  4227. }
  4228. if (renderer->memoryAllocator->subAllocators[i].allocations != NULL) {
  4229. SDL_free(renderer->memoryAllocator->subAllocators[i].allocations);
  4230. }
  4231. SDL_free(renderer->memoryAllocator->subAllocators[i].sortedFreeRegions);
  4232. }
  4233. SDL_free(renderer->memoryAllocator);
  4234. SDL_free(renderer->texturesToDestroy);
  4235. SDL_free(renderer->buffersToDestroy);
  4236. SDL_free(renderer->graphicsPipelinesToDestroy);
  4237. SDL_free(renderer->computePipelinesToDestroy);
  4238. SDL_free(renderer->shadersToDestroy);
  4239. SDL_free(renderer->samplersToDestroy);
  4240. SDL_free(renderer->framebuffersToDestroy);
  4241. SDL_free(renderer->allocationsToDefrag);
  4242. SDL_DestroyMutex(renderer->allocatorLock);
  4243. SDL_DestroyMutex(renderer->disposeLock);
  4244. SDL_DestroyMutex(renderer->submitLock);
  4245. SDL_DestroyMutex(renderer->acquireCommandBufferLock);
  4246. SDL_DestroyMutex(renderer->acquireUniformBufferLock);
  4247. SDL_DestroyMutex(renderer->renderPassFetchLock);
  4248. SDL_DestroyMutex(renderer->framebufferFetchLock);
  4249. SDL_DestroyMutex(renderer->graphicsPipelineLayoutFetchLock);
  4250. SDL_DestroyMutex(renderer->computePipelineLayoutFetchLock);
  4251. SDL_DestroyMutex(renderer->descriptorSetLayoutFetchLock);
  4252. SDL_DestroyMutex(renderer->windowLock);
  4253. renderer->vkDestroyDevice(renderer->logicalDevice, NULL);
  4254. renderer->vkDestroyInstance(renderer->instance, NULL);
  4255. SDL_free(renderer);
  4256. SDL_free(device);
  4257. SDL_Vulkan_UnloadLibrary();
  4258. }
  4259. static DescriptorSetCache *VULKAN_INTERNAL_AcquireDescriptorSetCache(
  4260. VulkanRenderer *renderer)
  4261. {
  4262. DescriptorSetCache *cache;
  4263. if (renderer->descriptorSetCachePoolCount == 0) {
  4264. cache = SDL_malloc(sizeof(DescriptorSetCache));
  4265. cache->poolCount = 0;
  4266. cache->pools = NULL;
  4267. } else {
  4268. cache = renderer->descriptorSetCachePool[renderer->descriptorSetCachePoolCount - 1];
  4269. renderer->descriptorSetCachePoolCount -= 1;
  4270. }
  4271. return cache;
  4272. }
  4273. static void VULKAN_INTERNAL_ReturnDescriptorSetCacheToPool(
  4274. VulkanRenderer *renderer,
  4275. DescriptorSetCache *descriptorSetCache)
  4276. {
  4277. EXPAND_ARRAY_IF_NEEDED(
  4278. renderer->descriptorSetCachePool,
  4279. DescriptorSetCache *,
  4280. renderer->descriptorSetCachePoolCount + 1,
  4281. renderer->descriptorSetCachePoolCapacity,
  4282. renderer->descriptorSetCachePoolCapacity * 2);
  4283. renderer->descriptorSetCachePool[renderer->descriptorSetCachePoolCount] = descriptorSetCache;
  4284. renderer->descriptorSetCachePoolCount += 1;
  4285. for (Uint32 i = 0; i < descriptorSetCache->poolCount; i += 1) {
  4286. descriptorSetCache->pools[i].descriptorSetIndex = 0;
  4287. }
  4288. }
  4289. static VkDescriptorSet VULKAN_INTERNAL_FetchDescriptorSet(
  4290. VulkanRenderer *renderer,
  4291. VulkanCommandBuffer *vulkanCommandBuffer,
  4292. DescriptorSetLayout *descriptorSetLayout)
  4293. {
  4294. // Grow the pool to meet the descriptor set layout ID
  4295. if (descriptorSetLayout->ID >= vulkanCommandBuffer->descriptorSetCache->poolCount) {
  4296. vulkanCommandBuffer->descriptorSetCache->pools = SDL_realloc(
  4297. vulkanCommandBuffer->descriptorSetCache->pools,
  4298. sizeof(DescriptorSetPool) * (descriptorSetLayout->ID + 1));
  4299. for (Uint32 i = vulkanCommandBuffer->descriptorSetCache->poolCount; i < descriptorSetLayout->ID + 1; i += 1) {
  4300. SDL_zero(vulkanCommandBuffer->descriptorSetCache->pools[i]);
  4301. }
  4302. vulkanCommandBuffer->descriptorSetCache->poolCount = descriptorSetLayout->ID + 1;
  4303. }
  4304. DescriptorSetPool *pool =
  4305. &vulkanCommandBuffer->descriptorSetCache->pools[descriptorSetLayout->ID];
  4306. if (pool->descriptorSetIndex == pool->descriptorSetCount) {
  4307. if (!VULKAN_INTERNAL_AllocateDescriptorsFromPool(
  4308. renderer,
  4309. descriptorSetLayout,
  4310. pool)) {
  4311. return VK_NULL_HANDLE;
  4312. }
  4313. }
  4314. VkDescriptorSet descriptorSet = pool->descriptorSets[pool->descriptorSetIndex];
  4315. pool->descriptorSetIndex += 1;
  4316. return descriptorSet;
  4317. }
  4318. static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
  4319. VulkanRenderer *renderer,
  4320. VulkanCommandBuffer *commandBuffer)
  4321. {
  4322. VulkanGraphicsPipelineResourceLayout *resourceLayout;
  4323. DescriptorSetLayout *descriptorSetLayout;
  4324. VkWriteDescriptorSet writeDescriptorSets[
  4325. (MAX_TEXTURE_SAMPLERS_PER_STAGE +
  4326. MAX_STORAGE_TEXTURES_PER_STAGE +
  4327. MAX_STORAGE_BUFFERS_PER_STAGE +
  4328. MAX_UNIFORM_BUFFERS_PER_STAGE) * 2];
  4329. VkDescriptorBufferInfo bufferInfos[MAX_STORAGE_BUFFERS_PER_STAGE * 2];
  4330. VkDescriptorImageInfo imageInfos[(MAX_TEXTURE_SAMPLERS_PER_STAGE + MAX_STORAGE_TEXTURES_PER_STAGE) * 2];
  4331. Uint32 dynamicOffsets[MAX_UNIFORM_BUFFERS_PER_STAGE * 2];
  4332. Uint32 writeCount = 0;
  4333. Uint32 bufferInfoCount = 0;
  4334. Uint32 imageInfoCount = 0;
  4335. Uint32 dynamicOffsetCount = 0;
  4336. if (
  4337. !commandBuffer->needVertexBufferBind &&
  4338. !commandBuffer->needNewVertexResourceDescriptorSet &&
  4339. !commandBuffer->needNewVertexUniformDescriptorSet &&
  4340. !commandBuffer->needNewVertexUniformOffsets &&
  4341. !commandBuffer->needNewFragmentResourceDescriptorSet &&
  4342. !commandBuffer->needNewFragmentUniformDescriptorSet &&
  4343. !commandBuffer->needNewFragmentUniformOffsets
  4344. ) {
  4345. return;
  4346. }
  4347. if (commandBuffer->needVertexBufferBind && commandBuffer->vertexBufferCount > 0) {
  4348. renderer->vkCmdBindVertexBuffers(
  4349. commandBuffer->commandBuffer,
  4350. 0,
  4351. commandBuffer->vertexBufferCount,
  4352. commandBuffer->vertexBuffers,
  4353. commandBuffer->vertexBufferOffsets);
  4354. commandBuffer->needVertexBufferBind = false;
  4355. }
  4356. resourceLayout = commandBuffer->currentGraphicsPipeline->resourceLayout;
  4357. if (commandBuffer->needNewVertexResourceDescriptorSet) {
  4358. descriptorSetLayout = resourceLayout->descriptorSetLayouts[0];
  4359. commandBuffer->vertexResourceDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
  4360. renderer,
  4361. commandBuffer,
  4362. descriptorSetLayout);
  4363. for (Uint32 i = 0; i < resourceLayout->vertexSamplerCount; i += 1) {
  4364. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  4365. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  4366. currentWriteDescriptorSet->pNext = NULL;
  4367. currentWriteDescriptorSet->descriptorCount = 1;
  4368. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  4369. currentWriteDescriptorSet->dstArrayElement = 0;
  4370. currentWriteDescriptorSet->dstBinding = i;
  4371. currentWriteDescriptorSet->dstSet = commandBuffer->vertexResourceDescriptorSet;
  4372. currentWriteDescriptorSet->pTexelBufferView = NULL;
  4373. currentWriteDescriptorSet->pBufferInfo = NULL;
  4374. imageInfos[imageInfoCount].sampler = commandBuffer->vertexSamplerBindings[i];
  4375. imageInfos[imageInfoCount].imageView = commandBuffer->vertexSamplerTextureViewBindings[i];
  4376. imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  4377. currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
  4378. writeCount += 1;
  4379. imageInfoCount += 1;
  4380. }
  4381. for (Uint32 i = 0; i < resourceLayout->vertexStorageTextureCount; i += 1) {
  4382. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  4383. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  4384. currentWriteDescriptorSet->pNext = NULL;
  4385. currentWriteDescriptorSet->descriptorCount = 1;
  4386. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; // Yes, we are declaring a storage image as a sampled image, because shaders are stupid.
  4387. currentWriteDescriptorSet->dstArrayElement = 0;
  4388. currentWriteDescriptorSet->dstBinding = resourceLayout->vertexSamplerCount + i;
  4389. currentWriteDescriptorSet->dstSet = commandBuffer->vertexResourceDescriptorSet;
  4390. currentWriteDescriptorSet->pTexelBufferView = NULL;
  4391. currentWriteDescriptorSet->pBufferInfo = NULL;
  4392. imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
  4393. imageInfos[imageInfoCount].imageView = commandBuffer->vertexStorageTextureViewBindings[i];
  4394. imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
  4395. currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
  4396. writeCount += 1;
  4397. imageInfoCount += 1;
  4398. }
  4399. for (Uint32 i = 0; i < resourceLayout->vertexStorageBufferCount; i += 1) {
  4400. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  4401. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  4402. currentWriteDescriptorSet->pNext = NULL;
  4403. currentWriteDescriptorSet->descriptorCount = 1;
  4404. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  4405. currentWriteDescriptorSet->dstArrayElement = 0;
  4406. currentWriteDescriptorSet->dstBinding = resourceLayout->vertexSamplerCount + resourceLayout->vertexStorageTextureCount + i;
  4407. currentWriteDescriptorSet->dstSet = commandBuffer->vertexResourceDescriptorSet;
  4408. currentWriteDescriptorSet->pTexelBufferView = NULL;
  4409. currentWriteDescriptorSet->pImageInfo = NULL;
  4410. bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexStorageBufferBindings[i];
  4411. bufferInfos[bufferInfoCount].offset = 0;
  4412. bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
  4413. currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
  4414. writeCount += 1;
  4415. bufferInfoCount += 1;
  4416. }
  4417. commandBuffer->needNewVertexResourceDescriptorSet = false;
  4418. }
  4419. if (commandBuffer->needNewVertexUniformDescriptorSet) {
  4420. descriptorSetLayout = resourceLayout->descriptorSetLayouts[1];
  4421. commandBuffer->vertexUniformDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
  4422. renderer,
  4423. commandBuffer,
  4424. descriptorSetLayout);
  4425. for (Uint32 i = 0; i < resourceLayout->vertexUniformBufferCount; i += 1) {
  4426. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  4427. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  4428. currentWriteDescriptorSet->pNext = NULL;
  4429. currentWriteDescriptorSet->descriptorCount = 1;
  4430. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
  4431. currentWriteDescriptorSet->dstArrayElement = 0;
  4432. currentWriteDescriptorSet->dstBinding = i;
  4433. currentWriteDescriptorSet->dstSet = commandBuffer->vertexUniformDescriptorSet;
  4434. currentWriteDescriptorSet->pTexelBufferView = NULL;
  4435. currentWriteDescriptorSet->pImageInfo = NULL;
  4436. bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexUniformBuffers[i]->buffer->buffer;
  4437. bufferInfos[bufferInfoCount].offset = 0;
  4438. bufferInfos[bufferInfoCount].range = MAX_UBO_SECTION_SIZE;
  4439. currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
  4440. writeCount += 1;
  4441. bufferInfoCount += 1;
  4442. }
  4443. commandBuffer->needNewVertexUniformDescriptorSet = false;
  4444. }
  4445. for (Uint32 i = 0; i < resourceLayout->vertexUniformBufferCount; i += 1) {
  4446. dynamicOffsets[dynamicOffsetCount] = commandBuffer->vertexUniformBuffers[i]->drawOffset;
  4447. dynamicOffsetCount += 1;
  4448. }
  4449. if (commandBuffer->needNewFragmentResourceDescriptorSet) {
  4450. descriptorSetLayout = resourceLayout->descriptorSetLayouts[2];
  4451. commandBuffer->fragmentResourceDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
  4452. renderer,
  4453. commandBuffer,
  4454. descriptorSetLayout);
  4455. for (Uint32 i = 0; i < resourceLayout->fragmentSamplerCount; i += 1) {
  4456. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  4457. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  4458. currentWriteDescriptorSet->pNext = NULL;
  4459. currentWriteDescriptorSet->descriptorCount = 1;
  4460. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  4461. currentWriteDescriptorSet->dstArrayElement = 0;
  4462. currentWriteDescriptorSet->dstBinding = i;
  4463. currentWriteDescriptorSet->dstSet = commandBuffer->fragmentResourceDescriptorSet;
  4464. currentWriteDescriptorSet->pTexelBufferView = NULL;
  4465. currentWriteDescriptorSet->pBufferInfo = NULL;
  4466. imageInfos[imageInfoCount].sampler = commandBuffer->fragmentSamplerBindings[i];
  4467. imageInfos[imageInfoCount].imageView = commandBuffer->fragmentSamplerTextureViewBindings[i];
  4468. imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  4469. currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
  4470. writeCount += 1;
  4471. imageInfoCount += 1;
  4472. }
  4473. for (Uint32 i = 0; i < resourceLayout->fragmentStorageTextureCount; i += 1) {
  4474. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  4475. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  4476. currentWriteDescriptorSet->pNext = NULL;
  4477. currentWriteDescriptorSet->descriptorCount = 1;
  4478. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; // Yes, we are declaring a storage image as a sampled image, because shaders are stupid.
  4479. currentWriteDescriptorSet->dstArrayElement = 0;
  4480. currentWriteDescriptorSet->dstBinding = resourceLayout->fragmentSamplerCount + i;
  4481. currentWriteDescriptorSet->dstSet = commandBuffer->fragmentResourceDescriptorSet;
  4482. currentWriteDescriptorSet->pTexelBufferView = NULL;
  4483. currentWriteDescriptorSet->pBufferInfo = NULL;
  4484. imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
  4485. imageInfos[imageInfoCount].imageView = commandBuffer->fragmentStorageTextureViewBindings[i];
  4486. imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
  4487. currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
  4488. writeCount += 1;
  4489. imageInfoCount += 1;
  4490. }
  4491. for (Uint32 i = 0; i < resourceLayout->fragmentStorageBufferCount; i += 1) {
  4492. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  4493. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  4494. currentWriteDescriptorSet->pNext = NULL;
  4495. currentWriteDescriptorSet->descriptorCount = 1;
  4496. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  4497. currentWriteDescriptorSet->dstArrayElement = 0;
  4498. currentWriteDescriptorSet->dstBinding = resourceLayout->fragmentSamplerCount + resourceLayout->fragmentStorageTextureCount + i;
  4499. currentWriteDescriptorSet->dstSet = commandBuffer->fragmentResourceDescriptorSet;
  4500. currentWriteDescriptorSet->pTexelBufferView = NULL;
  4501. currentWriteDescriptorSet->pImageInfo = NULL;
  4502. bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentStorageBufferBindings[i];
  4503. bufferInfos[bufferInfoCount].offset = 0;
  4504. bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
  4505. currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
  4506. writeCount += 1;
  4507. bufferInfoCount += 1;
  4508. }
  4509. commandBuffer->needNewFragmentResourceDescriptorSet = false;
  4510. }
  4511. if (commandBuffer->needNewFragmentUniformDescriptorSet) {
  4512. descriptorSetLayout = resourceLayout->descriptorSetLayouts[3];
  4513. commandBuffer->fragmentUniformDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
  4514. renderer,
  4515. commandBuffer,
  4516. descriptorSetLayout);
  4517. for (Uint32 i = 0; i < resourceLayout->fragmentUniformBufferCount; i += 1) {
  4518. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  4519. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  4520. currentWriteDescriptorSet->pNext = NULL;
  4521. currentWriteDescriptorSet->descriptorCount = 1;
  4522. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
  4523. currentWriteDescriptorSet->dstArrayElement = 0;
  4524. currentWriteDescriptorSet->dstBinding = i;
  4525. currentWriteDescriptorSet->dstSet = commandBuffer->fragmentUniformDescriptorSet;
  4526. currentWriteDescriptorSet->pTexelBufferView = NULL;
  4527. currentWriteDescriptorSet->pImageInfo = NULL;
  4528. bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentUniformBuffers[i]->buffer->buffer;
  4529. bufferInfos[bufferInfoCount].offset = 0;
  4530. bufferInfos[bufferInfoCount].range = MAX_UBO_SECTION_SIZE;
  4531. currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
  4532. writeCount += 1;
  4533. bufferInfoCount += 1;
  4534. }
  4535. commandBuffer->needNewFragmentUniformDescriptorSet = false;
  4536. }
  4537. for (Uint32 i = 0; i < resourceLayout->fragmentUniformBufferCount; i += 1) {
  4538. dynamicOffsets[dynamicOffsetCount] = commandBuffer->fragmentUniformBuffers[i]->drawOffset;
  4539. dynamicOffsetCount += 1;
  4540. }
  4541. renderer->vkUpdateDescriptorSets(
  4542. renderer->logicalDevice,
  4543. writeCount,
  4544. writeDescriptorSets,
  4545. 0,
  4546. NULL);
  4547. VkDescriptorSet sets[4];
  4548. sets[0] = commandBuffer->vertexResourceDescriptorSet;
  4549. sets[1] = commandBuffer->vertexUniformDescriptorSet;
  4550. sets[2] = commandBuffer->fragmentResourceDescriptorSet;
  4551. sets[3] = commandBuffer->fragmentUniformDescriptorSet;
  4552. renderer->vkCmdBindDescriptorSets(
  4553. commandBuffer->commandBuffer,
  4554. VK_PIPELINE_BIND_POINT_GRAPHICS,
  4555. resourceLayout->pipelineLayout,
  4556. 0,
  4557. 4,
  4558. sets,
  4559. dynamicOffsetCount,
  4560. dynamicOffsets);
  4561. commandBuffer->needNewVertexUniformOffsets = false;
  4562. commandBuffer->needNewFragmentUniformOffsets = false;
  4563. }
  4564. static void VULKAN_DrawIndexedPrimitives(
  4565. SDL_GPUCommandBuffer *commandBuffer,
  4566. Uint32 numIndices,
  4567. Uint32 numInstances,
  4568. Uint32 firstIndex,
  4569. Sint32 vertexOffset,
  4570. Uint32 firstInstance)
  4571. {
  4572. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  4573. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  4574. VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
  4575. renderer->vkCmdDrawIndexed(
  4576. vulkanCommandBuffer->commandBuffer,
  4577. numIndices,
  4578. numInstances,
  4579. firstIndex,
  4580. vertexOffset,
  4581. firstInstance);
  4582. }
  4583. static void VULKAN_DrawPrimitives(
  4584. SDL_GPUCommandBuffer *commandBuffer,
  4585. Uint32 numVertices,
  4586. Uint32 numInstances,
  4587. Uint32 firstVertex,
  4588. Uint32 firstInstance)
  4589. {
  4590. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  4591. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  4592. VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
  4593. renderer->vkCmdDraw(
  4594. vulkanCommandBuffer->commandBuffer,
  4595. numVertices,
  4596. numInstances,
  4597. firstVertex,
  4598. firstInstance);
  4599. }
  4600. static void VULKAN_DrawPrimitivesIndirect(
  4601. SDL_GPUCommandBuffer *commandBuffer,
  4602. SDL_GPUBuffer *buffer,
  4603. Uint32 offset,
  4604. Uint32 drawCount)
  4605. {
  4606. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  4607. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  4608. VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)buffer)->activeBuffer;
  4609. Uint32 pitch = sizeof(SDL_GPUIndirectDrawCommand);
  4610. Uint32 i;
  4611. VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
  4612. if (renderer->supportsMultiDrawIndirect) {
  4613. // Real multi-draw!
  4614. renderer->vkCmdDrawIndirect(
  4615. vulkanCommandBuffer->commandBuffer,
  4616. vulkanBuffer->buffer,
  4617. offset,
  4618. drawCount,
  4619. pitch);
  4620. } else {
  4621. // Fake multi-draw...
  4622. for (i = 0; i < drawCount; i += 1) {
  4623. renderer->vkCmdDrawIndirect(
  4624. vulkanCommandBuffer->commandBuffer,
  4625. vulkanBuffer->buffer,
  4626. offset + (pitch * i),
  4627. 1,
  4628. pitch);
  4629. }
  4630. }
  4631. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
  4632. }
  4633. static void VULKAN_DrawIndexedPrimitivesIndirect(
  4634. SDL_GPUCommandBuffer *commandBuffer,
  4635. SDL_GPUBuffer *buffer,
  4636. Uint32 offset,
  4637. Uint32 drawCount)
  4638. {
  4639. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  4640. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  4641. VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)buffer)->activeBuffer;
  4642. Uint32 pitch = sizeof(SDL_GPUIndexedIndirectDrawCommand);
  4643. Uint32 i;
  4644. VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
  4645. if (renderer->supportsMultiDrawIndirect) {
  4646. // Real multi-draw!
  4647. renderer->vkCmdDrawIndexedIndirect(
  4648. vulkanCommandBuffer->commandBuffer,
  4649. vulkanBuffer->buffer,
  4650. offset,
  4651. drawCount,
  4652. pitch);
  4653. } else {
  4654. // Fake multi-draw...
  4655. for (i = 0; i < drawCount; i += 1) {
  4656. renderer->vkCmdDrawIndexedIndirect(
  4657. vulkanCommandBuffer->commandBuffer,
  4658. vulkanBuffer->buffer,
  4659. offset + (pitch * i),
  4660. 1,
  4661. pitch);
  4662. }
  4663. }
  4664. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
  4665. }
  4666. // Debug Naming
  4667. static void VULKAN_INTERNAL_SetBufferName(
  4668. VulkanRenderer *renderer,
  4669. VulkanBuffer *buffer,
  4670. const char *text)
  4671. {
  4672. VkDebugUtilsObjectNameInfoEXT nameInfo;
  4673. if (renderer->debugMode && renderer->supportsDebugUtils) {
  4674. nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  4675. nameInfo.pNext = NULL;
  4676. nameInfo.pObjectName = text;
  4677. nameInfo.objectType = VK_OBJECT_TYPE_BUFFER;
  4678. nameInfo.objectHandle = (uint64_t)buffer->buffer;
  4679. renderer->vkSetDebugUtilsObjectNameEXT(
  4680. renderer->logicalDevice,
  4681. &nameInfo);
  4682. }
  4683. }
  4684. static void VULKAN_SetBufferName(
  4685. SDL_GPURenderer *driverData,
  4686. SDL_GPUBuffer *buffer,
  4687. const char *text)
  4688. {
  4689. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  4690. VulkanBufferContainer *container = (VulkanBufferContainer *)buffer;
  4691. size_t textLength = SDL_strlen(text) + 1;
  4692. if (renderer->debugMode && renderer->supportsDebugUtils) {
  4693. container->debugName = SDL_realloc(
  4694. container->debugName,
  4695. textLength);
  4696. SDL_utf8strlcpy(
  4697. container->debugName,
  4698. text,
  4699. textLength);
  4700. for (Uint32 i = 0; i < container->bufferCount; i += 1) {
  4701. VULKAN_INTERNAL_SetBufferName(
  4702. renderer,
  4703. container->buffers[i],
  4704. text);
  4705. }
  4706. }
  4707. }
  4708. static void VULKAN_INTERNAL_SetTextureName(
  4709. VulkanRenderer *renderer,
  4710. VulkanTexture *texture,
  4711. const char *text)
  4712. {
  4713. VkDebugUtilsObjectNameInfoEXT nameInfo;
  4714. if (renderer->debugMode && renderer->supportsDebugUtils) {
  4715. nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  4716. nameInfo.pNext = NULL;
  4717. nameInfo.pObjectName = text;
  4718. nameInfo.objectType = VK_OBJECT_TYPE_IMAGE;
  4719. nameInfo.objectHandle = (uint64_t)texture->image;
  4720. renderer->vkSetDebugUtilsObjectNameEXT(
  4721. renderer->logicalDevice,
  4722. &nameInfo);
  4723. }
  4724. }
  4725. static void VULKAN_SetTextureName(
  4726. SDL_GPURenderer *driverData,
  4727. SDL_GPUTexture *texture,
  4728. const char *text)
  4729. {
  4730. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  4731. VulkanTextureContainer *container = (VulkanTextureContainer *)texture;
  4732. size_t textLength = SDL_strlen(text) + 1;
  4733. if (renderer->debugMode && renderer->supportsDebugUtils) {
  4734. container->debugName = SDL_realloc(
  4735. container->debugName,
  4736. textLength);
  4737. SDL_utf8strlcpy(
  4738. container->debugName,
  4739. text,
  4740. textLength);
  4741. for (Uint32 i = 0; i < container->textureCount; i += 1) {
  4742. VULKAN_INTERNAL_SetTextureName(
  4743. renderer,
  4744. container->textures[i],
  4745. text);
  4746. }
  4747. }
  4748. }
  4749. static void VULKAN_InsertDebugLabel(
  4750. SDL_GPUCommandBuffer *commandBuffer,
  4751. const char *text)
  4752. {
  4753. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  4754. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  4755. VkDebugUtilsLabelEXT labelInfo;
  4756. if (renderer->supportsDebugUtils) {
  4757. SDL_zero(labelInfo);
  4758. labelInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
  4759. labelInfo.pLabelName = text;
  4760. renderer->vkCmdInsertDebugUtilsLabelEXT(
  4761. vulkanCommandBuffer->commandBuffer,
  4762. &labelInfo);
  4763. }
  4764. }
  4765. static void VULKAN_PushDebugGroup(
  4766. SDL_GPUCommandBuffer *commandBuffer,
  4767. const char *name)
  4768. {
  4769. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  4770. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  4771. VkDebugUtilsLabelEXT labelInfo;
  4772. if (renderer->supportsDebugUtils) {
  4773. SDL_zero(labelInfo);
  4774. labelInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
  4775. labelInfo.pLabelName = name;
  4776. renderer->vkCmdBeginDebugUtilsLabelEXT(
  4777. vulkanCommandBuffer->commandBuffer,
  4778. &labelInfo);
  4779. }
  4780. }
  4781. static void VULKAN_PopDebugGroup(
  4782. SDL_GPUCommandBuffer *commandBuffer)
  4783. {
  4784. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  4785. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  4786. if (renderer->supportsDebugUtils) {
  4787. renderer->vkCmdEndDebugUtilsLabelEXT(vulkanCommandBuffer->commandBuffer);
  4788. }
  4789. }
  4790. static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
  4791. VulkanRenderer *renderer,
  4792. bool transitionToDefaultLayout,
  4793. const SDL_GPUTextureCreateInfo *createinfo)
  4794. {
  4795. VkResult vulkanResult;
  4796. VkImageCreateInfo imageCreateInfo;
  4797. VkImageCreateFlags imageCreateFlags = 0;
  4798. VkImageViewCreateInfo imageViewCreateInfo;
  4799. Uint8 bindResult;
  4800. VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  4801. Uint32 layerCount = (createinfo->type == SDL_GPU_TEXTURETYPE_3D) ? 1 : createinfo->layer_count_or_depth;
  4802. Uint32 depth = (createinfo->type == SDL_GPU_TEXTURETYPE_3D) ? createinfo->layer_count_or_depth : 1;
  4803. VulkanTexture *texture = SDL_calloc(1, sizeof(VulkanTexture));
  4804. texture->swizzle = SwizzleForSDLFormat(createinfo->format);
  4805. texture->depth = depth;
  4806. texture->usage = createinfo->usage;
  4807. SDL_SetAtomicInt(&texture->referenceCount, 0);
  4808. if (IsDepthFormat(createinfo->format)) {
  4809. texture->aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
  4810. if (IsStencilFormat(createinfo->format)) {
  4811. texture->aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
  4812. }
  4813. } else {
  4814. texture->aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
  4815. }
  4816. if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
  4817. imageCreateFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
  4818. } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
  4819. imageCreateFlags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
  4820. }
  4821. if (createinfo->usage & (SDL_GPU_TEXTUREUSAGE_SAMPLER |
  4822. SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ |
  4823. SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)) {
  4824. vkUsageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
  4825. }
  4826. if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
  4827. vkUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  4828. }
  4829. if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
  4830. vkUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
  4831. }
  4832. if (createinfo->usage & (SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE |
  4833. SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) {
  4834. vkUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
  4835. }
  4836. imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  4837. imageCreateInfo.pNext = NULL;
  4838. imageCreateInfo.flags = imageCreateFlags;
  4839. imageCreateInfo.imageType = createinfo->type == SDL_GPU_TEXTURETYPE_3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
  4840. imageCreateInfo.format = SDLToVK_TextureFormat[createinfo->format];
  4841. imageCreateInfo.extent.width = createinfo->width;
  4842. imageCreateInfo.extent.height = createinfo->height;
  4843. imageCreateInfo.extent.depth = depth;
  4844. imageCreateInfo.mipLevels = createinfo->num_levels;
  4845. imageCreateInfo.arrayLayers = layerCount;
  4846. imageCreateInfo.samples = SDLToVK_SampleCount[createinfo->sample_count];
  4847. imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
  4848. imageCreateInfo.usage = vkUsageFlags;
  4849. imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  4850. imageCreateInfo.queueFamilyIndexCount = 0;
  4851. imageCreateInfo.pQueueFamilyIndices = NULL;
  4852. imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  4853. vulkanResult = renderer->vkCreateImage(
  4854. renderer->logicalDevice,
  4855. &imageCreateInfo,
  4856. NULL,
  4857. &texture->image);
  4858. if (vulkanResult != VK_SUCCESS) {
  4859. VULKAN_INTERNAL_DestroyTexture(renderer, texture);
  4860. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateImage, NULL);
  4861. }
  4862. bindResult = VULKAN_INTERNAL_BindMemoryForImage(
  4863. renderer,
  4864. texture->image,
  4865. &texture->usedRegion);
  4866. if (bindResult != 1) {
  4867. renderer->vkDestroyImage(
  4868. renderer->logicalDevice,
  4869. texture->image,
  4870. NULL);
  4871. VULKAN_INTERNAL_DestroyTexture(renderer, texture);
  4872. SET_STRING_ERROR_AND_RETURN("Unable to bind memory for texture!", NULL);
  4873. }
  4874. texture->usedRegion->vulkanTexture = texture; // lol
  4875. if (createinfo->usage & (SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)) {
  4876. imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  4877. imageViewCreateInfo.pNext = NULL;
  4878. imageViewCreateInfo.flags = 0;
  4879. imageViewCreateInfo.image = texture->image;
  4880. imageViewCreateInfo.format = SDLToVK_TextureFormat[createinfo->format];
  4881. imageViewCreateInfo.components = texture->swizzle;
  4882. imageViewCreateInfo.subresourceRange.aspectMask = texture->aspectFlags & ~VK_IMAGE_ASPECT_STENCIL_BIT; // Can't sample stencil values
  4883. imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
  4884. imageViewCreateInfo.subresourceRange.levelCount = createinfo->num_levels;
  4885. imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
  4886. imageViewCreateInfo.subresourceRange.layerCount = layerCount;
  4887. if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
  4888. imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
  4889. } else if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
  4890. imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
  4891. } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
  4892. imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
  4893. } else if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
  4894. imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
  4895. } else {
  4896. imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  4897. }
  4898. vulkanResult = renderer->vkCreateImageView(
  4899. renderer->logicalDevice,
  4900. &imageViewCreateInfo,
  4901. NULL,
  4902. &texture->fullView);
  4903. if (vulkanResult != VK_SUCCESS) {
  4904. VULKAN_INTERNAL_DestroyTexture(renderer, texture);
  4905. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, "vkCreateImageView", NULL);
  4906. }
  4907. }
  4908. // Define slices
  4909. texture->subresourceCount = layerCount * createinfo->num_levels;
  4910. texture->subresources = SDL_calloc(
  4911. texture->subresourceCount,
  4912. sizeof(VulkanTextureSubresource));
  4913. for (Uint32 i = 0; i < layerCount; i += 1) {
  4914. for (Uint32 j = 0; j < createinfo->num_levels; j += 1) {
  4915. Uint32 subresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
  4916. j,
  4917. i,
  4918. createinfo->num_levels);
  4919. if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
  4920. texture->subresources[subresourceIndex].renderTargetViews = SDL_malloc(
  4921. depth * sizeof(VkImageView));
  4922. if (depth > 1) {
  4923. for (Uint32 k = 0; k < depth; k += 1) {
  4924. if (!VULKAN_INTERNAL_CreateRenderTargetView(
  4925. renderer,
  4926. texture,
  4927. k,
  4928. j,
  4929. SDLToVK_TextureFormat[createinfo->format],
  4930. texture->swizzle,
  4931. &texture->subresources[subresourceIndex].renderTargetViews[k])) {
  4932. VULKAN_INTERNAL_DestroyTexture(renderer, texture);
  4933. return NULL;
  4934. }
  4935. }
  4936. } else {
  4937. if (!VULKAN_INTERNAL_CreateRenderTargetView(
  4938. renderer,
  4939. texture,
  4940. i,
  4941. j,
  4942. SDLToVK_TextureFormat[createinfo->format],
  4943. texture->swizzle,
  4944. &texture->subresources[subresourceIndex].renderTargetViews[0])) {
  4945. VULKAN_INTERNAL_DestroyTexture(renderer, texture);
  4946. return NULL;
  4947. }
  4948. }
  4949. }
  4950. if ((createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) || (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) {
  4951. if (!VULKAN_INTERNAL_CreateSubresourceView(
  4952. renderer,
  4953. createinfo,
  4954. texture,
  4955. i,
  4956. j,
  4957. texture->swizzle,
  4958. &texture->subresources[subresourceIndex].computeWriteView)) {
  4959. VULKAN_INTERNAL_DestroyTexture(renderer, texture);
  4960. return NULL;
  4961. }
  4962. }
  4963. if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
  4964. if (!VULKAN_INTERNAL_CreateSubresourceView(
  4965. renderer,
  4966. createinfo,
  4967. texture,
  4968. i,
  4969. j,
  4970. texture->swizzle,
  4971. &texture->subresources[subresourceIndex].depthStencilView)) {
  4972. VULKAN_INTERNAL_DestroyTexture(renderer, texture);
  4973. return NULL;
  4974. }
  4975. }
  4976. texture->subresources[subresourceIndex].parent = texture;
  4977. texture->subresources[subresourceIndex].layer = i;
  4978. texture->subresources[subresourceIndex].level = j;
  4979. }
  4980. }
  4981. // Set debug name if applicable
  4982. if (renderer->debugMode && renderer->supportsDebugUtils && SDL_HasProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING)) {
  4983. VkDebugUtilsObjectNameInfoEXT nameInfo;
  4984. nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  4985. nameInfo.pNext = NULL;
  4986. nameInfo.pObjectName = SDL_GetStringProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING, NULL);
  4987. nameInfo.objectType = VK_OBJECT_TYPE_IMAGE;
  4988. nameInfo.objectHandle = (uint64_t)texture->image;
  4989. renderer->vkSetDebugUtilsObjectNameEXT(
  4990. renderer->logicalDevice,
  4991. &nameInfo);
  4992. }
  4993. if (transitionToDefaultLayout) {
  4994. // Let's transition to the default barrier state, because for some reason Vulkan doesn't let us do that with initialLayout.
  4995. VulkanCommandBuffer *barrierCommandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
  4996. VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
  4997. renderer,
  4998. barrierCommandBuffer,
  4999. VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
  5000. texture);
  5001. VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture);
  5002. if (!VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer)) {
  5003. VULKAN_INTERNAL_DestroyTexture(renderer, texture);
  5004. return NULL;
  5005. }
  5006. }
  5007. return texture;
  5008. }
  5009. static void VULKAN_INTERNAL_CycleActiveBuffer(
  5010. VulkanRenderer *renderer,
  5011. VulkanBufferContainer *container)
  5012. {
  5013. VulkanBuffer *buffer;
  5014. // If a previously-cycled buffer is available, we can use that.
  5015. for (Uint32 i = 0; i < container->bufferCount; i += 1) {
  5016. buffer = container->buffers[i];
  5017. if (SDL_GetAtomicInt(&buffer->referenceCount) == 0) {
  5018. container->activeBuffer = buffer;
  5019. return;
  5020. }
  5021. }
  5022. // No buffer handle is available, create a new one.
  5023. buffer = VULKAN_INTERNAL_CreateBuffer(
  5024. renderer,
  5025. container->activeBuffer->size,
  5026. container->activeBuffer->usage,
  5027. container->activeBuffer->type,
  5028. container->dedicated,
  5029. container->debugName);
  5030. if (!buffer) {
  5031. return;
  5032. }
  5033. EXPAND_ARRAY_IF_NEEDED(
  5034. container->buffers,
  5035. VulkanBuffer *,
  5036. container->bufferCount + 1,
  5037. container->bufferCapacity,
  5038. container->bufferCapacity * 2);
  5039. container->buffers[container->bufferCount] = buffer;
  5040. buffer->container = container;
  5041. buffer->containerIndex = container->bufferCount;
  5042. container->bufferCount += 1;
  5043. container->activeBuffer = buffer;
  5044. }
  5045. static void VULKAN_INTERNAL_CycleActiveTexture(
  5046. VulkanRenderer *renderer,
  5047. VulkanCommandBuffer *commandBuffer,
  5048. VulkanTextureContainer *container)
  5049. {
  5050. VulkanTexture *texture;
  5051. // If a previously-cycled texture is available, we can use that.
  5052. for (Uint32 i = 0; i < container->textureCount; i += 1) {
  5053. texture = container->textures[i];
  5054. if (SDL_GetAtomicInt(&texture->referenceCount) == 0) {
  5055. container->activeTexture = texture;
  5056. return;
  5057. }
  5058. }
  5059. // No texture is available, generate a new one.
  5060. texture = VULKAN_INTERNAL_CreateTexture(
  5061. renderer,
  5062. false,
  5063. &container->header.info);
  5064. VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
  5065. renderer,
  5066. commandBuffer,
  5067. VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
  5068. texture);
  5069. if (!texture) {
  5070. return;
  5071. }
  5072. EXPAND_ARRAY_IF_NEEDED(
  5073. container->textures,
  5074. VulkanTexture *,
  5075. container->textureCount + 1,
  5076. container->textureCapacity,
  5077. container->textureCapacity * 2);
  5078. container->textures[container->textureCount] = texture;
  5079. texture->container = container;
  5080. texture->containerIndex = container->textureCount;
  5081. container->textureCount += 1;
  5082. container->activeTexture = texture;
  5083. }
  5084. static VulkanBuffer *VULKAN_INTERNAL_PrepareBufferForWrite(
  5085. VulkanRenderer *renderer,
  5086. VulkanCommandBuffer *commandBuffer,
  5087. VulkanBufferContainer *bufferContainer,
  5088. bool cycle,
  5089. VulkanBufferUsageMode destinationUsageMode)
  5090. {
  5091. if (
  5092. cycle &&
  5093. SDL_GetAtomicInt(&bufferContainer->activeBuffer->referenceCount) > 0) {
  5094. VULKAN_INTERNAL_CycleActiveBuffer(
  5095. renderer,
  5096. bufferContainer);
  5097. }
  5098. VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
  5099. renderer,
  5100. commandBuffer,
  5101. destinationUsageMode,
  5102. bufferContainer->activeBuffer);
  5103. return bufferContainer->activeBuffer;
  5104. }
  5105. static VulkanTextureSubresource *VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
  5106. VulkanRenderer *renderer,
  5107. VulkanCommandBuffer *commandBuffer,
  5108. VulkanTextureContainer *textureContainer,
  5109. Uint32 layer,
  5110. Uint32 level,
  5111. bool cycle,
  5112. VulkanTextureUsageMode destinationUsageMode)
  5113. {
  5114. VulkanTextureSubresource *textureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
  5115. textureContainer,
  5116. layer,
  5117. level);
  5118. if (
  5119. cycle &&
  5120. textureContainer->canBeCycled &&
  5121. SDL_GetAtomicInt(&textureContainer->activeTexture->referenceCount) > 0) {
  5122. VULKAN_INTERNAL_CycleActiveTexture(
  5123. renderer,
  5124. commandBuffer,
  5125. textureContainer);
  5126. textureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
  5127. textureContainer,
  5128. layer,
  5129. level);
  5130. }
  5131. // always do barrier because of layout transitions
  5132. VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  5133. renderer,
  5134. commandBuffer,
  5135. destinationUsageMode,
  5136. textureSubresource);
  5137. return textureSubresource;
  5138. }
  5139. static VkRenderPass VULKAN_INTERNAL_CreateRenderPass(
  5140. VulkanRenderer *renderer,
  5141. VulkanCommandBuffer *commandBuffer,
  5142. const SDL_GPUColorTargetInfo *colorTargetInfos,
  5143. Uint32 numColorTargets,
  5144. const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo)
  5145. {
  5146. VkResult vulkanResult;
  5147. VkAttachmentDescription attachmentDescriptions[2 * MAX_COLOR_TARGET_BINDINGS + 1 /* depth */];
  5148. VkAttachmentReference colorAttachmentReferences[MAX_COLOR_TARGET_BINDINGS];
  5149. VkAttachmentReference resolveReferences[MAX_COLOR_TARGET_BINDINGS];
  5150. VkAttachmentReference depthStencilAttachmentReference;
  5151. VkRenderPassCreateInfo renderPassCreateInfo;
  5152. VkSubpassDescription subpass;
  5153. VkRenderPass renderPass;
  5154. Uint32 i;
  5155. Uint32 attachmentDescriptionCount = 0;
  5156. Uint32 colorAttachmentReferenceCount = 0;
  5157. Uint32 resolveReferenceCount = 0;
  5158. for (i = 0; i < numColorTargets; i += 1) {
  5159. VulkanTextureContainer *container = (VulkanTextureContainer *)colorTargetInfos[i].texture;
  5160. attachmentDescriptions[attachmentDescriptionCount].flags = 0;
  5161. attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[container->header.info.format];
  5162. attachmentDescriptions[attachmentDescriptionCount].samples = SDLToVK_SampleCount[container->header.info.sample_count];
  5163. attachmentDescriptions[attachmentDescriptionCount].loadOp = SDLToVK_LoadOp[colorTargetInfos[i].load_op];
  5164. attachmentDescriptions[attachmentDescriptionCount].storeOp = SDLToVK_StoreOp[colorTargetInfos[i].store_op];
  5165. attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  5166. attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  5167. attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  5168. attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  5169. colorAttachmentReferences[colorAttachmentReferenceCount].attachment = attachmentDescriptionCount;
  5170. colorAttachmentReferences[colorAttachmentReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  5171. attachmentDescriptionCount += 1;
  5172. if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
  5173. VulkanTextureContainer *resolveContainer = (VulkanTextureContainer *)colorTargetInfos[i].resolve_texture;
  5174. attachmentDescriptions[attachmentDescriptionCount].flags = 0;
  5175. attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[resolveContainer->header.info.format];
  5176. attachmentDescriptions[attachmentDescriptionCount].samples = SDLToVK_SampleCount[resolveContainer->header.info.sample_count];
  5177. attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // The texture will be overwritten anyway
  5178. attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // Always store the resolve texture
  5179. attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  5180. attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  5181. attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  5182. attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  5183. resolveReferences[colorAttachmentReferenceCount].attachment = attachmentDescriptionCount;
  5184. resolveReferences[colorAttachmentReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  5185. attachmentDescriptionCount += 1;
  5186. resolveReferenceCount += 1;
  5187. } else {
  5188. resolveReferences[colorAttachmentReferenceCount].attachment = VK_ATTACHMENT_UNUSED;
  5189. }
  5190. colorAttachmentReferenceCount += 1;
  5191. }
  5192. subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  5193. subpass.flags = 0;
  5194. subpass.inputAttachmentCount = 0;
  5195. subpass.pInputAttachments = NULL;
  5196. subpass.colorAttachmentCount = numColorTargets;
  5197. subpass.pColorAttachments = colorAttachmentReferences;
  5198. subpass.preserveAttachmentCount = 0;
  5199. subpass.pPreserveAttachments = NULL;
  5200. if (depthStencilTargetInfo == NULL) {
  5201. subpass.pDepthStencilAttachment = NULL;
  5202. } else {
  5203. VulkanTextureContainer *container = (VulkanTextureContainer *)depthStencilTargetInfo->texture;
  5204. attachmentDescriptions[attachmentDescriptionCount].flags = 0;
  5205. attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[container->header.info.format];
  5206. attachmentDescriptions[attachmentDescriptionCount].samples = SDLToVK_SampleCount[container->header.info.sample_count];
  5207. attachmentDescriptions[attachmentDescriptionCount].loadOp = SDLToVK_LoadOp[depthStencilTargetInfo->load_op];
  5208. attachmentDescriptions[attachmentDescriptionCount].storeOp = SDLToVK_StoreOp[depthStencilTargetInfo->store_op];
  5209. attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = SDLToVK_LoadOp[depthStencilTargetInfo->stencil_load_op];
  5210. attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = SDLToVK_StoreOp[depthStencilTargetInfo->stencil_store_op];
  5211. attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  5212. attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  5213. depthStencilAttachmentReference.attachment = attachmentDescriptionCount;
  5214. depthStencilAttachmentReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  5215. subpass.pDepthStencilAttachment = &depthStencilAttachmentReference;
  5216. attachmentDescriptionCount += 1;
  5217. }
  5218. if (resolveReferenceCount > 0) {
  5219. subpass.pResolveAttachments = resolveReferences;
  5220. } else {
  5221. subpass.pResolveAttachments = NULL;
  5222. }
  5223. renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  5224. renderPassCreateInfo.pNext = NULL;
  5225. renderPassCreateInfo.flags = 0;
  5226. renderPassCreateInfo.pAttachments = attachmentDescriptions;
  5227. renderPassCreateInfo.attachmentCount = attachmentDescriptionCount;
  5228. renderPassCreateInfo.subpassCount = 1;
  5229. renderPassCreateInfo.pSubpasses = &subpass;
  5230. renderPassCreateInfo.dependencyCount = 0;
  5231. renderPassCreateInfo.pDependencies = NULL;
  5232. vulkanResult = renderer->vkCreateRenderPass(
  5233. renderer->logicalDevice,
  5234. &renderPassCreateInfo,
  5235. NULL,
  5236. &renderPass);
  5237. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateRenderPass, VK_NULL_HANDLE);
  5238. return renderPass;
  5239. }
  5240. static VkRenderPass VULKAN_INTERNAL_CreateTransientRenderPass(
  5241. VulkanRenderer *renderer,
  5242. SDL_GPUGraphicsPipelineTargetInfo targetInfo,
  5243. VkSampleCountFlagBits sampleCount)
  5244. {
  5245. VkAttachmentDescription attachmentDescriptions[MAX_COLOR_TARGET_BINDINGS + 1 /* depth */];
  5246. VkAttachmentReference colorAttachmentReferences[MAX_COLOR_TARGET_BINDINGS];
  5247. VkAttachmentReference depthStencilAttachmentReference;
  5248. SDL_GPUColorTargetDescription attachmentDescription;
  5249. VkSubpassDescription subpass;
  5250. VkRenderPassCreateInfo renderPassCreateInfo;
  5251. VkRenderPass renderPass;
  5252. VkResult result;
  5253. Uint32 attachmentDescriptionCount = 0;
  5254. Uint32 colorAttachmentReferenceCount = 0;
  5255. Uint32 i;
  5256. for (i = 0; i < targetInfo.num_color_targets; i += 1) {
  5257. attachmentDescription = targetInfo.color_target_descriptions[i];
  5258. attachmentDescriptions[attachmentDescriptionCount].flags = 0;
  5259. attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[attachmentDescription.format];
  5260. attachmentDescriptions[attachmentDescriptionCount].samples = sampleCount;
  5261. attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  5262. attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  5263. attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  5264. attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  5265. attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  5266. attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  5267. colorAttachmentReferences[colorAttachmentReferenceCount].attachment = attachmentDescriptionCount;
  5268. colorAttachmentReferences[colorAttachmentReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  5269. attachmentDescriptionCount += 1;
  5270. colorAttachmentReferenceCount += 1;
  5271. }
  5272. subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  5273. subpass.flags = 0;
  5274. subpass.inputAttachmentCount = 0;
  5275. subpass.pInputAttachments = NULL;
  5276. subpass.colorAttachmentCount = targetInfo.num_color_targets;
  5277. subpass.pColorAttachments = colorAttachmentReferences;
  5278. subpass.preserveAttachmentCount = 0;
  5279. subpass.pPreserveAttachments = NULL;
  5280. if (targetInfo.has_depth_stencil_target) {
  5281. attachmentDescriptions[attachmentDescriptionCount].flags = 0;
  5282. attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[targetInfo.depth_stencil_format];
  5283. attachmentDescriptions[attachmentDescriptionCount].samples = sampleCount;
  5284. attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  5285. attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  5286. attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  5287. attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  5288. attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  5289. attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  5290. depthStencilAttachmentReference.attachment = attachmentDescriptionCount;
  5291. depthStencilAttachmentReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  5292. subpass.pDepthStencilAttachment = &depthStencilAttachmentReference;
  5293. attachmentDescriptionCount += 1;
  5294. } else {
  5295. subpass.pDepthStencilAttachment = NULL;
  5296. }
  5297. // Resolve attachments aren't needed for transient passes
  5298. subpass.pResolveAttachments = NULL;
  5299. renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  5300. renderPassCreateInfo.pNext = NULL;
  5301. renderPassCreateInfo.flags = 0;
  5302. renderPassCreateInfo.pAttachments = attachmentDescriptions;
  5303. renderPassCreateInfo.attachmentCount = attachmentDescriptionCount;
  5304. renderPassCreateInfo.subpassCount = 1;
  5305. renderPassCreateInfo.pSubpasses = &subpass;
  5306. renderPassCreateInfo.dependencyCount = 0;
  5307. renderPassCreateInfo.pDependencies = NULL;
  5308. result = renderer->vkCreateRenderPass(
  5309. renderer->logicalDevice,
  5310. &renderPassCreateInfo,
  5311. NULL,
  5312. &renderPass);
  5313. CHECK_VULKAN_ERROR_AND_RETURN(result, vkCreateRenderPass, VK_NULL_HANDLE);
  5314. return renderPass;
  5315. }
  5316. static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
  5317. SDL_GPURenderer *driverData,
  5318. const SDL_GPUGraphicsPipelineCreateInfo *createinfo)
  5319. {
  5320. VkResult vulkanResult;
  5321. Uint32 i;
  5322. VulkanGraphicsPipeline *graphicsPipeline = (VulkanGraphicsPipeline *)SDL_malloc(sizeof(VulkanGraphicsPipeline));
  5323. VkGraphicsPipelineCreateInfo vkPipelineCreateInfo;
  5324. VkPipelineShaderStageCreateInfo shaderStageCreateInfos[2];
  5325. VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo;
  5326. VkVertexInputBindingDescription *vertexInputBindingDescriptions = SDL_stack_alloc(VkVertexInputBindingDescription, createinfo->vertex_input_state.num_vertex_buffers);
  5327. VkVertexInputAttributeDescription *vertexInputAttributeDescriptions = SDL_stack_alloc(VkVertexInputAttributeDescription, createinfo->vertex_input_state.num_vertex_attributes);
  5328. VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo;
  5329. VkPipelineViewportStateCreateInfo viewportStateCreateInfo;
  5330. VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo;
  5331. VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo;
  5332. VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo;
  5333. VkStencilOpState frontStencilState;
  5334. VkStencilOpState backStencilState;
  5335. VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo;
  5336. VkPipelineColorBlendAttachmentState *colorBlendAttachmentStates = SDL_stack_alloc(
  5337. VkPipelineColorBlendAttachmentState,
  5338. createinfo->target_info.num_color_targets);
  5339. static const VkDynamicState dynamicStates[] = {
  5340. VK_DYNAMIC_STATE_VIEWPORT,
  5341. VK_DYNAMIC_STATE_SCISSOR,
  5342. VK_DYNAMIC_STATE_BLEND_CONSTANTS,
  5343. VK_DYNAMIC_STATE_STENCIL_REFERENCE
  5344. };
  5345. VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo;
  5346. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5347. // Create a "compatible" render pass
  5348. VkRenderPass transientRenderPass = VULKAN_INTERNAL_CreateTransientRenderPass(
  5349. renderer,
  5350. createinfo->target_info,
  5351. SDLToVK_SampleCount[createinfo->multisample_state.sample_count]);
  5352. // Dynamic state
  5353. dynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
  5354. dynamicStateCreateInfo.pNext = NULL;
  5355. dynamicStateCreateInfo.flags = 0;
  5356. dynamicStateCreateInfo.dynamicStateCount = SDL_arraysize(dynamicStates);
  5357. dynamicStateCreateInfo.pDynamicStates = dynamicStates;
  5358. // Shader stages
  5359. graphicsPipeline->vertexShader = (VulkanShader *)createinfo->vertex_shader;
  5360. SDL_AtomicIncRef(&graphicsPipeline->vertexShader->referenceCount);
  5361. shaderStageCreateInfos[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  5362. shaderStageCreateInfos[0].pNext = NULL;
  5363. shaderStageCreateInfos[0].flags = 0;
  5364. shaderStageCreateInfos[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
  5365. shaderStageCreateInfos[0].module = graphicsPipeline->vertexShader->shaderModule;
  5366. shaderStageCreateInfos[0].pName = graphicsPipeline->vertexShader->entrypointName;
  5367. shaderStageCreateInfos[0].pSpecializationInfo = NULL;
  5368. graphicsPipeline->fragmentShader = (VulkanShader *)createinfo->fragment_shader;
  5369. SDL_AtomicIncRef(&graphicsPipeline->fragmentShader->referenceCount);
  5370. shaderStageCreateInfos[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  5371. shaderStageCreateInfos[1].pNext = NULL;
  5372. shaderStageCreateInfos[1].flags = 0;
  5373. shaderStageCreateInfos[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
  5374. shaderStageCreateInfos[1].module = graphicsPipeline->fragmentShader->shaderModule;
  5375. shaderStageCreateInfos[1].pName = graphicsPipeline->fragmentShader->entrypointName;
  5376. shaderStageCreateInfos[1].pSpecializationInfo = NULL;
  5377. if (renderer->debugMode) {
  5378. if (graphicsPipeline->vertexShader->stage != SDL_GPU_SHADERSTAGE_VERTEX) {
  5379. SDL_assert_release(!"CreateGraphicsPipeline was passed a fragment shader for the vertex stage");
  5380. }
  5381. if (graphicsPipeline->fragmentShader->stage != SDL_GPU_SHADERSTAGE_FRAGMENT) {
  5382. SDL_assert_release(!"CreateGraphicsPipeline was passed a vertex shader for the fragment stage");
  5383. }
  5384. }
  5385. // Vertex input
  5386. for (i = 0; i < createinfo->vertex_input_state.num_vertex_buffers; i += 1) {
  5387. vertexInputBindingDescriptions[i].binding = createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot;
  5388. vertexInputBindingDescriptions[i].inputRate = SDLToVK_VertexInputRate[createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate];
  5389. vertexInputBindingDescriptions[i].stride = createinfo->vertex_input_state.vertex_buffer_descriptions[i].pitch;
  5390. }
  5391. for (i = 0; i < createinfo->vertex_input_state.num_vertex_attributes; i += 1) {
  5392. vertexInputAttributeDescriptions[i].binding = createinfo->vertex_input_state.vertex_attributes[i].buffer_slot;
  5393. vertexInputAttributeDescriptions[i].format = SDLToVK_VertexFormat[createinfo->vertex_input_state.vertex_attributes[i].format];
  5394. vertexInputAttributeDescriptions[i].location = createinfo->vertex_input_state.vertex_attributes[i].location;
  5395. vertexInputAttributeDescriptions[i].offset = createinfo->vertex_input_state.vertex_attributes[i].offset;
  5396. }
  5397. vertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  5398. vertexInputStateCreateInfo.pNext = NULL;
  5399. vertexInputStateCreateInfo.flags = 0;
  5400. vertexInputStateCreateInfo.vertexBindingDescriptionCount = createinfo->vertex_input_state.num_vertex_buffers;
  5401. vertexInputStateCreateInfo.pVertexBindingDescriptions = vertexInputBindingDescriptions;
  5402. vertexInputStateCreateInfo.vertexAttributeDescriptionCount = createinfo->vertex_input_state.num_vertex_attributes;
  5403. vertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions;
  5404. // Topology
  5405. inputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  5406. inputAssemblyStateCreateInfo.pNext = NULL;
  5407. inputAssemblyStateCreateInfo.flags = 0;
  5408. inputAssemblyStateCreateInfo.primitiveRestartEnable = VK_FALSE;
  5409. inputAssemblyStateCreateInfo.topology = SDLToVK_PrimitiveType[createinfo->primitive_type];
  5410. graphicsPipeline->primitiveType = createinfo->primitive_type;
  5411. // Viewport
  5412. // NOTE: viewport and scissor are dynamic, and must be set using the command buffer
  5413. viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  5414. viewportStateCreateInfo.pNext = NULL;
  5415. viewportStateCreateInfo.flags = 0;
  5416. viewportStateCreateInfo.viewportCount = 1;
  5417. viewportStateCreateInfo.pViewports = NULL;
  5418. viewportStateCreateInfo.scissorCount = 1;
  5419. viewportStateCreateInfo.pScissors = NULL;
  5420. // Rasterization
  5421. rasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  5422. rasterizationStateCreateInfo.pNext = NULL;
  5423. rasterizationStateCreateInfo.flags = 0;
  5424. rasterizationStateCreateInfo.depthClampEnable = !createinfo->rasterizer_state.enable_depth_clip;
  5425. rasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE;
  5426. rasterizationStateCreateInfo.polygonMode = SDLToVK_PolygonMode(
  5427. renderer,
  5428. createinfo->rasterizer_state.fill_mode);
  5429. rasterizationStateCreateInfo.cullMode = SDLToVK_CullMode[createinfo->rasterizer_state.cull_mode];
  5430. rasterizationStateCreateInfo.frontFace = SDLToVK_FrontFace[createinfo->rasterizer_state.front_face];
  5431. rasterizationStateCreateInfo.depthBiasEnable =
  5432. createinfo->rasterizer_state.enable_depth_bias;
  5433. rasterizationStateCreateInfo.depthBiasConstantFactor =
  5434. createinfo->rasterizer_state.depth_bias_constant_factor;
  5435. rasterizationStateCreateInfo.depthBiasClamp =
  5436. createinfo->rasterizer_state.depth_bias_clamp;
  5437. rasterizationStateCreateInfo.depthBiasSlopeFactor =
  5438. createinfo->rasterizer_state.depth_bias_slope_factor;
  5439. rasterizationStateCreateInfo.lineWidth = 1.0f;
  5440. // Multisample
  5441. Uint32 sampleMask = 0xFFFFFFFF;
  5442. multisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  5443. multisampleStateCreateInfo.pNext = NULL;
  5444. multisampleStateCreateInfo.flags = 0;
  5445. multisampleStateCreateInfo.rasterizationSamples = SDLToVK_SampleCount[createinfo->multisample_state.sample_count];
  5446. multisampleStateCreateInfo.sampleShadingEnable = VK_FALSE;
  5447. multisampleStateCreateInfo.minSampleShading = 1.0f;
  5448. multisampleStateCreateInfo.pSampleMask = &sampleMask;
  5449. multisampleStateCreateInfo.alphaToCoverageEnable = VK_FALSE;
  5450. multisampleStateCreateInfo.alphaToOneEnable = VK_FALSE;
  5451. // Depth Stencil State
  5452. frontStencilState.failOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.front_stencil_state.fail_op];
  5453. frontStencilState.passOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.front_stencil_state.pass_op];
  5454. frontStencilState.depthFailOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.front_stencil_state.depth_fail_op];
  5455. frontStencilState.compareOp = SDLToVK_CompareOp[createinfo->depth_stencil_state.front_stencil_state.compare_op];
  5456. frontStencilState.compareMask =
  5457. createinfo->depth_stencil_state.compare_mask;
  5458. frontStencilState.writeMask =
  5459. createinfo->depth_stencil_state.write_mask;
  5460. frontStencilState.reference = 0;
  5461. backStencilState.failOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.back_stencil_state.fail_op];
  5462. backStencilState.passOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.back_stencil_state.pass_op];
  5463. backStencilState.depthFailOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.back_stencil_state.depth_fail_op];
  5464. backStencilState.compareOp = SDLToVK_CompareOp[createinfo->depth_stencil_state.back_stencil_state.compare_op];
  5465. backStencilState.compareMask =
  5466. createinfo->depth_stencil_state.compare_mask;
  5467. backStencilState.writeMask =
  5468. createinfo->depth_stencil_state.write_mask;
  5469. backStencilState.reference = 0;
  5470. depthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
  5471. depthStencilStateCreateInfo.pNext = NULL;
  5472. depthStencilStateCreateInfo.flags = 0;
  5473. depthStencilStateCreateInfo.depthTestEnable =
  5474. createinfo->depth_stencil_state.enable_depth_test;
  5475. depthStencilStateCreateInfo.depthWriteEnable =
  5476. createinfo->depth_stencil_state.enable_depth_write;
  5477. depthStencilStateCreateInfo.depthCompareOp = SDLToVK_CompareOp[createinfo->depth_stencil_state.compare_op];
  5478. depthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE;
  5479. depthStencilStateCreateInfo.stencilTestEnable =
  5480. createinfo->depth_stencil_state.enable_stencil_test;
  5481. depthStencilStateCreateInfo.front = frontStencilState;
  5482. depthStencilStateCreateInfo.back = backStencilState;
  5483. depthStencilStateCreateInfo.minDepthBounds = 0; // unused
  5484. depthStencilStateCreateInfo.maxDepthBounds = 0; // unused
  5485. // Color Blend
  5486. for (i = 0; i < createinfo->target_info.num_color_targets; i += 1) {
  5487. SDL_GPUColorTargetBlendState blendState = createinfo->target_info.color_target_descriptions[i].blend_state;
  5488. SDL_GPUColorComponentFlags colorWriteMask = blendState.enable_color_write_mask ?
  5489. blendState.color_write_mask :
  5490. 0xF;
  5491. colorBlendAttachmentStates[i].blendEnable =
  5492. blendState.enable_blend;
  5493. colorBlendAttachmentStates[i].srcColorBlendFactor = SDLToVK_BlendFactor[blendState.src_color_blendfactor];
  5494. colorBlendAttachmentStates[i].dstColorBlendFactor = SDLToVK_BlendFactor[blendState.dst_color_blendfactor];
  5495. colorBlendAttachmentStates[i].colorBlendOp = SDLToVK_BlendOp[blendState.color_blend_op];
  5496. colorBlendAttachmentStates[i].srcAlphaBlendFactor = SDLToVK_BlendFactor[blendState.src_alpha_blendfactor];
  5497. colorBlendAttachmentStates[i].dstAlphaBlendFactor = SDLToVK_BlendFactor[blendState.dst_alpha_blendfactor];
  5498. colorBlendAttachmentStates[i].alphaBlendOp = SDLToVK_BlendOp[blendState.alpha_blend_op];
  5499. colorBlendAttachmentStates[i].colorWriteMask =
  5500. colorWriteMask;
  5501. }
  5502. colorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  5503. colorBlendStateCreateInfo.pNext = NULL;
  5504. colorBlendStateCreateInfo.flags = 0;
  5505. colorBlendStateCreateInfo.attachmentCount =
  5506. createinfo->target_info.num_color_targets;
  5507. colorBlendStateCreateInfo.pAttachments =
  5508. colorBlendAttachmentStates;
  5509. colorBlendStateCreateInfo.blendConstants[0] = 1.0f;
  5510. colorBlendStateCreateInfo.blendConstants[1] = 1.0f;
  5511. colorBlendStateCreateInfo.blendConstants[2] = 1.0f;
  5512. colorBlendStateCreateInfo.blendConstants[3] = 1.0f;
  5513. // We don't support LogicOp, so this is easy.
  5514. colorBlendStateCreateInfo.logicOpEnable = VK_FALSE;
  5515. colorBlendStateCreateInfo.logicOp = 0;
  5516. // Pipeline Layout
  5517. graphicsPipeline->resourceLayout =
  5518. VULKAN_INTERNAL_FetchGraphicsPipelineResourceLayout(
  5519. renderer,
  5520. graphicsPipeline->vertexShader,
  5521. graphicsPipeline->fragmentShader);
  5522. if (graphicsPipeline->resourceLayout == NULL) {
  5523. SDL_stack_free(vertexInputBindingDescriptions);
  5524. SDL_stack_free(vertexInputAttributeDescriptions);
  5525. SDL_stack_free(colorBlendAttachmentStates);
  5526. SDL_free(graphicsPipeline);
  5527. SET_STRING_ERROR_AND_RETURN("Failed to initialize pipeline resource layout!", NULL);
  5528. }
  5529. // Pipeline
  5530. vkPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  5531. vkPipelineCreateInfo.pNext = NULL;
  5532. vkPipelineCreateInfo.flags = 0;
  5533. vkPipelineCreateInfo.stageCount = 2;
  5534. vkPipelineCreateInfo.pStages = shaderStageCreateInfos;
  5535. vkPipelineCreateInfo.pVertexInputState = &vertexInputStateCreateInfo;
  5536. vkPipelineCreateInfo.pInputAssemblyState = &inputAssemblyStateCreateInfo;
  5537. vkPipelineCreateInfo.pTessellationState = VK_NULL_HANDLE;
  5538. vkPipelineCreateInfo.pViewportState = &viewportStateCreateInfo;
  5539. vkPipelineCreateInfo.pRasterizationState = &rasterizationStateCreateInfo;
  5540. vkPipelineCreateInfo.pMultisampleState = &multisampleStateCreateInfo;
  5541. vkPipelineCreateInfo.pDepthStencilState = &depthStencilStateCreateInfo;
  5542. vkPipelineCreateInfo.pColorBlendState = &colorBlendStateCreateInfo;
  5543. vkPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
  5544. vkPipelineCreateInfo.layout = graphicsPipeline->resourceLayout->pipelineLayout;
  5545. vkPipelineCreateInfo.renderPass = transientRenderPass;
  5546. vkPipelineCreateInfo.subpass = 0;
  5547. vkPipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
  5548. vkPipelineCreateInfo.basePipelineIndex = 0;
  5549. // TODO: enable pipeline caching
  5550. vulkanResult = renderer->vkCreateGraphicsPipelines(
  5551. renderer->logicalDevice,
  5552. VK_NULL_HANDLE,
  5553. 1,
  5554. &vkPipelineCreateInfo,
  5555. NULL,
  5556. &graphicsPipeline->pipeline);
  5557. SDL_stack_free(vertexInputBindingDescriptions);
  5558. SDL_stack_free(vertexInputAttributeDescriptions);
  5559. SDL_stack_free(colorBlendAttachmentStates);
  5560. renderer->vkDestroyRenderPass(
  5561. renderer->logicalDevice,
  5562. transientRenderPass,
  5563. NULL);
  5564. if (vulkanResult != VK_SUCCESS) {
  5565. SDL_free(graphicsPipeline);
  5566. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateGraphicsPipelines, NULL);
  5567. }
  5568. SDL_SetAtomicInt(&graphicsPipeline->referenceCount, 0);
  5569. if (renderer->debugMode && renderer->supportsDebugUtils && SDL_HasProperty(createinfo->props, SDL_PROP_GPU_GRAPHICSPIPELINE_CREATE_NAME_STRING)) {
  5570. VkDebugUtilsObjectNameInfoEXT nameInfo;
  5571. nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  5572. nameInfo.pNext = NULL;
  5573. nameInfo.pObjectName = SDL_GetStringProperty(createinfo->props, SDL_PROP_GPU_GRAPHICSPIPELINE_CREATE_NAME_STRING, NULL);
  5574. nameInfo.objectType = VK_OBJECT_TYPE_PIPELINE;
  5575. nameInfo.objectHandle = (uint64_t)graphicsPipeline->pipeline;
  5576. renderer->vkSetDebugUtilsObjectNameEXT(
  5577. renderer->logicalDevice,
  5578. &nameInfo);
  5579. }
  5580. // Put this data in the pipeline we can do validation in gpu.c
  5581. graphicsPipeline->header.num_vertex_samplers = graphicsPipeline->resourceLayout->vertexSamplerCount;
  5582. graphicsPipeline->header.num_vertex_storage_buffers = graphicsPipeline->resourceLayout->vertexStorageBufferCount;
  5583. graphicsPipeline->header.num_vertex_storage_textures = graphicsPipeline->resourceLayout->vertexStorageTextureCount;
  5584. graphicsPipeline->header.num_vertex_uniform_buffers = graphicsPipeline->resourceLayout->vertexUniformBufferCount;
  5585. graphicsPipeline->header.num_fragment_samplers = graphicsPipeline->resourceLayout->fragmentSamplerCount;
  5586. graphicsPipeline->header.num_fragment_storage_buffers = graphicsPipeline->resourceLayout->fragmentStorageBufferCount;
  5587. graphicsPipeline->header.num_fragment_storage_textures = graphicsPipeline->resourceLayout->fragmentStorageTextureCount;
  5588. graphicsPipeline->header.num_fragment_uniform_buffers = graphicsPipeline->resourceLayout->fragmentUniformBufferCount;
  5589. return (SDL_GPUGraphicsPipeline *)graphicsPipeline;
  5590. }
  5591. static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
  5592. SDL_GPURenderer *driverData,
  5593. const SDL_GPUComputePipelineCreateInfo *createinfo)
  5594. {
  5595. VkShaderModuleCreateInfo shaderModuleCreateInfo;
  5596. VkComputePipelineCreateInfo vkShaderCreateInfo;
  5597. VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo;
  5598. VkResult vulkanResult;
  5599. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5600. VulkanComputePipeline *vulkanComputePipeline;
  5601. if (createinfo->format != SDL_GPU_SHADERFORMAT_SPIRV) {
  5602. SET_STRING_ERROR_AND_RETURN("Incompatible shader format for Vulkan!", NULL);
  5603. }
  5604. vulkanComputePipeline = SDL_malloc(sizeof(VulkanComputePipeline));
  5605. shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  5606. shaderModuleCreateInfo.pNext = NULL;
  5607. shaderModuleCreateInfo.flags = 0;
  5608. shaderModuleCreateInfo.codeSize = createinfo->code_size;
  5609. shaderModuleCreateInfo.pCode = (Uint32 *)createinfo->code;
  5610. vulkanResult = renderer->vkCreateShaderModule(
  5611. renderer->logicalDevice,
  5612. &shaderModuleCreateInfo,
  5613. NULL,
  5614. &vulkanComputePipeline->shaderModule);
  5615. if (vulkanResult != VK_SUCCESS) {
  5616. SDL_free(vulkanComputePipeline);
  5617. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateShaderModule, NULL);
  5618. }
  5619. pipelineShaderStageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  5620. pipelineShaderStageCreateInfo.pNext = NULL;
  5621. pipelineShaderStageCreateInfo.flags = 0;
  5622. pipelineShaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
  5623. pipelineShaderStageCreateInfo.module = vulkanComputePipeline->shaderModule;
  5624. pipelineShaderStageCreateInfo.pName = createinfo->entrypoint;
  5625. pipelineShaderStageCreateInfo.pSpecializationInfo = NULL;
  5626. vulkanComputePipeline->resourceLayout = VULKAN_INTERNAL_FetchComputePipelineResourceLayout(
  5627. renderer,
  5628. createinfo);
  5629. if (vulkanComputePipeline->resourceLayout == NULL) {
  5630. renderer->vkDestroyShaderModule(
  5631. renderer->logicalDevice,
  5632. vulkanComputePipeline->shaderModule,
  5633. NULL);
  5634. SDL_free(vulkanComputePipeline);
  5635. return NULL;
  5636. }
  5637. vkShaderCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
  5638. vkShaderCreateInfo.pNext = NULL;
  5639. vkShaderCreateInfo.flags = 0;
  5640. vkShaderCreateInfo.stage = pipelineShaderStageCreateInfo;
  5641. vkShaderCreateInfo.layout = vulkanComputePipeline->resourceLayout->pipelineLayout;
  5642. vkShaderCreateInfo.basePipelineHandle = (VkPipeline)VK_NULL_HANDLE;
  5643. vkShaderCreateInfo.basePipelineIndex = 0;
  5644. vulkanResult = renderer->vkCreateComputePipelines(
  5645. renderer->logicalDevice,
  5646. (VkPipelineCache)VK_NULL_HANDLE,
  5647. 1,
  5648. &vkShaderCreateInfo,
  5649. NULL,
  5650. &vulkanComputePipeline->pipeline);
  5651. if (vulkanResult != VK_SUCCESS) {
  5652. VULKAN_INTERNAL_DestroyComputePipeline(renderer, vulkanComputePipeline);
  5653. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateComputePipeline, NULL);
  5654. return NULL;
  5655. }
  5656. SDL_SetAtomicInt(&vulkanComputePipeline->referenceCount, 0);
  5657. if (renderer->debugMode && renderer->supportsDebugUtils && SDL_HasProperty(createinfo->props, SDL_PROP_GPU_COMPUTEPIPELINE_CREATE_NAME_STRING)) {
  5658. VkDebugUtilsObjectNameInfoEXT nameInfo;
  5659. nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  5660. nameInfo.pNext = NULL;
  5661. nameInfo.pObjectName = SDL_GetStringProperty(createinfo->props, SDL_PROP_GPU_COMPUTEPIPELINE_CREATE_NAME_STRING, NULL);
  5662. nameInfo.objectType = VK_OBJECT_TYPE_PIPELINE;
  5663. nameInfo.objectHandle = (uint64_t)vulkanComputePipeline->pipeline;
  5664. renderer->vkSetDebugUtilsObjectNameEXT(
  5665. renderer->logicalDevice,
  5666. &nameInfo);
  5667. }
  5668. // Track these here for debug layer
  5669. vulkanComputePipeline->header.numSamplers = vulkanComputePipeline->resourceLayout->numSamplers;
  5670. vulkanComputePipeline->header.numReadonlyStorageTextures = vulkanComputePipeline->resourceLayout->numReadonlyStorageTextures;
  5671. vulkanComputePipeline->header.numReadonlyStorageBuffers = vulkanComputePipeline->resourceLayout->numReadonlyStorageBuffers;
  5672. vulkanComputePipeline->header.numReadWriteStorageTextures = vulkanComputePipeline->resourceLayout->numReadWriteStorageTextures;
  5673. vulkanComputePipeline->header.numReadWriteStorageBuffers = vulkanComputePipeline->resourceLayout->numReadWriteStorageBuffers;
  5674. vulkanComputePipeline->header.numUniformBuffers = vulkanComputePipeline->resourceLayout->numUniformBuffers;
  5675. return (SDL_GPUComputePipeline *)vulkanComputePipeline;
  5676. }
  5677. static SDL_GPUSampler *VULKAN_CreateSampler(
  5678. SDL_GPURenderer *driverData,
  5679. const SDL_GPUSamplerCreateInfo *createinfo)
  5680. {
  5681. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5682. VulkanSampler *vulkanSampler = SDL_malloc(sizeof(VulkanSampler));
  5683. VkResult vulkanResult;
  5684. VkSamplerCreateInfo vkSamplerCreateInfo;
  5685. vkSamplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
  5686. vkSamplerCreateInfo.pNext = NULL;
  5687. vkSamplerCreateInfo.flags = 0;
  5688. vkSamplerCreateInfo.magFilter = SDLToVK_Filter[createinfo->mag_filter];
  5689. vkSamplerCreateInfo.minFilter = SDLToVK_Filter[createinfo->min_filter];
  5690. vkSamplerCreateInfo.mipmapMode = SDLToVK_SamplerMipmapMode[createinfo->mipmap_mode];
  5691. vkSamplerCreateInfo.addressModeU = SDLToVK_SamplerAddressMode[createinfo->address_mode_u];
  5692. vkSamplerCreateInfo.addressModeV = SDLToVK_SamplerAddressMode[createinfo->address_mode_v];
  5693. vkSamplerCreateInfo.addressModeW = SDLToVK_SamplerAddressMode[createinfo->address_mode_w];
  5694. vkSamplerCreateInfo.mipLodBias = createinfo->mip_lod_bias;
  5695. vkSamplerCreateInfo.anisotropyEnable = createinfo->enable_anisotropy;
  5696. vkSamplerCreateInfo.maxAnisotropy = createinfo->max_anisotropy;
  5697. vkSamplerCreateInfo.compareEnable = createinfo->enable_compare;
  5698. vkSamplerCreateInfo.compareOp = SDLToVK_CompareOp[createinfo->compare_op];
  5699. vkSamplerCreateInfo.minLod = createinfo->min_lod;
  5700. vkSamplerCreateInfo.maxLod = createinfo->max_lod;
  5701. vkSamplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; // arbitrary, unused
  5702. vkSamplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
  5703. vulkanResult = renderer->vkCreateSampler(
  5704. renderer->logicalDevice,
  5705. &vkSamplerCreateInfo,
  5706. NULL,
  5707. &vulkanSampler->sampler);
  5708. if (vulkanResult != VK_SUCCESS) {
  5709. SDL_free(vulkanSampler);
  5710. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSampler, NULL);
  5711. }
  5712. SDL_SetAtomicInt(&vulkanSampler->referenceCount, 0);
  5713. if (renderer->debugMode && renderer->supportsDebugUtils && SDL_HasProperty(createinfo->props, SDL_PROP_GPU_SAMPLER_CREATE_NAME_STRING)) {
  5714. VkDebugUtilsObjectNameInfoEXT nameInfo;
  5715. nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  5716. nameInfo.pNext = NULL;
  5717. nameInfo.pObjectName = SDL_GetStringProperty(createinfo->props, SDL_PROP_GPU_SAMPLER_CREATE_NAME_STRING, NULL);
  5718. nameInfo.objectType = VK_OBJECT_TYPE_SAMPLER;
  5719. nameInfo.objectHandle = (uint64_t)vulkanSampler->sampler;
  5720. renderer->vkSetDebugUtilsObjectNameEXT(
  5721. renderer->logicalDevice,
  5722. &nameInfo);
  5723. }
  5724. return (SDL_GPUSampler *)vulkanSampler;
  5725. }
  5726. static SDL_GPUShader *VULKAN_CreateShader(
  5727. SDL_GPURenderer *driverData,
  5728. const SDL_GPUShaderCreateInfo *createinfo)
  5729. {
  5730. VulkanShader *vulkanShader;
  5731. VkResult vulkanResult;
  5732. VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
  5733. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5734. vulkanShader = SDL_malloc(sizeof(VulkanShader));
  5735. vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  5736. vkShaderModuleCreateInfo.pNext = NULL;
  5737. vkShaderModuleCreateInfo.flags = 0;
  5738. vkShaderModuleCreateInfo.codeSize = createinfo->code_size;
  5739. vkShaderModuleCreateInfo.pCode = (Uint32 *)createinfo->code;
  5740. vulkanResult = renderer->vkCreateShaderModule(
  5741. renderer->logicalDevice,
  5742. &vkShaderModuleCreateInfo,
  5743. NULL,
  5744. &vulkanShader->shaderModule);
  5745. if (vulkanResult != VK_SUCCESS) {
  5746. SDL_free(vulkanShader);
  5747. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateShaderModule, NULL);
  5748. }
  5749. const char *entrypoint = createinfo->entrypoint;
  5750. if (!entrypoint) {
  5751. entrypoint = "main";
  5752. }
  5753. vulkanShader->entrypointName = SDL_strdup(entrypoint);
  5754. vulkanShader->stage = createinfo->stage;
  5755. vulkanShader->numSamplers = createinfo->num_samplers;
  5756. vulkanShader->numStorageTextures = createinfo->num_storage_textures;
  5757. vulkanShader->numStorageBuffers = createinfo->num_storage_buffers;
  5758. vulkanShader->numUniformBuffers = createinfo->num_uniform_buffers;
  5759. SDL_SetAtomicInt(&vulkanShader->referenceCount, 0);
  5760. if (renderer->debugMode && SDL_HasProperty(createinfo->props, SDL_PROP_GPU_SHADER_CREATE_NAME_STRING)) {
  5761. VkDebugUtilsObjectNameInfoEXT nameInfo;
  5762. nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  5763. nameInfo.pNext = NULL;
  5764. nameInfo.pObjectName = SDL_GetStringProperty(createinfo->props, SDL_PROP_GPU_SHADER_CREATE_NAME_STRING, NULL);
  5765. nameInfo.objectType = VK_OBJECT_TYPE_SHADER_MODULE;
  5766. nameInfo.objectHandle = (uint64_t)vulkanShader->shaderModule;
  5767. renderer->vkSetDebugUtilsObjectNameEXT(
  5768. renderer->logicalDevice,
  5769. &nameInfo);
  5770. }
  5771. return (SDL_GPUShader *)vulkanShader;
  5772. }
  5773. static bool VULKAN_SupportsSampleCount(
  5774. SDL_GPURenderer *driverData,
  5775. SDL_GPUTextureFormat format,
  5776. SDL_GPUSampleCount sampleCount)
  5777. {
  5778. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5779. VkSampleCountFlags bits = IsDepthFormat(format) ? renderer->physicalDeviceProperties.properties.limits.framebufferDepthSampleCounts : renderer->physicalDeviceProperties.properties.limits.framebufferColorSampleCounts;
  5780. VkSampleCountFlagBits vkSampleCount = SDLToVK_SampleCount[sampleCount];
  5781. return !!(bits & vkSampleCount);
  5782. }
  5783. static SDL_GPUTexture *VULKAN_CreateTexture(
  5784. SDL_GPURenderer *driverData,
  5785. const SDL_GPUTextureCreateInfo *createinfo)
  5786. {
  5787. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5788. VulkanTexture *texture;
  5789. VulkanTextureContainer *container;
  5790. texture = VULKAN_INTERNAL_CreateTexture(
  5791. renderer,
  5792. true,
  5793. createinfo);
  5794. if (texture == NULL) {
  5795. return NULL;
  5796. }
  5797. container = SDL_malloc(sizeof(VulkanTextureContainer));
  5798. // Copy properties so we don't lose information when the client destroys them
  5799. container->header.info = *createinfo;
  5800. container->header.info.props = SDL_CreateProperties();
  5801. if (createinfo->props) {
  5802. SDL_CopyProperties(createinfo->props, container->header.info.props);
  5803. }
  5804. container->canBeCycled = true;
  5805. container->activeTexture = texture;
  5806. container->textureCapacity = 1;
  5807. container->textureCount = 1;
  5808. container->textures = SDL_malloc(
  5809. container->textureCapacity * sizeof(VulkanTexture *));
  5810. container->textures[0] = container->activeTexture;
  5811. container->debugName = NULL;
  5812. if (SDL_HasProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING)) {
  5813. container->debugName = SDL_strdup(SDL_GetStringProperty(createinfo->props, SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING, NULL));
  5814. }
  5815. texture->container = container;
  5816. texture->containerIndex = 0;
  5817. return (SDL_GPUTexture *)container;
  5818. }
  5819. static SDL_GPUBuffer *VULKAN_CreateBuffer(
  5820. SDL_GPURenderer *driverData,
  5821. SDL_GPUBufferUsageFlags usageFlags,
  5822. Uint32 size,
  5823. const char *debugName)
  5824. {
  5825. return (SDL_GPUBuffer *)VULKAN_INTERNAL_CreateBufferContainer(
  5826. (VulkanRenderer *)driverData,
  5827. (VkDeviceSize)size,
  5828. usageFlags,
  5829. VULKAN_BUFFER_TYPE_GPU,
  5830. false,
  5831. debugName);
  5832. }
  5833. static VulkanUniformBuffer *VULKAN_INTERNAL_CreateUniformBuffer(
  5834. VulkanRenderer *renderer,
  5835. Uint32 size)
  5836. {
  5837. VulkanUniformBuffer *uniformBuffer = SDL_calloc(1, sizeof(VulkanUniformBuffer));
  5838. uniformBuffer->buffer = VULKAN_INTERNAL_CreateBuffer(
  5839. renderer,
  5840. (VkDeviceSize)size,
  5841. 0,
  5842. VULKAN_BUFFER_TYPE_UNIFORM,
  5843. false,
  5844. NULL);
  5845. uniformBuffer->drawOffset = 0;
  5846. uniformBuffer->writeOffset = 0;
  5847. uniformBuffer->buffer->uniformBufferForDefrag = uniformBuffer;
  5848. return uniformBuffer;
  5849. }
  5850. static SDL_GPUTransferBuffer *VULKAN_CreateTransferBuffer(
  5851. SDL_GPURenderer *driverData,
  5852. SDL_GPUTransferBufferUsage usage,
  5853. Uint32 size,
  5854. const char *debugName)
  5855. {
  5856. return (SDL_GPUTransferBuffer *)VULKAN_INTERNAL_CreateBufferContainer(
  5857. (VulkanRenderer *)driverData,
  5858. (VkDeviceSize)size,
  5859. 0,
  5860. VULKAN_BUFFER_TYPE_TRANSFER,
  5861. true, // Dedicated allocations preserve the data even if a defrag is triggered.
  5862. debugName);
  5863. }
  5864. static void VULKAN_INTERNAL_ReleaseTexture(
  5865. VulkanRenderer *renderer,
  5866. VulkanTexture *vulkanTexture)
  5867. {
  5868. if (vulkanTexture->markedForDestroy) {
  5869. return;
  5870. }
  5871. SDL_LockMutex(renderer->disposeLock);
  5872. EXPAND_ARRAY_IF_NEEDED(
  5873. renderer->texturesToDestroy,
  5874. VulkanTexture *,
  5875. renderer->texturesToDestroyCount + 1,
  5876. renderer->texturesToDestroyCapacity,
  5877. renderer->texturesToDestroyCapacity * 2);
  5878. renderer->texturesToDestroy[renderer->texturesToDestroyCount] = vulkanTexture;
  5879. renderer->texturesToDestroyCount += 1;
  5880. vulkanTexture->markedForDestroy = true;
  5881. SDL_UnlockMutex(renderer->disposeLock);
  5882. }
  5883. static void VULKAN_ReleaseTexture(
  5884. SDL_GPURenderer *driverData,
  5885. SDL_GPUTexture *texture)
  5886. {
  5887. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5888. VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer *)texture;
  5889. Uint32 i;
  5890. SDL_LockMutex(renderer->disposeLock);
  5891. for (i = 0; i < vulkanTextureContainer->textureCount; i += 1) {
  5892. VULKAN_INTERNAL_ReleaseTexture(renderer, vulkanTextureContainer->textures[i]);
  5893. }
  5894. SDL_DestroyProperties(vulkanTextureContainer->header.info.props);
  5895. // Containers are just client handles, so we can destroy immediately
  5896. if (vulkanTextureContainer->debugName != NULL) {
  5897. SDL_free(vulkanTextureContainer->debugName);
  5898. }
  5899. SDL_free(vulkanTextureContainer->textures);
  5900. SDL_free(vulkanTextureContainer);
  5901. SDL_UnlockMutex(renderer->disposeLock);
  5902. }
  5903. static void VULKAN_ReleaseSampler(
  5904. SDL_GPURenderer *driverData,
  5905. SDL_GPUSampler *sampler)
  5906. {
  5907. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5908. VulkanSampler *vulkanSampler = (VulkanSampler *)sampler;
  5909. SDL_LockMutex(renderer->disposeLock);
  5910. EXPAND_ARRAY_IF_NEEDED(
  5911. renderer->samplersToDestroy,
  5912. VulkanSampler *,
  5913. renderer->samplersToDestroyCount + 1,
  5914. renderer->samplersToDestroyCapacity,
  5915. renderer->samplersToDestroyCapacity * 2);
  5916. renderer->samplersToDestroy[renderer->samplersToDestroyCount] = vulkanSampler;
  5917. renderer->samplersToDestroyCount += 1;
  5918. SDL_UnlockMutex(renderer->disposeLock);
  5919. }
  5920. static void VULKAN_INTERNAL_ReleaseBuffer(
  5921. VulkanRenderer *renderer,
  5922. VulkanBuffer *vulkanBuffer)
  5923. {
  5924. if (vulkanBuffer->markedForDestroy) {
  5925. return;
  5926. }
  5927. SDL_LockMutex(renderer->disposeLock);
  5928. EXPAND_ARRAY_IF_NEEDED(
  5929. renderer->buffersToDestroy,
  5930. VulkanBuffer *,
  5931. renderer->buffersToDestroyCount + 1,
  5932. renderer->buffersToDestroyCapacity,
  5933. renderer->buffersToDestroyCapacity * 2);
  5934. renderer->buffersToDestroy[renderer->buffersToDestroyCount] = vulkanBuffer;
  5935. renderer->buffersToDestroyCount += 1;
  5936. vulkanBuffer->markedForDestroy = true;
  5937. vulkanBuffer->container = NULL;
  5938. SDL_UnlockMutex(renderer->disposeLock);
  5939. }
  5940. static void VULKAN_INTERNAL_ReleaseBufferContainer(
  5941. VulkanRenderer *renderer,
  5942. VulkanBufferContainer *bufferContainer)
  5943. {
  5944. Uint32 i;
  5945. SDL_LockMutex(renderer->disposeLock);
  5946. for (i = 0; i < bufferContainer->bufferCount; i += 1) {
  5947. VULKAN_INTERNAL_ReleaseBuffer(renderer, bufferContainer->buffers[i]);
  5948. }
  5949. // Containers are just client handles, so we can free immediately
  5950. if (bufferContainer->debugName != NULL) {
  5951. SDL_free(bufferContainer->debugName);
  5952. bufferContainer->debugName = NULL;
  5953. }
  5954. SDL_free(bufferContainer->buffers);
  5955. SDL_free(bufferContainer);
  5956. SDL_UnlockMutex(renderer->disposeLock);
  5957. }
  5958. static void VULKAN_ReleaseBuffer(
  5959. SDL_GPURenderer *driverData,
  5960. SDL_GPUBuffer *buffer)
  5961. {
  5962. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5963. VulkanBufferContainer *vulkanBufferContainer = (VulkanBufferContainer *)buffer;
  5964. VULKAN_INTERNAL_ReleaseBufferContainer(
  5965. renderer,
  5966. vulkanBufferContainer);
  5967. }
  5968. static void VULKAN_ReleaseTransferBuffer(
  5969. SDL_GPURenderer *driverData,
  5970. SDL_GPUTransferBuffer *transferBuffer)
  5971. {
  5972. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5973. VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)transferBuffer;
  5974. VULKAN_INTERNAL_ReleaseBufferContainer(
  5975. renderer,
  5976. transferBufferContainer);
  5977. }
  5978. static void VULKAN_ReleaseShader(
  5979. SDL_GPURenderer *driverData,
  5980. SDL_GPUShader *shader)
  5981. {
  5982. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  5983. VulkanShader *vulkanShader = (VulkanShader *)shader;
  5984. SDL_LockMutex(renderer->disposeLock);
  5985. EXPAND_ARRAY_IF_NEEDED(
  5986. renderer->shadersToDestroy,
  5987. VulkanShader *,
  5988. renderer->shadersToDestroyCount + 1,
  5989. renderer->shadersToDestroyCapacity,
  5990. renderer->shadersToDestroyCapacity * 2);
  5991. renderer->shadersToDestroy[renderer->shadersToDestroyCount] = vulkanShader;
  5992. renderer->shadersToDestroyCount += 1;
  5993. SDL_UnlockMutex(renderer->disposeLock);
  5994. }
  5995. static void VULKAN_ReleaseComputePipeline(
  5996. SDL_GPURenderer *driverData,
  5997. SDL_GPUComputePipeline *computePipeline)
  5998. {
  5999. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  6000. VulkanComputePipeline *vulkanComputePipeline = (VulkanComputePipeline *)computePipeline;
  6001. SDL_LockMutex(renderer->disposeLock);
  6002. EXPAND_ARRAY_IF_NEEDED(
  6003. renderer->computePipelinesToDestroy,
  6004. VulkanComputePipeline *,
  6005. renderer->computePipelinesToDestroyCount + 1,
  6006. renderer->computePipelinesToDestroyCapacity,
  6007. renderer->computePipelinesToDestroyCapacity * 2);
  6008. renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount] = vulkanComputePipeline;
  6009. renderer->computePipelinesToDestroyCount += 1;
  6010. SDL_UnlockMutex(renderer->disposeLock);
  6011. }
  6012. static void VULKAN_ReleaseGraphicsPipeline(
  6013. SDL_GPURenderer *driverData,
  6014. SDL_GPUGraphicsPipeline *graphicsPipeline)
  6015. {
  6016. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  6017. VulkanGraphicsPipeline *vulkanGraphicsPipeline = (VulkanGraphicsPipeline *)graphicsPipeline;
  6018. SDL_LockMutex(renderer->disposeLock);
  6019. EXPAND_ARRAY_IF_NEEDED(
  6020. renderer->graphicsPipelinesToDestroy,
  6021. VulkanGraphicsPipeline *,
  6022. renderer->graphicsPipelinesToDestroyCount + 1,
  6023. renderer->graphicsPipelinesToDestroyCapacity,
  6024. renderer->graphicsPipelinesToDestroyCapacity * 2);
  6025. renderer->graphicsPipelinesToDestroy[renderer->graphicsPipelinesToDestroyCount] = vulkanGraphicsPipeline;
  6026. renderer->graphicsPipelinesToDestroyCount += 1;
  6027. SDL_UnlockMutex(renderer->disposeLock);
  6028. }
  6029. // Command Buffer render state
  6030. static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
  6031. VulkanRenderer *renderer,
  6032. VulkanCommandBuffer *commandBuffer,
  6033. const SDL_GPUColorTargetInfo *colorTargetInfos,
  6034. Uint32 numColorTargets,
  6035. const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo)
  6036. {
  6037. VulkanRenderPassHashTableValue *renderPassWrapper = NULL;
  6038. VkRenderPass renderPassHandle;
  6039. RenderPassHashTableKey key;
  6040. Uint32 i;
  6041. SDL_zero(key);
  6042. for (i = 0; i < numColorTargets; i += 1) {
  6043. key.colorTargetDescriptions[i].format = SDLToVK_TextureFormat[((VulkanTextureContainer *)colorTargetInfos[i].texture)->header.info.format];
  6044. key.colorTargetDescriptions[i].loadOp = colorTargetInfos[i].load_op;
  6045. key.colorTargetDescriptions[i].storeOp = colorTargetInfos[i].store_op;
  6046. if (colorTargetInfos[i].resolve_texture != NULL) {
  6047. key.resolveTargetFormats[key.numResolveTargets] = SDLToVK_TextureFormat[((VulkanTextureContainer *)colorTargetInfos[i].resolve_texture)->header.info.format];
  6048. key.numResolveTargets += 1;
  6049. }
  6050. }
  6051. key.sampleCount = VK_SAMPLE_COUNT_1_BIT;
  6052. if (numColorTargets > 0) {
  6053. key.sampleCount = SDLToVK_SampleCount[((VulkanTextureContainer *)colorTargetInfos[0].texture)->header.info.sample_count];
  6054. }
  6055. key.numColorTargets = numColorTargets;
  6056. if (depthStencilTargetInfo == NULL) {
  6057. key.depthStencilTargetDescription.format = 0;
  6058. key.depthStencilTargetDescription.loadOp = SDL_GPU_LOADOP_DONT_CARE;
  6059. key.depthStencilTargetDescription.storeOp = SDL_GPU_STOREOP_DONT_CARE;
  6060. key.depthStencilTargetDescription.stencilLoadOp = SDL_GPU_LOADOP_DONT_CARE;
  6061. key.depthStencilTargetDescription.stencilStoreOp = SDL_GPU_STOREOP_DONT_CARE;
  6062. } else {
  6063. key.depthStencilTargetDescription.format = SDLToVK_TextureFormat[((VulkanTextureContainer *)depthStencilTargetInfo->texture)->header.info.format];
  6064. key.depthStencilTargetDescription.loadOp = depthStencilTargetInfo->load_op;
  6065. key.depthStencilTargetDescription.storeOp = depthStencilTargetInfo->store_op;
  6066. key.depthStencilTargetDescription.stencilLoadOp = depthStencilTargetInfo->stencil_load_op;
  6067. key.depthStencilTargetDescription.stencilStoreOp = depthStencilTargetInfo->stencil_store_op;
  6068. }
  6069. SDL_LockMutex(renderer->renderPassFetchLock);
  6070. bool result = SDL_FindInHashTable(
  6071. renderer->renderPassHashTable,
  6072. (const void *)&key,
  6073. (const void **)&renderPassWrapper);
  6074. if (result) {
  6075. SDL_UnlockMutex(renderer->renderPassFetchLock);
  6076. return renderPassWrapper->handle;
  6077. }
  6078. renderPassHandle = VULKAN_INTERNAL_CreateRenderPass(
  6079. renderer,
  6080. commandBuffer,
  6081. colorTargetInfos,
  6082. numColorTargets,
  6083. depthStencilTargetInfo);
  6084. if (renderPassHandle == VK_NULL_HANDLE) {
  6085. SDL_UnlockMutex(renderer->renderPassFetchLock);
  6086. return VK_NULL_HANDLE;
  6087. }
  6088. // Have to malloc the key to store it in the hashtable
  6089. RenderPassHashTableKey *allocedKey = SDL_malloc(sizeof(RenderPassHashTableKey));
  6090. SDL_memcpy(allocedKey, &key, sizeof(RenderPassHashTableKey));
  6091. renderPassWrapper = SDL_malloc(sizeof(VulkanRenderPassHashTableValue));
  6092. renderPassWrapper->handle = renderPassHandle;
  6093. SDL_InsertIntoHashTable(
  6094. renderer->renderPassHashTable,
  6095. (const void *)allocedKey,
  6096. (const void *)renderPassWrapper, true);
  6097. SDL_UnlockMutex(renderer->renderPassFetchLock);
  6098. return renderPassHandle;
  6099. }
  6100. static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
  6101. VulkanRenderer *renderer,
  6102. VkRenderPass renderPass,
  6103. const SDL_GPUColorTargetInfo *colorTargetInfos,
  6104. Uint32 numColorTargets,
  6105. const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo,
  6106. Uint32 width,
  6107. Uint32 height)
  6108. {
  6109. VulkanFramebuffer *vulkanFramebuffer = NULL;
  6110. VkFramebufferCreateInfo framebufferInfo;
  6111. VkResult result;
  6112. VkImageView imageViewAttachments[2 * MAX_COLOR_TARGET_BINDINGS + 1 /* depth */];
  6113. FramebufferHashTableKey key;
  6114. Uint32 attachmentCount = 0;
  6115. Uint32 i;
  6116. SDL_zero(imageViewAttachments);
  6117. SDL_zero(key);
  6118. key.numColorTargets = numColorTargets;
  6119. for (i = 0; i < numColorTargets; i += 1) {
  6120. VulkanTextureContainer *container = (VulkanTextureContainer *)colorTargetInfos[i].texture;
  6121. VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
  6122. container,
  6123. container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorTargetInfos[i].layer_or_depth_plane,
  6124. colorTargetInfos[i].mip_level);
  6125. Uint32 rtvIndex =
  6126. container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0;
  6127. key.colorAttachmentViews[i] = subresource->renderTargetViews[rtvIndex];
  6128. if (colorTargetInfos[i].resolve_texture != NULL) {
  6129. VulkanTextureContainer *resolveTextureContainer = (VulkanTextureContainer *)colorTargetInfos[i].resolve_texture;
  6130. VulkanTextureSubresource *resolveSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
  6131. resolveTextureContainer,
  6132. colorTargetInfos[i].layer_or_depth_plane,
  6133. colorTargetInfos[i].mip_level);
  6134. key.resolveAttachmentViews[key.numResolveAttachments] = resolveSubresource->renderTargetViews[0];
  6135. key.numResolveAttachments += 1;
  6136. }
  6137. }
  6138. if (depthStencilTargetInfo == NULL) {
  6139. key.depthStencilAttachmentView = VK_NULL_HANDLE;
  6140. } else {
  6141. VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
  6142. (VulkanTextureContainer *)depthStencilTargetInfo->texture,
  6143. 0,
  6144. 0);
  6145. key.depthStencilAttachmentView = subresource->depthStencilView;
  6146. }
  6147. key.width = width;
  6148. key.height = height;
  6149. SDL_LockMutex(renderer->framebufferFetchLock);
  6150. bool findResult = SDL_FindInHashTable(
  6151. renderer->framebufferHashTable,
  6152. (const void *)&key,
  6153. (const void **)&vulkanFramebuffer);
  6154. if (findResult) {
  6155. SDL_UnlockMutex(renderer->framebufferFetchLock);
  6156. return vulkanFramebuffer;
  6157. }
  6158. vulkanFramebuffer = SDL_malloc(sizeof(VulkanFramebuffer));
  6159. SDL_SetAtomicInt(&vulkanFramebuffer->referenceCount, 0);
  6160. // Create a new framebuffer
  6161. for (i = 0; i < numColorTargets; i += 1) {
  6162. VulkanTextureContainer *container = (VulkanTextureContainer *)colorTargetInfos[i].texture;
  6163. VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
  6164. container,
  6165. container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorTargetInfos[i].layer_or_depth_plane,
  6166. colorTargetInfos[i].mip_level);
  6167. Uint32 rtvIndex =
  6168. container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0;
  6169. imageViewAttachments[attachmentCount] = subresource->renderTargetViews[rtvIndex];
  6170. attachmentCount += 1;
  6171. if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
  6172. VulkanTextureContainer *resolveContainer = (VulkanTextureContainer *)colorTargetInfos[i].resolve_texture;
  6173. VulkanTextureSubresource *resolveSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
  6174. resolveContainer,
  6175. colorTargetInfos[i].resolve_layer,
  6176. colorTargetInfos[i].resolve_mip_level);
  6177. imageViewAttachments[attachmentCount] = resolveSubresource->renderTargetViews[0];
  6178. attachmentCount += 1;
  6179. }
  6180. }
  6181. if (depthStencilTargetInfo != NULL) {
  6182. VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
  6183. (VulkanTextureContainer *)depthStencilTargetInfo->texture,
  6184. 0,
  6185. 0);
  6186. imageViewAttachments[attachmentCount] = subresource->depthStencilView;
  6187. attachmentCount += 1;
  6188. }
  6189. framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  6190. framebufferInfo.pNext = NULL;
  6191. framebufferInfo.flags = 0;
  6192. framebufferInfo.renderPass = renderPass;
  6193. framebufferInfo.attachmentCount = attachmentCount;
  6194. framebufferInfo.pAttachments = imageViewAttachments;
  6195. framebufferInfo.width = key.width;
  6196. framebufferInfo.height = key.height;
  6197. framebufferInfo.layers = 1;
  6198. result = renderer->vkCreateFramebuffer(
  6199. renderer->logicalDevice,
  6200. &framebufferInfo,
  6201. NULL,
  6202. &vulkanFramebuffer->framebuffer);
  6203. if (result == VK_SUCCESS) {
  6204. // Have to malloc the key to store it in the hashtable
  6205. FramebufferHashTableKey *allocedKey = SDL_malloc(sizeof(FramebufferHashTableKey));
  6206. SDL_memcpy(allocedKey, &key, sizeof(FramebufferHashTableKey));
  6207. SDL_InsertIntoHashTable(
  6208. renderer->framebufferHashTable,
  6209. (const void *)allocedKey,
  6210. (const void *)vulkanFramebuffer, true);
  6211. } else {
  6212. SDL_free(vulkanFramebuffer);
  6213. SDL_UnlockMutex(renderer->framebufferFetchLock);
  6214. CHECK_VULKAN_ERROR_AND_RETURN(result, vkCreateFramebuffer, NULL);
  6215. }
  6216. SDL_UnlockMutex(renderer->framebufferFetchLock);
  6217. return vulkanFramebuffer;
  6218. }
  6219. static void VULKAN_INTERNAL_SetCurrentViewport(
  6220. VulkanCommandBuffer *commandBuffer,
  6221. const SDL_GPUViewport *viewport)
  6222. {
  6223. VulkanCommandBuffer *vulkanCommandBuffer = commandBuffer;
  6224. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6225. vulkanCommandBuffer->currentViewport.x = viewport->x;
  6226. vulkanCommandBuffer->currentViewport.width = viewport->w;
  6227. vulkanCommandBuffer->currentViewport.minDepth = viewport->min_depth;
  6228. vulkanCommandBuffer->currentViewport.maxDepth = viewport->max_depth;
  6229. // Viewport flip for consistency with other backends
  6230. vulkanCommandBuffer->currentViewport.y = viewport->y + viewport->h;
  6231. vulkanCommandBuffer->currentViewport.height = -viewport->h;
  6232. renderer->vkCmdSetViewport(
  6233. vulkanCommandBuffer->commandBuffer,
  6234. 0,
  6235. 1,
  6236. &vulkanCommandBuffer->currentViewport);
  6237. }
  6238. static void VULKAN_SetViewport(
  6239. SDL_GPUCommandBuffer *commandBuffer,
  6240. const SDL_GPUViewport *viewport)
  6241. {
  6242. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6243. VULKAN_INTERNAL_SetCurrentViewport(
  6244. vulkanCommandBuffer,
  6245. viewport);
  6246. }
  6247. static void VULKAN_INTERNAL_SetCurrentScissor(
  6248. VulkanCommandBuffer *vulkanCommandBuffer,
  6249. const SDL_Rect *scissor)
  6250. {
  6251. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6252. vulkanCommandBuffer->currentScissor.offset.x = scissor->x;
  6253. vulkanCommandBuffer->currentScissor.offset.y = scissor->y;
  6254. vulkanCommandBuffer->currentScissor.extent.width = scissor->w;
  6255. vulkanCommandBuffer->currentScissor.extent.height = scissor->h;
  6256. renderer->vkCmdSetScissor(
  6257. vulkanCommandBuffer->commandBuffer,
  6258. 0,
  6259. 1,
  6260. &vulkanCommandBuffer->currentScissor);
  6261. }
  6262. static void VULKAN_SetScissor(
  6263. SDL_GPUCommandBuffer *commandBuffer,
  6264. const SDL_Rect *scissor)
  6265. {
  6266. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6267. VULKAN_INTERNAL_SetCurrentScissor(
  6268. vulkanCommandBuffer,
  6269. scissor);
  6270. }
  6271. static void VULKAN_INTERNAL_SetCurrentBlendConstants(
  6272. VulkanCommandBuffer *vulkanCommandBuffer,
  6273. SDL_FColor blendConstants)
  6274. {
  6275. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6276. vulkanCommandBuffer->blendConstants[0] = blendConstants.r;
  6277. vulkanCommandBuffer->blendConstants[1] = blendConstants.g;
  6278. vulkanCommandBuffer->blendConstants[2] = blendConstants.b;
  6279. vulkanCommandBuffer->blendConstants[3] = blendConstants.a;
  6280. renderer->vkCmdSetBlendConstants(
  6281. vulkanCommandBuffer->commandBuffer,
  6282. vulkanCommandBuffer->blendConstants);
  6283. }
  6284. static void VULKAN_SetBlendConstants(
  6285. SDL_GPUCommandBuffer *commandBuffer,
  6286. SDL_FColor blendConstants)
  6287. {
  6288. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6289. VULKAN_INTERNAL_SetCurrentBlendConstants(
  6290. vulkanCommandBuffer,
  6291. blendConstants);
  6292. }
  6293. static void VULKAN_INTERNAL_SetCurrentStencilReference(
  6294. VulkanCommandBuffer *vulkanCommandBuffer,
  6295. Uint8 reference)
  6296. {
  6297. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6298. vulkanCommandBuffer->stencilRef = reference;
  6299. renderer->vkCmdSetStencilReference(
  6300. vulkanCommandBuffer->commandBuffer,
  6301. VK_STENCIL_FACE_FRONT_AND_BACK,
  6302. vulkanCommandBuffer->stencilRef);
  6303. }
  6304. static void VULKAN_SetStencilReference(
  6305. SDL_GPUCommandBuffer *commandBuffer,
  6306. Uint8 reference)
  6307. {
  6308. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6309. VULKAN_INTERNAL_SetCurrentStencilReference(
  6310. vulkanCommandBuffer,
  6311. reference);
  6312. }
  6313. static void VULKAN_BindVertexSamplers(
  6314. SDL_GPUCommandBuffer *commandBuffer,
  6315. Uint32 firstSlot,
  6316. const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
  6317. Uint32 numBindings)
  6318. {
  6319. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6320. for (Uint32 i = 0; i < numBindings; i += 1) {
  6321. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
  6322. VulkanSampler *sampler = (VulkanSampler *)textureSamplerBindings[i].sampler;
  6323. if (vulkanCommandBuffer->vertexSamplerBindings[firstSlot + i] != sampler->sampler) {
  6324. VULKAN_INTERNAL_TrackSampler(
  6325. vulkanCommandBuffer,
  6326. (VulkanSampler *)textureSamplerBindings[i].sampler);
  6327. vulkanCommandBuffer->vertexSamplerBindings[firstSlot + i] = sampler->sampler;
  6328. vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
  6329. }
  6330. if (vulkanCommandBuffer->vertexSamplerTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
  6331. VULKAN_INTERNAL_TrackTexture(
  6332. vulkanCommandBuffer,
  6333. textureContainer->activeTexture);
  6334. vulkanCommandBuffer->vertexSamplerTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
  6335. vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
  6336. }
  6337. }
  6338. }
  6339. static void VULKAN_BindVertexStorageTextures(
  6340. SDL_GPUCommandBuffer *commandBuffer,
  6341. Uint32 firstSlot,
  6342. SDL_GPUTexture *const *storageTextures,
  6343. Uint32 numBindings)
  6344. {
  6345. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6346. for (Uint32 i = 0; i < numBindings; i += 1) {
  6347. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
  6348. if (vulkanCommandBuffer->vertexStorageTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
  6349. VULKAN_INTERNAL_TrackTexture(
  6350. vulkanCommandBuffer,
  6351. textureContainer->activeTexture);
  6352. vulkanCommandBuffer->vertexStorageTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
  6353. vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
  6354. }
  6355. }
  6356. }
  6357. static void VULKAN_BindVertexStorageBuffers(
  6358. SDL_GPUCommandBuffer *commandBuffer,
  6359. Uint32 firstSlot,
  6360. SDL_GPUBuffer *const *storageBuffers,
  6361. Uint32 numBindings)
  6362. {
  6363. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6364. for (Uint32 i = 0; i < numBindings; i += 1) {
  6365. VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
  6366. if (vulkanCommandBuffer->vertexStorageBufferBindings[firstSlot + i] != bufferContainer->activeBuffer->buffer) {
  6367. VULKAN_INTERNAL_TrackBuffer(
  6368. vulkanCommandBuffer,
  6369. bufferContainer->activeBuffer);
  6370. vulkanCommandBuffer->vertexStorageBufferBindings[firstSlot + i] = bufferContainer->activeBuffer->buffer;
  6371. vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
  6372. }
  6373. }
  6374. }
  6375. static void VULKAN_BindFragmentSamplers(
  6376. SDL_GPUCommandBuffer *commandBuffer,
  6377. Uint32 firstSlot,
  6378. const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
  6379. Uint32 numBindings)
  6380. {
  6381. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6382. for (Uint32 i = 0; i < numBindings; i += 1) {
  6383. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
  6384. VulkanSampler *sampler = (VulkanSampler *)textureSamplerBindings[i].sampler;
  6385. if (vulkanCommandBuffer->fragmentSamplerBindings[firstSlot + i] != sampler->sampler) {
  6386. VULKAN_INTERNAL_TrackSampler(
  6387. vulkanCommandBuffer,
  6388. (VulkanSampler *)textureSamplerBindings[i].sampler);
  6389. vulkanCommandBuffer->fragmentSamplerBindings[firstSlot + i] = sampler->sampler;
  6390. vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
  6391. }
  6392. if (vulkanCommandBuffer->fragmentSamplerTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
  6393. VULKAN_INTERNAL_TrackTexture(
  6394. vulkanCommandBuffer,
  6395. textureContainer->activeTexture);
  6396. vulkanCommandBuffer->fragmentSamplerTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
  6397. vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
  6398. }
  6399. }
  6400. }
  6401. static void VULKAN_BindFragmentStorageTextures(
  6402. SDL_GPUCommandBuffer *commandBuffer,
  6403. Uint32 firstSlot,
  6404. SDL_GPUTexture *const *storageTextures,
  6405. Uint32 numBindings)
  6406. {
  6407. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6408. for (Uint32 i = 0; i < numBindings; i += 1) {
  6409. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
  6410. if (vulkanCommandBuffer->fragmentStorageTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
  6411. VULKAN_INTERNAL_TrackTexture(
  6412. vulkanCommandBuffer,
  6413. textureContainer->activeTexture);
  6414. vulkanCommandBuffer->fragmentStorageTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
  6415. vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
  6416. }
  6417. }
  6418. }
  6419. static void VULKAN_BindFragmentStorageBuffers(
  6420. SDL_GPUCommandBuffer *commandBuffer,
  6421. Uint32 firstSlot,
  6422. SDL_GPUBuffer *const *storageBuffers,
  6423. Uint32 numBindings)
  6424. {
  6425. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6426. VulkanBufferContainer *bufferContainer;
  6427. Uint32 i;
  6428. for (i = 0; i < numBindings; i += 1) {
  6429. bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
  6430. if (vulkanCommandBuffer->fragmentStorageBufferBindings[firstSlot + i] != bufferContainer->activeBuffer->buffer) {
  6431. VULKAN_INTERNAL_TrackBuffer(
  6432. vulkanCommandBuffer,
  6433. bufferContainer->activeBuffer);
  6434. vulkanCommandBuffer->fragmentStorageBufferBindings[firstSlot + i] = bufferContainer->activeBuffer->buffer;
  6435. vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
  6436. }
  6437. }
  6438. }
  6439. static VulkanUniformBuffer *VULKAN_INTERNAL_AcquireUniformBufferFromPool(
  6440. VulkanCommandBuffer *commandBuffer)
  6441. {
  6442. VulkanRenderer *renderer = commandBuffer->renderer;
  6443. VulkanUniformBuffer *uniformBuffer;
  6444. SDL_LockMutex(renderer->acquireUniformBufferLock);
  6445. if (renderer->uniformBufferPoolCount > 0) {
  6446. uniformBuffer = renderer->uniformBufferPool[renderer->uniformBufferPoolCount - 1];
  6447. renderer->uniformBufferPoolCount -= 1;
  6448. } else {
  6449. uniformBuffer = VULKAN_INTERNAL_CreateUniformBuffer(
  6450. renderer,
  6451. UNIFORM_BUFFER_SIZE);
  6452. }
  6453. SDL_UnlockMutex(renderer->acquireUniformBufferLock);
  6454. VULKAN_INTERNAL_TrackUniformBuffer(commandBuffer, uniformBuffer);
  6455. return uniformBuffer;
  6456. }
  6457. static void VULKAN_INTERNAL_ReturnUniformBufferToPool(
  6458. VulkanRenderer *renderer,
  6459. VulkanUniformBuffer *uniformBuffer)
  6460. {
  6461. if (renderer->uniformBufferPoolCount >= renderer->uniformBufferPoolCapacity) {
  6462. renderer->uniformBufferPoolCapacity *= 2;
  6463. renderer->uniformBufferPool = SDL_realloc(
  6464. renderer->uniformBufferPool,
  6465. renderer->uniformBufferPoolCapacity * sizeof(VulkanUniformBuffer *));
  6466. }
  6467. renderer->uniformBufferPool[renderer->uniformBufferPoolCount] = uniformBuffer;
  6468. renderer->uniformBufferPoolCount += 1;
  6469. uniformBuffer->writeOffset = 0;
  6470. uniformBuffer->drawOffset = 0;
  6471. }
  6472. static void VULKAN_INTERNAL_PushUniformData(
  6473. VulkanCommandBuffer *commandBuffer,
  6474. VulkanUniformBufferStage uniformBufferStage,
  6475. Uint32 slotIndex,
  6476. const void *data,
  6477. Uint32 length)
  6478. {
  6479. Uint32 blockSize =
  6480. VULKAN_INTERNAL_NextHighestAlignment32(
  6481. length,
  6482. commandBuffer->renderer->minUBOAlignment);
  6483. VulkanUniformBuffer *uniformBuffer;
  6484. if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_VERTEX) {
  6485. if (commandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
  6486. commandBuffer->vertexUniformBuffers[slotIndex] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
  6487. commandBuffer);
  6488. }
  6489. uniformBuffer = commandBuffer->vertexUniformBuffers[slotIndex];
  6490. } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT) {
  6491. if (commandBuffer->fragmentUniformBuffers[slotIndex] == NULL) {
  6492. commandBuffer->fragmentUniformBuffers[slotIndex] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
  6493. commandBuffer);
  6494. }
  6495. uniformBuffer = commandBuffer->fragmentUniformBuffers[slotIndex];
  6496. } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE) {
  6497. if (commandBuffer->computeUniformBuffers[slotIndex] == NULL) {
  6498. commandBuffer->computeUniformBuffers[slotIndex] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
  6499. commandBuffer);
  6500. }
  6501. uniformBuffer = commandBuffer->computeUniformBuffers[slotIndex];
  6502. } else {
  6503. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
  6504. return;
  6505. }
  6506. // If there is no more room, acquire a new uniform buffer
  6507. if (uniformBuffer->writeOffset + blockSize + MAX_UBO_SECTION_SIZE >= uniformBuffer->buffer->size) {
  6508. uniformBuffer = VULKAN_INTERNAL_AcquireUniformBufferFromPool(commandBuffer);
  6509. uniformBuffer->drawOffset = 0;
  6510. uniformBuffer->writeOffset = 0;
  6511. if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_VERTEX) {
  6512. commandBuffer->vertexUniformBuffers[slotIndex] = uniformBuffer;
  6513. commandBuffer->needNewVertexUniformDescriptorSet = true;
  6514. } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT) {
  6515. commandBuffer->fragmentUniformBuffers[slotIndex] = uniformBuffer;
  6516. commandBuffer->needNewFragmentUniformDescriptorSet = true;
  6517. } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE) {
  6518. commandBuffer->computeUniformBuffers[slotIndex] = uniformBuffer;
  6519. commandBuffer->needNewComputeUniformDescriptorSet = true;
  6520. } else {
  6521. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
  6522. return;
  6523. }
  6524. }
  6525. uniformBuffer->drawOffset = uniformBuffer->writeOffset;
  6526. Uint8 *dst =
  6527. uniformBuffer->buffer->usedRegion->allocation->mapPointer +
  6528. uniformBuffer->buffer->usedRegion->resourceOffset +
  6529. uniformBuffer->writeOffset;
  6530. SDL_memcpy(
  6531. dst,
  6532. data,
  6533. length);
  6534. uniformBuffer->writeOffset += blockSize;
  6535. if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_VERTEX) {
  6536. commandBuffer->needNewVertexUniformOffsets = true;
  6537. } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT) {
  6538. commandBuffer->needNewFragmentUniformOffsets = true;
  6539. } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE) {
  6540. commandBuffer->needNewComputeUniformOffsets = true;
  6541. } else {
  6542. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
  6543. return;
  6544. }
  6545. }
  6546. static void VULKAN_BeginRenderPass(
  6547. SDL_GPUCommandBuffer *commandBuffer,
  6548. const SDL_GPUColorTargetInfo *colorTargetInfos,
  6549. Uint32 numColorTargets,
  6550. const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo)
  6551. {
  6552. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6553. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6554. VkRenderPass renderPass;
  6555. VulkanFramebuffer *framebuffer;
  6556. Uint32 w, h;
  6557. VkClearValue *clearValues;
  6558. Uint32 clearCount = 0;
  6559. Uint32 totalColorAttachmentCount = 0;
  6560. Uint32 i;
  6561. SDL_GPUViewport defaultViewport;
  6562. SDL_Rect defaultScissor;
  6563. SDL_FColor defaultBlendConstants;
  6564. Uint32 framebufferWidth = SDL_MAX_UINT32;
  6565. Uint32 framebufferHeight = SDL_MAX_UINT32;
  6566. for (i = 0; i < numColorTargets; i += 1) {
  6567. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)colorTargetInfos[i].texture;
  6568. w = textureContainer->header.info.width >> colorTargetInfos[i].mip_level;
  6569. h = textureContainer->header.info.height >> colorTargetInfos[i].mip_level;
  6570. // The framebuffer cannot be larger than the smallest attachment.
  6571. if (w < framebufferWidth) {
  6572. framebufferWidth = w;
  6573. }
  6574. if (h < framebufferHeight) {
  6575. framebufferHeight = h;
  6576. }
  6577. }
  6578. if (depthStencilTargetInfo != NULL) {
  6579. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)depthStencilTargetInfo->texture;
  6580. w = textureContainer->header.info.width;
  6581. h = textureContainer->header.info.height;
  6582. // The framebuffer cannot be larger than the smallest attachment.
  6583. if (w < framebufferWidth) {
  6584. framebufferWidth = w;
  6585. }
  6586. if (h < framebufferHeight) {
  6587. framebufferHeight = h;
  6588. }
  6589. }
  6590. for (i = 0; i < numColorTargets; i += 1) {
  6591. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)colorTargetInfos[i].texture;
  6592. VulkanTextureSubresource *subresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
  6593. renderer,
  6594. vulkanCommandBuffer,
  6595. textureContainer,
  6596. textureContainer->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorTargetInfos[i].layer_or_depth_plane,
  6597. colorTargetInfos[i].mip_level,
  6598. colorTargetInfos[i].cycle,
  6599. VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT);
  6600. vulkanCommandBuffer->colorAttachmentSubresources[vulkanCommandBuffer->colorAttachmentSubresourceCount] = subresource;
  6601. vulkanCommandBuffer->colorAttachmentSubresourceCount += 1;
  6602. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, subresource->parent);
  6603. totalColorAttachmentCount += 1;
  6604. clearCount += 1;
  6605. if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
  6606. VulkanTextureContainer *resolveContainer = (VulkanTextureContainer *)colorTargetInfos[i].resolve_texture;
  6607. VulkanTextureSubresource *resolveSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
  6608. renderer,
  6609. vulkanCommandBuffer,
  6610. resolveContainer,
  6611. colorTargetInfos[i].resolve_layer,
  6612. colorTargetInfos[i].resolve_mip_level,
  6613. colorTargetInfos[i].cycle_resolve_texture,
  6614. VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT);
  6615. vulkanCommandBuffer->resolveAttachmentSubresources[vulkanCommandBuffer->resolveAttachmentSubresourceCount] = resolveSubresource;
  6616. vulkanCommandBuffer->resolveAttachmentSubresourceCount += 1;
  6617. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, resolveSubresource->parent);
  6618. totalColorAttachmentCount += 1;
  6619. clearCount += 1;
  6620. }
  6621. }
  6622. if (depthStencilTargetInfo != NULL) {
  6623. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)depthStencilTargetInfo->texture;
  6624. VulkanTextureSubresource *subresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
  6625. renderer,
  6626. vulkanCommandBuffer,
  6627. textureContainer,
  6628. 0,
  6629. 0,
  6630. depthStencilTargetInfo->cycle,
  6631. VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT);
  6632. vulkanCommandBuffer->depthStencilAttachmentSubresource = subresource;
  6633. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, subresource->parent);
  6634. clearCount += 1;
  6635. }
  6636. // Fetch required render objects
  6637. renderPass = VULKAN_INTERNAL_FetchRenderPass(
  6638. renderer,
  6639. vulkanCommandBuffer,
  6640. colorTargetInfos,
  6641. numColorTargets,
  6642. depthStencilTargetInfo);
  6643. if (renderPass == VK_NULL_HANDLE) {
  6644. return;
  6645. }
  6646. framebuffer = VULKAN_INTERNAL_FetchFramebuffer(
  6647. renderer,
  6648. renderPass,
  6649. colorTargetInfos,
  6650. numColorTargets,
  6651. depthStencilTargetInfo,
  6652. framebufferWidth,
  6653. framebufferHeight);
  6654. if (framebuffer == NULL) {
  6655. return;
  6656. }
  6657. VULKAN_INTERNAL_TrackFramebuffer(renderer, vulkanCommandBuffer, framebuffer);
  6658. // Set clear values
  6659. clearValues = SDL_stack_alloc(VkClearValue, clearCount);
  6660. int clearIndex = 0;
  6661. for (i = 0; i < numColorTargets; i += 1) {
  6662. clearValues[clearIndex].color.float32[0] = colorTargetInfos[i].clear_color.r;
  6663. clearValues[clearIndex].color.float32[1] = colorTargetInfos[i].clear_color.g;
  6664. clearValues[clearIndex].color.float32[2] = colorTargetInfos[i].clear_color.b;
  6665. clearValues[clearIndex].color.float32[3] = colorTargetInfos[i].clear_color.a;
  6666. clearIndex += 1;
  6667. if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
  6668. // Skip over the resolve texture, we're not clearing it
  6669. clearIndex += 1;
  6670. }
  6671. }
  6672. if (depthStencilTargetInfo != NULL) {
  6673. clearValues[totalColorAttachmentCount].depthStencil.depth =
  6674. depthStencilTargetInfo->clear_depth;
  6675. clearValues[totalColorAttachmentCount].depthStencil.stencil =
  6676. depthStencilTargetInfo->clear_stencil;
  6677. }
  6678. VkRenderPassBeginInfo renderPassBeginInfo;
  6679. renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  6680. renderPassBeginInfo.pNext = NULL;
  6681. renderPassBeginInfo.renderPass = renderPass;
  6682. renderPassBeginInfo.framebuffer = framebuffer->framebuffer;
  6683. renderPassBeginInfo.pClearValues = clearValues;
  6684. renderPassBeginInfo.clearValueCount = clearCount;
  6685. renderPassBeginInfo.renderArea.extent.width = framebufferWidth;
  6686. renderPassBeginInfo.renderArea.extent.height = framebufferHeight;
  6687. renderPassBeginInfo.renderArea.offset.x = 0;
  6688. renderPassBeginInfo.renderArea.offset.y = 0;
  6689. renderer->vkCmdBeginRenderPass(
  6690. vulkanCommandBuffer->commandBuffer,
  6691. &renderPassBeginInfo,
  6692. VK_SUBPASS_CONTENTS_INLINE);
  6693. SDL_stack_free(clearValues);
  6694. // Set sensible default states
  6695. defaultViewport.x = 0;
  6696. defaultViewport.y = 0;
  6697. defaultViewport.w = (float)framebufferWidth;
  6698. defaultViewport.h = (float)framebufferHeight;
  6699. defaultViewport.min_depth = 0;
  6700. defaultViewport.max_depth = 1;
  6701. VULKAN_INTERNAL_SetCurrentViewport(
  6702. vulkanCommandBuffer,
  6703. &defaultViewport);
  6704. defaultScissor.x = 0;
  6705. defaultScissor.y = 0;
  6706. defaultScissor.w = (Sint32)framebufferWidth;
  6707. defaultScissor.h = (Sint32)framebufferHeight;
  6708. VULKAN_INTERNAL_SetCurrentScissor(
  6709. vulkanCommandBuffer,
  6710. &defaultScissor);
  6711. defaultBlendConstants.r = 1.0f;
  6712. defaultBlendConstants.g = 1.0f;
  6713. defaultBlendConstants.b = 1.0f;
  6714. defaultBlendConstants.a = 1.0f;
  6715. VULKAN_INTERNAL_SetCurrentBlendConstants(
  6716. vulkanCommandBuffer,
  6717. defaultBlendConstants);
  6718. VULKAN_INTERNAL_SetCurrentStencilReference(
  6719. vulkanCommandBuffer,
  6720. 0);
  6721. }
  6722. static void VULKAN_BindGraphicsPipeline(
  6723. SDL_GPUCommandBuffer *commandBuffer,
  6724. SDL_GPUGraphicsPipeline *graphicsPipeline)
  6725. {
  6726. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6727. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6728. VulkanGraphicsPipeline *pipeline = (VulkanGraphicsPipeline *)graphicsPipeline;
  6729. renderer->vkCmdBindPipeline(
  6730. vulkanCommandBuffer->commandBuffer,
  6731. VK_PIPELINE_BIND_POINT_GRAPHICS,
  6732. pipeline->pipeline);
  6733. vulkanCommandBuffer->currentGraphicsPipeline = pipeline;
  6734. VULKAN_INTERNAL_TrackGraphicsPipeline(vulkanCommandBuffer, pipeline);
  6735. // Acquire uniform buffers if necessary
  6736. for (Uint32 i = 0; i < pipeline->resourceLayout->vertexUniformBufferCount; i += 1) {
  6737. if (vulkanCommandBuffer->vertexUniformBuffers[i] == NULL) {
  6738. vulkanCommandBuffer->vertexUniformBuffers[i] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
  6739. vulkanCommandBuffer);
  6740. }
  6741. }
  6742. for (Uint32 i = 0; i < pipeline->resourceLayout->fragmentUniformBufferCount; i += 1) {
  6743. if (vulkanCommandBuffer->fragmentUniformBuffers[i] == NULL) {
  6744. vulkanCommandBuffer->fragmentUniformBuffers[i] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
  6745. vulkanCommandBuffer);
  6746. }
  6747. }
  6748. // Mark bindings as needed
  6749. vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
  6750. vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
  6751. vulkanCommandBuffer->needNewVertexUniformDescriptorSet = true;
  6752. vulkanCommandBuffer->needNewFragmentUniformDescriptorSet = true;
  6753. vulkanCommandBuffer->needNewVertexUniformOffsets = true;
  6754. vulkanCommandBuffer->needNewFragmentUniformOffsets = true;
  6755. }
  6756. static void VULKAN_BindVertexBuffers(
  6757. SDL_GPUCommandBuffer *commandBuffer,
  6758. Uint32 firstSlot,
  6759. const SDL_GPUBufferBinding *bindings,
  6760. Uint32 numBindings)
  6761. {
  6762. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6763. for (Uint32 i = 0; i < numBindings; i += 1) {
  6764. VulkanBuffer *buffer = ((VulkanBufferContainer *)bindings[i].buffer)->activeBuffer;
  6765. if (vulkanCommandBuffer->vertexBuffers[firstSlot + i] != buffer->buffer || vulkanCommandBuffer->vertexBufferOffsets[firstSlot + i] != bindings[i].offset) {
  6766. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, buffer);
  6767. vulkanCommandBuffer->vertexBuffers[firstSlot + i] = buffer->buffer;
  6768. vulkanCommandBuffer->vertexBufferOffsets[firstSlot + i] = bindings[i].offset;
  6769. vulkanCommandBuffer->needVertexBufferBind = true;
  6770. }
  6771. }
  6772. vulkanCommandBuffer->vertexBufferCount =
  6773. SDL_max(vulkanCommandBuffer->vertexBufferCount, firstSlot + numBindings);
  6774. }
  6775. static void VULKAN_BindIndexBuffer(
  6776. SDL_GPUCommandBuffer *commandBuffer,
  6777. const SDL_GPUBufferBinding *binding,
  6778. SDL_GPUIndexElementSize indexElementSize)
  6779. {
  6780. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6781. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6782. VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)binding->buffer)->activeBuffer;
  6783. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
  6784. renderer->vkCmdBindIndexBuffer(
  6785. vulkanCommandBuffer->commandBuffer,
  6786. vulkanBuffer->buffer,
  6787. (VkDeviceSize)binding->offset,
  6788. SDLToVK_IndexType[indexElementSize]);
  6789. }
  6790. static void VULKAN_PushVertexUniformData(
  6791. SDL_GPUCommandBuffer *commandBuffer,
  6792. Uint32 slotIndex,
  6793. const void *data,
  6794. Uint32 length)
  6795. {
  6796. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6797. VULKAN_INTERNAL_PushUniformData(
  6798. vulkanCommandBuffer,
  6799. VULKAN_UNIFORM_BUFFER_STAGE_VERTEX,
  6800. slotIndex,
  6801. data,
  6802. length);
  6803. }
  6804. static void VULKAN_PushFragmentUniformData(
  6805. SDL_GPUCommandBuffer *commandBuffer,
  6806. Uint32 slotIndex,
  6807. const void *data,
  6808. Uint32 length)
  6809. {
  6810. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6811. VULKAN_INTERNAL_PushUniformData(
  6812. vulkanCommandBuffer,
  6813. VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT,
  6814. slotIndex,
  6815. data,
  6816. length);
  6817. }
  6818. static void VULKAN_EndRenderPass(
  6819. SDL_GPUCommandBuffer *commandBuffer)
  6820. {
  6821. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6822. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6823. Uint32 i;
  6824. renderer->vkCmdEndRenderPass(
  6825. vulkanCommandBuffer->commandBuffer);
  6826. for (i = 0; i < vulkanCommandBuffer->colorAttachmentSubresourceCount; i += 1) {
  6827. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  6828. renderer,
  6829. vulkanCommandBuffer,
  6830. VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT,
  6831. vulkanCommandBuffer->colorAttachmentSubresources[i]);
  6832. }
  6833. vulkanCommandBuffer->colorAttachmentSubresourceCount = 0;
  6834. for (i = 0; i < vulkanCommandBuffer->resolveAttachmentSubresourceCount; i += 1) {
  6835. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  6836. renderer,
  6837. vulkanCommandBuffer,
  6838. VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT,
  6839. vulkanCommandBuffer->resolveAttachmentSubresources[i]);
  6840. }
  6841. vulkanCommandBuffer->resolveAttachmentSubresourceCount = 0;
  6842. if (vulkanCommandBuffer->depthStencilAttachmentSubresource != NULL) {
  6843. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  6844. renderer,
  6845. vulkanCommandBuffer,
  6846. VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT,
  6847. vulkanCommandBuffer->depthStencilAttachmentSubresource);
  6848. vulkanCommandBuffer->depthStencilAttachmentSubresource = NULL;
  6849. }
  6850. vulkanCommandBuffer->currentGraphicsPipeline = NULL;
  6851. vulkanCommandBuffer->vertexResourceDescriptorSet = VK_NULL_HANDLE;
  6852. vulkanCommandBuffer->vertexUniformDescriptorSet = VK_NULL_HANDLE;
  6853. vulkanCommandBuffer->fragmentResourceDescriptorSet = VK_NULL_HANDLE;
  6854. vulkanCommandBuffer->fragmentUniformDescriptorSet = VK_NULL_HANDLE;
  6855. // Reset bind state
  6856. SDL_zeroa(vulkanCommandBuffer->colorAttachmentSubresources);
  6857. SDL_zeroa(vulkanCommandBuffer->resolveAttachmentSubresources);
  6858. vulkanCommandBuffer->depthStencilAttachmentSubresource = NULL;
  6859. SDL_zeroa(vulkanCommandBuffer->vertexBuffers);
  6860. SDL_zeroa(vulkanCommandBuffer->vertexBufferOffsets);
  6861. vulkanCommandBuffer->vertexBufferCount = 0;
  6862. SDL_zeroa(vulkanCommandBuffer->vertexSamplerBindings);
  6863. SDL_zeroa(vulkanCommandBuffer->vertexSamplerTextureViewBindings);
  6864. SDL_zeroa(vulkanCommandBuffer->vertexStorageTextureViewBindings);
  6865. SDL_zeroa(vulkanCommandBuffer->vertexStorageBufferBindings);
  6866. SDL_zeroa(vulkanCommandBuffer->fragmentSamplerBindings);
  6867. SDL_zeroa(vulkanCommandBuffer->fragmentSamplerTextureViewBindings);
  6868. SDL_zeroa(vulkanCommandBuffer->fragmentStorageTextureViewBindings);
  6869. SDL_zeroa(vulkanCommandBuffer->fragmentStorageBufferBindings);
  6870. }
  6871. static void VULKAN_BeginComputePass(
  6872. SDL_GPUCommandBuffer *commandBuffer,
  6873. const SDL_GPUStorageTextureReadWriteBinding *storageTextureBindings,
  6874. Uint32 numStorageTextureBindings,
  6875. const SDL_GPUStorageBufferReadWriteBinding *storageBufferBindings,
  6876. Uint32 numStorageBufferBindings)
  6877. {
  6878. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6879. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6880. VulkanBufferContainer *bufferContainer;
  6881. VulkanBuffer *buffer;
  6882. Uint32 i;
  6883. vulkanCommandBuffer->readWriteComputeStorageTextureSubresourceCount = numStorageTextureBindings;
  6884. for (i = 0; i < numStorageTextureBindings; i += 1) {
  6885. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextureBindings[i].texture;
  6886. VulkanTextureSubresource *subresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
  6887. renderer,
  6888. vulkanCommandBuffer,
  6889. textureContainer,
  6890. storageTextureBindings[i].layer,
  6891. storageTextureBindings[i].mip_level,
  6892. storageTextureBindings[i].cycle,
  6893. VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
  6894. vulkanCommandBuffer->readWriteComputeStorageTextureSubresources[i] = subresource;
  6895. vulkanCommandBuffer->readWriteComputeStorageTextureViewBindings[i] = subresource->computeWriteView;
  6896. VULKAN_INTERNAL_TrackTexture(
  6897. vulkanCommandBuffer,
  6898. subresource->parent);
  6899. }
  6900. for (i = 0; i < numStorageBufferBindings; i += 1) {
  6901. bufferContainer = (VulkanBufferContainer *)storageBufferBindings[i].buffer;
  6902. buffer = VULKAN_INTERNAL_PrepareBufferForWrite(
  6903. renderer,
  6904. vulkanCommandBuffer,
  6905. bufferContainer,
  6906. storageBufferBindings[i].cycle,
  6907. VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
  6908. vulkanCommandBuffer->readWriteComputeStorageBuffers[i] = buffer;
  6909. vulkanCommandBuffer->readWriteComputeStorageBufferBindings[i] = buffer->buffer;
  6910. VULKAN_INTERNAL_TrackBuffer(
  6911. vulkanCommandBuffer,
  6912. buffer);
  6913. }
  6914. }
  6915. static void VULKAN_BindComputePipeline(
  6916. SDL_GPUCommandBuffer *commandBuffer,
  6917. SDL_GPUComputePipeline *computePipeline)
  6918. {
  6919. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6920. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6921. VulkanComputePipeline *vulkanComputePipeline = (VulkanComputePipeline *)computePipeline;
  6922. renderer->vkCmdBindPipeline(
  6923. vulkanCommandBuffer->commandBuffer,
  6924. VK_PIPELINE_BIND_POINT_COMPUTE,
  6925. vulkanComputePipeline->pipeline);
  6926. vulkanCommandBuffer->currentComputePipeline = vulkanComputePipeline;
  6927. VULKAN_INTERNAL_TrackComputePipeline(vulkanCommandBuffer, vulkanComputePipeline);
  6928. // Acquire uniform buffers if necessary
  6929. for (Uint32 i = 0; i < vulkanComputePipeline->resourceLayout->numUniformBuffers; i += 1) {
  6930. if (vulkanCommandBuffer->computeUniformBuffers[i] == NULL) {
  6931. vulkanCommandBuffer->computeUniformBuffers[i] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
  6932. vulkanCommandBuffer);
  6933. }
  6934. }
  6935. // Mark binding as needed
  6936. vulkanCommandBuffer->needNewComputeReadWriteDescriptorSet = true;
  6937. vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
  6938. vulkanCommandBuffer->needNewComputeUniformDescriptorSet = true;
  6939. vulkanCommandBuffer->needNewComputeUniformOffsets = true;
  6940. }
  6941. static void VULKAN_BindComputeSamplers(
  6942. SDL_GPUCommandBuffer *commandBuffer,
  6943. Uint32 firstSlot,
  6944. const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
  6945. Uint32 numBindings)
  6946. {
  6947. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6948. for (Uint32 i = 0; i < numBindings; i += 1) {
  6949. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
  6950. VulkanSampler *sampler = (VulkanSampler *)textureSamplerBindings[i].sampler;
  6951. if (vulkanCommandBuffer->computeSamplerBindings[firstSlot + i] != sampler->sampler) {
  6952. VULKAN_INTERNAL_TrackSampler(
  6953. vulkanCommandBuffer,
  6954. sampler);
  6955. vulkanCommandBuffer->computeSamplerBindings[firstSlot + i] = sampler->sampler;
  6956. vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
  6957. }
  6958. if (vulkanCommandBuffer->computeSamplerTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
  6959. VULKAN_INTERNAL_TrackTexture(
  6960. vulkanCommandBuffer,
  6961. textureContainer->activeTexture);
  6962. vulkanCommandBuffer->computeSamplerTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
  6963. vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
  6964. }
  6965. }
  6966. }
  6967. static void VULKAN_BindComputeStorageTextures(
  6968. SDL_GPUCommandBuffer *commandBuffer,
  6969. Uint32 firstSlot,
  6970. SDL_GPUTexture *const *storageTextures,
  6971. Uint32 numBindings)
  6972. {
  6973. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  6974. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  6975. for (Uint32 i = 0; i < numBindings; i += 1) {
  6976. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
  6977. if (vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i] != textureContainer->activeTexture) {
  6978. /* If a different texture as in this slot, transition it back to its default usage */
  6979. if (vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i] != NULL) {
  6980. VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
  6981. renderer,
  6982. vulkanCommandBuffer,
  6983. VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
  6984. vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i]);
  6985. }
  6986. /* Then transition the new texture and prepare it for binding */
  6987. VULKAN_INTERNAL_TextureTransitionFromDefaultUsage(
  6988. renderer,
  6989. vulkanCommandBuffer,
  6990. VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
  6991. textureContainer->activeTexture);
  6992. VULKAN_INTERNAL_TrackTexture(
  6993. vulkanCommandBuffer,
  6994. textureContainer->activeTexture);
  6995. vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i] = textureContainer->activeTexture;
  6996. vulkanCommandBuffer->readOnlyComputeStorageTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
  6997. vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
  6998. }
  6999. }
  7000. }
  7001. static void VULKAN_BindComputeStorageBuffers(
  7002. SDL_GPUCommandBuffer *commandBuffer,
  7003. Uint32 firstSlot,
  7004. SDL_GPUBuffer *const *storageBuffers,
  7005. Uint32 numBindings)
  7006. {
  7007. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7008. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7009. for (Uint32 i = 0; i < numBindings; i += 1) {
  7010. VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
  7011. if (vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i] != bufferContainer->activeBuffer) {
  7012. /* If a different buffer was in this slot, transition it back to its default usage */
  7013. if (vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i] != NULL) {
  7014. VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
  7015. renderer,
  7016. vulkanCommandBuffer,
  7017. VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
  7018. vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i]);
  7019. }
  7020. /* Then transition the new buffer and prepare it for binding */
  7021. VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
  7022. renderer,
  7023. vulkanCommandBuffer,
  7024. VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
  7025. bufferContainer->activeBuffer);
  7026. VULKAN_INTERNAL_TrackBuffer(
  7027. vulkanCommandBuffer,
  7028. bufferContainer->activeBuffer);
  7029. vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
  7030. vulkanCommandBuffer->readOnlyComputeStorageBufferBindings[firstSlot + i] = bufferContainer->activeBuffer->buffer;
  7031. vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
  7032. }
  7033. }
  7034. }
  7035. static void VULKAN_PushComputeUniformData(
  7036. SDL_GPUCommandBuffer *commandBuffer,
  7037. Uint32 slotIndex,
  7038. const void *data,
  7039. Uint32 length)
  7040. {
  7041. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7042. VULKAN_INTERNAL_PushUniformData(
  7043. vulkanCommandBuffer,
  7044. VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE,
  7045. slotIndex,
  7046. data,
  7047. length);
  7048. }
  7049. static void VULKAN_INTERNAL_BindComputeDescriptorSets(
  7050. VulkanRenderer *renderer,
  7051. VulkanCommandBuffer *commandBuffer)
  7052. {
  7053. VulkanComputePipelineResourceLayout *resourceLayout;
  7054. DescriptorSetLayout *descriptorSetLayout;
  7055. VkWriteDescriptorSet writeDescriptorSets[
  7056. MAX_TEXTURE_SAMPLERS_PER_STAGE +
  7057. MAX_STORAGE_TEXTURES_PER_STAGE +
  7058. MAX_STORAGE_BUFFERS_PER_STAGE +
  7059. MAX_COMPUTE_WRITE_TEXTURES +
  7060. MAX_COMPUTE_WRITE_BUFFERS +
  7061. MAX_UNIFORM_BUFFERS_PER_STAGE];
  7062. VkDescriptorBufferInfo bufferInfos[MAX_STORAGE_BUFFERS_PER_STAGE + MAX_COMPUTE_WRITE_BUFFERS + MAX_UNIFORM_BUFFERS_PER_STAGE];
  7063. VkDescriptorImageInfo imageInfos[MAX_TEXTURE_SAMPLERS_PER_STAGE + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_COMPUTE_WRITE_TEXTURES];
  7064. Uint32 dynamicOffsets[MAX_UNIFORM_BUFFERS_PER_STAGE];
  7065. Uint32 writeCount = 0;
  7066. Uint32 bufferInfoCount = 0;
  7067. Uint32 imageInfoCount = 0;
  7068. Uint32 dynamicOffsetCount = 0;
  7069. if (
  7070. !commandBuffer->needNewComputeReadOnlyDescriptorSet &&
  7071. !commandBuffer->needNewComputeReadWriteDescriptorSet &&
  7072. !commandBuffer->needNewComputeUniformDescriptorSet &&
  7073. !commandBuffer->needNewComputeUniformOffsets
  7074. ) {
  7075. return;
  7076. }
  7077. resourceLayout = commandBuffer->currentComputePipeline->resourceLayout;
  7078. if (commandBuffer->needNewComputeReadOnlyDescriptorSet) {
  7079. descriptorSetLayout = resourceLayout->descriptorSetLayouts[0];
  7080. commandBuffer->computeReadOnlyDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
  7081. renderer,
  7082. commandBuffer,
  7083. descriptorSetLayout);
  7084. for (Uint32 i = 0; i < resourceLayout->numSamplers; i += 1) {
  7085. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  7086. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  7087. currentWriteDescriptorSet->pNext = NULL;
  7088. currentWriteDescriptorSet->descriptorCount = 1;
  7089. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  7090. currentWriteDescriptorSet->dstArrayElement = 0;
  7091. currentWriteDescriptorSet->dstBinding = i;
  7092. currentWriteDescriptorSet->dstSet = commandBuffer->computeReadOnlyDescriptorSet;
  7093. currentWriteDescriptorSet->pTexelBufferView = NULL;
  7094. currentWriteDescriptorSet->pBufferInfo = NULL;
  7095. imageInfos[imageInfoCount].sampler = commandBuffer->computeSamplerBindings[i];
  7096. imageInfos[imageInfoCount].imageView = commandBuffer->computeSamplerTextureViewBindings[i];
  7097. imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  7098. currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
  7099. writeCount += 1;
  7100. imageInfoCount += 1;
  7101. }
  7102. for (Uint32 i = 0; i < resourceLayout->numReadonlyStorageTextures; i += 1) {
  7103. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  7104. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  7105. currentWriteDescriptorSet->pNext = NULL;
  7106. currentWriteDescriptorSet->descriptorCount = 1;
  7107. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; // Yes, we are declaring the readonly storage texture as a sampled image, because shaders are stupid.
  7108. currentWriteDescriptorSet->dstArrayElement = 0;
  7109. currentWriteDescriptorSet->dstBinding = resourceLayout->numSamplers + i;
  7110. currentWriteDescriptorSet->dstSet = commandBuffer->computeReadOnlyDescriptorSet;
  7111. currentWriteDescriptorSet->pTexelBufferView = NULL;
  7112. currentWriteDescriptorSet->pBufferInfo = NULL;
  7113. imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
  7114. imageInfos[imageInfoCount].imageView = commandBuffer->readOnlyComputeStorageTextureViewBindings[i];
  7115. imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
  7116. currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
  7117. writeCount += 1;
  7118. imageInfoCount += 1;
  7119. }
  7120. for (Uint32 i = 0; i < resourceLayout->numReadonlyStorageBuffers; i += 1) {
  7121. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  7122. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  7123. currentWriteDescriptorSet->pNext = NULL;
  7124. currentWriteDescriptorSet->descriptorCount = 1;
  7125. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  7126. currentWriteDescriptorSet->dstArrayElement = 0;
  7127. currentWriteDescriptorSet->dstBinding = resourceLayout->numSamplers + resourceLayout->numReadonlyStorageTextures + i;
  7128. currentWriteDescriptorSet->dstSet = commandBuffer->computeReadOnlyDescriptorSet;
  7129. currentWriteDescriptorSet->pTexelBufferView = NULL;
  7130. currentWriteDescriptorSet->pImageInfo = NULL;
  7131. bufferInfos[bufferInfoCount].buffer = commandBuffer->readOnlyComputeStorageBufferBindings[i];
  7132. bufferInfos[bufferInfoCount].offset = 0;
  7133. bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
  7134. currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
  7135. writeCount += 1;
  7136. bufferInfoCount += 1;
  7137. }
  7138. commandBuffer->needNewComputeReadOnlyDescriptorSet = false;
  7139. }
  7140. if (commandBuffer->needNewComputeReadWriteDescriptorSet) {
  7141. descriptorSetLayout = resourceLayout->descriptorSetLayouts[1];
  7142. commandBuffer->computeReadWriteDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
  7143. renderer,
  7144. commandBuffer,
  7145. descriptorSetLayout);
  7146. for (Uint32 i = 0; i < resourceLayout->numReadWriteStorageTextures; i += 1) {
  7147. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  7148. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  7149. currentWriteDescriptorSet->pNext = NULL;
  7150. currentWriteDescriptorSet->descriptorCount = 1;
  7151. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
  7152. currentWriteDescriptorSet->dstArrayElement = 0;
  7153. currentWriteDescriptorSet->dstBinding = i;
  7154. currentWriteDescriptorSet->dstSet = commandBuffer->computeReadWriteDescriptorSet;
  7155. currentWriteDescriptorSet->pTexelBufferView = NULL;
  7156. currentWriteDescriptorSet->pBufferInfo = NULL;
  7157. imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
  7158. imageInfos[imageInfoCount].imageView = commandBuffer->readWriteComputeStorageTextureViewBindings[i];
  7159. imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
  7160. currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
  7161. writeCount += 1;
  7162. imageInfoCount += 1;
  7163. }
  7164. for (Uint32 i = 0; i < resourceLayout->numReadWriteStorageBuffers; i += 1) {
  7165. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  7166. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  7167. currentWriteDescriptorSet->pNext = NULL;
  7168. currentWriteDescriptorSet->descriptorCount = 1;
  7169. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  7170. currentWriteDescriptorSet->dstArrayElement = 0;
  7171. currentWriteDescriptorSet->dstBinding = resourceLayout->numReadWriteStorageTextures + i;
  7172. currentWriteDescriptorSet->dstSet = commandBuffer->computeReadWriteDescriptorSet;
  7173. currentWriteDescriptorSet->pTexelBufferView = NULL;
  7174. currentWriteDescriptorSet->pImageInfo = NULL;
  7175. bufferInfos[bufferInfoCount].buffer = commandBuffer->readWriteComputeStorageBufferBindings[i];
  7176. bufferInfos[bufferInfoCount].offset = 0;
  7177. bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
  7178. currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
  7179. writeCount += 1;
  7180. bufferInfoCount += 1;
  7181. }
  7182. commandBuffer->needNewComputeReadWriteDescriptorSet = false;
  7183. }
  7184. if (commandBuffer->needNewComputeUniformDescriptorSet) {
  7185. descriptorSetLayout = resourceLayout->descriptorSetLayouts[2];
  7186. commandBuffer->computeUniformDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
  7187. renderer,
  7188. commandBuffer,
  7189. descriptorSetLayout);
  7190. for (Uint32 i = 0; i < resourceLayout->numUniformBuffers; i += 1) {
  7191. VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
  7192. currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  7193. currentWriteDescriptorSet->pNext = NULL;
  7194. currentWriteDescriptorSet->descriptorCount = 1;
  7195. currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
  7196. currentWriteDescriptorSet->dstArrayElement = 0;
  7197. currentWriteDescriptorSet->dstBinding = i;
  7198. currentWriteDescriptorSet->dstSet = commandBuffer->computeUniformDescriptorSet;
  7199. currentWriteDescriptorSet->pTexelBufferView = NULL;
  7200. currentWriteDescriptorSet->pImageInfo = NULL;
  7201. bufferInfos[bufferInfoCount].buffer = commandBuffer->computeUniformBuffers[i]->buffer->buffer;
  7202. bufferInfos[bufferInfoCount].offset = 0;
  7203. bufferInfos[bufferInfoCount].range = MAX_UBO_SECTION_SIZE;
  7204. currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
  7205. writeCount += 1;
  7206. bufferInfoCount += 1;
  7207. }
  7208. commandBuffer->needNewComputeUniformDescriptorSet = false;
  7209. }
  7210. for (Uint32 i = 0; i < resourceLayout->numUniformBuffers; i += 1) {
  7211. dynamicOffsets[i] = commandBuffer->computeUniformBuffers[i]->drawOffset;
  7212. dynamicOffsetCount += 1;
  7213. }
  7214. renderer->vkUpdateDescriptorSets(
  7215. renderer->logicalDevice,
  7216. writeCount,
  7217. writeDescriptorSets,
  7218. 0,
  7219. NULL);
  7220. VkDescriptorSet sets[3];
  7221. sets[0] = commandBuffer->computeReadOnlyDescriptorSet;
  7222. sets[1] = commandBuffer->computeReadWriteDescriptorSet;
  7223. sets[2] = commandBuffer->computeUniformDescriptorSet;
  7224. renderer->vkCmdBindDescriptorSets(
  7225. commandBuffer->commandBuffer,
  7226. VK_PIPELINE_BIND_POINT_COMPUTE,
  7227. resourceLayout->pipelineLayout,
  7228. 0,
  7229. 3,
  7230. sets,
  7231. dynamicOffsetCount,
  7232. dynamicOffsets);
  7233. commandBuffer->needNewComputeUniformOffsets = false;
  7234. }
  7235. static void VULKAN_DispatchCompute(
  7236. SDL_GPUCommandBuffer *commandBuffer,
  7237. Uint32 groupcountX,
  7238. Uint32 groupcountY,
  7239. Uint32 groupcountZ)
  7240. {
  7241. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7242. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7243. VULKAN_INTERNAL_BindComputeDescriptorSets(renderer, vulkanCommandBuffer);
  7244. renderer->vkCmdDispatch(
  7245. vulkanCommandBuffer->commandBuffer,
  7246. groupcountX,
  7247. groupcountY,
  7248. groupcountZ);
  7249. }
  7250. static void VULKAN_DispatchComputeIndirect(
  7251. SDL_GPUCommandBuffer *commandBuffer,
  7252. SDL_GPUBuffer *buffer,
  7253. Uint32 offset)
  7254. {
  7255. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7256. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7257. VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)buffer)->activeBuffer;
  7258. VULKAN_INTERNAL_BindComputeDescriptorSets(renderer, vulkanCommandBuffer);
  7259. renderer->vkCmdDispatchIndirect(
  7260. vulkanCommandBuffer->commandBuffer,
  7261. vulkanBuffer->buffer,
  7262. offset);
  7263. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
  7264. }
  7265. static void VULKAN_EndComputePass(
  7266. SDL_GPUCommandBuffer *commandBuffer)
  7267. {
  7268. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7269. Uint32 i;
  7270. for (i = 0; i < vulkanCommandBuffer->readWriteComputeStorageTextureSubresourceCount; i += 1) {
  7271. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  7272. vulkanCommandBuffer->renderer,
  7273. vulkanCommandBuffer,
  7274. VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
  7275. vulkanCommandBuffer->readWriteComputeStorageTextureSubresources[i]);
  7276. vulkanCommandBuffer->readWriteComputeStorageTextureSubresources[i] = NULL;
  7277. }
  7278. vulkanCommandBuffer->readWriteComputeStorageTextureSubresourceCount = 0;
  7279. for (i = 0; i < MAX_COMPUTE_WRITE_BUFFERS; i += 1) {
  7280. if (vulkanCommandBuffer->readWriteComputeStorageBuffers[i] != NULL) {
  7281. VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
  7282. vulkanCommandBuffer->renderer,
  7283. vulkanCommandBuffer,
  7284. VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
  7285. vulkanCommandBuffer->readWriteComputeStorageBuffers[i]);
  7286. vulkanCommandBuffer->readWriteComputeStorageBuffers[i] = NULL;
  7287. }
  7288. }
  7289. for (i = 0; i < MAX_STORAGE_TEXTURES_PER_STAGE; i += 1) {
  7290. if (vulkanCommandBuffer->readOnlyComputeStorageTextures[i] != NULL) {
  7291. VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
  7292. vulkanCommandBuffer->renderer,
  7293. vulkanCommandBuffer,
  7294. VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
  7295. vulkanCommandBuffer->readOnlyComputeStorageTextures[i]);
  7296. vulkanCommandBuffer->readOnlyComputeStorageTextures[i] = NULL;
  7297. }
  7298. }
  7299. for (i = 0; i < MAX_STORAGE_BUFFERS_PER_STAGE; i += 1) {
  7300. if (vulkanCommandBuffer->readOnlyComputeStorageBuffers[i] != NULL) {
  7301. VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
  7302. vulkanCommandBuffer->renderer,
  7303. vulkanCommandBuffer,
  7304. VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
  7305. vulkanCommandBuffer->readOnlyComputeStorageBuffers[i]);
  7306. vulkanCommandBuffer->readOnlyComputeStorageBuffers[i] = NULL;
  7307. }
  7308. }
  7309. // we don't need a barrier for sampler resources because sampler state is always the default if sampler bit is set
  7310. SDL_zeroa(vulkanCommandBuffer->computeSamplerTextureViewBindings);
  7311. SDL_zeroa(vulkanCommandBuffer->computeSamplerBindings);
  7312. SDL_zeroa(vulkanCommandBuffer->readWriteComputeStorageTextureViewBindings);
  7313. SDL_zeroa(vulkanCommandBuffer->readWriteComputeStorageBufferBindings);
  7314. vulkanCommandBuffer->currentComputePipeline = NULL;
  7315. vulkanCommandBuffer->computeReadOnlyDescriptorSet = VK_NULL_HANDLE;
  7316. vulkanCommandBuffer->computeReadWriteDescriptorSet = VK_NULL_HANDLE;
  7317. vulkanCommandBuffer->computeUniformDescriptorSet = VK_NULL_HANDLE;
  7318. }
  7319. static void *VULKAN_MapTransferBuffer(
  7320. SDL_GPURenderer *driverData,
  7321. SDL_GPUTransferBuffer *transferBuffer,
  7322. bool cycle)
  7323. {
  7324. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  7325. VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)transferBuffer;
  7326. if (
  7327. cycle &&
  7328. SDL_GetAtomicInt(&transferBufferContainer->activeBuffer->referenceCount) > 0) {
  7329. VULKAN_INTERNAL_CycleActiveBuffer(
  7330. renderer,
  7331. transferBufferContainer);
  7332. }
  7333. Uint8 *bufferPointer =
  7334. transferBufferContainer->activeBuffer->usedRegion->allocation->mapPointer +
  7335. transferBufferContainer->activeBuffer->usedRegion->resourceOffset;
  7336. return bufferPointer;
  7337. }
  7338. static void VULKAN_UnmapTransferBuffer(
  7339. SDL_GPURenderer *driverData,
  7340. SDL_GPUTransferBuffer *transferBuffer)
  7341. {
  7342. // no-op because transfer buffers are persistently mapped
  7343. (void)driverData;
  7344. (void)transferBuffer;
  7345. }
  7346. static void VULKAN_BeginCopyPass(
  7347. SDL_GPUCommandBuffer *commandBuffer)
  7348. {
  7349. // no-op
  7350. (void)commandBuffer;
  7351. }
  7352. static void VULKAN_UploadToTexture(
  7353. SDL_GPUCommandBuffer *commandBuffer,
  7354. const SDL_GPUTextureTransferInfo *source,
  7355. const SDL_GPUTextureRegion *destination,
  7356. bool cycle)
  7357. {
  7358. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7359. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7360. VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)source->transfer_buffer;
  7361. VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer *)destination->texture;
  7362. VulkanTextureSubresource *vulkanTextureSubresource;
  7363. VkBufferImageCopy imageCopy;
  7364. // Note that the transfer buffer does not need a barrier, as it is synced by the client
  7365. vulkanTextureSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
  7366. renderer,
  7367. vulkanCommandBuffer,
  7368. vulkanTextureContainer,
  7369. destination->layer,
  7370. destination->mip_level,
  7371. cycle,
  7372. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION);
  7373. imageCopy.imageExtent.width = destination->w;
  7374. imageCopy.imageExtent.height = destination->h;
  7375. imageCopy.imageExtent.depth = destination->d;
  7376. imageCopy.imageOffset.x = destination->x;
  7377. imageCopy.imageOffset.y = destination->y;
  7378. imageCopy.imageOffset.z = destination->z;
  7379. imageCopy.imageSubresource.aspectMask = vulkanTextureSubresource->parent->aspectFlags;
  7380. imageCopy.imageSubresource.baseArrayLayer = destination->layer;
  7381. imageCopy.imageSubresource.layerCount = 1;
  7382. imageCopy.imageSubresource.mipLevel = destination->mip_level;
  7383. imageCopy.bufferOffset = source->offset;
  7384. imageCopy.bufferRowLength = source->pixels_per_row;
  7385. imageCopy.bufferImageHeight = source->rows_per_layer;
  7386. renderer->vkCmdCopyBufferToImage(
  7387. vulkanCommandBuffer->commandBuffer,
  7388. transferBufferContainer->activeBuffer->buffer,
  7389. vulkanTextureSubresource->parent->image,
  7390. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  7391. 1,
  7392. &imageCopy);
  7393. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  7394. renderer,
  7395. vulkanCommandBuffer,
  7396. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
  7397. vulkanTextureSubresource);
  7398. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
  7399. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, vulkanTextureSubresource->parent);
  7400. }
  7401. static void VULKAN_UploadToBuffer(
  7402. SDL_GPUCommandBuffer *commandBuffer,
  7403. const SDL_GPUTransferBufferLocation *source,
  7404. const SDL_GPUBufferRegion *destination,
  7405. bool cycle)
  7406. {
  7407. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7408. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7409. VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)source->transfer_buffer;
  7410. VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)destination->buffer;
  7411. VkBufferCopy bufferCopy;
  7412. // Note that the transfer buffer does not need a barrier, as it is synced by the client
  7413. VulkanBuffer *vulkanBuffer = VULKAN_INTERNAL_PrepareBufferForWrite(
  7414. renderer,
  7415. vulkanCommandBuffer,
  7416. bufferContainer,
  7417. cycle,
  7418. VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION);
  7419. bufferCopy.srcOffset = source->offset;
  7420. bufferCopy.dstOffset = destination->offset;
  7421. bufferCopy.size = destination->size;
  7422. renderer->vkCmdCopyBuffer(
  7423. vulkanCommandBuffer->commandBuffer,
  7424. transferBufferContainer->activeBuffer->buffer,
  7425. vulkanBuffer->buffer,
  7426. 1,
  7427. &bufferCopy);
  7428. VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
  7429. renderer,
  7430. vulkanCommandBuffer,
  7431. VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
  7432. vulkanBuffer);
  7433. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
  7434. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
  7435. }
  7436. // Readback
  7437. static void VULKAN_DownloadFromTexture(
  7438. SDL_GPUCommandBuffer *commandBuffer,
  7439. const SDL_GPUTextureRegion *source,
  7440. const SDL_GPUTextureTransferInfo *destination)
  7441. {
  7442. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7443. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7444. VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)source->texture;
  7445. VulkanTextureSubresource *vulkanTextureSubresource;
  7446. VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)destination->transfer_buffer;
  7447. VkBufferImageCopy imageCopy;
  7448. vulkanTextureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
  7449. textureContainer,
  7450. source->layer,
  7451. source->mip_level);
  7452. // Note that the transfer buffer does not need a barrier, as it is synced by the client
  7453. VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  7454. renderer,
  7455. vulkanCommandBuffer,
  7456. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  7457. vulkanTextureSubresource);
  7458. imageCopy.imageExtent.width = source->w;
  7459. imageCopy.imageExtent.height = source->h;
  7460. imageCopy.imageExtent.depth = source->d;
  7461. imageCopy.imageOffset.x = source->x;
  7462. imageCopy.imageOffset.y = source->y;
  7463. imageCopy.imageOffset.z = source->z;
  7464. imageCopy.imageSubresource.aspectMask = vulkanTextureSubresource->parent->aspectFlags;
  7465. imageCopy.imageSubresource.baseArrayLayer = source->layer;
  7466. imageCopy.imageSubresource.layerCount = 1;
  7467. imageCopy.imageSubresource.mipLevel = source->mip_level;
  7468. imageCopy.bufferOffset = destination->offset;
  7469. imageCopy.bufferRowLength = destination->pixels_per_row;
  7470. imageCopy.bufferImageHeight = destination->rows_per_layer;
  7471. renderer->vkCmdCopyImageToBuffer(
  7472. vulkanCommandBuffer->commandBuffer,
  7473. vulkanTextureSubresource->parent->image,
  7474. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  7475. transferBufferContainer->activeBuffer->buffer,
  7476. 1,
  7477. &imageCopy);
  7478. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  7479. renderer,
  7480. vulkanCommandBuffer,
  7481. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  7482. vulkanTextureSubresource);
  7483. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
  7484. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, vulkanTextureSubresource->parent);
  7485. }
  7486. static void VULKAN_DownloadFromBuffer(
  7487. SDL_GPUCommandBuffer *commandBuffer,
  7488. const SDL_GPUBufferRegion *source,
  7489. const SDL_GPUTransferBufferLocation *destination)
  7490. {
  7491. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7492. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7493. VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)source->buffer;
  7494. VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)destination->transfer_buffer;
  7495. VkBufferCopy bufferCopy;
  7496. // Note that transfer buffer does not need a barrier, as it is synced by the client
  7497. VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
  7498. renderer,
  7499. vulkanCommandBuffer,
  7500. VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
  7501. bufferContainer->activeBuffer);
  7502. bufferCopy.srcOffset = source->offset;
  7503. bufferCopy.dstOffset = destination->offset;
  7504. bufferCopy.size = source->size;
  7505. renderer->vkCmdCopyBuffer(
  7506. vulkanCommandBuffer->commandBuffer,
  7507. bufferContainer->activeBuffer->buffer,
  7508. transferBufferContainer->activeBuffer->buffer,
  7509. 1,
  7510. &bufferCopy);
  7511. VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
  7512. renderer,
  7513. vulkanCommandBuffer,
  7514. VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
  7515. bufferContainer->activeBuffer);
  7516. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
  7517. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, bufferContainer->activeBuffer);
  7518. }
  7519. static void VULKAN_CopyTextureToTexture(
  7520. SDL_GPUCommandBuffer *commandBuffer,
  7521. const SDL_GPUTextureLocation *source,
  7522. const SDL_GPUTextureLocation *destination,
  7523. Uint32 w,
  7524. Uint32 h,
  7525. Uint32 d,
  7526. bool cycle)
  7527. {
  7528. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7529. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7530. VulkanTextureSubresource *srcSubresource;
  7531. VulkanTextureSubresource *dstSubresource;
  7532. VkImageCopy imageCopy;
  7533. srcSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
  7534. (VulkanTextureContainer *)source->texture,
  7535. source->layer,
  7536. source->mip_level);
  7537. dstSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
  7538. renderer,
  7539. vulkanCommandBuffer,
  7540. (VulkanTextureContainer *)destination->texture,
  7541. destination->layer,
  7542. destination->mip_level,
  7543. cycle,
  7544. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION);
  7545. VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  7546. renderer,
  7547. vulkanCommandBuffer,
  7548. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  7549. srcSubresource);
  7550. imageCopy.srcOffset.x = source->x;
  7551. imageCopy.srcOffset.y = source->y;
  7552. imageCopy.srcOffset.z = source->z;
  7553. imageCopy.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
  7554. imageCopy.srcSubresource.baseArrayLayer = source->layer;
  7555. imageCopy.srcSubresource.layerCount = 1;
  7556. imageCopy.srcSubresource.mipLevel = source->mip_level;
  7557. imageCopy.dstOffset.x = destination->x;
  7558. imageCopy.dstOffset.y = destination->y;
  7559. imageCopy.dstOffset.z = destination->z;
  7560. imageCopy.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
  7561. imageCopy.dstSubresource.baseArrayLayer = destination->layer;
  7562. imageCopy.dstSubresource.layerCount = 1;
  7563. imageCopy.dstSubresource.mipLevel = destination->mip_level;
  7564. imageCopy.extent.width = w;
  7565. imageCopy.extent.height = h;
  7566. imageCopy.extent.depth = d;
  7567. renderer->vkCmdCopyImage(
  7568. vulkanCommandBuffer->commandBuffer,
  7569. srcSubresource->parent->image,
  7570. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  7571. dstSubresource->parent->image,
  7572. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  7573. 1,
  7574. &imageCopy);
  7575. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  7576. renderer,
  7577. vulkanCommandBuffer,
  7578. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  7579. srcSubresource);
  7580. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  7581. renderer,
  7582. vulkanCommandBuffer,
  7583. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
  7584. dstSubresource);
  7585. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcSubresource->parent);
  7586. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstSubresource->parent);
  7587. }
  7588. static void VULKAN_CopyBufferToBuffer(
  7589. SDL_GPUCommandBuffer *commandBuffer,
  7590. const SDL_GPUBufferLocation *source,
  7591. const SDL_GPUBufferLocation *destination,
  7592. Uint32 size,
  7593. bool cycle)
  7594. {
  7595. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7596. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7597. VulkanBufferContainer *srcContainer = (VulkanBufferContainer *)source->buffer;
  7598. VulkanBufferContainer *dstContainer = (VulkanBufferContainer *)destination->buffer;
  7599. VkBufferCopy bufferCopy;
  7600. VulkanBuffer *dstBuffer = VULKAN_INTERNAL_PrepareBufferForWrite(
  7601. renderer,
  7602. vulkanCommandBuffer,
  7603. dstContainer,
  7604. cycle,
  7605. VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION);
  7606. VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
  7607. renderer,
  7608. vulkanCommandBuffer,
  7609. VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
  7610. srcContainer->activeBuffer);
  7611. bufferCopy.srcOffset = source->offset;
  7612. bufferCopy.dstOffset = destination->offset;
  7613. bufferCopy.size = size;
  7614. renderer->vkCmdCopyBuffer(
  7615. vulkanCommandBuffer->commandBuffer,
  7616. srcContainer->activeBuffer->buffer,
  7617. dstBuffer->buffer,
  7618. 1,
  7619. &bufferCopy);
  7620. VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
  7621. renderer,
  7622. vulkanCommandBuffer,
  7623. VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
  7624. srcContainer->activeBuffer);
  7625. VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
  7626. renderer,
  7627. vulkanCommandBuffer,
  7628. VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
  7629. dstBuffer);
  7630. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, srcContainer->activeBuffer);
  7631. VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, dstBuffer);
  7632. }
  7633. static void VULKAN_GenerateMipmaps(
  7634. SDL_GPUCommandBuffer *commandBuffer,
  7635. SDL_GPUTexture *texture)
  7636. {
  7637. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7638. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7639. VulkanTextureContainer *container = (VulkanTextureContainer *)texture;
  7640. VulkanTextureSubresource *srcTextureSubresource;
  7641. VulkanTextureSubresource *dstTextureSubresource;
  7642. VkImageBlit blit;
  7643. // Blit each slice sequentially. Barriers, barriers everywhere!
  7644. for (Uint32 layerOrDepthIndex = 0; layerOrDepthIndex < container->header.info.layer_count_or_depth; layerOrDepthIndex += 1)
  7645. for (Uint32 level = 1; level < container->header.info.num_levels; level += 1) {
  7646. Uint32 layer = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : layerOrDepthIndex;
  7647. Uint32 depth = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? layerOrDepthIndex : 0;
  7648. Uint32 srcSubresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
  7649. level - 1,
  7650. layer,
  7651. container->header.info.num_levels);
  7652. Uint32 dstSubresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
  7653. level,
  7654. layer,
  7655. container->header.info.num_levels);
  7656. srcTextureSubresource = &container->activeTexture->subresources[srcSubresourceIndex];
  7657. dstTextureSubresource = &container->activeTexture->subresources[dstSubresourceIndex];
  7658. VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  7659. renderer,
  7660. vulkanCommandBuffer,
  7661. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  7662. srcTextureSubresource);
  7663. VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  7664. renderer,
  7665. vulkanCommandBuffer,
  7666. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
  7667. dstTextureSubresource);
  7668. blit.srcOffsets[0].x = 0;
  7669. blit.srcOffsets[0].y = 0;
  7670. blit.srcOffsets[0].z = depth;
  7671. blit.srcOffsets[1].x = container->header.info.width >> (level - 1);
  7672. blit.srcOffsets[1].y = container->header.info.height >> (level - 1);
  7673. blit.srcOffsets[1].z = depth + 1;
  7674. blit.dstOffsets[0].x = 0;
  7675. blit.dstOffsets[0].y = 0;
  7676. blit.dstOffsets[0].z = depth;
  7677. blit.dstOffsets[1].x = container->header.info.width >> level;
  7678. blit.dstOffsets[1].y = container->header.info.height >> level;
  7679. blit.dstOffsets[1].z = depth + 1;
  7680. blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  7681. blit.srcSubresource.baseArrayLayer = layer;
  7682. blit.srcSubresource.layerCount = 1;
  7683. blit.srcSubresource.mipLevel = level - 1;
  7684. blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  7685. blit.dstSubresource.baseArrayLayer = layer;
  7686. blit.dstSubresource.layerCount = 1;
  7687. blit.dstSubresource.mipLevel = level;
  7688. renderer->vkCmdBlitImage(
  7689. vulkanCommandBuffer->commandBuffer,
  7690. container->activeTexture->image,
  7691. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  7692. container->activeTexture->image,
  7693. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  7694. 1,
  7695. &blit,
  7696. VK_FILTER_LINEAR);
  7697. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  7698. renderer,
  7699. vulkanCommandBuffer,
  7700. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  7701. srcTextureSubresource);
  7702. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  7703. renderer,
  7704. vulkanCommandBuffer,
  7705. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
  7706. dstTextureSubresource);
  7707. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcTextureSubresource->parent);
  7708. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstTextureSubresource->parent);
  7709. }
  7710. }
  7711. static void VULKAN_EndCopyPass(
  7712. SDL_GPUCommandBuffer *commandBuffer)
  7713. {
  7714. // no-op
  7715. (void)commandBuffer;
  7716. }
  7717. static void VULKAN_Blit(
  7718. SDL_GPUCommandBuffer *commandBuffer,
  7719. const SDL_GPUBlitInfo *info)
  7720. {
  7721. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  7722. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  7723. TextureCommonHeader *srcHeader = (TextureCommonHeader *)info->source.texture;
  7724. TextureCommonHeader *dstHeader = (TextureCommonHeader *)info->destination.texture;
  7725. VkImageBlit region;
  7726. Uint32 srcLayer = srcHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : info->source.layer_or_depth_plane;
  7727. Uint32 srcDepth = srcHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? info->source.layer_or_depth_plane : 0;
  7728. Uint32 dstLayer = dstHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : info->destination.layer_or_depth_plane;
  7729. Uint32 dstDepth = dstHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? info->destination.layer_or_depth_plane : 0;
  7730. int32_t swap;
  7731. // Using BeginRenderPass to clear because vkCmdClearColorImage requires barriers anyway
  7732. if (info->load_op == SDL_GPU_LOADOP_CLEAR) {
  7733. SDL_GPUColorTargetInfo targetInfo;
  7734. SDL_zero(targetInfo);
  7735. targetInfo.texture = info->destination.texture;
  7736. targetInfo.mip_level = info->destination.mip_level;
  7737. targetInfo.layer_or_depth_plane = info->destination.layer_or_depth_plane;
  7738. targetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
  7739. targetInfo.store_op = SDL_GPU_STOREOP_STORE;
  7740. targetInfo.clear_color = info->clear_color;
  7741. targetInfo.cycle = info->cycle;
  7742. VULKAN_BeginRenderPass(
  7743. commandBuffer,
  7744. &targetInfo,
  7745. 1,
  7746. NULL);
  7747. VULKAN_EndRenderPass(commandBuffer);
  7748. }
  7749. VulkanTextureSubresource *srcSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
  7750. (VulkanTextureContainer *)info->source.texture,
  7751. srcLayer,
  7752. info->source.mip_level);
  7753. VulkanTextureSubresource *dstSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
  7754. renderer,
  7755. vulkanCommandBuffer,
  7756. (VulkanTextureContainer *)info->destination.texture,
  7757. dstLayer,
  7758. info->destination.mip_level,
  7759. info->cycle,
  7760. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION);
  7761. VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  7762. renderer,
  7763. vulkanCommandBuffer,
  7764. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  7765. srcSubresource);
  7766. region.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
  7767. region.srcSubresource.baseArrayLayer = srcSubresource->layer;
  7768. region.srcSubresource.layerCount = 1;
  7769. region.srcSubresource.mipLevel = srcSubresource->level;
  7770. region.srcOffsets[0].x = info->source.x;
  7771. region.srcOffsets[0].y = info->source.y;
  7772. region.srcOffsets[0].z = srcDepth;
  7773. region.srcOffsets[1].x = info->source.x + info->source.w;
  7774. region.srcOffsets[1].y = info->source.y + info->source.h;
  7775. region.srcOffsets[1].z = srcDepth + 1;
  7776. if (info->flip_mode & SDL_FLIP_HORIZONTAL) {
  7777. // flip the x positions
  7778. swap = region.srcOffsets[0].x;
  7779. region.srcOffsets[0].x = region.srcOffsets[1].x;
  7780. region.srcOffsets[1].x = swap;
  7781. }
  7782. if (info->flip_mode & SDL_FLIP_VERTICAL) {
  7783. // flip the y positions
  7784. swap = region.srcOffsets[0].y;
  7785. region.srcOffsets[0].y = region.srcOffsets[1].y;
  7786. region.srcOffsets[1].y = swap;
  7787. }
  7788. region.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
  7789. region.dstSubresource.baseArrayLayer = dstSubresource->layer;
  7790. region.dstSubresource.layerCount = 1;
  7791. region.dstSubresource.mipLevel = dstSubresource->level;
  7792. region.dstOffsets[0].x = info->destination.x;
  7793. region.dstOffsets[0].y = info->destination.y;
  7794. region.dstOffsets[0].z = dstDepth;
  7795. region.dstOffsets[1].x = info->destination.x + info->destination.w;
  7796. region.dstOffsets[1].y = info->destination.y + info->destination.h;
  7797. region.dstOffsets[1].z = dstDepth + 1;
  7798. renderer->vkCmdBlitImage(
  7799. vulkanCommandBuffer->commandBuffer,
  7800. srcSubresource->parent->image,
  7801. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  7802. dstSubresource->parent->image,
  7803. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  7804. 1,
  7805. &region,
  7806. SDLToVK_Filter[info->filter]);
  7807. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  7808. renderer,
  7809. vulkanCommandBuffer,
  7810. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  7811. srcSubresource);
  7812. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  7813. renderer,
  7814. vulkanCommandBuffer,
  7815. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
  7816. dstSubresource);
  7817. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcSubresource->parent);
  7818. VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstSubresource->parent);
  7819. }
  7820. static bool VULKAN_INTERNAL_AllocateCommandBuffer(
  7821. VulkanRenderer *renderer,
  7822. VulkanCommandPool *vulkanCommandPool)
  7823. {
  7824. VkCommandBufferAllocateInfo allocateInfo;
  7825. VkResult vulkanResult;
  7826. VkCommandBuffer commandBufferHandle;
  7827. VulkanCommandBuffer *commandBuffer;
  7828. vulkanCommandPool->inactiveCommandBufferCapacity += 1;
  7829. vulkanCommandPool->inactiveCommandBuffers = SDL_realloc(
  7830. vulkanCommandPool->inactiveCommandBuffers,
  7831. sizeof(VulkanCommandBuffer *) *
  7832. vulkanCommandPool->inactiveCommandBufferCapacity);
  7833. allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  7834. allocateInfo.pNext = NULL;
  7835. allocateInfo.commandPool = vulkanCommandPool->commandPool;
  7836. allocateInfo.commandBufferCount = 1;
  7837. allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  7838. vulkanResult = renderer->vkAllocateCommandBuffers(
  7839. renderer->logicalDevice,
  7840. &allocateInfo,
  7841. &commandBufferHandle);
  7842. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkAllocateCommandBuffers, false);
  7843. commandBuffer = SDL_malloc(sizeof(VulkanCommandBuffer));
  7844. commandBuffer->renderer = renderer;
  7845. commandBuffer->commandPool = vulkanCommandPool;
  7846. commandBuffer->commandBuffer = commandBufferHandle;
  7847. commandBuffer->inFlightFence = VK_NULL_HANDLE;
  7848. // Presentation tracking
  7849. commandBuffer->presentDataCapacity = 1;
  7850. commandBuffer->presentDataCount = 0;
  7851. commandBuffer->presentDatas = SDL_malloc(
  7852. commandBuffer->presentDataCapacity * sizeof(VulkanPresentData));
  7853. commandBuffer->waitSemaphoreCapacity = 1;
  7854. commandBuffer->waitSemaphoreCount = 0;
  7855. commandBuffer->waitSemaphores = SDL_malloc(
  7856. commandBuffer->waitSemaphoreCapacity * sizeof(VkSemaphore));
  7857. commandBuffer->signalSemaphoreCapacity = 1;
  7858. commandBuffer->signalSemaphoreCount = 0;
  7859. commandBuffer->signalSemaphores = SDL_malloc(
  7860. commandBuffer->signalSemaphoreCapacity * sizeof(VkSemaphore));
  7861. // Resource bind tracking
  7862. commandBuffer->needVertexBufferBind = false;
  7863. commandBuffer->needNewVertexResourceDescriptorSet = true;
  7864. commandBuffer->needNewVertexUniformDescriptorSet = true;
  7865. commandBuffer->needNewVertexUniformOffsets = true;
  7866. commandBuffer->needNewFragmentResourceDescriptorSet = true;
  7867. commandBuffer->needNewFragmentUniformDescriptorSet = true;
  7868. commandBuffer->needNewFragmentUniformOffsets = true;
  7869. commandBuffer->needNewComputeReadWriteDescriptorSet = true;
  7870. commandBuffer->needNewComputeReadOnlyDescriptorSet = true;
  7871. commandBuffer->needNewComputeUniformDescriptorSet = true;
  7872. commandBuffer->needNewComputeUniformOffsets = true;
  7873. commandBuffer->vertexResourceDescriptorSet = VK_NULL_HANDLE;
  7874. commandBuffer->vertexUniformDescriptorSet = VK_NULL_HANDLE;
  7875. commandBuffer->fragmentResourceDescriptorSet = VK_NULL_HANDLE;
  7876. commandBuffer->fragmentUniformDescriptorSet = VK_NULL_HANDLE;
  7877. commandBuffer->computeReadOnlyDescriptorSet = VK_NULL_HANDLE;
  7878. commandBuffer->computeReadWriteDescriptorSet = VK_NULL_HANDLE;
  7879. commandBuffer->computeUniformDescriptorSet = VK_NULL_HANDLE;
  7880. // Resource tracking
  7881. commandBuffer->usedBufferCapacity = 4;
  7882. commandBuffer->usedBufferCount = 0;
  7883. commandBuffer->usedBuffers = SDL_malloc(
  7884. commandBuffer->usedBufferCapacity * sizeof(VulkanBuffer *));
  7885. commandBuffer->usedTextureCapacity = 4;
  7886. commandBuffer->usedTextureCount = 0;
  7887. commandBuffer->usedTextures = SDL_malloc(
  7888. commandBuffer->usedTextureCapacity * sizeof(VulkanTexture *));
  7889. commandBuffer->usedSamplerCapacity = 4;
  7890. commandBuffer->usedSamplerCount = 0;
  7891. commandBuffer->usedSamplers = SDL_malloc(
  7892. commandBuffer->usedSamplerCapacity * sizeof(VulkanSampler *));
  7893. commandBuffer->usedGraphicsPipelineCapacity = 4;
  7894. commandBuffer->usedGraphicsPipelineCount = 0;
  7895. commandBuffer->usedGraphicsPipelines = SDL_malloc(
  7896. commandBuffer->usedGraphicsPipelineCapacity * sizeof(VulkanGraphicsPipeline *));
  7897. commandBuffer->usedComputePipelineCapacity = 4;
  7898. commandBuffer->usedComputePipelineCount = 0;
  7899. commandBuffer->usedComputePipelines = SDL_malloc(
  7900. commandBuffer->usedComputePipelineCapacity * sizeof(VulkanComputePipeline *));
  7901. commandBuffer->usedFramebufferCapacity = 4;
  7902. commandBuffer->usedFramebufferCount = 0;
  7903. commandBuffer->usedFramebuffers = SDL_malloc(
  7904. commandBuffer->usedFramebufferCapacity * sizeof(VulkanFramebuffer *));
  7905. commandBuffer->usedUniformBufferCapacity = 4;
  7906. commandBuffer->usedUniformBufferCount = 0;
  7907. commandBuffer->usedUniformBuffers = SDL_malloc(
  7908. commandBuffer->usedUniformBufferCapacity * sizeof(VulkanUniformBuffer *));
  7909. commandBuffer->swapchainRequested = false;
  7910. // Pool it!
  7911. vulkanCommandPool->inactiveCommandBuffers[vulkanCommandPool->inactiveCommandBufferCount] = commandBuffer;
  7912. vulkanCommandPool->inactiveCommandBufferCount += 1;
  7913. return true;
  7914. }
  7915. static VulkanCommandPool *VULKAN_INTERNAL_FetchCommandPool(
  7916. VulkanRenderer *renderer,
  7917. SDL_ThreadID threadID)
  7918. {
  7919. VulkanCommandPool *vulkanCommandPool = NULL;
  7920. VkCommandPoolCreateInfo commandPoolCreateInfo;
  7921. VkResult vulkanResult;
  7922. CommandPoolHashTableKey key;
  7923. key.threadID = threadID;
  7924. bool result = SDL_FindInHashTable(
  7925. renderer->commandPoolHashTable,
  7926. (const void *)&key,
  7927. (const void **)&vulkanCommandPool);
  7928. if (result) {
  7929. return vulkanCommandPool;
  7930. }
  7931. vulkanCommandPool = (VulkanCommandPool *)SDL_malloc(sizeof(VulkanCommandPool));
  7932. commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  7933. commandPoolCreateInfo.pNext = NULL;
  7934. commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
  7935. commandPoolCreateInfo.queueFamilyIndex = renderer->queueFamilyIndex;
  7936. vulkanResult = renderer->vkCreateCommandPool(
  7937. renderer->logicalDevice,
  7938. &commandPoolCreateInfo,
  7939. NULL,
  7940. &vulkanCommandPool->commandPool);
  7941. if (vulkanResult != VK_SUCCESS) {
  7942. SDL_free(vulkanCommandPool);
  7943. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateCommandPool, NULL);
  7944. return NULL;
  7945. }
  7946. vulkanCommandPool->threadID = threadID;
  7947. vulkanCommandPool->inactiveCommandBufferCapacity = 0;
  7948. vulkanCommandPool->inactiveCommandBufferCount = 0;
  7949. vulkanCommandPool->inactiveCommandBuffers = NULL;
  7950. if (!VULKAN_INTERNAL_AllocateCommandBuffer(
  7951. renderer,
  7952. vulkanCommandPool)) {
  7953. VULKAN_INTERNAL_DestroyCommandPool(renderer, vulkanCommandPool);
  7954. return NULL;
  7955. }
  7956. CommandPoolHashTableKey *allocedKey = SDL_malloc(sizeof(CommandPoolHashTableKey));
  7957. allocedKey->threadID = threadID;
  7958. SDL_InsertIntoHashTable(
  7959. renderer->commandPoolHashTable,
  7960. (const void *)allocedKey,
  7961. (const void *)vulkanCommandPool, true);
  7962. return vulkanCommandPool;
  7963. }
  7964. static VulkanCommandBuffer *VULKAN_INTERNAL_GetInactiveCommandBufferFromPool(
  7965. VulkanRenderer *renderer,
  7966. SDL_ThreadID threadID)
  7967. {
  7968. VulkanCommandPool *commandPool =
  7969. VULKAN_INTERNAL_FetchCommandPool(renderer, threadID);
  7970. VulkanCommandBuffer *commandBuffer;
  7971. if (commandPool == NULL) {
  7972. return NULL;
  7973. }
  7974. if (commandPool->inactiveCommandBufferCount == 0) {
  7975. if (!VULKAN_INTERNAL_AllocateCommandBuffer(
  7976. renderer,
  7977. commandPool)) {
  7978. return NULL;
  7979. }
  7980. }
  7981. commandBuffer = commandPool->inactiveCommandBuffers[commandPool->inactiveCommandBufferCount - 1];
  7982. commandPool->inactiveCommandBufferCount -= 1;
  7983. return commandBuffer;
  7984. }
  7985. static SDL_GPUCommandBuffer *VULKAN_AcquireCommandBuffer(
  7986. SDL_GPURenderer *driverData)
  7987. {
  7988. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  7989. VkResult result;
  7990. Uint32 i;
  7991. SDL_ThreadID threadID = SDL_GetCurrentThreadID();
  7992. SDL_LockMutex(renderer->acquireCommandBufferLock);
  7993. VulkanCommandBuffer *commandBuffer =
  7994. VULKAN_INTERNAL_GetInactiveCommandBufferFromPool(renderer, threadID);
  7995. DescriptorSetCache *descriptorSetCache =
  7996. VULKAN_INTERNAL_AcquireDescriptorSetCache(renderer);
  7997. SDL_UnlockMutex(renderer->acquireCommandBufferLock);
  7998. if (commandBuffer == NULL) {
  7999. return NULL;
  8000. }
  8001. commandBuffer->descriptorSetCache = descriptorSetCache;
  8002. // Reset state
  8003. commandBuffer->currentComputePipeline = NULL;
  8004. commandBuffer->currentGraphicsPipeline = NULL;
  8005. SDL_zeroa(commandBuffer->colorAttachmentSubresources);
  8006. SDL_zeroa(commandBuffer->resolveAttachmentSubresources);
  8007. commandBuffer->depthStencilAttachmentSubresource = NULL;
  8008. commandBuffer->colorAttachmentSubresourceCount = 0;
  8009. commandBuffer->resolveAttachmentSubresourceCount = 0;
  8010. for (i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
  8011. commandBuffer->vertexUniformBuffers[i] = NULL;
  8012. commandBuffer->fragmentUniformBuffers[i] = NULL;
  8013. commandBuffer->computeUniformBuffers[i] = NULL;
  8014. }
  8015. commandBuffer->needVertexBufferBind = false;
  8016. commandBuffer->needNewVertexResourceDescriptorSet = true;
  8017. commandBuffer->needNewVertexUniformDescriptorSet = true;
  8018. commandBuffer->needNewVertexUniformOffsets = true;
  8019. commandBuffer->needNewFragmentResourceDescriptorSet = true;
  8020. commandBuffer->needNewFragmentUniformDescriptorSet = true;
  8021. commandBuffer->needNewFragmentUniformOffsets = true;
  8022. commandBuffer->needNewComputeReadOnlyDescriptorSet = true;
  8023. commandBuffer->needNewComputeUniformDescriptorSet = true;
  8024. commandBuffer->needNewComputeUniformOffsets = true;
  8025. commandBuffer->vertexResourceDescriptorSet = VK_NULL_HANDLE;
  8026. commandBuffer->vertexUniformDescriptorSet = VK_NULL_HANDLE;
  8027. commandBuffer->fragmentResourceDescriptorSet = VK_NULL_HANDLE;
  8028. commandBuffer->fragmentUniformDescriptorSet = VK_NULL_HANDLE;
  8029. commandBuffer->computeReadOnlyDescriptorSet = VK_NULL_HANDLE;
  8030. commandBuffer->computeReadWriteDescriptorSet = VK_NULL_HANDLE;
  8031. commandBuffer->computeUniformDescriptorSet = VK_NULL_HANDLE;
  8032. SDL_zeroa(commandBuffer->vertexBuffers);
  8033. SDL_zeroa(commandBuffer->vertexBufferOffsets);
  8034. commandBuffer->vertexBufferCount = 0;
  8035. SDL_zeroa(commandBuffer->vertexSamplerTextureViewBindings);
  8036. SDL_zeroa(commandBuffer->vertexSamplerBindings);
  8037. SDL_zeroa(commandBuffer->vertexStorageTextureViewBindings);
  8038. SDL_zeroa(commandBuffer->vertexStorageBufferBindings);
  8039. SDL_zeroa(commandBuffer->fragmentSamplerTextureViewBindings);
  8040. SDL_zeroa(commandBuffer->fragmentSamplerBindings);
  8041. SDL_zeroa(commandBuffer->fragmentStorageTextureViewBindings);
  8042. SDL_zeroa(commandBuffer->fragmentStorageBufferBindings);
  8043. SDL_zeroa(commandBuffer->readWriteComputeStorageTextureSubresources);
  8044. commandBuffer->readWriteComputeStorageTextureSubresourceCount = 0;
  8045. SDL_zeroa(commandBuffer->readWriteComputeStorageBuffers);
  8046. SDL_zeroa(commandBuffer->computeSamplerTextureViewBindings);
  8047. SDL_zeroa(commandBuffer->computeSamplerBindings);
  8048. SDL_zeroa(commandBuffer->readOnlyComputeStorageTextureViewBindings);
  8049. SDL_zeroa(commandBuffer->readOnlyComputeStorageBufferBindings);
  8050. SDL_zeroa(commandBuffer->readOnlyComputeStorageTextures);
  8051. SDL_zeroa(commandBuffer->readOnlyComputeStorageBuffers);
  8052. commandBuffer->autoReleaseFence = true;
  8053. commandBuffer->swapchainRequested = false;
  8054. commandBuffer->isDefrag = 0;
  8055. /* Reset the command buffer here to avoid resets being called
  8056. * from a separate thread than where the command buffer was acquired
  8057. */
  8058. result = renderer->vkResetCommandBuffer(
  8059. commandBuffer->commandBuffer,
  8060. VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
  8061. CHECK_VULKAN_ERROR_AND_RETURN(result, vkResetCommandBuffer, NULL);
  8062. if (!VULKAN_INTERNAL_BeginCommandBuffer(renderer, commandBuffer)) {
  8063. return NULL;
  8064. }
  8065. return (SDL_GPUCommandBuffer *)commandBuffer;
  8066. }
  8067. static bool VULKAN_QueryFence(
  8068. SDL_GPURenderer *driverData,
  8069. SDL_GPUFence *fence)
  8070. {
  8071. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8072. VkResult result;
  8073. result = renderer->vkGetFenceStatus(
  8074. renderer->logicalDevice,
  8075. ((VulkanFenceHandle *)fence)->fence);
  8076. if (result == VK_SUCCESS) {
  8077. return true;
  8078. } else if (result == VK_NOT_READY) {
  8079. return false;
  8080. } else {
  8081. SET_ERROR_AND_RETURN("vkGetFenceStatus: %s", VkErrorMessages(result), false);
  8082. }
  8083. }
  8084. static void VULKAN_INTERNAL_ReturnFenceToPool(
  8085. VulkanRenderer *renderer,
  8086. VulkanFenceHandle *fenceHandle)
  8087. {
  8088. SDL_LockMutex(renderer->fencePool.lock);
  8089. EXPAND_ARRAY_IF_NEEDED(
  8090. renderer->fencePool.availableFences,
  8091. VulkanFenceHandle *,
  8092. renderer->fencePool.availableFenceCount + 1,
  8093. renderer->fencePool.availableFenceCapacity,
  8094. renderer->fencePool.availableFenceCapacity * 2);
  8095. renderer->fencePool.availableFences[renderer->fencePool.availableFenceCount] = fenceHandle;
  8096. renderer->fencePool.availableFenceCount += 1;
  8097. SDL_UnlockMutex(renderer->fencePool.lock);
  8098. }
  8099. static void VULKAN_ReleaseFence(
  8100. SDL_GPURenderer *driverData,
  8101. SDL_GPUFence *fence)
  8102. {
  8103. VulkanFenceHandle *handle = (VulkanFenceHandle *)fence;
  8104. if (SDL_AtomicDecRef(&handle->referenceCount)) {
  8105. VULKAN_INTERNAL_ReturnFenceToPool((VulkanRenderer *)driverData, handle);
  8106. }
  8107. }
  8108. static WindowData *VULKAN_INTERNAL_FetchWindowData(
  8109. SDL_Window *window)
  8110. {
  8111. SDL_PropertiesID properties = SDL_GetWindowProperties(window);
  8112. return (WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
  8113. }
  8114. static bool VULKAN_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
  8115. {
  8116. SDL_Window *w = (SDL_Window *)userdata;
  8117. WindowData *data;
  8118. if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
  8119. data = VULKAN_INTERNAL_FetchWindowData(w);
  8120. data->needsSwapchainRecreate = true;
  8121. data->swapchainCreateWidth = e->window.data1;
  8122. data->swapchainCreateHeight = e->window.data2;
  8123. }
  8124. #ifdef SDL_PLATFORM_ANDROID
  8125. if (e->type == SDL_EVENT_DID_ENTER_BACKGROUND) {
  8126. data = VULKAN_INTERNAL_FetchWindowData(w);
  8127. data->needsSwapchainRecreate = true;
  8128. }
  8129. #endif
  8130. return true;
  8131. }
  8132. static bool VULKAN_SupportsSwapchainComposition(
  8133. SDL_GPURenderer *driverData,
  8134. SDL_Window *window,
  8135. SDL_GPUSwapchainComposition swapchainComposition)
  8136. {
  8137. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8138. WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
  8139. VkSurfaceKHR surface;
  8140. SwapchainSupportDetails supportDetails;
  8141. bool result = false;
  8142. if (windowData == NULL) {
  8143. SET_STRING_ERROR_AND_RETURN("Must claim window before querying swapchain composition support!", false);
  8144. }
  8145. surface = windowData->surface;
  8146. if (!surface) {
  8147. SET_STRING_ERROR_AND_RETURN("Window has no Vulkan surface", false);
  8148. }
  8149. if (VULKAN_INTERNAL_QuerySwapchainSupport(
  8150. renderer,
  8151. renderer->physicalDevice,
  8152. surface,
  8153. &supportDetails)) {
  8154. result = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
  8155. SwapchainCompositionToFormat[swapchainComposition],
  8156. SwapchainCompositionToColorSpace[swapchainComposition],
  8157. supportDetails.formats,
  8158. supportDetails.formatsLength);
  8159. if (!result) {
  8160. // Let's try again with the fallback format...
  8161. result = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
  8162. SwapchainCompositionToFallbackFormat[swapchainComposition],
  8163. SwapchainCompositionToColorSpace[swapchainComposition],
  8164. supportDetails.formats,
  8165. supportDetails.formatsLength);
  8166. }
  8167. SDL_free(supportDetails.formats);
  8168. SDL_free(supportDetails.presentModes);
  8169. }
  8170. return result;
  8171. }
  8172. static bool VULKAN_SupportsPresentMode(
  8173. SDL_GPURenderer *driverData,
  8174. SDL_Window *window,
  8175. SDL_GPUPresentMode presentMode)
  8176. {
  8177. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8178. WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
  8179. VkSurfaceKHR surface;
  8180. SwapchainSupportDetails supportDetails;
  8181. bool result = false;
  8182. if (windowData == NULL) {
  8183. SET_STRING_ERROR_AND_RETURN("Must claim window before querying present mode support!", false);
  8184. }
  8185. surface = windowData->surface;
  8186. if (!surface) {
  8187. SET_STRING_ERROR_AND_RETURN("Window has no Vulkan surface", false);
  8188. }
  8189. if (VULKAN_INTERNAL_QuerySwapchainSupport(
  8190. renderer,
  8191. renderer->physicalDevice,
  8192. surface,
  8193. &supportDetails)) {
  8194. result = VULKAN_INTERNAL_VerifySwapPresentMode(
  8195. SDLToVK_PresentMode[presentMode],
  8196. supportDetails.presentModes,
  8197. supportDetails.presentModesLength);
  8198. SDL_free(supportDetails.formats);
  8199. SDL_free(supportDetails.presentModes);
  8200. }
  8201. return result;
  8202. }
  8203. static bool VULKAN_ClaimWindow(
  8204. SDL_GPURenderer *driverData,
  8205. SDL_Window *window)
  8206. {
  8207. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8208. WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
  8209. if (windowData == NULL) {
  8210. windowData = SDL_calloc(1, sizeof(WindowData));
  8211. windowData->window = window;
  8212. windowData->presentMode = SDL_GPU_PRESENTMODE_VSYNC;
  8213. windowData->swapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR;
  8214. // On non-Apple platforms the swapchain capability currentExtent can be different from the window,
  8215. // so we have to query the window size.
  8216. #ifndef SDL_PLATFORM_APPLE
  8217. int w, h;
  8218. SDL_SyncWindow(window);
  8219. SDL_GetWindowSizeInPixels(window, &w, &h);
  8220. windowData->swapchainCreateWidth = w;
  8221. windowData->swapchainCreateHeight = h;
  8222. #endif
  8223. Uint32 createSwapchainResult = VULKAN_INTERNAL_CreateSwapchain(renderer, windowData);
  8224. if (createSwapchainResult == 1) {
  8225. SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
  8226. SDL_LockMutex(renderer->windowLock);
  8227. if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
  8228. renderer->claimedWindowCapacity *= 2;
  8229. renderer->claimedWindows = SDL_realloc(
  8230. renderer->claimedWindows,
  8231. renderer->claimedWindowCapacity * sizeof(WindowData *));
  8232. }
  8233. renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
  8234. renderer->claimedWindowCount += 1;
  8235. SDL_UnlockMutex(renderer->windowLock);
  8236. SDL_AddEventWatch(VULKAN_INTERNAL_OnWindowResize, window);
  8237. return true;
  8238. } else if (createSwapchainResult == VULKAN_INTERNAL_TRY_AGAIN) {
  8239. windowData->needsSwapchainRecreate = true;
  8240. return true;
  8241. } else {
  8242. SDL_free(windowData);
  8243. return false;
  8244. }
  8245. } else {
  8246. SET_STRING_ERROR_AND_RETURN("Window already claimed!", false);
  8247. }
  8248. }
  8249. static void VULKAN_ReleaseWindow(
  8250. SDL_GPURenderer *driverData,
  8251. SDL_Window *window)
  8252. {
  8253. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8254. WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
  8255. Uint32 i;
  8256. if (windowData == NULL) {
  8257. return;
  8258. }
  8259. VULKAN_Wait(driverData);
  8260. for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
  8261. if (windowData->inFlightFences[i] != NULL) {
  8262. VULKAN_ReleaseFence(
  8263. driverData,
  8264. windowData->inFlightFences[i]);
  8265. }
  8266. }
  8267. VULKAN_INTERNAL_DestroySwapchain(
  8268. (VulkanRenderer *)driverData,
  8269. windowData);
  8270. SDL_LockMutex(renderer->windowLock);
  8271. for (i = 0; i < renderer->claimedWindowCount; i += 1) {
  8272. if (renderer->claimedWindows[i]->window == window) {
  8273. renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
  8274. renderer->claimedWindowCount -= 1;
  8275. break;
  8276. }
  8277. }
  8278. SDL_UnlockMutex(renderer->windowLock);
  8279. SDL_free(windowData);
  8280. SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
  8281. SDL_RemoveEventWatch(VULKAN_INTERNAL_OnWindowResize, window);
  8282. }
  8283. static Uint32 VULKAN_INTERNAL_RecreateSwapchain(
  8284. VulkanRenderer *renderer,
  8285. WindowData *windowData)
  8286. {
  8287. Uint32 i;
  8288. if (!VULKAN_Wait((SDL_GPURenderer *)renderer)) {
  8289. return false;
  8290. }
  8291. for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
  8292. if (windowData->inFlightFences[i] != NULL) {
  8293. VULKAN_ReleaseFence(
  8294. (SDL_GPURenderer *)renderer,
  8295. windowData->inFlightFences[i]);
  8296. windowData->inFlightFences[i] = NULL;
  8297. }
  8298. }
  8299. VULKAN_INTERNAL_DestroySwapchain(renderer, windowData);
  8300. return VULKAN_INTERNAL_CreateSwapchain(renderer, windowData);
  8301. }
  8302. static bool VULKAN_WaitForSwapchain(
  8303. SDL_GPURenderer *driverData,
  8304. SDL_Window *window)
  8305. {
  8306. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8307. WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
  8308. if (windowData == NULL) {
  8309. SET_STRING_ERROR_AND_RETURN("Cannot wait for a swapchain from an unclaimed window!", false);
  8310. }
  8311. if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
  8312. if (!VULKAN_WaitForFences(
  8313. driverData,
  8314. true,
  8315. &windowData->inFlightFences[windowData->frameCounter],
  8316. 1)) {
  8317. return false;
  8318. }
  8319. }
  8320. return true;
  8321. }
  8322. static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
  8323. bool block,
  8324. SDL_GPUCommandBuffer *commandBuffer,
  8325. SDL_Window *window,
  8326. SDL_GPUTexture **swapchainTexture,
  8327. Uint32 *swapchainTextureWidth,
  8328. Uint32 *swapchainTextureHeight)
  8329. {
  8330. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  8331. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  8332. Uint32 swapchainImageIndex;
  8333. WindowData *windowData;
  8334. VkResult acquireResult = VK_SUCCESS;
  8335. VulkanTextureContainer *swapchainTextureContainer = NULL;
  8336. VulkanPresentData *presentData;
  8337. *swapchainTexture = NULL;
  8338. if (swapchainTextureWidth) {
  8339. *swapchainTextureWidth = 0;
  8340. }
  8341. if (swapchainTextureHeight) {
  8342. *swapchainTextureHeight = 0;
  8343. }
  8344. windowData = VULKAN_INTERNAL_FetchWindowData(window);
  8345. if (windowData == NULL) {
  8346. SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false);
  8347. }
  8348. // The command buffer is flagged for cleanup when the swapchain is requested as a cleanup timing mechanism
  8349. vulkanCommandBuffer->swapchainRequested = true;
  8350. if (window->flags & SDL_WINDOW_HIDDEN) {
  8351. // Edge case, texture is filled in with NULL but not an error
  8352. return true;
  8353. }
  8354. // If window data marked as needing swapchain recreate, try to recreate
  8355. if (windowData->needsSwapchainRecreate) {
  8356. Uint32 recreateSwapchainResult = VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
  8357. if (!recreateSwapchainResult) {
  8358. return false;
  8359. } else if (recreateSwapchainResult == VULKAN_INTERNAL_TRY_AGAIN) {
  8360. // Edge case, texture is filled in with NULL but not an error
  8361. if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
  8362. VULKAN_ReleaseFence(
  8363. (SDL_GPURenderer *)renderer,
  8364. windowData->inFlightFences[windowData->frameCounter]);
  8365. windowData->inFlightFences[windowData->frameCounter] = NULL;
  8366. }
  8367. return true;
  8368. }
  8369. }
  8370. if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
  8371. if (block) {
  8372. // If we are blocking, just wait for the fence!
  8373. if (!VULKAN_WaitForFences(
  8374. (SDL_GPURenderer *)renderer,
  8375. true,
  8376. &windowData->inFlightFences[windowData->frameCounter],
  8377. 1)) {
  8378. return false;
  8379. }
  8380. } else {
  8381. // If we are not blocking and the least recent fence is not signaled,
  8382. // return true to indicate that there is no error but rendering should be skipped.
  8383. if (!VULKAN_QueryFence(
  8384. (SDL_GPURenderer *)renderer,
  8385. windowData->inFlightFences[windowData->frameCounter])) {
  8386. return true;
  8387. }
  8388. }
  8389. VULKAN_ReleaseFence(
  8390. (SDL_GPURenderer *)renderer,
  8391. windowData->inFlightFences[windowData->frameCounter]);
  8392. windowData->inFlightFences[windowData->frameCounter] = NULL;
  8393. }
  8394. // Finally, try to acquire!
  8395. while (true) {
  8396. acquireResult = renderer->vkAcquireNextImageKHR(
  8397. renderer->logicalDevice,
  8398. windowData->swapchain,
  8399. SDL_MAX_UINT64,
  8400. windowData->imageAvailableSemaphore[windowData->frameCounter],
  8401. VK_NULL_HANDLE,
  8402. &swapchainImageIndex);
  8403. if (acquireResult == VK_SUCCESS || acquireResult == VK_SUBOPTIMAL_KHR) {
  8404. break; // we got the next image!
  8405. }
  8406. // If acquisition is invalid, let's try to recreate
  8407. Uint32 recreateSwapchainResult = VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
  8408. if (!recreateSwapchainResult) {
  8409. return false;
  8410. } else if (recreateSwapchainResult == VULKAN_INTERNAL_TRY_AGAIN) {
  8411. // Edge case, texture is filled in with NULL but not an error
  8412. return true;
  8413. }
  8414. }
  8415. if (swapchainTextureWidth) {
  8416. *swapchainTextureWidth = windowData->width;
  8417. }
  8418. if (swapchainTextureHeight) {
  8419. *swapchainTextureHeight = windowData->height;
  8420. }
  8421. swapchainTextureContainer = &windowData->textureContainers[swapchainImageIndex];
  8422. // We need a special execution dependency with pWaitDstStageMask or image transition can start before acquire finishes
  8423. VkImageMemoryBarrier imageBarrier;
  8424. imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  8425. imageBarrier.pNext = NULL;
  8426. imageBarrier.srcAccessMask = 0;
  8427. imageBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  8428. imageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  8429. imageBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  8430. imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  8431. imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  8432. imageBarrier.image = swapchainTextureContainer->activeTexture->image;
  8433. imageBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  8434. imageBarrier.subresourceRange.baseMipLevel = 0;
  8435. imageBarrier.subresourceRange.levelCount = 1;
  8436. imageBarrier.subresourceRange.baseArrayLayer = 0;
  8437. imageBarrier.subresourceRange.layerCount = 1;
  8438. renderer->vkCmdPipelineBarrier(
  8439. vulkanCommandBuffer->commandBuffer,
  8440. VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  8441. VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  8442. 0,
  8443. 0,
  8444. NULL,
  8445. 0,
  8446. NULL,
  8447. 1,
  8448. &imageBarrier);
  8449. // Set up present struct
  8450. if (vulkanCommandBuffer->presentDataCount == vulkanCommandBuffer->presentDataCapacity) {
  8451. vulkanCommandBuffer->presentDataCapacity += 1;
  8452. vulkanCommandBuffer->presentDatas = SDL_realloc(
  8453. vulkanCommandBuffer->presentDatas,
  8454. vulkanCommandBuffer->presentDataCapacity * sizeof(VulkanPresentData));
  8455. }
  8456. presentData = &vulkanCommandBuffer->presentDatas[vulkanCommandBuffer->presentDataCount];
  8457. vulkanCommandBuffer->presentDataCount += 1;
  8458. presentData->windowData = windowData;
  8459. presentData->swapchainImageIndex = swapchainImageIndex;
  8460. // Set up present semaphores
  8461. if (vulkanCommandBuffer->waitSemaphoreCount == vulkanCommandBuffer->waitSemaphoreCapacity) {
  8462. vulkanCommandBuffer->waitSemaphoreCapacity += 1;
  8463. vulkanCommandBuffer->waitSemaphores = SDL_realloc(
  8464. vulkanCommandBuffer->waitSemaphores,
  8465. vulkanCommandBuffer->waitSemaphoreCapacity * sizeof(VkSemaphore));
  8466. }
  8467. vulkanCommandBuffer->waitSemaphores[vulkanCommandBuffer->waitSemaphoreCount] =
  8468. windowData->imageAvailableSemaphore[windowData->frameCounter];
  8469. vulkanCommandBuffer->waitSemaphoreCount += 1;
  8470. if (vulkanCommandBuffer->signalSemaphoreCount == vulkanCommandBuffer->signalSemaphoreCapacity) {
  8471. vulkanCommandBuffer->signalSemaphoreCapacity += 1;
  8472. vulkanCommandBuffer->signalSemaphores = SDL_realloc(
  8473. vulkanCommandBuffer->signalSemaphores,
  8474. vulkanCommandBuffer->signalSemaphoreCapacity * sizeof(VkSemaphore));
  8475. }
  8476. vulkanCommandBuffer->signalSemaphores[vulkanCommandBuffer->signalSemaphoreCount] =
  8477. windowData->renderFinishedSemaphore[swapchainImageIndex];
  8478. vulkanCommandBuffer->signalSemaphoreCount += 1;
  8479. *swapchainTexture = (SDL_GPUTexture *)swapchainTextureContainer;
  8480. return true;
  8481. }
  8482. static bool VULKAN_AcquireSwapchainTexture(
  8483. SDL_GPUCommandBuffer *command_buffer,
  8484. SDL_Window *window,
  8485. SDL_GPUTexture **swapchain_texture,
  8486. Uint32 *swapchain_texture_width,
  8487. Uint32 *swapchain_texture_height
  8488. ) {
  8489. return VULKAN_INTERNAL_AcquireSwapchainTexture(
  8490. false,
  8491. command_buffer,
  8492. window,
  8493. swapchain_texture,
  8494. swapchain_texture_width,
  8495. swapchain_texture_height);
  8496. }
  8497. static bool VULKAN_WaitAndAcquireSwapchainTexture(
  8498. SDL_GPUCommandBuffer *command_buffer,
  8499. SDL_Window *window,
  8500. SDL_GPUTexture **swapchain_texture,
  8501. Uint32 *swapchain_texture_width,
  8502. Uint32 *swapchain_texture_height
  8503. ) {
  8504. return VULKAN_INTERNAL_AcquireSwapchainTexture(
  8505. true,
  8506. command_buffer,
  8507. window,
  8508. swapchain_texture,
  8509. swapchain_texture_width,
  8510. swapchain_texture_height);
  8511. }
  8512. static SDL_GPUTextureFormat VULKAN_GetSwapchainTextureFormat(
  8513. SDL_GPURenderer *driverData,
  8514. SDL_Window *window)
  8515. {
  8516. VulkanRenderer *renderer = (VulkanRenderer*)driverData;
  8517. WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
  8518. if (windowData == NULL) {
  8519. SET_STRING_ERROR_AND_RETURN("Cannot get swapchain format, window has not been claimed!", SDL_GPU_TEXTUREFORMAT_INVALID);
  8520. }
  8521. return SwapchainCompositionToSDLFormat(
  8522. windowData->swapchainComposition,
  8523. windowData->usingFallbackFormat);
  8524. }
  8525. static bool VULKAN_SetSwapchainParameters(
  8526. SDL_GPURenderer *driverData,
  8527. SDL_Window *window,
  8528. SDL_GPUSwapchainComposition swapchainComposition,
  8529. SDL_GPUPresentMode presentMode)
  8530. {
  8531. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8532. WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
  8533. if (windowData == NULL) {
  8534. SET_STRING_ERROR_AND_RETURN("Cannot set swapchain parameters on unclaimed window!", false);
  8535. }
  8536. if (!VULKAN_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
  8537. SET_STRING_ERROR_AND_RETURN("Swapchain composition not supported!", false);
  8538. }
  8539. if (!VULKAN_SupportsPresentMode(driverData, window, presentMode)) {
  8540. SET_STRING_ERROR_AND_RETURN("Present mode not supported!", false);
  8541. }
  8542. windowData->presentMode = presentMode;
  8543. windowData->swapchainComposition = swapchainComposition;
  8544. Uint32 recreateSwapchainResult = VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
  8545. if (!recreateSwapchainResult) {
  8546. return false;
  8547. } else if (recreateSwapchainResult == VULKAN_INTERNAL_TRY_AGAIN) {
  8548. // Edge case, swapchain extent is (0, 0) but this is not an error
  8549. windowData->needsSwapchainRecreate = true;
  8550. return true;
  8551. }
  8552. return true;
  8553. }
  8554. static bool VULKAN_SetAllowedFramesInFlight(
  8555. SDL_GPURenderer *driverData,
  8556. Uint32 allowedFramesInFlight)
  8557. {
  8558. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8559. renderer->allowedFramesInFlight = allowedFramesInFlight;
  8560. for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
  8561. WindowData *windowData = renderer->claimedWindows[i];
  8562. Uint32 recreateResult = VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
  8563. if (!recreateResult) {
  8564. return false;
  8565. } else if (recreateResult == VULKAN_INTERNAL_TRY_AGAIN) {
  8566. // Edge case, swapchain extent is (0, 0) but this is not an error
  8567. windowData->needsSwapchainRecreate = true;
  8568. }
  8569. }
  8570. return true;
  8571. }
  8572. // Submission structure
  8573. static VulkanFenceHandle *VULKAN_INTERNAL_AcquireFenceFromPool(
  8574. VulkanRenderer *renderer)
  8575. {
  8576. VulkanFenceHandle *handle;
  8577. VkFenceCreateInfo fenceCreateInfo;
  8578. VkFence fence;
  8579. VkResult vulkanResult;
  8580. if (renderer->fencePool.availableFenceCount == 0) {
  8581. // Create fence
  8582. fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  8583. fenceCreateInfo.pNext = NULL;
  8584. fenceCreateInfo.flags = 0;
  8585. vulkanResult = renderer->vkCreateFence(
  8586. renderer->logicalDevice,
  8587. &fenceCreateInfo,
  8588. NULL,
  8589. &fence);
  8590. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateFence, NULL);
  8591. handle = SDL_malloc(sizeof(VulkanFenceHandle));
  8592. handle->fence = fence;
  8593. SDL_SetAtomicInt(&handle->referenceCount, 0);
  8594. return handle;
  8595. }
  8596. SDL_LockMutex(renderer->fencePool.lock);
  8597. handle = renderer->fencePool.availableFences[renderer->fencePool.availableFenceCount - 1];
  8598. renderer->fencePool.availableFenceCount -= 1;
  8599. vulkanResult = renderer->vkResetFences(
  8600. renderer->logicalDevice,
  8601. 1,
  8602. &handle->fence);
  8603. SDL_UnlockMutex(renderer->fencePool.lock);
  8604. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkResetFences, NULL);
  8605. return handle;
  8606. }
  8607. static void VULKAN_INTERNAL_PerformPendingDestroys(
  8608. VulkanRenderer *renderer)
  8609. {
  8610. SDL_LockMutex(renderer->disposeLock);
  8611. for (Sint32 i = renderer->texturesToDestroyCount - 1; i >= 0; i -= 1) {
  8612. if (SDL_GetAtomicInt(&renderer->texturesToDestroy[i]->referenceCount) == 0) {
  8613. VULKAN_INTERNAL_DestroyTexture(
  8614. renderer,
  8615. renderer->texturesToDestroy[i]);
  8616. renderer->texturesToDestroy[i] = renderer->texturesToDestroy[renderer->texturesToDestroyCount - 1];
  8617. renderer->texturesToDestroyCount -= 1;
  8618. }
  8619. }
  8620. for (Sint32 i = renderer->buffersToDestroyCount - 1; i >= 0; i -= 1) {
  8621. if (SDL_GetAtomicInt(&renderer->buffersToDestroy[i]->referenceCount) == 0) {
  8622. VULKAN_INTERNAL_DestroyBuffer(
  8623. renderer,
  8624. renderer->buffersToDestroy[i]);
  8625. renderer->buffersToDestroy[i] = renderer->buffersToDestroy[renderer->buffersToDestroyCount - 1];
  8626. renderer->buffersToDestroyCount -= 1;
  8627. }
  8628. }
  8629. for (Sint32 i = renderer->graphicsPipelinesToDestroyCount - 1; i >= 0; i -= 1) {
  8630. if (SDL_GetAtomicInt(&renderer->graphicsPipelinesToDestroy[i]->referenceCount) == 0) {
  8631. VULKAN_INTERNAL_DestroyGraphicsPipeline(
  8632. renderer,
  8633. renderer->graphicsPipelinesToDestroy[i]);
  8634. renderer->graphicsPipelinesToDestroy[i] = renderer->graphicsPipelinesToDestroy[renderer->graphicsPipelinesToDestroyCount - 1];
  8635. renderer->graphicsPipelinesToDestroyCount -= 1;
  8636. }
  8637. }
  8638. for (Sint32 i = renderer->computePipelinesToDestroyCount - 1; i >= 0; i -= 1) {
  8639. if (SDL_GetAtomicInt(&renderer->computePipelinesToDestroy[i]->referenceCount) == 0) {
  8640. VULKAN_INTERNAL_DestroyComputePipeline(
  8641. renderer,
  8642. renderer->computePipelinesToDestroy[i]);
  8643. renderer->computePipelinesToDestroy[i] = renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount - 1];
  8644. renderer->computePipelinesToDestroyCount -= 1;
  8645. }
  8646. }
  8647. for (Sint32 i = renderer->shadersToDestroyCount - 1; i >= 0; i -= 1) {
  8648. if (SDL_GetAtomicInt(&renderer->shadersToDestroy[i]->referenceCount) == 0) {
  8649. VULKAN_INTERNAL_DestroyShader(
  8650. renderer,
  8651. renderer->shadersToDestroy[i]);
  8652. renderer->shadersToDestroy[i] = renderer->shadersToDestroy[renderer->shadersToDestroyCount - 1];
  8653. renderer->shadersToDestroyCount -= 1;
  8654. }
  8655. }
  8656. for (Sint32 i = renderer->samplersToDestroyCount - 1; i >= 0; i -= 1) {
  8657. if (SDL_GetAtomicInt(&renderer->samplersToDestroy[i]->referenceCount) == 0) {
  8658. VULKAN_INTERNAL_DestroySampler(
  8659. renderer,
  8660. renderer->samplersToDestroy[i]);
  8661. renderer->samplersToDestroy[i] = renderer->samplersToDestroy[renderer->samplersToDestroyCount - 1];
  8662. renderer->samplersToDestroyCount -= 1;
  8663. }
  8664. }
  8665. for (Sint32 i = renderer->framebuffersToDestroyCount - 1; i >= 0; i -= 1) {
  8666. if (SDL_GetAtomicInt(&renderer->framebuffersToDestroy[i]->referenceCount) == 0) {
  8667. VULKAN_INTERNAL_DestroyFramebuffer(
  8668. renderer,
  8669. renderer->framebuffersToDestroy[i]);
  8670. renderer->framebuffersToDestroy[i] = renderer->framebuffersToDestroy[renderer->framebuffersToDestroyCount - 1];
  8671. renderer->framebuffersToDestroyCount -= 1;
  8672. }
  8673. }
  8674. SDL_UnlockMutex(renderer->disposeLock);
  8675. }
  8676. static void VULKAN_INTERNAL_CleanCommandBuffer(
  8677. VulkanRenderer *renderer,
  8678. VulkanCommandBuffer *commandBuffer,
  8679. bool cancel)
  8680. {
  8681. if (commandBuffer->autoReleaseFence) {
  8682. VULKAN_ReleaseFence(
  8683. (SDL_GPURenderer *)renderer,
  8684. (SDL_GPUFence *)commandBuffer->inFlightFence);
  8685. commandBuffer->inFlightFence = NULL;
  8686. }
  8687. // Uniform buffers are now available
  8688. SDL_LockMutex(renderer->acquireUniformBufferLock);
  8689. for (Sint32 i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
  8690. VULKAN_INTERNAL_ReturnUniformBufferToPool(
  8691. renderer,
  8692. commandBuffer->usedUniformBuffers[i]);
  8693. }
  8694. commandBuffer->usedUniformBufferCount = 0;
  8695. SDL_UnlockMutex(renderer->acquireUniformBufferLock);
  8696. // Decrement reference counts
  8697. for (Sint32 i = 0; i < commandBuffer->usedBufferCount; i += 1) {
  8698. (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
  8699. }
  8700. commandBuffer->usedBufferCount = 0;
  8701. for (Sint32 i = 0; i < commandBuffer->usedTextureCount; i += 1) {
  8702. (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
  8703. }
  8704. commandBuffer->usedTextureCount = 0;
  8705. for (Sint32 i = 0; i < commandBuffer->usedSamplerCount; i += 1) {
  8706. (void)SDL_AtomicDecRef(&commandBuffer->usedSamplers[i]->referenceCount);
  8707. }
  8708. commandBuffer->usedSamplerCount = 0;
  8709. for (Sint32 i = 0; i < commandBuffer->usedGraphicsPipelineCount; i += 1) {
  8710. (void)SDL_AtomicDecRef(&commandBuffer->usedGraphicsPipelines[i]->referenceCount);
  8711. }
  8712. commandBuffer->usedGraphicsPipelineCount = 0;
  8713. for (Sint32 i = 0; i < commandBuffer->usedComputePipelineCount; i += 1) {
  8714. (void)SDL_AtomicDecRef(&commandBuffer->usedComputePipelines[i]->referenceCount);
  8715. }
  8716. commandBuffer->usedComputePipelineCount = 0;
  8717. for (Sint32 i = 0; i < commandBuffer->usedFramebufferCount; i += 1) {
  8718. (void)SDL_AtomicDecRef(&commandBuffer->usedFramebuffers[i]->referenceCount);
  8719. }
  8720. commandBuffer->usedFramebufferCount = 0;
  8721. // Reset presentation data
  8722. commandBuffer->presentDataCount = 0;
  8723. commandBuffer->waitSemaphoreCount = 0;
  8724. commandBuffer->signalSemaphoreCount = 0;
  8725. commandBuffer->swapchainRequested = false;
  8726. // Reset defrag state
  8727. if (commandBuffer->isDefrag) {
  8728. renderer->defragInProgress = 0;
  8729. }
  8730. // Return command buffer to pool
  8731. SDL_LockMutex(renderer->acquireCommandBufferLock);
  8732. if (commandBuffer->commandPool->inactiveCommandBufferCount == commandBuffer->commandPool->inactiveCommandBufferCapacity) {
  8733. commandBuffer->commandPool->inactiveCommandBufferCapacity += 1;
  8734. commandBuffer->commandPool->inactiveCommandBuffers = SDL_realloc(
  8735. commandBuffer->commandPool->inactiveCommandBuffers,
  8736. commandBuffer->commandPool->inactiveCommandBufferCapacity * sizeof(VulkanCommandBuffer *));
  8737. }
  8738. commandBuffer->commandPool->inactiveCommandBuffers[commandBuffer->commandPool->inactiveCommandBufferCount] = commandBuffer;
  8739. commandBuffer->commandPool->inactiveCommandBufferCount += 1;
  8740. // Release descriptor set cache
  8741. VULKAN_INTERNAL_ReturnDescriptorSetCacheToPool(
  8742. renderer,
  8743. commandBuffer->descriptorSetCache);
  8744. commandBuffer->descriptorSetCache = NULL;
  8745. SDL_UnlockMutex(renderer->acquireCommandBufferLock);
  8746. // Remove this command buffer from the submitted list
  8747. if (!cancel) {
  8748. for (Uint32 i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
  8749. if (renderer->submittedCommandBuffers[i] == commandBuffer) {
  8750. renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
  8751. renderer->submittedCommandBufferCount -= 1;
  8752. }
  8753. }
  8754. }
  8755. }
  8756. static bool VULKAN_WaitForFences(
  8757. SDL_GPURenderer *driverData,
  8758. bool waitAll,
  8759. SDL_GPUFence *const *fences,
  8760. Uint32 numFences)
  8761. {
  8762. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8763. VkFence *vkFences = SDL_stack_alloc(VkFence, numFences);
  8764. VkResult result;
  8765. for (Uint32 i = 0; i < numFences; i += 1) {
  8766. vkFences[i] = ((VulkanFenceHandle *)fences[i])->fence;
  8767. }
  8768. result = renderer->vkWaitForFences(
  8769. renderer->logicalDevice,
  8770. numFences,
  8771. vkFences,
  8772. waitAll,
  8773. SDL_MAX_UINT64);
  8774. CHECK_VULKAN_ERROR_AND_RETURN(result, vkWaitForFences, false);
  8775. SDL_stack_free(vkFences);
  8776. SDL_LockMutex(renderer->submitLock);
  8777. for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
  8778. result = renderer->vkGetFenceStatus(
  8779. renderer->logicalDevice,
  8780. renderer->submittedCommandBuffers[i]->inFlightFence->fence);
  8781. if (result == VK_SUCCESS) {
  8782. VULKAN_INTERNAL_CleanCommandBuffer(
  8783. renderer,
  8784. renderer->submittedCommandBuffers[i],
  8785. false);
  8786. }
  8787. }
  8788. VULKAN_INTERNAL_PerformPendingDestroys(renderer);
  8789. SDL_UnlockMutex(renderer->submitLock);
  8790. return true;
  8791. }
  8792. static bool VULKAN_Wait(
  8793. SDL_GPURenderer *driverData)
  8794. {
  8795. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  8796. VulkanCommandBuffer *commandBuffer;
  8797. VkResult result;
  8798. Sint32 i;
  8799. SDL_LockMutex(renderer->submitLock);
  8800. result = renderer->vkDeviceWaitIdle(renderer->logicalDevice);
  8801. if (result != VK_SUCCESS) {
  8802. if (renderer->debugMode) {
  8803. SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s %s", "vkDeviceWaitIdle", VkErrorMessages(result));
  8804. }
  8805. SDL_SetError("%s %s", "vkDeviceWaitIdle", VkErrorMessages(result));
  8806. SDL_UnlockMutex(renderer->submitLock);
  8807. return false;
  8808. }
  8809. for (i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
  8810. commandBuffer = renderer->submittedCommandBuffers[i];
  8811. VULKAN_INTERNAL_CleanCommandBuffer(renderer, commandBuffer, false);
  8812. }
  8813. VULKAN_INTERNAL_PerformPendingDestroys(renderer);
  8814. SDL_UnlockMutex(renderer->submitLock);
  8815. return true;
  8816. }
  8817. static SDL_GPUFence *VULKAN_SubmitAndAcquireFence(
  8818. SDL_GPUCommandBuffer *commandBuffer)
  8819. {
  8820. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  8821. vulkanCommandBuffer->autoReleaseFence = false;
  8822. if (!VULKAN_Submit(commandBuffer)) {
  8823. return NULL;
  8824. }
  8825. return (SDL_GPUFence *)vulkanCommandBuffer->inFlightFence;
  8826. }
  8827. static void VULKAN_INTERNAL_ReleaseCommandBuffer(VulkanCommandBuffer *vulkanCommandBuffer)
  8828. {
  8829. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  8830. if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) {
  8831. renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
  8832. renderer->submittedCommandBuffers = SDL_realloc(
  8833. renderer->submittedCommandBuffers,
  8834. sizeof(VulkanCommandBuffer *) * renderer->submittedCommandBufferCapacity);
  8835. }
  8836. renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = vulkanCommandBuffer;
  8837. renderer->submittedCommandBufferCount += 1;
  8838. }
  8839. static bool VULKAN_Submit(
  8840. SDL_GPUCommandBuffer *commandBuffer)
  8841. {
  8842. VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  8843. VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
  8844. VkSubmitInfo submitInfo;
  8845. VkPresentInfoKHR presentInfo;
  8846. VulkanPresentData *presentData;
  8847. VkResult vulkanResult, presentResult = VK_SUCCESS;
  8848. VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT];
  8849. Uint32 swapchainImageIndex;
  8850. VulkanTextureSubresource *swapchainTextureSubresource;
  8851. VulkanMemorySubAllocator *allocator;
  8852. bool performCleanups =
  8853. (renderer->claimedWindowCount > 0 && vulkanCommandBuffer->swapchainRequested) ||
  8854. renderer->claimedWindowCount == 0;
  8855. SDL_LockMutex(renderer->submitLock);
  8856. // FIXME: Can this just be permanent?
  8857. for (Uint32 i = 0; i < MAX_PRESENT_COUNT; i += 1) {
  8858. waitStages[i] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  8859. }
  8860. for (Uint32 j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) {
  8861. swapchainImageIndex = vulkanCommandBuffer->presentDatas[j].swapchainImageIndex;
  8862. swapchainTextureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
  8863. &vulkanCommandBuffer->presentDatas[j].windowData->textureContainers[swapchainImageIndex],
  8864. 0,
  8865. 0);
  8866. VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  8867. renderer,
  8868. vulkanCommandBuffer,
  8869. VULKAN_TEXTURE_USAGE_MODE_PRESENT,
  8870. swapchainTextureSubresource);
  8871. }
  8872. if (performCleanups &&
  8873. renderer->allocationsToDefragCount > 0 &&
  8874. !renderer->defragInProgress) {
  8875. if (!VULKAN_INTERNAL_DefragmentMemory(renderer, vulkanCommandBuffer))
  8876. {
  8877. SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to defragment memory, likely OOM!");
  8878. }
  8879. }
  8880. if (!VULKAN_INTERNAL_EndCommandBuffer(renderer, vulkanCommandBuffer)) {
  8881. SDL_UnlockMutex(renderer->submitLock);
  8882. return false;
  8883. }
  8884. vulkanCommandBuffer->inFlightFence = VULKAN_INTERNAL_AcquireFenceFromPool(renderer);
  8885. if (vulkanCommandBuffer->inFlightFence == NULL) {
  8886. SDL_UnlockMutex(renderer->submitLock);
  8887. return false;
  8888. }
  8889. // Command buffer has a reference to the in-flight fence
  8890. (void)SDL_AtomicIncRef(&vulkanCommandBuffer->inFlightFence->referenceCount);
  8891. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  8892. submitInfo.pNext = NULL;
  8893. submitInfo.commandBufferCount = 1;
  8894. submitInfo.pCommandBuffers = &vulkanCommandBuffer->commandBuffer;
  8895. submitInfo.pWaitDstStageMask = waitStages;
  8896. submitInfo.pWaitSemaphores = vulkanCommandBuffer->waitSemaphores;
  8897. submitInfo.waitSemaphoreCount = vulkanCommandBuffer->waitSemaphoreCount;
  8898. submitInfo.pSignalSemaphores = vulkanCommandBuffer->signalSemaphores;
  8899. submitInfo.signalSemaphoreCount = vulkanCommandBuffer->signalSemaphoreCount;
  8900. vulkanResult = renderer->vkQueueSubmit(
  8901. renderer->unifiedQueue,
  8902. 1,
  8903. &submitInfo,
  8904. vulkanCommandBuffer->inFlightFence->fence);
  8905. if (vulkanResult != VK_SUCCESS) {
  8906. SDL_UnlockMutex(renderer->submitLock);
  8907. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkQueueSubmit, false);
  8908. }
  8909. // Present, if applicable
  8910. for (Uint32 j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) {
  8911. presentData = &vulkanCommandBuffer->presentDatas[j];
  8912. presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  8913. presentInfo.pNext = NULL;
  8914. presentInfo.pWaitSemaphores =
  8915. &presentData->windowData->renderFinishedSemaphore[presentData->swapchainImageIndex];
  8916. presentInfo.waitSemaphoreCount = 1;
  8917. presentInfo.pSwapchains = &presentData->windowData->swapchain;
  8918. presentInfo.swapchainCount = 1;
  8919. presentInfo.pImageIndices = &presentData->swapchainImageIndex;
  8920. presentInfo.pResults = NULL;
  8921. presentResult = renderer->vkQueuePresentKHR(
  8922. renderer->unifiedQueue,
  8923. &presentInfo);
  8924. if (presentResult == VK_SUCCESS || presentResult == VK_SUBOPTIMAL_KHR || presentResult == VK_ERROR_OUT_OF_DATE_KHR) {
  8925. // If presenting, the swapchain is using the in-flight fence
  8926. presentData->windowData->inFlightFences[presentData->windowData->frameCounter] = (SDL_GPUFence*)vulkanCommandBuffer->inFlightFence;
  8927. (void)SDL_AtomicIncRef(&vulkanCommandBuffer->inFlightFence->referenceCount);
  8928. // On the Android platform, VK_SUBOPTIMAL_KHR is returned whenever the device is rotated. We'll just ignore this for now.
  8929. #ifndef SDL_PLATFORM_ANDROID
  8930. if (presentResult == VK_SUBOPTIMAL_KHR) {
  8931. presentData->windowData->needsSwapchainRecreate = true;
  8932. }
  8933. #endif
  8934. if (presentResult == VK_ERROR_OUT_OF_DATE_KHR) {
  8935. presentData->windowData->needsSwapchainRecreate = true;
  8936. }
  8937. } else {
  8938. if (presentResult != VK_SUCCESS) {
  8939. VULKAN_INTERNAL_ReleaseCommandBuffer(vulkanCommandBuffer);
  8940. SDL_UnlockMutex(renderer->submitLock);
  8941. }
  8942. CHECK_VULKAN_ERROR_AND_RETURN(presentResult, vkQueuePresentKHR, false);
  8943. }
  8944. presentData->windowData->frameCounter =
  8945. (presentData->windowData->frameCounter + 1) % renderer->allowedFramesInFlight;
  8946. }
  8947. if (performCleanups) {
  8948. for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
  8949. vulkanResult = renderer->vkGetFenceStatus(
  8950. renderer->logicalDevice,
  8951. renderer->submittedCommandBuffers[i]->inFlightFence->fence);
  8952. if (vulkanResult == VK_SUCCESS) {
  8953. VULKAN_INTERNAL_CleanCommandBuffer(
  8954. renderer,
  8955. renderer->submittedCommandBuffers[i],
  8956. false);
  8957. }
  8958. }
  8959. if (renderer->checkEmptyAllocations) {
  8960. SDL_LockMutex(renderer->allocatorLock);
  8961. for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
  8962. allocator = &renderer->memoryAllocator->subAllocators[i];
  8963. for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
  8964. if (allocator->allocations[j]->usedRegionCount == 0) {
  8965. VULKAN_INTERNAL_DeallocateMemory(
  8966. renderer,
  8967. allocator,
  8968. j);
  8969. }
  8970. }
  8971. }
  8972. renderer->checkEmptyAllocations = false;
  8973. SDL_UnlockMutex(renderer->allocatorLock);
  8974. }
  8975. VULKAN_INTERNAL_PerformPendingDestroys(renderer);
  8976. }
  8977. // Mark command buffer as submitted
  8978. VULKAN_INTERNAL_ReleaseCommandBuffer(vulkanCommandBuffer);
  8979. SDL_UnlockMutex(renderer->submitLock);
  8980. return true;
  8981. }
  8982. static bool VULKAN_Cancel(
  8983. SDL_GPUCommandBuffer *commandBuffer)
  8984. {
  8985. VulkanRenderer *renderer;
  8986. VulkanCommandBuffer *vulkanCommandBuffer;
  8987. VkResult result;
  8988. vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
  8989. renderer = vulkanCommandBuffer->renderer;
  8990. result = renderer->vkResetCommandBuffer(
  8991. vulkanCommandBuffer->commandBuffer,
  8992. VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
  8993. CHECK_VULKAN_ERROR_AND_RETURN(result, vkResetCommandBuffer, false);
  8994. vulkanCommandBuffer->autoReleaseFence = false;
  8995. SDL_LockMutex(renderer->submitLock);
  8996. VULKAN_INTERNAL_CleanCommandBuffer(renderer, vulkanCommandBuffer, true);
  8997. SDL_UnlockMutex(renderer->submitLock);
  8998. return true;
  8999. }
  9000. static bool VULKAN_INTERNAL_DefragmentMemory(
  9001. VulkanRenderer *renderer,
  9002. VulkanCommandBuffer *commandBuffer)
  9003. {
  9004. renderer->defragInProgress = 1;
  9005. commandBuffer->isDefrag = 1;
  9006. SDL_LockMutex(renderer->allocatorLock);
  9007. VulkanMemoryAllocation *allocation = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
  9008. renderer->allocationsToDefragCount -= 1;
  9009. /* For each used region in the allocation
  9010. * create a new resource, copy the data
  9011. * and re-point the resource containers
  9012. */
  9013. for (Uint32 i = 0; i < allocation->usedRegionCount; i += 1) {
  9014. VulkanMemoryUsedRegion *currentRegion = allocation->usedRegions[i];
  9015. if (currentRegion->isBuffer && !currentRegion->vulkanBuffer->markedForDestroy) {
  9016. currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
  9017. VulkanBuffer *newBuffer = VULKAN_INTERNAL_CreateBuffer(
  9018. renderer,
  9019. currentRegion->vulkanBuffer->size,
  9020. currentRegion->vulkanBuffer->usage,
  9021. currentRegion->vulkanBuffer->type,
  9022. false,
  9023. currentRegion->vulkanBuffer->container != NULL ? currentRegion->vulkanBuffer->container->debugName : NULL);
  9024. if (newBuffer == NULL) {
  9025. SDL_UnlockMutex(renderer->allocatorLock);
  9026. SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to allocate defrag buffer!");
  9027. return false;
  9028. }
  9029. // Copy buffer contents if necessary
  9030. if (
  9031. currentRegion->vulkanBuffer->type == VULKAN_BUFFER_TYPE_GPU && currentRegion->vulkanBuffer->transitioned) {
  9032. VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
  9033. renderer,
  9034. commandBuffer,
  9035. VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
  9036. currentRegion->vulkanBuffer);
  9037. VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
  9038. renderer,
  9039. commandBuffer,
  9040. VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
  9041. newBuffer);
  9042. VkBufferCopy bufferCopy;
  9043. bufferCopy.srcOffset = 0;
  9044. bufferCopy.dstOffset = 0;
  9045. bufferCopy.size = currentRegion->resourceSize;
  9046. renderer->vkCmdCopyBuffer(
  9047. commandBuffer->commandBuffer,
  9048. currentRegion->vulkanBuffer->buffer,
  9049. newBuffer->buffer,
  9050. 1,
  9051. &bufferCopy);
  9052. VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
  9053. renderer,
  9054. commandBuffer,
  9055. VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
  9056. newBuffer);
  9057. VULKAN_INTERNAL_TrackBuffer(commandBuffer, currentRegion->vulkanBuffer);
  9058. VULKAN_INTERNAL_TrackBuffer(commandBuffer, newBuffer);
  9059. }
  9060. // re-point original container to new buffer
  9061. newBuffer->container = currentRegion->vulkanBuffer->container;
  9062. newBuffer->containerIndex = currentRegion->vulkanBuffer->containerIndex;
  9063. if (newBuffer->type == VULKAN_BUFFER_TYPE_UNIFORM) {
  9064. currentRegion->vulkanBuffer->uniformBufferForDefrag->buffer = newBuffer;
  9065. } else {
  9066. newBuffer->container->buffers[newBuffer->containerIndex] = newBuffer;
  9067. if (newBuffer->container->activeBuffer == currentRegion->vulkanBuffer) {
  9068. newBuffer->container->activeBuffer = newBuffer;
  9069. }
  9070. }
  9071. if (currentRegion->vulkanBuffer->uniformBufferForDefrag) {
  9072. newBuffer->uniformBufferForDefrag = currentRegion->vulkanBuffer->uniformBufferForDefrag;
  9073. }
  9074. VULKAN_INTERNAL_ReleaseBuffer(renderer, currentRegion->vulkanBuffer);
  9075. } else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) {
  9076. VulkanTexture *newTexture = VULKAN_INTERNAL_CreateTexture(
  9077. renderer,
  9078. false,
  9079. &currentRegion->vulkanTexture->container->header.info);
  9080. if (newTexture == NULL) {
  9081. SDL_UnlockMutex(renderer->allocatorLock);
  9082. SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s", "Failed to allocate defrag buffer!");
  9083. return false;
  9084. }
  9085. SDL_GPUTextureCreateInfo info = currentRegion->vulkanTexture->container->header.info;
  9086. for (Uint32 subresourceIndex = 0; subresourceIndex < currentRegion->vulkanTexture->subresourceCount; subresourceIndex += 1) {
  9087. // copy subresource if necessary
  9088. VulkanTextureSubresource *srcSubresource = &currentRegion->vulkanTexture->subresources[subresourceIndex];
  9089. VulkanTextureSubresource *dstSubresource = &newTexture->subresources[subresourceIndex];
  9090. VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
  9091. renderer,
  9092. commandBuffer,
  9093. VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
  9094. srcSubresource);
  9095. VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
  9096. renderer,
  9097. commandBuffer,
  9098. VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
  9099. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
  9100. dstSubresource);
  9101. VkImageCopy imageCopy;
  9102. imageCopy.srcOffset.x = 0;
  9103. imageCopy.srcOffset.y = 0;
  9104. imageCopy.srcOffset.z = 0;
  9105. imageCopy.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
  9106. imageCopy.srcSubresource.baseArrayLayer = srcSubresource->layer;
  9107. imageCopy.srcSubresource.layerCount = 1;
  9108. imageCopy.srcSubresource.mipLevel = srcSubresource->level;
  9109. imageCopy.extent.width = SDL_max(1, info.width >> srcSubresource->level);
  9110. imageCopy.extent.height = SDL_max(1, info.height >> srcSubresource->level);
  9111. imageCopy.extent.depth = info.type == SDL_GPU_TEXTURETYPE_3D ? info.layer_count_or_depth : 1;
  9112. imageCopy.dstOffset.x = 0;
  9113. imageCopy.dstOffset.y = 0;
  9114. imageCopy.dstOffset.z = 0;
  9115. imageCopy.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
  9116. imageCopy.dstSubresource.baseArrayLayer = dstSubresource->layer;
  9117. imageCopy.dstSubresource.layerCount = 1;
  9118. imageCopy.dstSubresource.mipLevel = dstSubresource->level;
  9119. renderer->vkCmdCopyImage(
  9120. commandBuffer->commandBuffer,
  9121. currentRegion->vulkanTexture->image,
  9122. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  9123. newTexture->image,
  9124. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  9125. 1,
  9126. &imageCopy);
  9127. VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
  9128. renderer,
  9129. commandBuffer,
  9130. VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
  9131. dstSubresource);
  9132. VULKAN_INTERNAL_TrackTexture(commandBuffer, srcSubresource->parent);
  9133. VULKAN_INTERNAL_TrackTexture(commandBuffer, dstSubresource->parent);
  9134. }
  9135. // re-point original container to new texture
  9136. newTexture->container = currentRegion->vulkanTexture->container;
  9137. newTexture->containerIndex = currentRegion->vulkanTexture->containerIndex;
  9138. newTexture->container->textures[currentRegion->vulkanTexture->containerIndex] = newTexture;
  9139. if (currentRegion->vulkanTexture == currentRegion->vulkanTexture->container->activeTexture) {
  9140. newTexture->container->activeTexture = newTexture;
  9141. }
  9142. VULKAN_INTERNAL_ReleaseTexture(renderer, currentRegion->vulkanTexture);
  9143. }
  9144. }
  9145. SDL_UnlockMutex(renderer->allocatorLock);
  9146. return true;
  9147. }
  9148. // Format Info
  9149. static bool VULKAN_SupportsTextureFormat(
  9150. SDL_GPURenderer *driverData,
  9151. SDL_GPUTextureFormat format,
  9152. SDL_GPUTextureType type,
  9153. SDL_GPUTextureUsageFlags usage)
  9154. {
  9155. VulkanRenderer *renderer = (VulkanRenderer *)driverData;
  9156. VkFormat vulkanFormat = SDLToVK_TextureFormat[format];
  9157. VkImageUsageFlags vulkanUsage = 0;
  9158. VkImageCreateFlags createFlags = 0;
  9159. VkImageFormatProperties properties;
  9160. VkResult vulkanResult;
  9161. if (usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) {
  9162. vulkanUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
  9163. }
  9164. if (usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
  9165. vulkanUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  9166. }
  9167. if (usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
  9168. vulkanUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
  9169. }
  9170. if (usage & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ |
  9171. SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ |
  9172. SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE |
  9173. SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) {
  9174. vulkanUsage |= VK_IMAGE_USAGE_STORAGE_BIT;
  9175. }
  9176. if (type == SDL_GPU_TEXTURETYPE_CUBE || type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
  9177. createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
  9178. }
  9179. vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties(
  9180. renderer->physicalDevice,
  9181. vulkanFormat,
  9182. (type == SDL_GPU_TEXTURETYPE_3D) ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D,
  9183. VK_IMAGE_TILING_OPTIMAL,
  9184. vulkanUsage,
  9185. createFlags,
  9186. &properties);
  9187. return vulkanResult == VK_SUCCESS;
  9188. }
  9189. // Device instantiation
  9190. static inline Uint8 CheckDeviceExtensions(
  9191. VkExtensionProperties *extensions,
  9192. Uint32 numExtensions,
  9193. VulkanExtensions *supports)
  9194. {
  9195. Uint32 i;
  9196. SDL_memset(supports, '\0', sizeof(VulkanExtensions));
  9197. for (i = 0; i < numExtensions; i += 1) {
  9198. const char *name = extensions[i].extensionName;
  9199. #define CHECK(ext) \
  9200. if (SDL_strcmp(name, "VK_" #ext) == 0) { \
  9201. supports->ext = 1; \
  9202. }
  9203. CHECK(KHR_swapchain)
  9204. else CHECK(KHR_maintenance1) else CHECK(KHR_driver_properties) else CHECK(KHR_portability_subset) else CHECK(EXT_texture_compression_astc_hdr)
  9205. #undef CHECK
  9206. }
  9207. return (supports->KHR_swapchain &&
  9208. supports->KHR_maintenance1);
  9209. }
  9210. static inline Uint32 GetDeviceExtensionCount(VulkanExtensions *supports)
  9211. {
  9212. return (
  9213. supports->KHR_swapchain +
  9214. supports->KHR_maintenance1 +
  9215. supports->KHR_driver_properties +
  9216. supports->KHR_portability_subset +
  9217. supports->EXT_texture_compression_astc_hdr);
  9218. }
  9219. static inline void CreateDeviceExtensionArray(
  9220. VulkanExtensions *supports,
  9221. const char **extensions)
  9222. {
  9223. Uint8 cur = 0;
  9224. #define CHECK(ext) \
  9225. if (supports->ext) { \
  9226. extensions[cur++] = "VK_" #ext; \
  9227. }
  9228. CHECK(KHR_swapchain)
  9229. CHECK(KHR_maintenance1)
  9230. CHECK(KHR_driver_properties)
  9231. CHECK(KHR_portability_subset)
  9232. CHECK(EXT_texture_compression_astc_hdr)
  9233. #undef CHECK
  9234. }
  9235. static inline Uint8 SupportsInstanceExtension(
  9236. const char *ext,
  9237. VkExtensionProperties *availableExtensions,
  9238. Uint32 numAvailableExtensions)
  9239. {
  9240. Uint32 i;
  9241. for (i = 0; i < numAvailableExtensions; i += 1) {
  9242. if (SDL_strcmp(ext, availableExtensions[i].extensionName) == 0) {
  9243. return 1;
  9244. }
  9245. }
  9246. return 0;
  9247. }
  9248. static Uint8 VULKAN_INTERNAL_CheckInstanceExtensions(
  9249. const char **requiredExtensions,
  9250. Uint32 requiredExtensionsLength,
  9251. bool *supportsDebugUtils,
  9252. bool *supportsColorspace,
  9253. bool *supportsPhysicalDeviceProperties2)
  9254. {
  9255. Uint32 extensionCount, i;
  9256. VkExtensionProperties *availableExtensions;
  9257. Uint8 allExtensionsSupported = 1;
  9258. vkEnumerateInstanceExtensionProperties(
  9259. NULL,
  9260. &extensionCount,
  9261. NULL);
  9262. availableExtensions = SDL_malloc(
  9263. extensionCount * sizeof(VkExtensionProperties));
  9264. vkEnumerateInstanceExtensionProperties(
  9265. NULL,
  9266. &extensionCount,
  9267. availableExtensions);
  9268. for (i = 0; i < requiredExtensionsLength; i += 1) {
  9269. if (!SupportsInstanceExtension(
  9270. requiredExtensions[i],
  9271. availableExtensions,
  9272. extensionCount)) {
  9273. allExtensionsSupported = 0;
  9274. break;
  9275. }
  9276. }
  9277. // This is optional, but nice to have!
  9278. *supportsDebugUtils = SupportsInstanceExtension(
  9279. VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
  9280. availableExtensions,
  9281. extensionCount);
  9282. // Also optional and nice to have!
  9283. *supportsColorspace = SupportsInstanceExtension(
  9284. VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
  9285. availableExtensions,
  9286. extensionCount);
  9287. // Only needed for KHR_driver_properties!
  9288. *supportsPhysicalDeviceProperties2 = SupportsInstanceExtension(
  9289. VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
  9290. availableExtensions,
  9291. extensionCount);
  9292. SDL_free(availableExtensions);
  9293. return allExtensionsSupported;
  9294. }
  9295. static Uint8 VULKAN_INTERNAL_CheckDeviceExtensions(
  9296. VulkanRenderer *renderer,
  9297. VkPhysicalDevice physicalDevice,
  9298. VulkanExtensions *physicalDeviceExtensions)
  9299. {
  9300. Uint32 extensionCount;
  9301. VkExtensionProperties *availableExtensions;
  9302. Uint8 allExtensionsSupported;
  9303. renderer->vkEnumerateDeviceExtensionProperties(
  9304. physicalDevice,
  9305. NULL,
  9306. &extensionCount,
  9307. NULL);
  9308. availableExtensions = (VkExtensionProperties *)SDL_malloc(
  9309. extensionCount * sizeof(VkExtensionProperties));
  9310. renderer->vkEnumerateDeviceExtensionProperties(
  9311. physicalDevice,
  9312. NULL,
  9313. &extensionCount,
  9314. availableExtensions);
  9315. allExtensionsSupported = CheckDeviceExtensions(
  9316. availableExtensions,
  9317. extensionCount,
  9318. physicalDeviceExtensions);
  9319. SDL_free(availableExtensions);
  9320. return allExtensionsSupported;
  9321. }
  9322. static Uint8 VULKAN_INTERNAL_CheckValidationLayers(
  9323. const char **validationLayers,
  9324. Uint32 validationLayersLength)
  9325. {
  9326. Uint32 layerCount;
  9327. VkLayerProperties *availableLayers;
  9328. Uint32 i, j;
  9329. Uint8 layerFound = 0;
  9330. vkEnumerateInstanceLayerProperties(&layerCount, NULL);
  9331. availableLayers = (VkLayerProperties *)SDL_malloc(
  9332. layerCount * sizeof(VkLayerProperties));
  9333. vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
  9334. for (i = 0; i < validationLayersLength; i += 1) {
  9335. layerFound = 0;
  9336. for (j = 0; j < layerCount; j += 1) {
  9337. if (SDL_strcmp(validationLayers[i], availableLayers[j].layerName) == 0) {
  9338. layerFound = 1;
  9339. break;
  9340. }
  9341. }
  9342. if (!layerFound) {
  9343. break;
  9344. }
  9345. }
  9346. SDL_free(availableLayers);
  9347. return layerFound;
  9348. }
  9349. static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer)
  9350. {
  9351. VkResult vulkanResult;
  9352. VkApplicationInfo appInfo;
  9353. VkInstanceCreateFlags createFlags;
  9354. const char *const *originalInstanceExtensionNames;
  9355. const char **instanceExtensionNames;
  9356. Uint32 instanceExtensionCount;
  9357. VkInstanceCreateInfo createInfo;
  9358. static const char *layerNames[] = { "VK_LAYER_KHRONOS_validation" };
  9359. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  9360. appInfo.pNext = NULL;
  9361. appInfo.pApplicationName = NULL;
  9362. appInfo.applicationVersion = 0;
  9363. appInfo.pEngineName = "SDLGPU";
  9364. appInfo.engineVersion = SDL_VERSION;
  9365. appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0);
  9366. createFlags = 0;
  9367. originalInstanceExtensionNames = SDL_Vulkan_GetInstanceExtensions(&instanceExtensionCount);
  9368. if (!originalInstanceExtensionNames) {
  9369. SDL_LogError(
  9370. SDL_LOG_CATEGORY_GPU,
  9371. "SDL_Vulkan_GetInstanceExtensions(): getExtensionCount: %s",
  9372. SDL_GetError());
  9373. return 0;
  9374. }
  9375. /* Extra space for the following extensions:
  9376. * VK_KHR_get_physical_device_properties2
  9377. * VK_EXT_swapchain_colorspace
  9378. * VK_EXT_debug_utils
  9379. * VK_KHR_portability_enumeration
  9380. */
  9381. instanceExtensionNames = SDL_stack_alloc(
  9382. const char *,
  9383. instanceExtensionCount + 4);
  9384. SDL_memcpy((void *)instanceExtensionNames, originalInstanceExtensionNames, instanceExtensionCount * sizeof(const char *));
  9385. #ifdef SDL_PLATFORM_APPLE
  9386. instanceExtensionNames[instanceExtensionCount++] =
  9387. VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME;
  9388. createFlags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
  9389. #endif
  9390. if (!VULKAN_INTERNAL_CheckInstanceExtensions(
  9391. instanceExtensionNames,
  9392. instanceExtensionCount,
  9393. &renderer->supportsDebugUtils,
  9394. &renderer->supportsColorspace,
  9395. &renderer->supportsPhysicalDeviceProperties2)) {
  9396. SDL_stack_free((char *)instanceExtensionNames);
  9397. SET_STRING_ERROR_AND_RETURN("Required Vulkan instance extensions not supported", false);
  9398. }
  9399. if (renderer->supportsDebugUtils) {
  9400. // Append the debug extension
  9401. instanceExtensionNames[instanceExtensionCount++] =
  9402. VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
  9403. } else {
  9404. SDL_LogWarn(
  9405. SDL_LOG_CATEGORY_GPU,
  9406. "%s is not supported!",
  9407. VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
  9408. }
  9409. if (renderer->supportsColorspace) {
  9410. // Append colorspace extension
  9411. instanceExtensionNames[instanceExtensionCount++] =
  9412. VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME;
  9413. }
  9414. if (renderer->supportsPhysicalDeviceProperties2) {
  9415. // Append KHR_physical_device_properties2 extension
  9416. instanceExtensionNames[instanceExtensionCount++] =
  9417. VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
  9418. }
  9419. createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  9420. createInfo.pNext = NULL;
  9421. createInfo.flags = createFlags;
  9422. createInfo.pApplicationInfo = &appInfo;
  9423. createInfo.ppEnabledLayerNames = layerNames;
  9424. createInfo.enabledExtensionCount = instanceExtensionCount;
  9425. createInfo.ppEnabledExtensionNames = instanceExtensionNames;
  9426. if (renderer->debugMode) {
  9427. createInfo.enabledLayerCount = SDL_arraysize(layerNames);
  9428. if (!VULKAN_INTERNAL_CheckValidationLayers(
  9429. layerNames,
  9430. createInfo.enabledLayerCount)) {
  9431. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Validation layers not found, continuing without validation");
  9432. createInfo.enabledLayerCount = 0;
  9433. } else {
  9434. SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Validation layers enabled, expect debug level performance!");
  9435. }
  9436. } else {
  9437. createInfo.enabledLayerCount = 0;
  9438. }
  9439. vulkanResult = vkCreateInstance(&createInfo, NULL, &renderer->instance);
  9440. SDL_stack_free((char *)instanceExtensionNames);
  9441. if (vulkanResult != VK_SUCCESS) {
  9442. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateInstance, 0);
  9443. }
  9444. return 1;
  9445. }
  9446. static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
  9447. VulkanRenderer *renderer,
  9448. VkPhysicalDevice physicalDevice,
  9449. VulkanExtensions *physicalDeviceExtensions,
  9450. Uint32 *queueFamilyIndex,
  9451. Uint8 *deviceRank)
  9452. {
  9453. Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
  9454. VkQueueFamilyProperties *queueProps;
  9455. bool supportsPresent;
  9456. VkPhysicalDeviceProperties deviceProperties;
  9457. VkPhysicalDeviceFeatures deviceFeatures;
  9458. Uint32 i;
  9459. const Uint8 *devicePriority = renderer->preferLowPower ? DEVICE_PRIORITY_LOWPOWER : DEVICE_PRIORITY_HIGHPERFORMANCE;
  9460. /* Get the device rank before doing any checks, in case one fails.
  9461. * Note: If no dedicated device exists, one that supports our features
  9462. * would be fine
  9463. */
  9464. renderer->vkGetPhysicalDeviceProperties(
  9465. physicalDevice,
  9466. &deviceProperties);
  9467. if (*deviceRank < devicePriority[deviceProperties.deviceType]) {
  9468. /* This device outranks the best device we've found so far!
  9469. * This includes a dedicated GPU that has less features than an
  9470. * integrated GPU, because this is a freak case that is almost
  9471. * never intentionally desired by the end user
  9472. */
  9473. *deviceRank = devicePriority[deviceProperties.deviceType];
  9474. } else if (*deviceRank > devicePriority[deviceProperties.deviceType]) {
  9475. /* Device is outranked by a previous device, don't even try to
  9476. * run a query and reset the rank to avoid overwrites
  9477. */
  9478. *deviceRank = 0;
  9479. return 0;
  9480. }
  9481. renderer->vkGetPhysicalDeviceFeatures(
  9482. physicalDevice,
  9483. &deviceFeatures);
  9484. if (!deviceFeatures.independentBlend ||
  9485. !deviceFeatures.imageCubeArray ||
  9486. !deviceFeatures.depthClamp ||
  9487. !deviceFeatures.shaderClipDistance ||
  9488. !deviceFeatures.drawIndirectFirstInstance) {
  9489. return 0;
  9490. }
  9491. if (!VULKAN_INTERNAL_CheckDeviceExtensions(
  9492. renderer,
  9493. physicalDevice,
  9494. physicalDeviceExtensions)) {
  9495. return 0;
  9496. }
  9497. renderer->vkGetPhysicalDeviceQueueFamilyProperties(
  9498. physicalDevice,
  9499. &queueFamilyCount,
  9500. NULL);
  9501. queueProps = SDL_stack_alloc(
  9502. VkQueueFamilyProperties,
  9503. queueFamilyCount);
  9504. renderer->vkGetPhysicalDeviceQueueFamilyProperties(
  9505. physicalDevice,
  9506. &queueFamilyCount,
  9507. queueProps);
  9508. queueFamilyBest = 0;
  9509. *queueFamilyIndex = SDL_MAX_UINT32;
  9510. for (i = 0; i < queueFamilyCount; i += 1) {
  9511. supportsPresent = SDL_Vulkan_GetPresentationSupport(
  9512. renderer->instance,
  9513. physicalDevice,
  9514. i);
  9515. if (!supportsPresent ||
  9516. !(queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) {
  9517. // Not a graphics family, ignore.
  9518. continue;
  9519. }
  9520. /* The queue family bitflags are kind of annoying.
  9521. *
  9522. * We of course need a graphics family, but we ideally want the
  9523. * _primary_ graphics family. The spec states that at least one
  9524. * graphics family must also be a compute family, so generally
  9525. * drivers make that the first one. But hey, maybe something
  9526. * genuinely can't do compute or something, and FNA doesn't
  9527. * need it, so we'll be open to a non-compute queue family.
  9528. *
  9529. * Additionally, it's common to see the primary queue family
  9530. * have the transfer bit set, which is great! But this is
  9531. * actually optional; it's impossible to NOT have transfers in
  9532. * graphics/compute but it _is_ possible for a graphics/compute
  9533. * family, even the primary one, to just decide not to set the
  9534. * bitflag. Admittedly, a driver may want to isolate transfer
  9535. * queues to a dedicated family so that queues made solely for
  9536. * transfers can have an optimized DMA queue.
  9537. *
  9538. * That, or the driver author got lazy and decided not to set
  9539. * the bit. Looking at you, Android.
  9540. *
  9541. * -flibit
  9542. */
  9543. if (queueProps[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
  9544. if (queueProps[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
  9545. // Has all attribs!
  9546. queueFamilyRank = 3;
  9547. } else {
  9548. // Probably has a DMA transfer queue family
  9549. queueFamilyRank = 2;
  9550. }
  9551. } else {
  9552. // Just a graphics family, probably has something better
  9553. queueFamilyRank = 1;
  9554. }
  9555. if (queueFamilyRank > queueFamilyBest) {
  9556. *queueFamilyIndex = i;
  9557. queueFamilyBest = queueFamilyRank;
  9558. }
  9559. }
  9560. SDL_stack_free(queueProps);
  9561. if (*queueFamilyIndex == SDL_MAX_UINT32) {
  9562. // Somehow no graphics queues existed. Compute-only device?
  9563. return 0;
  9564. }
  9565. // FIXME: Need better structure for checking vs storing swapchain support details
  9566. return 1;
  9567. }
  9568. static Uint8 VULKAN_INTERNAL_DeterminePhysicalDevice(VulkanRenderer *renderer)
  9569. {
  9570. VkResult vulkanResult;
  9571. VkPhysicalDevice *physicalDevices;
  9572. VulkanExtensions *physicalDeviceExtensions;
  9573. Uint32 i, physicalDeviceCount;
  9574. Sint32 suitableIndex;
  9575. Uint32 queueFamilyIndex, suitableQueueFamilyIndex;
  9576. Uint8 deviceRank, highestRank;
  9577. vulkanResult = renderer->vkEnumeratePhysicalDevices(
  9578. renderer->instance,
  9579. &physicalDeviceCount,
  9580. NULL);
  9581. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkEnumeratePhysicalDevices, 0);
  9582. if (physicalDeviceCount == 0) {
  9583. SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Failed to find any GPUs with Vulkan support");
  9584. return 0;
  9585. }
  9586. physicalDevices = SDL_stack_alloc(VkPhysicalDevice, physicalDeviceCount);
  9587. physicalDeviceExtensions = SDL_stack_alloc(VulkanExtensions, physicalDeviceCount);
  9588. vulkanResult = renderer->vkEnumeratePhysicalDevices(
  9589. renderer->instance,
  9590. &physicalDeviceCount,
  9591. physicalDevices);
  9592. /* This should be impossible to hit, but from what I can tell this can
  9593. * be triggered not because the array is too small, but because there
  9594. * were drivers that turned out to be bogus, so this is the loader's way
  9595. * of telling us that the list is now smaller than expected :shrug:
  9596. */
  9597. if (vulkanResult == VK_INCOMPLETE) {
  9598. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "vkEnumeratePhysicalDevices returned VK_INCOMPLETE, will keep trying anyway...");
  9599. vulkanResult = VK_SUCCESS;
  9600. }
  9601. if (vulkanResult != VK_SUCCESS) {
  9602. SDL_LogWarn(
  9603. SDL_LOG_CATEGORY_GPU,
  9604. "vkEnumeratePhysicalDevices failed: %s",
  9605. VkErrorMessages(vulkanResult));
  9606. SDL_stack_free(physicalDevices);
  9607. SDL_stack_free(physicalDeviceExtensions);
  9608. return 0;
  9609. }
  9610. // Any suitable device will do, but we'd like the best
  9611. suitableIndex = -1;
  9612. suitableQueueFamilyIndex = 0;
  9613. highestRank = 0;
  9614. for (i = 0; i < physicalDeviceCount; i += 1) {
  9615. deviceRank = highestRank;
  9616. if (VULKAN_INTERNAL_IsDeviceSuitable(
  9617. renderer,
  9618. physicalDevices[i],
  9619. &physicalDeviceExtensions[i],
  9620. &queueFamilyIndex,
  9621. &deviceRank)) {
  9622. /* Use this for rendering.
  9623. * Note that this may override a previous device that
  9624. * supports rendering, but shares the same device rank.
  9625. */
  9626. suitableIndex = i;
  9627. suitableQueueFamilyIndex = queueFamilyIndex;
  9628. highestRank = deviceRank;
  9629. } else if (deviceRank > highestRank) {
  9630. /* In this case, we found a... "realer?" GPU,
  9631. * but it doesn't actually support our Vulkan.
  9632. * We should disqualify all devices below as a
  9633. * result, because if we don't we end up
  9634. * ignoring real hardware and risk using
  9635. * something like LLVMpipe instead!
  9636. * -flibit
  9637. */
  9638. suitableIndex = -1;
  9639. highestRank = deviceRank;
  9640. }
  9641. }
  9642. if (suitableIndex != -1) {
  9643. renderer->supports = physicalDeviceExtensions[suitableIndex];
  9644. renderer->physicalDevice = physicalDevices[suitableIndex];
  9645. renderer->queueFamilyIndex = suitableQueueFamilyIndex;
  9646. } else {
  9647. SDL_stack_free(physicalDevices);
  9648. SDL_stack_free(physicalDeviceExtensions);
  9649. return 0;
  9650. }
  9651. renderer->physicalDeviceProperties.sType =
  9652. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
  9653. if (renderer->supports.KHR_driver_properties) {
  9654. renderer->physicalDeviceDriverProperties.sType =
  9655. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
  9656. renderer->physicalDeviceDriverProperties.pNext = NULL;
  9657. renderer->physicalDeviceProperties.pNext =
  9658. &renderer->physicalDeviceDriverProperties;
  9659. renderer->vkGetPhysicalDeviceProperties2KHR(
  9660. renderer->physicalDevice,
  9661. &renderer->physicalDeviceProperties);
  9662. } else {
  9663. renderer->physicalDeviceProperties.pNext = NULL;
  9664. renderer->vkGetPhysicalDeviceProperties(
  9665. renderer->physicalDevice,
  9666. &renderer->physicalDeviceProperties.properties);
  9667. }
  9668. renderer->vkGetPhysicalDeviceMemoryProperties(
  9669. renderer->physicalDevice,
  9670. &renderer->memoryProperties);
  9671. SDL_stack_free(physicalDevices);
  9672. SDL_stack_free(physicalDeviceExtensions);
  9673. return 1;
  9674. }
  9675. static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
  9676. VulkanRenderer *renderer)
  9677. {
  9678. VkResult vulkanResult;
  9679. VkDeviceCreateInfo deviceCreateInfo;
  9680. VkPhysicalDeviceFeatures desiredDeviceFeatures;
  9681. VkPhysicalDeviceFeatures haveDeviceFeatures;
  9682. VkPhysicalDevicePortabilitySubsetFeaturesKHR portabilityFeatures;
  9683. const char **deviceExtensions;
  9684. VkDeviceQueueCreateInfo queueCreateInfo;
  9685. float queuePriority = 1.0f;
  9686. queueCreateInfo.sType =
  9687. VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  9688. queueCreateInfo.pNext = NULL;
  9689. queueCreateInfo.flags = 0;
  9690. queueCreateInfo.queueFamilyIndex = renderer->queueFamilyIndex;
  9691. queueCreateInfo.queueCount = 1;
  9692. queueCreateInfo.pQueuePriorities = &queuePriority;
  9693. // check feature support
  9694. renderer->vkGetPhysicalDeviceFeatures(
  9695. renderer->physicalDevice,
  9696. &haveDeviceFeatures);
  9697. // specifying used device features
  9698. SDL_zero(desiredDeviceFeatures);
  9699. desiredDeviceFeatures.independentBlend = VK_TRUE;
  9700. desiredDeviceFeatures.samplerAnisotropy = VK_TRUE;
  9701. desiredDeviceFeatures.imageCubeArray = VK_TRUE;
  9702. desiredDeviceFeatures.depthClamp = VK_TRUE;
  9703. desiredDeviceFeatures.shaderClipDistance = VK_TRUE;
  9704. desiredDeviceFeatures.drawIndirectFirstInstance = VK_TRUE;
  9705. if (haveDeviceFeatures.fillModeNonSolid) {
  9706. desiredDeviceFeatures.fillModeNonSolid = VK_TRUE;
  9707. renderer->supportsFillModeNonSolid = true;
  9708. }
  9709. if (haveDeviceFeatures.multiDrawIndirect) {
  9710. desiredDeviceFeatures.multiDrawIndirect = VK_TRUE;
  9711. renderer->supportsMultiDrawIndirect = true;
  9712. }
  9713. // creating the logical device
  9714. deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  9715. if (renderer->supports.KHR_portability_subset) {
  9716. portabilityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR;
  9717. portabilityFeatures.pNext = NULL;
  9718. portabilityFeatures.constantAlphaColorBlendFactors = VK_FALSE;
  9719. portabilityFeatures.events = VK_FALSE;
  9720. portabilityFeatures.imageViewFormatReinterpretation = VK_FALSE;
  9721. portabilityFeatures.imageViewFormatSwizzle = VK_TRUE;
  9722. portabilityFeatures.imageView2DOn3DImage = VK_FALSE;
  9723. portabilityFeatures.multisampleArrayImage = VK_FALSE;
  9724. portabilityFeatures.mutableComparisonSamplers = VK_FALSE;
  9725. portabilityFeatures.pointPolygons = VK_FALSE;
  9726. portabilityFeatures.samplerMipLodBias = VK_FALSE; // Technically should be true, but eh
  9727. portabilityFeatures.separateStencilMaskRef = VK_FALSE;
  9728. portabilityFeatures.shaderSampleRateInterpolationFunctions = VK_FALSE;
  9729. portabilityFeatures.tessellationIsolines = VK_FALSE;
  9730. portabilityFeatures.tessellationPointMode = VK_FALSE;
  9731. portabilityFeatures.triangleFans = VK_FALSE;
  9732. portabilityFeatures.vertexAttributeAccessBeyondStride = VK_FALSE;
  9733. deviceCreateInfo.pNext = &portabilityFeatures;
  9734. } else {
  9735. deviceCreateInfo.pNext = NULL;
  9736. }
  9737. deviceCreateInfo.flags = 0;
  9738. deviceCreateInfo.queueCreateInfoCount = 1;
  9739. deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
  9740. deviceCreateInfo.enabledLayerCount = 0;
  9741. deviceCreateInfo.ppEnabledLayerNames = NULL;
  9742. deviceCreateInfo.enabledExtensionCount = GetDeviceExtensionCount(
  9743. &renderer->supports);
  9744. deviceExtensions = SDL_stack_alloc(
  9745. const char *,
  9746. deviceCreateInfo.enabledExtensionCount);
  9747. CreateDeviceExtensionArray(&renderer->supports, deviceExtensions);
  9748. deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions;
  9749. deviceCreateInfo.pEnabledFeatures = &desiredDeviceFeatures;
  9750. vulkanResult = renderer->vkCreateDevice(
  9751. renderer->physicalDevice,
  9752. &deviceCreateInfo,
  9753. NULL,
  9754. &renderer->logicalDevice);
  9755. SDL_stack_free((void *)deviceExtensions);
  9756. CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDevice, 0);
  9757. // Load vkDevice entry points
  9758. #define VULKAN_DEVICE_FUNCTION(func) \
  9759. renderer->func = (PFN_##func) \
  9760. renderer->vkGetDeviceProcAddr( \
  9761. renderer->logicalDevice, \
  9762. #func);
  9763. #include "SDL_gpu_vulkan_vkfuncs.h"
  9764. renderer->vkGetDeviceQueue(
  9765. renderer->logicalDevice,
  9766. renderer->queueFamilyIndex,
  9767. 0,
  9768. &renderer->unifiedQueue);
  9769. return 1;
  9770. }
  9771. static void VULKAN_INTERNAL_LoadEntryPoints(void)
  9772. {
  9773. // Required for MoltenVK support
  9774. SDL_setenv_unsafe("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
  9775. // Load Vulkan entry points
  9776. if (!SDL_Vulkan_LoadLibrary(NULL)) {
  9777. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Vulkan: SDL_Vulkan_LoadLibrary failed!");
  9778. return;
  9779. }
  9780. #ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
  9781. #pragma GCC diagnostic push
  9782. #pragma GCC diagnostic ignored "-Wpedantic"
  9783. #endif
  9784. vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr();
  9785. #ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
  9786. #pragma GCC diagnostic pop
  9787. #endif
  9788. if (vkGetInstanceProcAddr == NULL) {
  9789. SDL_LogWarn(
  9790. SDL_LOG_CATEGORY_GPU,
  9791. "SDL_Vulkan_GetVkGetInstanceProcAddr(): %s",
  9792. SDL_GetError());
  9793. return;
  9794. }
  9795. #define VULKAN_GLOBAL_FUNCTION(name) \
  9796. name = (PFN_##name)vkGetInstanceProcAddr(VK_NULL_HANDLE, #name); \
  9797. if (name == NULL) { \
  9798. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "vkGetInstanceProcAddr(VK_NULL_HANDLE, \"" #name "\") failed"); \
  9799. return; \
  9800. }
  9801. #include "SDL_gpu_vulkan_vkfuncs.h"
  9802. }
  9803. static bool VULKAN_INTERNAL_PrepareVulkan(
  9804. VulkanRenderer *renderer)
  9805. {
  9806. VULKAN_INTERNAL_LoadEntryPoints();
  9807. if (!VULKAN_INTERNAL_CreateInstance(renderer)) {
  9808. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Vulkan: Could not create Vulkan instance");
  9809. return false;
  9810. }
  9811. #define VULKAN_INSTANCE_FUNCTION(func) \
  9812. renderer->func = (PFN_##func)vkGetInstanceProcAddr(renderer->instance, #func);
  9813. #include "SDL_gpu_vulkan_vkfuncs.h"
  9814. if (!VULKAN_INTERNAL_DeterminePhysicalDevice(renderer)) {
  9815. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Vulkan: Failed to determine a suitable physical device");
  9816. return false;
  9817. }
  9818. return true;
  9819. }
  9820. static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
  9821. {
  9822. // Set up dummy VulkanRenderer
  9823. VulkanRenderer *renderer;
  9824. bool result = false;
  9825. if (_this->Vulkan_CreateSurface == NULL) {
  9826. return false;
  9827. }
  9828. if (!SDL_Vulkan_LoadLibrary(NULL)) {
  9829. return false;
  9830. }
  9831. renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
  9832. if (renderer) {
  9833. result = VULKAN_INTERNAL_PrepareVulkan(renderer);
  9834. if (result) {
  9835. renderer->vkDestroyInstance(renderer->instance, NULL);
  9836. }
  9837. SDL_free(renderer);
  9838. }
  9839. SDL_Vulkan_UnloadLibrary();
  9840. return result;
  9841. }
  9842. static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, SDL_PropertiesID props)
  9843. {
  9844. VulkanRenderer *renderer;
  9845. SDL_GPUDevice *result;
  9846. Uint32 i;
  9847. if (!SDL_Vulkan_LoadLibrary(NULL)) {
  9848. SDL_assert(!"This should have failed in PrepareDevice first!");
  9849. return NULL;
  9850. }
  9851. renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
  9852. if (!renderer) {
  9853. SDL_Vulkan_UnloadLibrary();
  9854. return NULL;
  9855. }
  9856. renderer->debugMode = debugMode;
  9857. renderer->preferLowPower = preferLowPower;
  9858. renderer->allowedFramesInFlight = 2;
  9859. if (!VULKAN_INTERNAL_PrepareVulkan(renderer)) {
  9860. SET_STRING_ERROR("Failed to initialize Vulkan!");
  9861. SDL_free(renderer);
  9862. SDL_Vulkan_UnloadLibrary();
  9863. return NULL;
  9864. }
  9865. SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Vulkan");
  9866. SDL_LogInfo(
  9867. SDL_LOG_CATEGORY_GPU,
  9868. "Vulkan Device: %s",
  9869. renderer->physicalDeviceProperties.properties.deviceName);
  9870. if (renderer->supports.KHR_driver_properties) {
  9871. SDL_LogInfo(
  9872. SDL_LOG_CATEGORY_GPU,
  9873. "Vulkan Driver: %s %s",
  9874. renderer->physicalDeviceDriverProperties.driverName,
  9875. renderer->physicalDeviceDriverProperties.driverInfo);
  9876. SDL_LogInfo(
  9877. SDL_LOG_CATEGORY_GPU,
  9878. "Vulkan Conformance: %u.%u.%u",
  9879. renderer->physicalDeviceDriverProperties.conformanceVersion.major,
  9880. renderer->physicalDeviceDriverProperties.conformanceVersion.minor,
  9881. renderer->physicalDeviceDriverProperties.conformanceVersion.patch);
  9882. } else {
  9883. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "KHR_driver_properties unsupported! Bother your vendor about this!");
  9884. }
  9885. if (!VULKAN_INTERNAL_CreateLogicalDevice(
  9886. renderer)) {
  9887. SET_STRING_ERROR("Failed to create logical device!");
  9888. SDL_free(renderer);
  9889. SDL_Vulkan_UnloadLibrary();
  9890. return NULL;
  9891. }
  9892. // FIXME: just move this into this function
  9893. result = (SDL_GPUDevice *)SDL_calloc(1, sizeof(SDL_GPUDevice));
  9894. ASSIGN_DRIVER(VULKAN)
  9895. result->driverData = (SDL_GPURenderer *)renderer;
  9896. result->shader_formats = SDL_GPU_SHADERFORMAT_SPIRV;
  9897. /*
  9898. * Create initial swapchain array
  9899. */
  9900. renderer->claimedWindowCapacity = 1;
  9901. renderer->claimedWindowCount = 0;
  9902. renderer->claimedWindows = SDL_malloc(
  9903. renderer->claimedWindowCapacity * sizeof(WindowData *));
  9904. // Threading
  9905. renderer->allocatorLock = SDL_CreateMutex();
  9906. renderer->disposeLock = SDL_CreateMutex();
  9907. renderer->submitLock = SDL_CreateMutex();
  9908. renderer->acquireCommandBufferLock = SDL_CreateMutex();
  9909. renderer->acquireUniformBufferLock = SDL_CreateMutex();
  9910. renderer->renderPassFetchLock = SDL_CreateMutex();
  9911. renderer->framebufferFetchLock = SDL_CreateMutex();
  9912. renderer->graphicsPipelineLayoutFetchLock = SDL_CreateMutex();
  9913. renderer->computePipelineLayoutFetchLock = SDL_CreateMutex();
  9914. renderer->descriptorSetLayoutFetchLock = SDL_CreateMutex();
  9915. renderer->windowLock = SDL_CreateMutex();
  9916. /*
  9917. * Create submitted command buffer list
  9918. */
  9919. renderer->submittedCommandBufferCapacity = 16;
  9920. renderer->submittedCommandBufferCount = 0;
  9921. renderer->submittedCommandBuffers = SDL_malloc(sizeof(VulkanCommandBuffer *) * renderer->submittedCommandBufferCapacity);
  9922. // Memory Allocator
  9923. renderer->memoryAllocator = (VulkanMemoryAllocator *)SDL_malloc(
  9924. sizeof(VulkanMemoryAllocator));
  9925. for (i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
  9926. renderer->memoryAllocator->subAllocators[i].memoryTypeIndex = i;
  9927. renderer->memoryAllocator->subAllocators[i].allocations = NULL;
  9928. renderer->memoryAllocator->subAllocators[i].allocationCount = 0;
  9929. renderer->memoryAllocator->subAllocators[i].sortedFreeRegions = SDL_malloc(
  9930. sizeof(VulkanMemoryFreeRegion *) * 4);
  9931. renderer->memoryAllocator->subAllocators[i].sortedFreeRegionCount = 0;
  9932. renderer->memoryAllocator->subAllocators[i].sortedFreeRegionCapacity = 4;
  9933. }
  9934. // Create uniform buffer pool
  9935. renderer->uniformBufferPoolCount = 32;
  9936. renderer->uniformBufferPoolCapacity = 32;
  9937. renderer->uniformBufferPool = SDL_malloc(
  9938. renderer->uniformBufferPoolCapacity * sizeof(VulkanUniformBuffer *));
  9939. for (i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
  9940. renderer->uniformBufferPool[i] = VULKAN_INTERNAL_CreateUniformBuffer(
  9941. renderer,
  9942. UNIFORM_BUFFER_SIZE);
  9943. }
  9944. renderer->descriptorSetCachePoolCapacity = 8;
  9945. renderer->descriptorSetCachePoolCount = 0;
  9946. renderer->descriptorSetCachePool = SDL_calloc(renderer->descriptorSetCachePoolCapacity, sizeof(DescriptorSetCache *));
  9947. SDL_SetAtomicInt(&renderer->layoutResourceID, 0);
  9948. // Device limits
  9949. renderer->minUBOAlignment = (Uint32)renderer->physicalDeviceProperties.properties.limits.minUniformBufferOffsetAlignment;
  9950. // Initialize caches
  9951. renderer->commandPoolHashTable = SDL_CreateHashTable(
  9952. 0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
  9953. false, // manually synchronized due to submission timing
  9954. VULKAN_INTERNAL_CommandPoolHashFunction,
  9955. VULKAN_INTERNAL_CommandPoolHashKeyMatch,
  9956. VULKAN_INTERNAL_CommandPoolHashDestroy,
  9957. (void *)renderer);
  9958. renderer->renderPassHashTable = SDL_CreateHashTable(
  9959. 0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
  9960. false, // manually synchronized due to lookup timing
  9961. VULKAN_INTERNAL_RenderPassHashFunction,
  9962. VULKAN_INTERNAL_RenderPassHashKeyMatch,
  9963. VULKAN_INTERNAL_RenderPassHashDestroy,
  9964. (void *)renderer);
  9965. renderer->framebufferHashTable = SDL_CreateHashTable(
  9966. 0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
  9967. false, // manually synchronized due to iteration
  9968. VULKAN_INTERNAL_FramebufferHashFunction,
  9969. VULKAN_INTERNAL_FramebufferHashKeyMatch,
  9970. VULKAN_INTERNAL_FramebufferHashDestroy,
  9971. (void *)renderer);
  9972. renderer->graphicsPipelineResourceLayoutHashTable = SDL_CreateHashTable(
  9973. 0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
  9974. false, // manually synchronized due to lookup timing
  9975. VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashFunction,
  9976. VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashKeyMatch,
  9977. VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashDestroy,
  9978. (void *)renderer);
  9979. renderer->computePipelineResourceLayoutHashTable = SDL_CreateHashTable(
  9980. 0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
  9981. false, // manually synchronized due to lookup timing
  9982. VULKAN_INTERNAL_ComputePipelineResourceLayoutHashFunction,
  9983. VULKAN_INTERNAL_ComputePipelineResourceLayoutHashKeyMatch,
  9984. VULKAN_INTERNAL_ComputePipelineResourceLayoutHashDestroy,
  9985. (void *)renderer);
  9986. renderer->descriptorSetLayoutHashTable = SDL_CreateHashTable(
  9987. 0, // !!! FIXME: a real guess here, for a _minimum_ if not a maximum, could be useful.
  9988. false, // manually synchronized due to lookup timing
  9989. VULKAN_INTERNAL_DescriptorSetLayoutHashFunction,
  9990. VULKAN_INTERNAL_DescriptorSetLayoutHashKeyMatch,
  9991. VULKAN_INTERNAL_DescriptorSetLayoutHashDestroy,
  9992. (void *)renderer);
  9993. // Initialize fence pool
  9994. renderer->fencePool.lock = SDL_CreateMutex();
  9995. renderer->fencePool.availableFenceCapacity = 4;
  9996. renderer->fencePool.availableFenceCount = 0;
  9997. renderer->fencePool.availableFences = SDL_malloc(
  9998. renderer->fencePool.availableFenceCapacity * sizeof(VulkanFenceHandle *));
  9999. // Deferred destroy storage
  10000. renderer->texturesToDestroyCapacity = 16;
  10001. renderer->texturesToDestroyCount = 0;
  10002. renderer->texturesToDestroy = (VulkanTexture **)SDL_malloc(
  10003. sizeof(VulkanTexture *) *
  10004. renderer->texturesToDestroyCapacity);
  10005. renderer->buffersToDestroyCapacity = 16;
  10006. renderer->buffersToDestroyCount = 0;
  10007. renderer->buffersToDestroy = SDL_malloc(
  10008. sizeof(VulkanBuffer *) *
  10009. renderer->buffersToDestroyCapacity);
  10010. renderer->samplersToDestroyCapacity = 16;
  10011. renderer->samplersToDestroyCount = 0;
  10012. renderer->samplersToDestroy = SDL_malloc(
  10013. sizeof(VulkanSampler *) *
  10014. renderer->samplersToDestroyCapacity);
  10015. renderer->graphicsPipelinesToDestroyCapacity = 16;
  10016. renderer->graphicsPipelinesToDestroyCount = 0;
  10017. renderer->graphicsPipelinesToDestroy = SDL_malloc(
  10018. sizeof(VulkanGraphicsPipeline *) *
  10019. renderer->graphicsPipelinesToDestroyCapacity);
  10020. renderer->computePipelinesToDestroyCapacity = 16;
  10021. renderer->computePipelinesToDestroyCount = 0;
  10022. renderer->computePipelinesToDestroy = SDL_malloc(
  10023. sizeof(VulkanComputePipeline *) *
  10024. renderer->computePipelinesToDestroyCapacity);
  10025. renderer->shadersToDestroyCapacity = 16;
  10026. renderer->shadersToDestroyCount = 0;
  10027. renderer->shadersToDestroy = SDL_malloc(
  10028. sizeof(VulkanShader *) *
  10029. renderer->shadersToDestroyCapacity);
  10030. renderer->framebuffersToDestroyCapacity = 16;
  10031. renderer->framebuffersToDestroyCount = 0;
  10032. renderer->framebuffersToDestroy = SDL_malloc(
  10033. sizeof(VulkanFramebuffer *) *
  10034. renderer->framebuffersToDestroyCapacity);
  10035. // Defrag state
  10036. renderer->defragInProgress = 0;
  10037. renderer->allocationsToDefragCount = 0;
  10038. renderer->allocationsToDefragCapacity = 4;
  10039. renderer->allocationsToDefrag = SDL_malloc(
  10040. renderer->allocationsToDefragCapacity * sizeof(VulkanMemoryAllocation *));
  10041. return result;
  10042. }
  10043. SDL_GPUBootstrap VulkanDriver = {
  10044. "vulkan",
  10045. SDL_GPU_SHADERFORMAT_SPIRV,
  10046. VULKAN_PrepareDriver,
  10047. VULKAN_CreateDevice
  10048. };
  10049. #endif // SDL_GPU_VULKAN