12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2024 Sam Lantinga <[email protected]>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "SDL_internal.h"
- #ifdef SDL_GPU_VULKAN
- // Needed for VK_KHR_portability_subset
- #define VK_ENABLE_BETA_EXTENSIONS
- #define VK_NO_PROTOTYPES
- #include "../../video/khronos/vulkan/vulkan.h"
- #include "SDL_hashtable.h"
- #include <SDL3/SDL_vulkan.h>
- #include "../SDL_sysgpu.h"
- #define VULKAN_INTERNAL_clamp(val, min, max) SDL_max(min, SDL_min(val, max))
- // Global Vulkan Loader Entry Points
- static PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
- #define VULKAN_GLOBAL_FUNCTION(name) \
- static PFN_##name name = NULL;
- #include "SDL_gpu_vulkan_vkfuncs.h"
- typedef struct VulkanExtensions
- {
- // These extensions are required!
- // Globally supported
- Uint8 KHR_swapchain;
- // Core since 1.1, needed for negative VkViewport::height
- Uint8 KHR_maintenance1;
- // These extensions are optional!
- // Core since 1.2, but requires annoying paperwork to implement
- Uint8 KHR_driver_properties;
- // EXT, probably not going to be Core
- Uint8 EXT_vertex_attribute_divisor;
- // Only required for special implementations (i.e. MoltenVK)
- Uint8 KHR_portability_subset;
- } VulkanExtensions;
- // Defines
- #define SMALL_ALLOCATION_THRESHOLD 2097152 // 2 MiB
- #define SMALL_ALLOCATION_SIZE 16777216 // 16 MiB
- #define LARGE_ALLOCATION_INCREMENT 67108864 // 64 MiB
- #define MAX_UBO_SECTION_SIZE 4096 // 4 KiB
- #define DESCRIPTOR_POOL_SIZE 128
- #define WINDOW_PROPERTY_DATA "SDL_GPUVulkanWindowPropertyData"
- #define IDENTITY_SWIZZLE \
- { \
- VK_COMPONENT_SWIZZLE_IDENTITY, \
- VK_COMPONENT_SWIZZLE_IDENTITY, \
- VK_COMPONENT_SWIZZLE_IDENTITY, \
- VK_COMPONENT_SWIZZLE_IDENTITY \
- }
- #define NULL_DESC_LAYOUT (VkDescriptorSetLayout)0
- #define NULL_PIPELINE_LAYOUT (VkPipelineLayout)0
- #define NULL_RENDER_PASS (SDL_GPURenderPass *)0
- #define EXPAND_ELEMENTS_IF_NEEDED(arr, initialValue, type) \
- if (arr->count == arr->capacity) { \
- if (arr->capacity == 0) { \
- arr->capacity = initialValue; \
- } else { \
- arr->capacity *= 2; \
- } \
- arr->elements = (type *)SDL_realloc( \
- arr->elements, \
- arr->capacity * sizeof(type)); \
- }
- #define EXPAND_ARRAY_IF_NEEDED(arr, elementType, newCount, capacity, newCapacity) \
- if (newCount >= capacity) { \
- capacity = newCapacity; \
- arr = (elementType *)SDL_realloc( \
- arr, \
- sizeof(elementType) * capacity); \
- }
- #define MOVE_ARRAY_CONTENTS_AND_RESET(i, dstArr, dstCount, srcArr, srcCount) \
- for (i = 0; i < srcCount; i += 1) { \
- dstArr[i] = srcArr[i]; \
- } \
- dstCount = srcCount; \
- srcCount = 0;
- // Conversions
- static const Uint8 DEVICE_PRIORITY_HIGHPERFORMANCE[] = {
- 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
- 3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
- 4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
- 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
- 1 // VK_PHYSICAL_DEVICE_TYPE_CPU
- };
- static const Uint8 DEVICE_PRIORITY_LOWPOWER[] = {
- 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
- 4, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
- 3, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
- 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
- 1 // VK_PHYSICAL_DEVICE_TYPE_CPU
- };
- static VkPresentModeKHR SDLToVK_PresentMode[] = {
- VK_PRESENT_MODE_FIFO_KHR,
- VK_PRESENT_MODE_IMMEDIATE_KHR,
- VK_PRESENT_MODE_MAILBOX_KHR
- };
- static VkFormat SDLToVK_TextureFormat[] = {
- VK_FORMAT_UNDEFINED, // INVALID
- VK_FORMAT_R8_UNORM, // A8_UNORM
- VK_FORMAT_R8_UNORM, // R8_UNORM
- VK_FORMAT_R8G8_UNORM, // R8G8_UNORM
- VK_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
- VK_FORMAT_R16_UNORM, // R16_UNORM
- VK_FORMAT_R16G16_UNORM, // R16G16_UNORM
- VK_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
- VK_FORMAT_A2B10G10R10_UNORM_PACK32, // R10G10B10A2_UNORM
- VK_FORMAT_R5G6B5_UNORM_PACK16, // B5G6R5_UNORM
- VK_FORMAT_A1R5G5B5_UNORM_PACK16, // B5G5R5A1_UNORM
- VK_FORMAT_B4G4R4A4_UNORM_PACK16, // B4G4R4A4_UNORM
- VK_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
- VK_FORMAT_BC1_RGBA_UNORM_BLOCK, // BC1_UNORM
- VK_FORMAT_BC2_UNORM_BLOCK, // BC2_UNORM
- VK_FORMAT_BC3_UNORM_BLOCK, // BC3_UNORM
- VK_FORMAT_BC4_UNORM_BLOCK, // BC4_UNORM
- VK_FORMAT_BC5_UNORM_BLOCK, // BC5_UNORM
- VK_FORMAT_BC7_UNORM_BLOCK, // BC7_UNORM
- VK_FORMAT_BC6H_SFLOAT_BLOCK, // BC6H_FLOAT
- VK_FORMAT_BC6H_UFLOAT_BLOCK, // BC6H_UFLOAT
- VK_FORMAT_R8_SNORM, // R8_SNORM
- VK_FORMAT_R8G8_SNORM, // R8G8_SNORM
- VK_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
- VK_FORMAT_R16_SNORM, // R16_SNORM
- VK_FORMAT_R16G16_SNORM, // R16G16_SNORM
- VK_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
- VK_FORMAT_R16_SFLOAT, // R16_FLOAT
- VK_FORMAT_R16G16_SFLOAT, // R16G16_FLOAT
- VK_FORMAT_R16G16B16A16_SFLOAT, // R16G16B16A16_FLOAT
- VK_FORMAT_R32_SFLOAT, // R32_FLOAT
- VK_FORMAT_R32G32_SFLOAT, // R32G32_FLOAT
- VK_FORMAT_R32G32B32A32_SFLOAT, // R32G32B32A32_FLOAT
- VK_FORMAT_B10G11R11_UFLOAT_PACK32, // R11G11B10_UFLOAT
- VK_FORMAT_R8_UINT, // R8_UINT
- VK_FORMAT_R8G8_UINT, // R8G8_UINT
- VK_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
- VK_FORMAT_R16_UINT, // R16_UINT
- VK_FORMAT_R16G16_UINT, // R16G16_UINT
- VK_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
- VK_FORMAT_R32_UINT, // R32_UINT
- VK_FORMAT_R32G32_UINT, // R32G32_UINT
- VK_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
- VK_FORMAT_R8_SINT, // R8_INT
- VK_FORMAT_R8G8_SINT, // R8G8_INT
- VK_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
- VK_FORMAT_R16_SINT, // R16_INT
- VK_FORMAT_R16G16_SINT, // R16G16_INT
- VK_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
- VK_FORMAT_R32_SINT, // R32_INT
- VK_FORMAT_R32G32_SINT, // R32G32_INT
- VK_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
- VK_FORMAT_R8G8B8A8_SRGB, // R8G8B8A8_UNORM_SRGB
- VK_FORMAT_B8G8R8A8_SRGB, // B8G8R8A8_UNORM_SRGB
- VK_FORMAT_BC1_RGBA_SRGB_BLOCK, // BC1_UNORM_SRGB
- VK_FORMAT_BC2_SRGB_BLOCK, // BC3_UNORM_SRGB
- VK_FORMAT_BC3_SRGB_BLOCK, // BC3_UNORM_SRGB
- VK_FORMAT_BC7_SRGB_BLOCK, // BC7_UNORM_SRGB
- VK_FORMAT_D16_UNORM, // D16_UNORM
- VK_FORMAT_X8_D24_UNORM_PACK32, // D24_UNORM
- VK_FORMAT_D32_SFLOAT, // D32_FLOAT
- VK_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT
- VK_FORMAT_D32_SFLOAT_S8_UINT, // D32_FLOAT_S8_UINT
- };
- SDL_COMPILE_TIME_ASSERT(SDLToVK_TextureFormat, SDL_arraysize(SDLToVK_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
- static VkComponentMapping SwizzleForSDLFormat(SDL_GPUTextureFormat format)
- {
- if (format == SDL_GPU_TEXTUREFORMAT_A8_UNORM) {
- // TODO: use VK_FORMAT_A8_UNORM_KHR from VK_KHR_maintenance5 when available
- return (VkComponentMapping){
- VK_COMPONENT_SWIZZLE_ZERO,
- VK_COMPONENT_SWIZZLE_ZERO,
- VK_COMPONENT_SWIZZLE_ZERO,
- VK_COMPONENT_SWIZZLE_R,
- };
- }
- if (format == SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM) {
- // ARGB -> BGRA
- // TODO: use VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT from VK_EXT_4444_formats when available
- return (VkComponentMapping){
- VK_COMPONENT_SWIZZLE_G,
- VK_COMPONENT_SWIZZLE_R,
- VK_COMPONENT_SWIZZLE_A,
- VK_COMPONENT_SWIZZLE_B,
- };
- }
- return (VkComponentMapping)IDENTITY_SWIZZLE;
- }
- static VkFormat SwapchainCompositionToFormat[] = {
- VK_FORMAT_B8G8R8A8_UNORM, // SDR
- VK_FORMAT_B8G8R8A8_SRGB, // SDR_LINEAR
- VK_FORMAT_R16G16B16A16_SFLOAT, // HDR_EXTENDED_LINEAR
- VK_FORMAT_A2B10G10R10_UNORM_PACK32 // HDR10_ST2048
- };
- static VkFormat SwapchainCompositionToFallbackFormat[] = {
- VK_FORMAT_R8G8B8A8_UNORM,
- VK_FORMAT_R8G8B8A8_SRGB,
- VK_FORMAT_UNDEFINED, // no fallback
- VK_FORMAT_UNDEFINED // no fallback
- };
- static SDL_GPUTextureFormat SwapchainCompositionToSDLFormat(
- SDL_GPUSwapchainComposition composition,
- bool usingFallback)
- {
- switch (composition) {
- case SDL_GPU_SWAPCHAINCOMPOSITION_SDR:
- return usingFallback ? SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM : SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM;
- case SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR:
- return usingFallback ? SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB : SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB;
- case SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR:
- return SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT;
- case SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048:
- return SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM;
- default:
- return SDL_GPU_TEXTUREFORMAT_INVALID;
- }
- }
- static VkColorSpaceKHR SwapchainCompositionToColorSpace[] = {
- VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
- VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
- VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT,
- VK_COLOR_SPACE_HDR10_ST2084_EXT
- };
- static VkComponentMapping SwapchainCompositionSwizzle[] = {
- IDENTITY_SWIZZLE, // SDR
- IDENTITY_SWIZZLE, // SDR_SRGB
- IDENTITY_SWIZZLE, // HDR
- {
- // HDR_ADVANCED
- VK_COMPONENT_SWIZZLE_R,
- VK_COMPONENT_SWIZZLE_G,
- VK_COMPONENT_SWIZZLE_B,
- VK_COMPONENT_SWIZZLE_A,
- }
- };
- static VkFormat SDLToVK_VertexFormat[] = {
- VK_FORMAT_UNDEFINED, // INVALID
- VK_FORMAT_R32_SINT, // INT
- VK_FORMAT_R32G32_SINT, // INT2
- VK_FORMAT_R32G32B32_SINT, // INT3
- VK_FORMAT_R32G32B32A32_SINT, // INT4
- VK_FORMAT_R32_UINT, // UINT
- VK_FORMAT_R32G32_UINT, // UINT2
- VK_FORMAT_R32G32B32_UINT, // UINT3
- VK_FORMAT_R32G32B32A32_UINT, // UINT4
- VK_FORMAT_R32_SFLOAT, // FLOAT
- VK_FORMAT_R32G32_SFLOAT, // FLOAT2
- VK_FORMAT_R32G32B32_SFLOAT, // FLOAT3
- VK_FORMAT_R32G32B32A32_SFLOAT, // FLOAT4
- VK_FORMAT_R8G8_SINT, // BYTE2
- VK_FORMAT_R8G8B8A8_SINT, // BYTE4
- VK_FORMAT_R8G8_UINT, // UBYTE2
- VK_FORMAT_R8G8B8A8_UINT, // UBYTE4
- VK_FORMAT_R8G8_SNORM, // BYTE2_NORM
- VK_FORMAT_R8G8B8A8_SNORM, // BYTE4_NORM
- VK_FORMAT_R8G8_UNORM, // UBYTE2_NORM
- VK_FORMAT_R8G8B8A8_UNORM, // UBYTE4_NORM
- VK_FORMAT_R16G16_SINT, // SHORT2
- VK_FORMAT_R16G16B16A16_SINT, // SHORT4
- VK_FORMAT_R16G16_UINT, // USHORT2
- VK_FORMAT_R16G16B16A16_UINT, // USHORT4
- VK_FORMAT_R16G16_SNORM, // SHORT2_NORM
- VK_FORMAT_R16G16B16A16_SNORM, // SHORT4_NORM
- VK_FORMAT_R16G16_UNORM, // USHORT2_NORM
- VK_FORMAT_R16G16B16A16_UNORM, // USHORT4_NORM
- VK_FORMAT_R16G16_SFLOAT, // HALF2
- VK_FORMAT_R16G16B16A16_SFLOAT // HALF4
- };
- SDL_COMPILE_TIME_ASSERT(SDLToVK_VertexFormat, SDL_arraysize(SDLToVK_VertexFormat) == SDL_GPU_VERTEXELEMENTFORMAT_MAX_ENUM_VALUE);
- static VkIndexType SDLToVK_IndexType[] = {
- VK_INDEX_TYPE_UINT16,
- VK_INDEX_TYPE_UINT32
- };
- static VkPrimitiveTopology SDLToVK_PrimitiveType[] = {
- VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
- VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
- VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
- VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
- VK_PRIMITIVE_TOPOLOGY_POINT_LIST
- };
- static VkCullModeFlags SDLToVK_CullMode[] = {
- VK_CULL_MODE_NONE,
- VK_CULL_MODE_FRONT_BIT,
- VK_CULL_MODE_BACK_BIT,
- VK_CULL_MODE_FRONT_AND_BACK
- };
- static VkFrontFace SDLToVK_FrontFace[] = {
- VK_FRONT_FACE_COUNTER_CLOCKWISE,
- VK_FRONT_FACE_CLOCKWISE
- };
- static VkBlendFactor SDLToVK_BlendFactor[] = {
- VK_BLEND_FACTOR_ZERO, // INVALID
- VK_BLEND_FACTOR_ZERO,
- VK_BLEND_FACTOR_ONE,
- VK_BLEND_FACTOR_SRC_COLOR,
- VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
- VK_BLEND_FACTOR_DST_COLOR,
- VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
- VK_BLEND_FACTOR_SRC_ALPHA,
- VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
- VK_BLEND_FACTOR_DST_ALPHA,
- VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
- VK_BLEND_FACTOR_CONSTANT_COLOR,
- VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
- VK_BLEND_FACTOR_SRC_ALPHA_SATURATE
- };
- SDL_COMPILE_TIME_ASSERT(SDLToVK_BlendFactor, SDL_arraysize(SDLToVK_BlendFactor) == SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE);
- static VkBlendOp SDLToVK_BlendOp[] = {
- VK_BLEND_OP_ADD, // INVALID
- VK_BLEND_OP_ADD,
- VK_BLEND_OP_SUBTRACT,
- VK_BLEND_OP_REVERSE_SUBTRACT,
- VK_BLEND_OP_MIN,
- VK_BLEND_OP_MAX
- };
- SDL_COMPILE_TIME_ASSERT(SDLToVK_BlendOp, SDL_arraysize(SDLToVK_BlendOp) == SDL_GPU_BLENDOP_MAX_ENUM_VALUE);
- static VkCompareOp SDLToVK_CompareOp[] = {
- VK_COMPARE_OP_NEVER, // INVALID
- VK_COMPARE_OP_NEVER,
- VK_COMPARE_OP_LESS,
- VK_COMPARE_OP_EQUAL,
- VK_COMPARE_OP_LESS_OR_EQUAL,
- VK_COMPARE_OP_GREATER,
- VK_COMPARE_OP_NOT_EQUAL,
- VK_COMPARE_OP_GREATER_OR_EQUAL,
- VK_COMPARE_OP_ALWAYS
- };
- SDL_COMPILE_TIME_ASSERT(SDLToVK_CompareOp, SDL_arraysize(SDLToVK_CompareOp) == SDL_GPU_COMPAREOP_MAX_ENUM_VALUE);
- static VkStencilOp SDLToVK_StencilOp[] = {
- VK_STENCIL_OP_KEEP, // INVALID
- VK_STENCIL_OP_KEEP,
- VK_STENCIL_OP_ZERO,
- VK_STENCIL_OP_REPLACE,
- VK_STENCIL_OP_INCREMENT_AND_CLAMP,
- VK_STENCIL_OP_DECREMENT_AND_CLAMP,
- VK_STENCIL_OP_INVERT,
- VK_STENCIL_OP_INCREMENT_AND_WRAP,
- VK_STENCIL_OP_DECREMENT_AND_WRAP
- };
- SDL_COMPILE_TIME_ASSERT(SDLToVK_StencilOp, SDL_arraysize(SDLToVK_StencilOp) == SDL_GPU_STENCILOP_MAX_ENUM_VALUE);
- static VkAttachmentLoadOp SDLToVK_LoadOp[] = {
- VK_ATTACHMENT_LOAD_OP_LOAD,
- VK_ATTACHMENT_LOAD_OP_CLEAR,
- VK_ATTACHMENT_LOAD_OP_DONT_CARE
- };
- static VkAttachmentStoreOp SDLToVK_StoreOp[] = {
- VK_ATTACHMENT_STORE_OP_STORE,
- VK_ATTACHMENT_STORE_OP_DONT_CARE,
- VK_ATTACHMENT_STORE_OP_DONT_CARE,
- VK_ATTACHMENT_STORE_OP_STORE
- };
- static VkSampleCountFlagBits SDLToVK_SampleCount[] = {
- VK_SAMPLE_COUNT_1_BIT,
- VK_SAMPLE_COUNT_2_BIT,
- VK_SAMPLE_COUNT_4_BIT,
- VK_SAMPLE_COUNT_8_BIT
- };
- static VkVertexInputRate SDLToVK_VertexInputRate[] = {
- VK_VERTEX_INPUT_RATE_VERTEX,
- VK_VERTEX_INPUT_RATE_INSTANCE
- };
- static VkFilter SDLToVK_Filter[] = {
- VK_FILTER_NEAREST,
- VK_FILTER_LINEAR
- };
- static VkSamplerMipmapMode SDLToVK_SamplerMipmapMode[] = {
- VK_SAMPLER_MIPMAP_MODE_NEAREST,
- VK_SAMPLER_MIPMAP_MODE_LINEAR
- };
- static VkSamplerAddressMode SDLToVK_SamplerAddressMode[] = {
- VK_SAMPLER_ADDRESS_MODE_REPEAT,
- VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
- VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
- };
- // Structures
- typedef struct VulkanMemoryAllocation VulkanMemoryAllocation;
- typedef struct VulkanBuffer VulkanBuffer;
- typedef struct VulkanBufferContainer VulkanBufferContainer;
- typedef struct VulkanTexture VulkanTexture;
- typedef struct VulkanTextureContainer VulkanTextureContainer;
- typedef struct VulkanFenceHandle
- {
- VkFence fence;
- SDL_AtomicInt referenceCount;
- } VulkanFenceHandle;
- // Memory Allocation
- typedef struct VulkanMemoryFreeRegion
- {
- VulkanMemoryAllocation *allocation;
- VkDeviceSize offset;
- VkDeviceSize size;
- Uint32 allocationIndex;
- Uint32 sortedIndex;
- } VulkanMemoryFreeRegion;
- typedef struct VulkanMemoryUsedRegion
- {
- VulkanMemoryAllocation *allocation;
- VkDeviceSize offset;
- VkDeviceSize size;
- VkDeviceSize resourceOffset; // differs from offset based on alignment
- VkDeviceSize resourceSize; // differs from size based on alignment
- VkDeviceSize alignment;
- Uint8 isBuffer;
- union
- {
- VulkanBuffer *vulkanBuffer;
- VulkanTexture *vulkanTexture;
- };
- } VulkanMemoryUsedRegion;
- typedef struct VulkanMemorySubAllocator
- {
- Uint32 memoryTypeIndex;
- VulkanMemoryAllocation **allocations;
- Uint32 allocationCount;
- VulkanMemoryFreeRegion **sortedFreeRegions;
- Uint32 sortedFreeRegionCount;
- Uint32 sortedFreeRegionCapacity;
- } VulkanMemorySubAllocator;
- struct VulkanMemoryAllocation
- {
- VulkanMemorySubAllocator *allocator;
- VkDeviceMemory memory;
- VkDeviceSize size;
- VulkanMemoryUsedRegion **usedRegions;
- Uint32 usedRegionCount;
- Uint32 usedRegionCapacity;
- VulkanMemoryFreeRegion **freeRegions;
- Uint32 freeRegionCount;
- Uint32 freeRegionCapacity;
- Uint8 availableForAllocation;
- VkDeviceSize freeSpace;
- VkDeviceSize usedSpace;
- Uint8 *mapPointer;
- SDL_Mutex *memoryLock;
- };
- typedef struct VulkanMemoryAllocator
- {
- VulkanMemorySubAllocator subAllocators[VK_MAX_MEMORY_TYPES];
- } VulkanMemoryAllocator;
- // Memory structures
- typedef enum VulkanBufferType
- {
- VULKAN_BUFFER_TYPE_GPU,
- VULKAN_BUFFER_TYPE_UNIFORM,
- VULKAN_BUFFER_TYPE_TRANSFER
- } VulkanBufferType;
- struct VulkanBuffer
- {
- VulkanBufferContainer *container;
- Uint32 containerIndex;
- VkBuffer buffer;
- VulkanMemoryUsedRegion *usedRegion;
- // Needed for uniforms and defrag
- VulkanBufferType type;
- SDL_GPUBufferUsageFlags usage;
- VkDeviceSize size;
- SDL_AtomicInt referenceCount;
- bool transitioned;
- bool markedForDestroy; // so that defrag doesn't double-free
- };
- struct VulkanBufferContainer
- {
- VulkanBuffer *activeBuffer;
- VulkanBuffer **buffers;
- Uint32 bufferCapacity;
- Uint32 bufferCount;
- char *debugName;
- };
- // Renderer Structure
- typedef struct QueueFamilyIndices
- {
- Uint32 graphicsFamily;
- Uint32 presentFamily;
- Uint32 computeFamily;
- Uint32 transferFamily;
- } QueueFamilyIndices;
- typedef struct VulkanSampler
- {
- VkSampler sampler;
- SDL_AtomicInt referenceCount;
- } VulkanSampler;
- typedef struct VulkanShader
- {
- VkShaderModule shaderModule;
- const char *entrypointName;
- Uint32 numSamplers;
- Uint32 numStorageTextures;
- Uint32 numStorageBuffers;
- Uint32 numUniformBuffers;
- SDL_AtomicInt referenceCount;
- } VulkanShader;
- /* Textures are made up of individual subresources.
- * This helps us barrier the resource efficiently.
- */
- typedef struct VulkanTextureSubresource
- {
- VulkanTexture *parent;
- Uint32 layer;
- Uint32 level;
- VkImageView *renderTargetViews; // One render target view per depth slice
- VkImageView computeWriteView;
- VkImageView depthStencilView;
- bool transitioned; // used for layout tracking
- } VulkanTextureSubresource;
- struct VulkanTexture
- {
- VulkanTextureContainer *container;
- Uint32 containerIndex;
- VulkanMemoryUsedRegion *usedRegion;
- VkImage image;
- VkImageView fullView; // used for samplers and storage reads
- VkComponentMapping swizzle;
- VkImageAspectFlags aspectFlags;
- Uint32 depth; // used for cleanup only
- // FIXME: It'd be nice if we didn't have to have this on the texture...
- SDL_GPUTextureUsageFlags usage; // used for defrag transitions only.
- Uint32 subresourceCount;
- VulkanTextureSubresource *subresources;
- bool markedForDestroy; // so that defrag doesn't double-free
- SDL_AtomicInt referenceCount;
- };
- struct VulkanTextureContainer
- {
- TextureCommonHeader header;
- VulkanTexture *activeTexture;
- Uint32 textureCapacity;
- Uint32 textureCount;
- VulkanTexture **textures;
- char *debugName;
- bool canBeCycled;
- };
- typedef enum VulkanBufferUsageMode
- {
- VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
- VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
- VULKAN_BUFFER_USAGE_MODE_VERTEX_READ,
- VULKAN_BUFFER_USAGE_MODE_INDEX_READ,
- VULKAN_BUFFER_USAGE_MODE_INDIRECT,
- VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ,
- VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
- VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
- } VulkanBufferUsageMode;
- typedef enum VulkanTextureUsageMode
- {
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
- VULKAN_TEXTURE_USAGE_MODE_SAMPLER,
- VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ,
- VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
- VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
- VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT,
- VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT,
- VULKAN_TEXTURE_USAGE_MODE_PRESENT
- } VulkanTextureUsageMode;
- typedef enum VulkanUniformBufferStage
- {
- VULKAN_UNIFORM_BUFFER_STAGE_VERTEX,
- VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT,
- VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE
- } VulkanUniformBufferStage;
- typedef struct VulkanFramebuffer
- {
- VkFramebuffer framebuffer;
- SDL_AtomicInt referenceCount;
- } VulkanFramebuffer;
- typedef struct VulkanSwapchainData
- {
- // Window surface
- VkSurfaceKHR surface;
- // Swapchain for window surface
- VkSwapchainKHR swapchain;
- VkFormat format;
- VkColorSpaceKHR colorSpace;
- VkComponentMapping swapchainSwizzle;
- VkPresentModeKHR presentMode;
- bool usingFallbackFormat;
- // Swapchain images
- VulkanTextureContainer *textureContainers; // use containers so that swapchain textures can use the same API as other textures
- Uint32 imageCount;
- // Synchronization primitives
- VkSemaphore imageAvailableSemaphore[MAX_FRAMES_IN_FLIGHT];
- VkSemaphore renderFinishedSemaphore[MAX_FRAMES_IN_FLIGHT];
- SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
- Uint32 frameCounter;
- } VulkanSwapchainData;
- typedef struct WindowData
- {
- SDL_Window *window;
- SDL_GPUSwapchainComposition swapchainComposition;
- SDL_GPUPresentMode presentMode;
- VulkanSwapchainData *swapchainData;
- bool needsSwapchainRecreate;
- } WindowData;
- typedef struct SwapchainSupportDetails
- {
- VkSurfaceCapabilitiesKHR capabilities;
- VkSurfaceFormatKHR *formats;
- Uint32 formatsLength;
- VkPresentModeKHR *presentModes;
- Uint32 presentModesLength;
- } SwapchainSupportDetails;
- typedef struct VulkanPresentData
- {
- WindowData *windowData;
- Uint32 swapchainImageIndex;
- } VulkanPresentData;
- typedef struct VulkanUniformBuffer
- {
- VulkanBuffer *buffer;
- Uint32 drawOffset;
- Uint32 writeOffset;
- } VulkanUniformBuffer;
- typedef struct VulkanDescriptorInfo
- {
- VkDescriptorType descriptorType;
- VkShaderStageFlagBits stageFlag;
- } VulkanDescriptorInfo;
- typedef struct DescriptorSetPool
- {
- // It's a pool... of pools!!!
- Uint32 poolCount;
- VkDescriptorPool *descriptorPools;
- // We'll just manage the descriptor sets ourselves instead of freeing the sets
- VkDescriptorSet *descriptorSets;
- Uint32 descriptorSetCount;
- Uint32 descriptorSetIndex;
- } DescriptorSetPool;
- // A command buffer acquires a cache at command buffer acquisition time
- typedef struct DescriptorSetCache
- {
- // Pools are indexed by DescriptorSetLayoutID which increases monotonically
- // There's only a certain number of maximum layouts possible since we de-duplicate them.
- DescriptorSetPool *pools;
- Uint32 poolCount;
- } DescriptorSetCache;
- typedef struct DescriptorSetLayoutHashTableKey
- {
- VkShaderStageFlagBits shaderStage;
- // Category 1: read resources
- Uint32 samplerCount;
- Uint32 storageBufferCount;
- Uint32 storageTextureCount;
- // Category 2: write resources
- Uint32 writeStorageBufferCount;
- Uint32 writeStorageTextureCount;
- // Category 3: uniform buffers
- Uint32 uniformBufferCount;
- } DescriptorSetLayoutHashTableKey;
- typedef uint32_t DescriptorSetLayoutID;
- typedef struct DescriptorSetLayout
- {
- DescriptorSetLayoutID ID;
- VkDescriptorSetLayout descriptorSetLayout;
- // Category 1: read resources
- Uint32 samplerCount;
- Uint32 storageBufferCount;
- Uint32 storageTextureCount;
- // Category 2: write resources
- Uint32 writeStorageBufferCount;
- Uint32 writeStorageTextureCount;
- // Category 3: uniform buffers
- Uint32 uniformBufferCount;
- } DescriptorSetLayout;
- typedef struct GraphicsPipelineResourceLayoutHashTableKey
- {
- Uint32 vertexSamplerCount;
- Uint32 vertexStorageBufferCount;
- Uint32 vertexStorageTextureCount;
- Uint32 vertexUniformBufferCount;
- Uint32 fragmentSamplerCount;
- Uint32 fragmentStorageBufferCount;
- Uint32 fragmentStorageTextureCount;
- Uint32 fragmentUniformBufferCount;
- } GraphicsPipelineResourceLayoutHashTableKey;
- typedef struct VulkanGraphicsPipelineResourceLayout
- {
- VkPipelineLayout pipelineLayout;
- /*
- * Descriptor set layout is as follows:
- * 0: vertex resources
- * 1: vertex uniform buffers
- * 2: fragment resources
- * 3: fragment uniform buffers
- */
- DescriptorSetLayout *descriptorSetLayouts[4];
- Uint32 vertexSamplerCount;
- Uint32 vertexStorageBufferCount;
- Uint32 vertexStorageTextureCount;
- Uint32 vertexUniformBufferCount;
- Uint32 fragmentSamplerCount;
- Uint32 fragmentStorageBufferCount;
- Uint32 fragmentStorageTextureCount;
- Uint32 fragmentUniformBufferCount;
- } VulkanGraphicsPipelineResourceLayout;
- typedef struct VulkanGraphicsPipeline
- {
- VkPipeline pipeline;
- SDL_GPUPrimitiveType primitiveType;
- VulkanGraphicsPipelineResourceLayout *resourceLayout;
- VulkanShader *vertexShader;
- VulkanShader *fragmentShader;
- SDL_AtomicInt referenceCount;
- } VulkanGraphicsPipeline;
- typedef struct ComputePipelineResourceLayoutHashTableKey
- {
- Uint32 samplerCount;
- Uint32 readonlyStorageTextureCount;
- Uint32 readonlyStorageBufferCount;
- Uint32 readWriteStorageTextureCount;
- Uint32 readWriteStorageBufferCount;
- Uint32 uniformBufferCount;
- } ComputePipelineResourceLayoutHashTableKey;
- typedef struct VulkanComputePipelineResourceLayout
- {
- VkPipelineLayout pipelineLayout;
- /*
- * Descriptor set layout is as follows:
- * 0: samplers, then read-only textures, then read-only buffers
- * 1: write-only textures, then write-only buffers
- * 2: uniform buffers
- */
- DescriptorSetLayout *descriptorSetLayouts[3];
- Uint32 numSamplers;
- Uint32 numReadonlyStorageTextures;
- Uint32 numReadonlyStorageBuffers;
- Uint32 numReadWriteStorageTextures;
- Uint32 numReadWriteStorageBuffers;
- Uint32 numUniformBuffers;
- } VulkanComputePipelineResourceLayout;
- typedef struct VulkanComputePipeline
- {
- VkShaderModule shaderModule;
- VkPipeline pipeline;
- VulkanComputePipelineResourceLayout *resourceLayout;
- SDL_AtomicInt referenceCount;
- } VulkanComputePipeline;
- typedef struct RenderPassColorTargetDescription
- {
- VkFormat format;
- SDL_GPULoadOp loadOp;
- SDL_GPUStoreOp storeOp;
- } RenderPassColorTargetDescription;
- typedef struct RenderPassDepthStencilTargetDescription
- {
- VkFormat format;
- SDL_GPULoadOp loadOp;
- SDL_GPUStoreOp storeOp;
- SDL_GPULoadOp stencilLoadOp;
- SDL_GPUStoreOp stencilStoreOp;
- } RenderPassDepthStencilTargetDescription;
- typedef struct CommandPoolHashTableKey
- {
- SDL_ThreadID threadID;
- } CommandPoolHashTableKey;
- typedef struct RenderPassHashTableKey
- {
- RenderPassColorTargetDescription colorTargetDescriptions[MAX_COLOR_TARGET_BINDINGS];
- Uint32 numColorTargets;
- VkFormat resolveTargetFormats[MAX_COLOR_TARGET_BINDINGS];
- Uint32 numResolveTargets;
- RenderPassDepthStencilTargetDescription depthStencilTargetDescription;
- VkSampleCountFlagBits sampleCount;
- } RenderPassHashTableKey;
- typedef struct VulkanRenderPassHashTableValue
- {
- VkRenderPass handle;
- } VulkanRenderPassHashTableValue;
- typedef struct FramebufferHashTableKey
- {
- VkImageView colorAttachmentViews[MAX_COLOR_TARGET_BINDINGS];
- Uint32 numColorTargets;
- VkImageView resolveAttachmentViews[MAX_COLOR_TARGET_BINDINGS];
- Uint32 numResolveAttachments;
- VkImageView depthStencilAttachmentView;
- Uint32 width;
- Uint32 height;
- } FramebufferHashTableKey;
- // Command structures
- typedef struct VulkanFencePool
- {
- SDL_Mutex *lock;
- VulkanFenceHandle **availableFences;
- Uint32 availableFenceCount;
- Uint32 availableFenceCapacity;
- } VulkanFencePool;
- typedef struct VulkanCommandPool VulkanCommandPool;
- typedef struct VulkanRenderer VulkanRenderer;
- typedef struct VulkanCommandBuffer
- {
- CommandBufferCommonHeader common;
- VulkanRenderer *renderer;
- VkCommandBuffer commandBuffer;
- VulkanCommandPool *commandPool;
- VulkanPresentData *presentDatas;
- Uint32 presentDataCount;
- Uint32 presentDataCapacity;
- VkSemaphore *waitSemaphores;
- Uint32 waitSemaphoreCount;
- Uint32 waitSemaphoreCapacity;
- VkSemaphore *signalSemaphores;
- Uint32 signalSemaphoreCount;
- Uint32 signalSemaphoreCapacity;
- VulkanComputePipeline *currentComputePipeline;
- VulkanGraphicsPipeline *currentGraphicsPipeline;
- // Keep track of resources transitioned away from their default state to barrier them on pass end
- VulkanTextureSubresource *colorAttachmentSubresources[MAX_COLOR_TARGET_BINDINGS];
- Uint32 colorAttachmentSubresourceCount;
- VulkanTextureSubresource *resolveAttachmentSubresources[MAX_COLOR_TARGET_BINDINGS];
- Uint32 resolveAttachmentSubresourceCount;
- VulkanTextureSubresource *depthStencilAttachmentSubresource; // may be NULL
- // Dynamic state
- VkViewport currentViewport;
- VkRect2D currentScissor;
- float blendConstants[4];
- Uint8 stencilRef;
- // Resource bind state
- DescriptorSetCache *descriptorSetCache; // acquired when command buffer is acquired
- bool needNewVertexResourceDescriptorSet;
- bool needNewVertexUniformDescriptorSet;
- bool needNewVertexUniformOffsets;
- bool needNewFragmentResourceDescriptorSet;
- bool needNewFragmentUniformDescriptorSet;
- bool needNewFragmentUniformOffsets;
- bool needNewComputeReadOnlyDescriptorSet;
- bool needNewComputeReadWriteDescriptorSet;
- bool needNewComputeUniformDescriptorSet;
- bool needNewComputeUniformOffsets;
- VkDescriptorSet vertexResourceDescriptorSet;
- VkDescriptorSet vertexUniformDescriptorSet;
- VkDescriptorSet fragmentResourceDescriptorSet;
- VkDescriptorSet fragmentUniformDescriptorSet;
- VkDescriptorSet computeReadOnlyDescriptorSet;
- VkDescriptorSet computeReadWriteDescriptorSet;
- VkDescriptorSet computeUniformDescriptorSet;
- VulkanTexture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- VulkanSampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- VulkanTexture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
- VulkanBuffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
- VulkanTexture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- VulkanSampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- VulkanTexture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
- VulkanBuffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
- VulkanTextureSubresource *readWriteComputeStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
- Uint32 readWriteComputeStorageTextureSubresourceCount;
- VulkanBuffer *readWriteComputeStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
- VulkanTexture *computeSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- VulkanSampler *computeSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- VulkanTexture *readOnlyComputeStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
- VulkanBuffer *readOnlyComputeStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
- // Uniform buffers
- VulkanUniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
- VulkanUniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
- VulkanUniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
- // Track used resources
- VulkanBuffer **usedBuffers;
- Sint32 usedBufferCount;
- Sint32 usedBufferCapacity;
- VulkanTexture **usedTextures;
- Sint32 usedTextureCount;
- Sint32 usedTextureCapacity;
- VulkanSampler **usedSamplers;
- Sint32 usedSamplerCount;
- Sint32 usedSamplerCapacity;
- VulkanGraphicsPipeline **usedGraphicsPipelines;
- Sint32 usedGraphicsPipelineCount;
- Sint32 usedGraphicsPipelineCapacity;
- VulkanComputePipeline **usedComputePipelines;
- Sint32 usedComputePipelineCount;
- Sint32 usedComputePipelineCapacity;
- VulkanFramebuffer **usedFramebuffers;
- Sint32 usedFramebufferCount;
- Sint32 usedFramebufferCapacity;
- VulkanUniformBuffer **usedUniformBuffers;
- Sint32 usedUniformBufferCount;
- Sint32 usedUniformBufferCapacity;
- VulkanFenceHandle *inFlightFence;
- Uint8 autoReleaseFence;
- Uint8 isDefrag; // Whether this CB was created for defragging
- } VulkanCommandBuffer;
- struct VulkanCommandPool
- {
- SDL_ThreadID threadID;
- VkCommandPool commandPool;
- VulkanCommandBuffer **inactiveCommandBuffers;
- Uint32 inactiveCommandBufferCapacity;
- Uint32 inactiveCommandBufferCount;
- };
- // Context
- struct VulkanRenderer
- {
- VkInstance instance;
- VkPhysicalDevice physicalDevice;
- VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
- VkPhysicalDeviceDriverPropertiesKHR physicalDeviceDriverProperties;
- VkDevice logicalDevice;
- Uint8 integratedMemoryNotification;
- Uint8 outOfDeviceLocalMemoryWarning;
- Uint8 outofBARMemoryWarning;
- Uint8 fillModeOnlyWarning;
- bool debugMode;
- bool preferLowPower;
- VulkanExtensions supports;
- bool supportsDebugUtils;
- bool supportsColorspace;
- bool supportsFillModeNonSolid;
- bool supportsMultiDrawIndirect;
- VulkanMemoryAllocator *memoryAllocator;
- VkPhysicalDeviceMemoryProperties memoryProperties;
- WindowData **claimedWindows;
- Uint32 claimedWindowCount;
- Uint32 claimedWindowCapacity;
- Uint32 queueFamilyIndex;
- VkQueue unifiedQueue;
- VulkanCommandBuffer **submittedCommandBuffers;
- Uint32 submittedCommandBufferCount;
- Uint32 submittedCommandBufferCapacity;
- VulkanFencePool fencePool;
- SDL_HashTable *commandPoolHashTable;
- SDL_HashTable *renderPassHashTable;
- SDL_HashTable *framebufferHashTable;
- SDL_HashTable *graphicsPipelineResourceLayoutHashTable;
- SDL_HashTable *computePipelineResourceLayoutHashTable;
- SDL_HashTable *descriptorSetLayoutHashTable;
- VulkanUniformBuffer **uniformBufferPool;
- Uint32 uniformBufferPoolCount;
- Uint32 uniformBufferPoolCapacity;
- DescriptorSetCache **descriptorSetCachePool;
- Uint32 descriptorSetCachePoolCount;
- Uint32 descriptorSetCachePoolCapacity;
- SDL_AtomicInt layoutResourceID;
- Uint32 minUBOAlignment;
- // Deferred resource destruction
- VulkanTexture **texturesToDestroy;
- Uint32 texturesToDestroyCount;
- Uint32 texturesToDestroyCapacity;
- VulkanBuffer **buffersToDestroy;
- Uint32 buffersToDestroyCount;
- Uint32 buffersToDestroyCapacity;
- VulkanSampler **samplersToDestroy;
- Uint32 samplersToDestroyCount;
- Uint32 samplersToDestroyCapacity;
- VulkanGraphicsPipeline **graphicsPipelinesToDestroy;
- Uint32 graphicsPipelinesToDestroyCount;
- Uint32 graphicsPipelinesToDestroyCapacity;
- VulkanComputePipeline **computePipelinesToDestroy;
- Uint32 computePipelinesToDestroyCount;
- Uint32 computePipelinesToDestroyCapacity;
- VulkanShader **shadersToDestroy;
- Uint32 shadersToDestroyCount;
- Uint32 shadersToDestroyCapacity;
- VulkanFramebuffer **framebuffersToDestroy;
- Uint32 framebuffersToDestroyCount;
- Uint32 framebuffersToDestroyCapacity;
- SDL_Mutex *allocatorLock;
- SDL_Mutex *disposeLock;
- SDL_Mutex *submitLock;
- SDL_Mutex *acquireCommandBufferLock;
- SDL_Mutex *acquireUniformBufferLock;
- SDL_Mutex *renderPassFetchLock;
- SDL_Mutex *framebufferFetchLock;
- Uint8 defragInProgress;
- VulkanMemoryAllocation **allocationsToDefrag;
- Uint32 allocationsToDefragCount;
- Uint32 allocationsToDefragCapacity;
- #define VULKAN_INSTANCE_FUNCTION(func) \
- PFN_##func func;
- #define VULKAN_DEVICE_FUNCTION(func) \
- PFN_##func func;
- #include "SDL_gpu_vulkan_vkfuncs.h"
- };
- // Forward declarations
- static bool VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer);
- static bool VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
- static void VULKAN_ReleaseWindow(SDL_GPURenderer *driverData, SDL_Window *window);
- static bool VULKAN_Wait(SDL_GPURenderer *driverData);
- static bool VULKAN_WaitForFences(SDL_GPURenderer *driverData, bool waitAll, SDL_GPUFence *const *fences, Uint32 numFences);
- static bool VULKAN_Submit(SDL_GPUCommandBuffer *commandBuffer);
- // Error Handling
- static inline const char *VkErrorMessages(VkResult code)
- {
- #define ERR_TO_STR(e) \
- case e: \
- return #e;
- switch (code) {
- ERR_TO_STR(VK_ERROR_OUT_OF_HOST_MEMORY)
- ERR_TO_STR(VK_ERROR_OUT_OF_DEVICE_MEMORY)
- ERR_TO_STR(VK_ERROR_FRAGMENTED_POOL)
- ERR_TO_STR(VK_ERROR_OUT_OF_POOL_MEMORY)
- ERR_TO_STR(VK_ERROR_INITIALIZATION_FAILED)
- ERR_TO_STR(VK_ERROR_LAYER_NOT_PRESENT)
- ERR_TO_STR(VK_ERROR_EXTENSION_NOT_PRESENT)
- ERR_TO_STR(VK_ERROR_FEATURE_NOT_PRESENT)
- ERR_TO_STR(VK_ERROR_TOO_MANY_OBJECTS)
- ERR_TO_STR(VK_ERROR_DEVICE_LOST)
- ERR_TO_STR(VK_ERROR_INCOMPATIBLE_DRIVER)
- ERR_TO_STR(VK_ERROR_OUT_OF_DATE_KHR)
- ERR_TO_STR(VK_ERROR_SURFACE_LOST_KHR)
- ERR_TO_STR(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
- ERR_TO_STR(VK_SUBOPTIMAL_KHR)
- default:
- return "Unhandled VkResult!";
- }
- #undef ERR_TO_STR
- }
- #define SET_ERROR_AND_RETURN(fmt, msg, ret) \
- if (renderer->debugMode) { \
- SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
- } \
- SDL_SetError(fmt, msg); \
- return ret; \
- #define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
- #define CHECK_VULKAN_ERROR_AND_RETURN(res, fn, ret) \
- if (res != VK_SUCCESS) { \
- if (renderer->debugMode) { \
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s %s", #fn, VkErrorMessages(res)); \
- } \
- SDL_SetError("%s %s", #fn, VkErrorMessages(res)); \
- }
- // Utility
- static inline VkPolygonMode SDLToVK_PolygonMode(
- VulkanRenderer *renderer,
- SDL_GPUFillMode mode)
- {
- if (mode == SDL_GPU_FILLMODE_FILL) {
- return VK_POLYGON_MODE_FILL; // always available!
- }
- if (renderer->supportsFillModeNonSolid && mode == SDL_GPU_FILLMODE_LINE) {
- return VK_POLYGON_MODE_LINE;
- }
- if (!renderer->fillModeOnlyWarning) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Unsupported fill mode requested, using FILL!");
- renderer->fillModeOnlyWarning = 1;
- }
- return VK_POLYGON_MODE_FILL;
- }
- // Memory Management
- // Vulkan: Memory Allocation
- static inline VkDeviceSize VULKAN_INTERNAL_NextHighestAlignment(
- VkDeviceSize n,
- VkDeviceSize align)
- {
- return align * ((n + align - 1) / align);
- }
- static inline Uint32 VULKAN_INTERNAL_NextHighestAlignment32(
- Uint32 n,
- Uint32 align)
- {
- return align * ((n + align - 1) / align);
- }
- static void VULKAN_INTERNAL_MakeMemoryUnavailable(
- VulkanRenderer *renderer,
- VulkanMemoryAllocation *allocation)
- {
- Uint32 i, j;
- VulkanMemoryFreeRegion *freeRegion;
- allocation->availableForAllocation = 0;
- for (i = 0; i < allocation->freeRegionCount; i += 1) {
- freeRegion = allocation->freeRegions[i];
- // close the gap in the sorted list
- if (allocation->allocator->sortedFreeRegionCount > 1) {
- for (j = freeRegion->sortedIndex; j < allocation->allocator->sortedFreeRegionCount - 1; j += 1) {
- allocation->allocator->sortedFreeRegions[j] =
- allocation->allocator->sortedFreeRegions[j + 1];
- allocation->allocator->sortedFreeRegions[j]->sortedIndex = j;
- }
- }
- allocation->allocator->sortedFreeRegionCount -= 1;
- }
- }
- static void VULKAN_INTERNAL_MarkAllocationsForDefrag(
- VulkanRenderer *renderer)
- {
- Uint32 memoryType, allocationIndex;
- VulkanMemorySubAllocator *currentAllocator;
- for (memoryType = 0; memoryType < VK_MAX_MEMORY_TYPES; memoryType += 1) {
- currentAllocator = &renderer->memoryAllocator->subAllocators[memoryType];
- for (allocationIndex = 0; allocationIndex < currentAllocator->allocationCount; allocationIndex += 1) {
- if (currentAllocator->allocations[allocationIndex]->availableForAllocation == 1) {
- if (currentAllocator->allocations[allocationIndex]->freeRegionCount > 1) {
- EXPAND_ARRAY_IF_NEEDED(
- renderer->allocationsToDefrag,
- VulkanMemoryAllocation *,
- renderer->allocationsToDefragCount + 1,
- renderer->allocationsToDefragCapacity,
- renderer->allocationsToDefragCapacity * 2);
- renderer->allocationsToDefrag[renderer->allocationsToDefragCount] =
- currentAllocator->allocations[allocationIndex];
- renderer->allocationsToDefragCount += 1;
- VULKAN_INTERNAL_MakeMemoryUnavailable(
- renderer,
- currentAllocator->allocations[allocationIndex]);
- }
- }
- }
- }
- }
- static void VULKAN_INTERNAL_RemoveMemoryFreeRegion(
- VulkanRenderer *renderer,
- VulkanMemoryFreeRegion *freeRegion)
- {
- Uint32 i;
- SDL_LockMutex(renderer->allocatorLock);
- if (freeRegion->allocation->availableForAllocation) {
- // close the gap in the sorted list
- if (freeRegion->allocation->allocator->sortedFreeRegionCount > 1) {
- for (i = freeRegion->sortedIndex; i < freeRegion->allocation->allocator->sortedFreeRegionCount - 1; i += 1) {
- freeRegion->allocation->allocator->sortedFreeRegions[i] =
- freeRegion->allocation->allocator->sortedFreeRegions[i + 1];
- freeRegion->allocation->allocator->sortedFreeRegions[i]->sortedIndex = i;
- }
- }
- freeRegion->allocation->allocator->sortedFreeRegionCount -= 1;
- }
- // close the gap in the buffer list
- if (freeRegion->allocation->freeRegionCount > 1 && freeRegion->allocationIndex != freeRegion->allocation->freeRegionCount - 1) {
- freeRegion->allocation->freeRegions[freeRegion->allocationIndex] =
- freeRegion->allocation->freeRegions[freeRegion->allocation->freeRegionCount - 1];
- freeRegion->allocation->freeRegions[freeRegion->allocationIndex]->allocationIndex =
- freeRegion->allocationIndex;
- }
- freeRegion->allocation->freeRegionCount -= 1;
- freeRegion->allocation->freeSpace -= freeRegion->size;
- SDL_free(freeRegion);
- SDL_UnlockMutex(renderer->allocatorLock);
- }
- static void VULKAN_INTERNAL_NewMemoryFreeRegion(
- VulkanRenderer *renderer,
- VulkanMemoryAllocation *allocation,
- VkDeviceSize offset,
- VkDeviceSize size)
- {
- VulkanMemoryFreeRegion *newFreeRegion;
- VkDeviceSize newOffset, newSize;
- Sint32 insertionIndex = 0;
- SDL_LockMutex(renderer->allocatorLock);
- // look for an adjacent region to merge
- for (Sint32 i = allocation->freeRegionCount - 1; i >= 0; i -= 1) {
- // check left side
- if (allocation->freeRegions[i]->offset + allocation->freeRegions[i]->size == offset) {
- newOffset = allocation->freeRegions[i]->offset;
- newSize = allocation->freeRegions[i]->size + size;
- VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, allocation->freeRegions[i]);
- VULKAN_INTERNAL_NewMemoryFreeRegion(renderer, allocation, newOffset, newSize);
- SDL_UnlockMutex(renderer->allocatorLock);
- return;
- }
- // check right side
- if (allocation->freeRegions[i]->offset == offset + size) {
- newOffset = offset;
- newSize = allocation->freeRegions[i]->size + size;
- VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, allocation->freeRegions[i]);
- VULKAN_INTERNAL_NewMemoryFreeRegion(renderer, allocation, newOffset, newSize);
- SDL_UnlockMutex(renderer->allocatorLock);
- return;
- }
- }
- // region is not contiguous with another free region, make a new one
- allocation->freeRegionCount += 1;
- if (allocation->freeRegionCount > allocation->freeRegionCapacity) {
- allocation->freeRegionCapacity *= 2;
- allocation->freeRegions = SDL_realloc(
- allocation->freeRegions,
- sizeof(VulkanMemoryFreeRegion *) * allocation->freeRegionCapacity);
- }
- newFreeRegion = SDL_malloc(sizeof(VulkanMemoryFreeRegion));
- newFreeRegion->offset = offset;
- newFreeRegion->size = size;
- newFreeRegion->allocation = allocation;
- allocation->freeSpace += size;
- allocation->freeRegions[allocation->freeRegionCount - 1] = newFreeRegion;
- newFreeRegion->allocationIndex = allocation->freeRegionCount - 1;
- if (allocation->availableForAllocation) {
- for (Uint32 i = 0; i < allocation->allocator->sortedFreeRegionCount; i += 1) {
- if (allocation->allocator->sortedFreeRegions[i]->size < size) {
- // this is where the new region should go
- break;
- }
- insertionIndex += 1;
- }
- if (allocation->allocator->sortedFreeRegionCount + 1 > allocation->allocator->sortedFreeRegionCapacity) {
- allocation->allocator->sortedFreeRegionCapacity *= 2;
- allocation->allocator->sortedFreeRegions = SDL_realloc(
- allocation->allocator->sortedFreeRegions,
- sizeof(VulkanMemoryFreeRegion *) * allocation->allocator->sortedFreeRegionCapacity);
- }
- // perform insertion sort
- if (allocation->allocator->sortedFreeRegionCount > 0 && (Uint32)insertionIndex != allocation->allocator->sortedFreeRegionCount) {
- for (Sint32 i = allocation->allocator->sortedFreeRegionCount; i > insertionIndex && i > 0; i -= 1) {
- allocation->allocator->sortedFreeRegions[i] = allocation->allocator->sortedFreeRegions[i - 1];
- allocation->allocator->sortedFreeRegions[i]->sortedIndex = i;
- }
- }
- allocation->allocator->sortedFreeRegionCount += 1;
- allocation->allocator->sortedFreeRegions[insertionIndex] = newFreeRegion;
- newFreeRegion->sortedIndex = insertionIndex;
- }
- SDL_UnlockMutex(renderer->allocatorLock);
- }
- static VulkanMemoryUsedRegion *VULKAN_INTERNAL_NewMemoryUsedRegion(
- VulkanRenderer *renderer,
- VulkanMemoryAllocation *allocation,
- VkDeviceSize offset,
- VkDeviceSize size,
- VkDeviceSize resourceOffset,
- VkDeviceSize resourceSize,
- VkDeviceSize alignment)
- {
- VulkanMemoryUsedRegion *memoryUsedRegion;
- SDL_LockMutex(renderer->allocatorLock);
- if (allocation->usedRegionCount == allocation->usedRegionCapacity) {
- allocation->usedRegionCapacity *= 2;
- allocation->usedRegions = SDL_realloc(
- allocation->usedRegions,
- allocation->usedRegionCapacity * sizeof(VulkanMemoryUsedRegion *));
- }
- memoryUsedRegion = SDL_malloc(sizeof(VulkanMemoryUsedRegion));
- memoryUsedRegion->allocation = allocation;
- memoryUsedRegion->offset = offset;
- memoryUsedRegion->size = size;
- memoryUsedRegion->resourceOffset = resourceOffset;
- memoryUsedRegion->resourceSize = resourceSize;
- memoryUsedRegion->alignment = alignment;
- allocation->usedSpace += size;
- allocation->usedRegions[allocation->usedRegionCount] = memoryUsedRegion;
- allocation->usedRegionCount += 1;
- SDL_UnlockMutex(renderer->allocatorLock);
- return memoryUsedRegion;
- }
- static void VULKAN_INTERNAL_RemoveMemoryUsedRegion(
- VulkanRenderer *renderer,
- VulkanMemoryUsedRegion *usedRegion)
- {
- Uint32 i;
- SDL_LockMutex(renderer->allocatorLock);
- for (i = 0; i < usedRegion->allocation->usedRegionCount; i += 1) {
- if (usedRegion->allocation->usedRegions[i] == usedRegion) {
- // plug the hole
- if (i != usedRegion->allocation->usedRegionCount - 1) {
- usedRegion->allocation->usedRegions[i] = usedRegion->allocation->usedRegions[usedRegion->allocation->usedRegionCount - 1];
- }
- break;
- }
- }
- usedRegion->allocation->usedSpace -= usedRegion->size;
- usedRegion->allocation->usedRegionCount -= 1;
- VULKAN_INTERNAL_NewMemoryFreeRegion(
- renderer,
- usedRegion->allocation,
- usedRegion->offset,
- usedRegion->size);
- SDL_free(usedRegion);
- SDL_UnlockMutex(renderer->allocatorLock);
- }
- static bool VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
- Uint32 memoryTypeIndex,
- Uint32 *memoryTypeIndexArray,
- Uint32 count)
- {
- Uint32 i = 0;
- for (i = 0; i < count; i += 1) {
- if (memoryTypeIndexArray[i] == memoryTypeIndex) {
- return false;
- }
- }
- return true;
- }
- /* Returns an array of memory type indices in order of preference.
- * Memory types are requested with the following three guidelines:
- *
- * Required: Absolutely necessary
- * Preferred: Nice to have, but not necessary
- * Tolerable: Can be allowed if there are no other options
- *
- * We return memory types in this order:
- * 1. Required and preferred. This is the best category.
- * 2. Required only.
- * 3. Required, preferred, and tolerable.
- * 4. Required and tolerable. This is the worst category.
- */
- static Uint32 *VULKAN_INTERNAL_FindBestMemoryTypes(
- VulkanRenderer *renderer,
- Uint32 typeFilter,
- VkMemoryPropertyFlags requiredProperties,
- VkMemoryPropertyFlags preferredProperties,
- VkMemoryPropertyFlags tolerableProperties,
- Uint32 *pCount)
- {
- Uint32 i;
- Uint32 index = 0;
- Uint32 *result = SDL_malloc(sizeof(Uint32) * renderer->memoryProperties.memoryTypeCount);
- // required + preferred + !tolerable
- for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
- if ((typeFilter & (1 << i)) &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == preferredProperties &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == 0) {
- if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
- i,
- result,
- index)) {
- result[index] = i;
- index += 1;
- }
- }
- }
- // required + !preferred + !tolerable
- for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
- if ((typeFilter & (1 << i)) &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == 0 &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == 0) {
- if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
- i,
- result,
- index)) {
- result[index] = i;
- index += 1;
- }
- }
- }
- // required + preferred + tolerable
- for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
- if ((typeFilter & (1 << i)) &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == preferredProperties &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == tolerableProperties) {
- if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
- i,
- result,
- index)) {
- result[index] = i;
- index += 1;
- }
- }
- }
- // required + !preferred + tolerable
- for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
- if ((typeFilter & (1 << i)) &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == 0 &&
- (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == tolerableProperties) {
- if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
- i,
- result,
- index)) {
- result[index] = i;
- index += 1;
- }
- }
- }
- *pCount = index;
- return result;
- }
- static Uint32 *VULKAN_INTERNAL_FindBestBufferMemoryTypes(
- VulkanRenderer *renderer,
- VkBuffer buffer,
- VkMemoryPropertyFlags requiredMemoryProperties,
- VkMemoryPropertyFlags preferredMemoryProperties,
- VkMemoryPropertyFlags tolerableMemoryProperties,
- VkMemoryRequirements *pMemoryRequirements,
- Uint32 *pCount)
- {
- renderer->vkGetBufferMemoryRequirements(
- renderer->logicalDevice,
- buffer,
- pMemoryRequirements);
- return VULKAN_INTERNAL_FindBestMemoryTypes(
- renderer,
- pMemoryRequirements->memoryTypeBits,
- requiredMemoryProperties,
- preferredMemoryProperties,
- tolerableMemoryProperties,
- pCount);
- }
- static Uint32 *VULKAN_INTERNAL_FindBestImageMemoryTypes(
- VulkanRenderer *renderer,
- VkImage image,
- VkMemoryPropertyFlags preferredMemoryPropertyFlags,
- VkMemoryRequirements *pMemoryRequirements,
- Uint32 *pCount)
- {
- renderer->vkGetImageMemoryRequirements(
- renderer->logicalDevice,
- image,
- pMemoryRequirements);
- return VULKAN_INTERNAL_FindBestMemoryTypes(
- renderer,
- pMemoryRequirements->memoryTypeBits,
- 0,
- preferredMemoryPropertyFlags,
- 0,
- pCount);
- }
- static void VULKAN_INTERNAL_DeallocateMemory(
- VulkanRenderer *renderer,
- VulkanMemorySubAllocator *allocator,
- Uint32 allocationIndex)
- {
- Uint32 i;
- VulkanMemoryAllocation *allocation = allocator->allocations[allocationIndex];
- SDL_LockMutex(renderer->allocatorLock);
- // If this allocation was marked for defrag, cancel that
- for (i = 0; i < renderer->allocationsToDefragCount; i += 1) {
- if (allocation == renderer->allocationsToDefrag[i]) {
- renderer->allocationsToDefrag[i] = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
- renderer->allocationsToDefragCount -= 1;
- break;
- }
- }
- for (i = 0; i < allocation->freeRegionCount; i += 1) {
- VULKAN_INTERNAL_RemoveMemoryFreeRegion(
- renderer,
- allocation->freeRegions[i]);
- }
- SDL_free(allocation->freeRegions);
- /* no need to iterate used regions because deallocate
- * only happens when there are 0 used regions
- */
- SDL_free(allocation->usedRegions);
- renderer->vkFreeMemory(
- renderer->logicalDevice,
- allocation->memory,
- NULL);
- SDL_DestroyMutex(allocation->memoryLock);
- SDL_free(allocation);
- if (allocationIndex != allocator->allocationCount - 1) {
- allocator->allocations[allocationIndex] = allocator->allocations[allocator->allocationCount - 1];
- }
- allocator->allocationCount -= 1;
- SDL_UnlockMutex(renderer->allocatorLock);
- }
- static Uint8 VULKAN_INTERNAL_AllocateMemory(
- VulkanRenderer *renderer,
- VkBuffer buffer,
- VkImage image,
- Uint32 memoryTypeIndex,
- VkDeviceSize allocationSize,
- Uint8 isHostVisible,
- VulkanMemoryAllocation **pMemoryAllocation)
- {
- VulkanMemoryAllocation *allocation;
- VulkanMemorySubAllocator *allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex];
- VkMemoryAllocateInfo allocInfo;
- VkResult result;
- allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- allocInfo.pNext = NULL;
- allocInfo.memoryTypeIndex = memoryTypeIndex;
- allocInfo.allocationSize = allocationSize;
- allocation = SDL_malloc(sizeof(VulkanMemoryAllocation));
- allocation->size = allocationSize;
- allocation->freeSpace = 0; // added by FreeRegions
- allocation->usedSpace = 0; // added by UsedRegions
- allocation->memoryLock = SDL_CreateMutex();
- allocator->allocationCount += 1;
- allocator->allocations = SDL_realloc(
- allocator->allocations,
- sizeof(VulkanMemoryAllocation *) * allocator->allocationCount);
- allocator->allocations[allocator->allocationCount - 1] = allocation;
- allocInfo.pNext = NULL;
- allocation->availableForAllocation = 1;
- allocation->usedRegions = SDL_malloc(sizeof(VulkanMemoryUsedRegion *));
- allocation->usedRegionCount = 0;
- allocation->usedRegionCapacity = 1;
- allocation->freeRegions = SDL_malloc(sizeof(VulkanMemoryFreeRegion *));
- allocation->freeRegionCount = 0;
- allocation->freeRegionCapacity = 1;
- allocation->allocator = allocator;
- result = renderer->vkAllocateMemory(
- renderer->logicalDevice,
- &allocInfo,
- NULL,
- &allocation->memory);
- if (result != VK_SUCCESS) {
- // Uh oh, we couldn't allocate, time to clean up
- SDL_free(allocation->freeRegions);
- allocator->allocationCount -= 1;
- allocator->allocations = SDL_realloc(
- allocator->allocations,
- sizeof(VulkanMemoryAllocation *) * allocator->allocationCount);
- SDL_free(allocation);
- return 0;
- }
- // Persistent mapping for host-visible memory
- if (isHostVisible) {
- result = renderer->vkMapMemory(
- renderer->logicalDevice,
- allocation->memory,
- 0,
- VK_WHOLE_SIZE,
- 0,
- (void **)&allocation->mapPointer);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkMapMemory, 0)
- } else {
- allocation->mapPointer = NULL;
- }
- VULKAN_INTERNAL_NewMemoryFreeRegion(
- renderer,
- allocation,
- 0,
- allocation->size);
- *pMemoryAllocation = allocation;
- return 1;
- }
- static Uint8 VULKAN_INTERNAL_BindBufferMemory(
- VulkanRenderer *renderer,
- VulkanMemoryUsedRegion *usedRegion,
- VkDeviceSize alignedOffset,
- VkBuffer buffer)
- {
- VkResult vulkanResult;
- SDL_LockMutex(usedRegion->allocation->memoryLock);
- vulkanResult = renderer->vkBindBufferMemory(
- renderer->logicalDevice,
- buffer,
- usedRegion->allocation->memory,
- alignedOffset);
- SDL_UnlockMutex(usedRegion->allocation->memoryLock);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkBindBufferMemory, 0)
- return 1;
- }
- static Uint8 VULKAN_INTERNAL_BindImageMemory(
- VulkanRenderer *renderer,
- VulkanMemoryUsedRegion *usedRegion,
- VkDeviceSize alignedOffset,
- VkImage image)
- {
- VkResult vulkanResult;
- SDL_LockMutex(usedRegion->allocation->memoryLock);
- vulkanResult = renderer->vkBindImageMemory(
- renderer->logicalDevice,
- image,
- usedRegion->allocation->memory,
- alignedOffset);
- SDL_UnlockMutex(usedRegion->allocation->memoryLock);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkBindBufferMemory, 0)
- return 1;
- }
- static Uint8 VULKAN_INTERNAL_BindResourceMemory(
- VulkanRenderer *renderer,
- Uint32 memoryTypeIndex,
- VkMemoryRequirements *memoryRequirements,
- VkDeviceSize resourceSize, // may be different from requirements size!
- VkBuffer buffer, // may be VK_NULL_HANDLE
- VkImage image, // may be VK_NULL_HANDLE
- VulkanMemoryUsedRegion **pMemoryUsedRegion)
- {
- VulkanMemoryAllocation *allocation;
- VulkanMemorySubAllocator *allocator;
- VulkanMemoryFreeRegion *region;
- VulkanMemoryFreeRegion *selectedRegion;
- VulkanMemoryUsedRegion *usedRegion;
- VkDeviceSize requiredSize, allocationSize;
- VkDeviceSize alignedOffset = 0;
- VkDeviceSize newRegionSize, newRegionOffset;
- Uint8 isHostVisible, smallAllocation, allocationResult;
- Sint32 i;
- isHostVisible =
- (renderer->memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags &
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
- allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex];
- requiredSize = memoryRequirements->size;
- smallAllocation = requiredSize <= SMALL_ALLOCATION_THRESHOLD;
- if ((buffer == VK_NULL_HANDLE && image == VK_NULL_HANDLE) ||
- (buffer != VK_NULL_HANDLE && image != VK_NULL_HANDLE)) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "BindResourceMemory must be given either a VulkanBuffer or a VulkanTexture");
- return 0;
- }
- SDL_LockMutex(renderer->allocatorLock);
- selectedRegion = NULL;
- for (i = allocator->sortedFreeRegionCount - 1; i >= 0; i -= 1) {
- region = allocator->sortedFreeRegions[i];
- if (smallAllocation && region->allocation->size != SMALL_ALLOCATION_SIZE) {
- // region is not in a small allocation
- continue;
- }
- if (!smallAllocation && region->allocation->size == SMALL_ALLOCATION_SIZE) {
- // allocation is not small and current region is in a small allocation
- continue;
- }
- alignedOffset = VULKAN_INTERNAL_NextHighestAlignment(
- region->offset,
- memoryRequirements->alignment);
- if (alignedOffset + requiredSize <= region->offset + region->size) {
- selectedRegion = region;
- break;
- }
- }
- if (selectedRegion != NULL) {
- region = selectedRegion;
- allocation = region->allocation;
- usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion(
- renderer,
- allocation,
- region->offset,
- requiredSize + (alignedOffset - region->offset),
- alignedOffset,
- resourceSize,
- memoryRequirements->alignment);
- usedRegion->isBuffer = buffer != VK_NULL_HANDLE;
- newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize);
- newRegionOffset = alignedOffset + requiredSize;
- // remove and add modified region to re-sort
- VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region);
- // if size is 0, no need to re-insert
- if (newRegionSize != 0) {
- VULKAN_INTERNAL_NewMemoryFreeRegion(
- renderer,
- allocation,
- newRegionOffset,
- newRegionSize);
- }
- SDL_UnlockMutex(renderer->allocatorLock);
- if (buffer != VK_NULL_HANDLE) {
- if (!VULKAN_INTERNAL_BindBufferMemory(
- renderer,
- usedRegion,
- alignedOffset,
- buffer)) {
- VULKAN_INTERNAL_RemoveMemoryUsedRegion(
- renderer,
- usedRegion);
- return 0;
- }
- } else if (image != VK_NULL_HANDLE) {
- if (!VULKAN_INTERNAL_BindImageMemory(
- renderer,
- usedRegion,
- alignedOffset,
- image)) {
- VULKAN_INTERNAL_RemoveMemoryUsedRegion(
- renderer,
- usedRegion);
- return 0;
- }
- }
- *pMemoryUsedRegion = usedRegion;
- return 1;
- }
- // No suitable free regions exist, allocate a new memory region
- if (
- renderer->allocationsToDefragCount == 0 &&
- !renderer->defragInProgress) {
- // Mark currently fragmented allocations for defrag
- VULKAN_INTERNAL_MarkAllocationsForDefrag(renderer);
- }
- if (requiredSize > SMALL_ALLOCATION_THRESHOLD) {
- // allocate a page of required size aligned to LARGE_ALLOCATION_INCREMENT increments
- allocationSize =
- VULKAN_INTERNAL_NextHighestAlignment(requiredSize, LARGE_ALLOCATION_INCREMENT);
- } else {
- allocationSize = SMALL_ALLOCATION_SIZE;
- }
- allocationResult = VULKAN_INTERNAL_AllocateMemory(
- renderer,
- buffer,
- image,
- memoryTypeIndex,
- allocationSize,
- isHostVisible,
- &allocation);
- // Uh oh, we're out of memory
- if (allocationResult == 0) {
- SDL_UnlockMutex(renderer->allocatorLock);
- // Responsibility of the caller to handle being out of memory
- return 2;
- }
- usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion(
- renderer,
- allocation,
- 0,
- requiredSize,
- 0,
- resourceSize,
- memoryRequirements->alignment);
- usedRegion->isBuffer = buffer != VK_NULL_HANDLE;
- region = allocation->freeRegions[0];
- newRegionOffset = region->offset + requiredSize;
- newRegionSize = region->size - requiredSize;
- VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region);
- if (newRegionSize != 0) {
- VULKAN_INTERNAL_NewMemoryFreeRegion(
- renderer,
- allocation,
- newRegionOffset,
- newRegionSize);
- }
- SDL_UnlockMutex(renderer->allocatorLock);
- if (buffer != VK_NULL_HANDLE) {
- if (!VULKAN_INTERNAL_BindBufferMemory(
- renderer,
- usedRegion,
- 0,
- buffer)) {
- VULKAN_INTERNAL_RemoveMemoryUsedRegion(
- renderer,
- usedRegion);
- return 0;
- }
- } else if (image != VK_NULL_HANDLE) {
- if (!VULKAN_INTERNAL_BindImageMemory(
- renderer,
- usedRegion,
- 0,
- image)) {
- VULKAN_INTERNAL_RemoveMemoryUsedRegion(
- renderer,
- usedRegion);
- return 0;
- }
- }
- *pMemoryUsedRegion = usedRegion;
- return 1;
- }
- static Uint8 VULKAN_INTERNAL_BindMemoryForImage(
- VulkanRenderer *renderer,
- VkImage image,
- VulkanMemoryUsedRegion **usedRegion)
- {
- Uint8 bindResult = 0;
- Uint32 memoryTypeCount = 0;
- Uint32 *memoryTypesToTry = NULL;
- Uint32 selectedMemoryTypeIndex = 0;
- Uint32 i;
- VkMemoryPropertyFlags preferredMemoryPropertyFlags;
- VkMemoryRequirements memoryRequirements;
- /* Vulkan memory types have several memory properties.
- *
- * Unlike buffers, images are always optimally stored device-local,
- * so that is the only property we prefer here.
- *
- * If memory is constrained, it is fine for the texture to not
- * be device-local.
- */
- preferredMemoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- memoryTypesToTry = VULKAN_INTERNAL_FindBestImageMemoryTypes(
- renderer,
- image,
- preferredMemoryPropertyFlags,
- &memoryRequirements,
- &memoryTypeCount);
- for (i = 0; i < memoryTypeCount; i += 1) {
- bindResult = VULKAN_INTERNAL_BindResourceMemory(
- renderer,
- memoryTypesToTry[i],
- &memoryRequirements,
- memoryRequirements.size,
- VK_NULL_HANDLE,
- image,
- usedRegion);
- if (bindResult == 1) {
- selectedMemoryTypeIndex = memoryTypesToTry[i];
- break;
- }
- }
- SDL_free(memoryTypesToTry);
- // Check for warnings on success
- if (bindResult == 1) {
- if (!renderer->outOfDeviceLocalMemoryWarning) {
- if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Out of device-local memory, allocating textures on host-local memory!");
- renderer->outOfDeviceLocalMemoryWarning = 1;
- }
- }
- }
- return bindResult;
- }
- static Uint8 VULKAN_INTERNAL_BindMemoryForBuffer(
- VulkanRenderer *renderer,
- VkBuffer buffer,
- VkDeviceSize size,
- VulkanBufferType type,
- VulkanMemoryUsedRegion **usedRegion)
- {
- Uint8 bindResult = 0;
- Uint32 memoryTypeCount = 0;
- Uint32 *memoryTypesToTry = NULL;
- Uint32 selectedMemoryTypeIndex = 0;
- Uint32 i;
- VkMemoryPropertyFlags requiredMemoryPropertyFlags = 0;
- VkMemoryPropertyFlags preferredMemoryPropertyFlags = 0;
- VkMemoryPropertyFlags tolerableMemoryPropertyFlags = 0;
- VkMemoryRequirements memoryRequirements;
- /* Buffers need to be optimally bound to a memory type
- * based on their use case and the architecture of the system.
- *
- * It is important to understand the distinction between device and host.
- *
- * On a traditional high-performance desktop computer,
- * the "device" would be the GPU, and the "host" would be the CPU.
- * Memory being copied between these two must cross the PCI bus.
- * On these systems we have to be concerned about bandwidth limitations
- * and causing memory stalls, so we have taken a great deal of care
- * to structure this API to guide the client towards optimal usage.
- *
- * Other kinds of devices do not necessarily have this distinction.
- * On an iPhone or Nintendo Switch, all memory is accessible both to the
- * GPU and the CPU at all times. These kinds of systems are known as
- * UMA, or Unified Memory Architecture. A desktop computer using the
- * CPU's integrated graphics can also be thought of as UMA.
- *
- * Vulkan memory types have several memory properties.
- * The relevant memory properties are as follows:
- *
- * DEVICE_LOCAL:
- * This memory is on-device and most efficient for device access.
- * On UMA systems all memory is device-local.
- * If memory is not device-local, then it is host-local.
- *
- * HOST_VISIBLE:
- * This memory can be mapped for host access, meaning we can obtain
- * a pointer to directly access the memory.
- *
- * HOST_COHERENT:
- * Host-coherent memory does not require cache management operations
- * when mapped, so we always set this alongside HOST_VISIBLE
- * to avoid extra record keeping.
- *
- * HOST_CACHED:
- * Host-cached memory is faster to access than uncached memory
- * but memory of this type might not always be available.
- *
- * GPU buffers, like vertex buffers, indirect buffers, etc
- * are optimally stored in device-local memory.
- * However, if device-local memory is low, these buffers
- * can be accessed from host-local memory with a performance penalty.
- *
- * Uniform buffers must be host-visible and coherent because
- * the client uses them to quickly push small amounts of data.
- * We prefer uniform buffers to also be device-local because
- * they are accessed by shaders, but the amount of memory
- * that is both device-local and host-visible
- * is often constrained, particularly on low-end devices.
- *
- * Transfer buffers must be host-visible and coherent because
- * the client uses them to stage data to be transferred
- * to device-local memory, or to read back data transferred
- * from the device. We prefer the cache bit for performance
- * but it isn't strictly necessary. We tolerate device-local
- * memory in this situation because, as mentioned above,
- * on certain devices all memory is device-local, and even
- * though the transfer isn't strictly necessary it is still
- * useful for correctly timelining data.
- */
- if (type == VULKAN_BUFFER_TYPE_GPU) {
- preferredMemoryPropertyFlags |=
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- } else if (type == VULKAN_BUFFER_TYPE_UNIFORM) {
- requiredMemoryPropertyFlags |=
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- preferredMemoryPropertyFlags |=
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- } else if (type == VULKAN_BUFFER_TYPE_TRANSFER) {
- requiredMemoryPropertyFlags |=
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- preferredMemoryPropertyFlags |=
- VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
- tolerableMemoryPropertyFlags |=
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer type!");
- return 0;
- }
- memoryTypesToTry = VULKAN_INTERNAL_FindBestBufferMemoryTypes(
- renderer,
- buffer,
- requiredMemoryPropertyFlags,
- preferredMemoryPropertyFlags,
- tolerableMemoryPropertyFlags,
- &memoryRequirements,
- &memoryTypeCount);
- for (i = 0; i < memoryTypeCount; i += 1) {
- bindResult = VULKAN_INTERNAL_BindResourceMemory(
- renderer,
- memoryTypesToTry[i],
- &memoryRequirements,
- size,
- buffer,
- VK_NULL_HANDLE,
- usedRegion);
- if (bindResult == 1) {
- selectedMemoryTypeIndex = memoryTypesToTry[i];
- break;
- }
- }
- SDL_free(memoryTypesToTry);
- // Check for warnings on success
- if (bindResult == 1) {
- if (type == VULKAN_BUFFER_TYPE_GPU) {
- if (!renderer->outOfDeviceLocalMemoryWarning) {
- if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Out of device-local memory, allocating buffers on host-local memory, expect degraded performance!");
- renderer->outOfDeviceLocalMemoryWarning = 1;
- }
- }
- } else if (type == VULKAN_BUFFER_TYPE_UNIFORM) {
- if (!renderer->outofBARMemoryWarning) {
- if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Out of BAR memory, allocating uniform buffers on host-local memory, expect degraded performance!");
- renderer->outofBARMemoryWarning = 1;
- }
- }
- } else if (type == VULKAN_BUFFER_TYPE_TRANSFER) {
- if (!renderer->integratedMemoryNotification) {
- if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
- SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Integrated memory detected, allocating TransferBuffers on device-local memory!");
- renderer->integratedMemoryNotification = 1;
- }
- }
- }
- }
- return bindResult;
- }
- // Resource tracking
- #define ADD_TO_ARRAY_UNIQUE(resource, type, array, count, capacity) \
- Uint32 i; \
- \
- for (i = 0; i < commandBuffer->count; i += 1) { \
- if (commandBuffer->array[i] == resource) { \
- return; \
- } \
- } \
- \
- if (commandBuffer->count == commandBuffer->capacity) { \
- commandBuffer->capacity += 1; \
- commandBuffer->array = SDL_realloc( \
- commandBuffer->array, \
- commandBuffer->capacity * sizeof(type)); \
- } \
- commandBuffer->array[commandBuffer->count] = resource; \
- commandBuffer->count += 1;
- #define TRACK_RESOURCE(resource, type, array, count, capacity) \
- for (Sint32 i = commandBuffer->count - 1; i >= 0; i -= 1) { \
- if (commandBuffer->array[i] == resource) { \
- return; \
- } \
- } \
- \
- if (commandBuffer->count == commandBuffer->capacity) { \
- commandBuffer->capacity += 1; \
- commandBuffer->array = SDL_realloc( \
- commandBuffer->array, \
- commandBuffer->capacity * sizeof(type)); \
- } \
- commandBuffer->array[commandBuffer->count] = resource; \
- commandBuffer->count += 1; \
- SDL_AtomicIncRef(&resource->referenceCount);
- static void VULKAN_INTERNAL_TrackBuffer(
- VulkanCommandBuffer *commandBuffer,
- VulkanBuffer *buffer)
- {
- TRACK_RESOURCE(
- buffer,
- VulkanBuffer *,
- usedBuffers,
- usedBufferCount,
- usedBufferCapacity)
- }
- static void VULKAN_INTERNAL_TrackTexture(
- VulkanCommandBuffer *commandBuffer,
- VulkanTexture *texture)
- {
- TRACK_RESOURCE(
- texture,
- VulkanTexture *,
- usedTextures,
- usedTextureCount,
- usedTextureCapacity)
- }
- static void VULKAN_INTERNAL_TrackSampler(
- VulkanCommandBuffer *commandBuffer,
- VulkanSampler *sampler)
- {
- TRACK_RESOURCE(
- sampler,
- VulkanSampler *,
- usedSamplers,
- usedSamplerCount,
- usedSamplerCapacity)
- }
- static void VULKAN_INTERNAL_TrackGraphicsPipeline(
- VulkanCommandBuffer *commandBuffer,
- VulkanGraphicsPipeline *graphicsPipeline)
- {
- TRACK_RESOURCE(
- graphicsPipeline,
- VulkanGraphicsPipeline *,
- usedGraphicsPipelines,
- usedGraphicsPipelineCount,
- usedGraphicsPipelineCapacity)
- }
- static void VULKAN_INTERNAL_TrackComputePipeline(
- VulkanCommandBuffer *commandBuffer,
- VulkanComputePipeline *computePipeline)
- {
- TRACK_RESOURCE(
- computePipeline,
- VulkanComputePipeline *,
- usedComputePipelines,
- usedComputePipelineCount,
- usedComputePipelineCapacity)
- }
- static void VULKAN_INTERNAL_TrackFramebuffer(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanFramebuffer *framebuffer)
- {
- TRACK_RESOURCE(
- framebuffer,
- VulkanFramebuffer *,
- usedFramebuffers,
- usedFramebufferCount,
- usedFramebufferCapacity);
- }
- static void VULKAN_INTERNAL_TrackUniformBuffer(
- VulkanCommandBuffer *commandBuffer,
- VulkanUniformBuffer *uniformBuffer)
- {
- for (Sint32 i = commandBuffer->usedUniformBufferCount - 1; i >= 0; i -= 1) {
- if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) {
- return;
- }
- }
- if (commandBuffer->usedUniformBufferCount == commandBuffer->usedUniformBufferCapacity) {
- commandBuffer->usedUniformBufferCapacity += 1;
- commandBuffer->usedUniformBuffers = SDL_realloc(
- commandBuffer->usedUniformBuffers,
- commandBuffer->usedUniformBufferCapacity * sizeof(VulkanUniformBuffer *));
- }
- commandBuffer->usedUniformBuffers[commandBuffer->usedUniformBufferCount] = uniformBuffer;
- commandBuffer->usedUniformBufferCount += 1;
- VULKAN_INTERNAL_TrackBuffer(
- commandBuffer,
- uniformBuffer->buffer);
- }
- #undef TRACK_RESOURCE
- // Memory Barriers
- /*
- * In Vulkan, we must manually synchronize operations that write to resources on the GPU
- * so that read-after-write, write-after-read, and write-after-write hazards do not occur.
- * Additionally, textures are required to be in specific layouts for specific use cases.
- * Both of these tasks are accomplished with vkCmdPipelineBarrier.
- *
- * To insert the correct barriers, we keep track of "usage modes" for buffers and textures.
- * These indicate the current usage of that resource on the command buffer.
- * The transition from one usage mode to another indicates how the barrier should be constructed.
- *
- * Pipeline barriers cannot be inserted during a render pass, but they can be inserted
- * during a compute or copy pass.
- *
- * This means that the "default" usage mode of any given resource should be that it should be
- * ready for a graphics-read operation, because we cannot barrier during a render pass.
- * In the case where a resource is only used in compute, its default usage mode can be compute-read.
- * This strategy allows us to avoid expensive record keeping of command buffer/resource usage mode pairs,
- * and it fully covers synchronization between all combinations of stages.
- *
- * In Upload and Copy functions, we transition the resource immediately before and after the copy command.
- *
- * When binding a resource for compute, we transition when the Bind functions are called.
- * If a bind slot containing a resource is overwritten, we transition the resource in that slot back to its default.
- * When EndComputePass is called we transition all bound resources back to their default state.
- *
- * When binding a texture as a render pass attachment, we transition the resource on BeginRenderPass
- * and transition it back to its default on EndRenderPass.
- *
- * This strategy imposes certain limitations on resource usage flags.
- * For example, a texture cannot have both the SAMPLER and GRAPHICS_STORAGE usage flags,
- * because then it is impossible for the backend to infer which default usage mode the texture should use.
- *
- * Sync hazards can be detected by setting VK_KHRONOS_VALIDATION_VALIDATE_SYNC=1 when using validation layers.
- */
- static void VULKAN_INTERNAL_BufferMemoryBarrier(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanBufferUsageMode sourceUsageMode,
- VulkanBufferUsageMode destinationUsageMode,
- VulkanBuffer *buffer)
- {
- VkPipelineStageFlags srcStages = 0;
- VkPipelineStageFlags dstStages = 0;
- VkBufferMemoryBarrier memoryBarrier;
- memoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
- memoryBarrier.pNext = NULL;
- memoryBarrier.srcAccessMask = 0;
- memoryBarrier.dstAccessMask = 0;
- memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- memoryBarrier.buffer = buffer->buffer;
- memoryBarrier.offset = 0;
- memoryBarrier.size = buffer->size;
- if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE) {
- srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION) {
- srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_VERTEX_READ) {
- srcStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
- } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_INDEX_READ) {
- srcStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_INDEX_READ_BIT;
- } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_INDIRECT) {
- srcStages = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
- } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ) {
- srcStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
- } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ) {
- srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
- } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
- srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer source barrier type!");
- return;
- }
- if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE) {
- dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION) {
- dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_VERTEX_READ) {
- dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
- } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_INDEX_READ) {
- dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_INDEX_READ_BIT;
- } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_INDIRECT) {
- dstStages = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
- } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ) {
- dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ) {
- dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
- dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer destination barrier type!");
- return;
- }
- renderer->vkCmdPipelineBarrier(
- commandBuffer->commandBuffer,
- srcStages,
- dstStages,
- 0,
- 0,
- NULL,
- 1,
- &memoryBarrier,
- 0,
- NULL);
- buffer->transitioned = true;
- }
- static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanTextureUsageMode sourceUsageMode,
- VulkanTextureUsageMode destinationUsageMode,
- VulkanTextureSubresource *textureSubresource)
- {
- VkPipelineStageFlags srcStages = 0;
- VkPipelineStageFlags dstStages = 0;
- VkImageMemoryBarrier memoryBarrier;
- memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- memoryBarrier.pNext = NULL;
- memoryBarrier.srcAccessMask = 0;
- memoryBarrier.dstAccessMask = 0;
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- memoryBarrier.image = textureSubresource->parent->image;
- memoryBarrier.subresourceRange.aspectMask = textureSubresource->parent->aspectFlags;
- memoryBarrier.subresourceRange.baseArrayLayer = textureSubresource->layer;
- memoryBarrier.subresourceRange.layerCount = 1;
- memoryBarrier.subresourceRange.baseMipLevel = textureSubresource->level;
- memoryBarrier.subresourceRange.levelCount = 1;
- if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE) {
- srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
- } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION) {
- srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_SAMPLER) {
- srcStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ) {
- srcStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
- } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ) {
- srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
- } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
- srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
- } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT) {
- srcStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT) {
- srcStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized texture source barrier type!");
- return;
- }
- if (!textureSubresource->transitioned) {
- memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- }
- if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE) {
- dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
- } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION) {
- dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_SAMPLER) {
- dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ) {
- dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
- } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ) {
- dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
- } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
- dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
- } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT) {
- dstStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT) {
- dstStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_PRESENT) {
- dstStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
- memoryBarrier.dstAccessMask = 0;
- memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized texture destination barrier type!");
- return;
- }
- renderer->vkCmdPipelineBarrier(
- commandBuffer->commandBuffer,
- srcStages,
- dstStages,
- 0,
- 0,
- NULL,
- 0,
- NULL,
- 1,
- &memoryBarrier);
- textureSubresource->transitioned = true;
- }
- static VulkanBufferUsageMode VULKAN_INTERNAL_DefaultBufferUsageMode(
- VulkanBuffer *buffer)
- {
- // NOTE: order matters here!
- if (buffer->usage & SDL_GPU_BUFFERUSAGE_VERTEX) {
- return VULKAN_BUFFER_USAGE_MODE_VERTEX_READ;
- } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_INDEX) {
- return VULKAN_BUFFER_USAGE_MODE_INDEX_READ;
- } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_INDIRECT) {
- return VULKAN_BUFFER_USAGE_MODE_INDIRECT;
- } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ) {
- return VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ;
- } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ) {
- return VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ;
- } else if (buffer->usage & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE) {
- return VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Buffer has no default usage mode!");
- return VULKAN_BUFFER_USAGE_MODE_VERTEX_READ;
- }
- }
- static VulkanTextureUsageMode VULKAN_INTERNAL_DefaultTextureUsageMode(
- VulkanTexture *texture)
- {
- // NOTE: order matters here!
- // NOTE: graphics storage bits and sampler bit are mutually exclusive!
- if (texture->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) {
- return VULKAN_TEXTURE_USAGE_MODE_SAMPLER;
- } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) {
- return VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ;
- } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
- return VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT;
- } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
- return VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT;
- } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ) {
- return VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ;
- } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) {
- return VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE;
- } else if (texture->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE) {
- return VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Texture has no default usage mode!");
- return VULKAN_TEXTURE_USAGE_MODE_SAMPLER;
- }
- }
- static void VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanBufferUsageMode destinationUsageMode,
- VulkanBuffer *buffer)
- {
- VULKAN_INTERNAL_BufferMemoryBarrier(
- renderer,
- commandBuffer,
- VULKAN_INTERNAL_DefaultBufferUsageMode(buffer),
- destinationUsageMode,
- buffer);
- }
- static void VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanBufferUsageMode sourceUsageMode,
- VulkanBuffer *buffer)
- {
- VULKAN_INTERNAL_BufferMemoryBarrier(
- renderer,
- commandBuffer,
- sourceUsageMode,
- VULKAN_INTERNAL_DefaultBufferUsageMode(buffer),
- buffer);
- }
- static void VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanTextureUsageMode destinationUsageMode,
- VulkanTextureSubresource *textureSubresource)
- {
- VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
- renderer,
- commandBuffer,
- VULKAN_INTERNAL_DefaultTextureUsageMode(textureSubresource->parent),
- destinationUsageMode,
- textureSubresource);
- }
- static void VULKAN_INTERNAL_TextureTransitionFromDefaultUsage(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanTextureUsageMode destinationUsageMode,
- VulkanTexture *texture)
- {
- for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- commandBuffer,
- destinationUsageMode,
- &texture->subresources[i]);
- }
- }
- static void VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanTextureUsageMode sourceUsageMode,
- VulkanTextureSubresource *textureSubresource)
- {
- VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
- renderer,
- commandBuffer,
- sourceUsageMode,
- VULKAN_INTERNAL_DefaultTextureUsageMode(textureSubresource->parent),
- textureSubresource);
- }
- static void VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanTextureUsageMode sourceUsageMode,
- VulkanTexture *texture)
- {
- // FIXME: could optimize this barrier
- for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- commandBuffer,
- sourceUsageMode,
- &texture->subresources[i]);
- }
- }
- // Resource Disposal
- static void VULKAN_INTERNAL_ReleaseFramebuffer(
- VulkanRenderer *renderer,
- VulkanFramebuffer *framebuffer)
- {
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->framebuffersToDestroy,
- VulkanFramebuffer *,
- renderer->framebuffersToDestroyCount + 1,
- renderer->framebuffersToDestroyCapacity,
- renderer->framebuffersToDestroyCapacity * 2)
- renderer->framebuffersToDestroy[renderer->framebuffersToDestroyCount] = framebuffer;
- renderer->framebuffersToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void VULKAN_INTERNAL_DestroyFramebuffer(
- VulkanRenderer *renderer,
- VulkanFramebuffer *framebuffer)
- {
- renderer->vkDestroyFramebuffer(
- renderer->logicalDevice,
- framebuffer->framebuffer,
- NULL);
- SDL_free(framebuffer);
- }
- static void VULKAN_INTERNAL_RemoveFramebuffersContainingView(
- VulkanRenderer *renderer,
- VkImageView view)
- {
- FramebufferHashTableKey *key;
- VulkanFramebuffer *value;
- void *iter = NULL;
- // Can't remove while iterating!
- Uint32 keysToRemoveCapacity = 8;
- Uint32 keysToRemoveCount = 0;
- FramebufferHashTableKey **keysToRemove = SDL_malloc(keysToRemoveCapacity * sizeof(FramebufferHashTableKey *));
- SDL_LockMutex(renderer->framebufferFetchLock);
- while (SDL_IterateHashTable(renderer->framebufferHashTable, (const void **)&key, (const void **)&value, &iter)) {
- bool remove = false;
- for (Uint32 i = 0; i < key->numColorTargets; i += 1) {
- if (key->colorAttachmentViews[i] == view) {
- remove = true;
- }
- }
- for (Uint32 i = 0; i < key->numResolveAttachments; i += 1) {
- if (key->resolveAttachmentViews[i] == view) {
- remove = true;
- }
- }
- if (key->depthStencilAttachmentView == view) {
- remove = true;
- }
- if (remove) {
- if (keysToRemoveCount == keysToRemoveCapacity) {
- keysToRemoveCapacity *= 2;
- keysToRemove = SDL_realloc(
- keysToRemove,
- keysToRemoveCapacity * sizeof(FramebufferHashTableKey *));
- }
- keysToRemove[keysToRemoveCount] = key;
- keysToRemoveCount += 1;
- }
- }
- for (Uint32 i = 0; i < keysToRemoveCount; i += 1) {
- SDL_RemoveFromHashTable(renderer->framebufferHashTable, (void *)keysToRemove[i]);
- }
- SDL_UnlockMutex(renderer->framebufferFetchLock);
- SDL_free(keysToRemove);
- }
- static void VULKAN_INTERNAL_DestroyTexture(
- VulkanRenderer *renderer,
- VulkanTexture *texture)
- {
- // Clean up subresources
- for (Uint32 subresourceIndex = 0; subresourceIndex < texture->subresourceCount; subresourceIndex += 1) {
- if (texture->subresources[subresourceIndex].renderTargetViews != NULL) {
- for (Uint32 depthIndex = 0; depthIndex < texture->depth; depthIndex += 1) {
- VULKAN_INTERNAL_RemoveFramebuffersContainingView(
- renderer,
- texture->subresources[subresourceIndex].renderTargetViews[depthIndex]);
- }
- for (Uint32 depthIndex = 0; depthIndex < texture->depth; depthIndex += 1) {
- renderer->vkDestroyImageView(
- renderer->logicalDevice,
- texture->subresources[subresourceIndex].renderTargetViews[depthIndex],
- NULL);
- }
- SDL_free(texture->subresources[subresourceIndex].renderTargetViews);
- }
- if (texture->subresources[subresourceIndex].computeWriteView != VK_NULL_HANDLE) {
- renderer->vkDestroyImageView(
- renderer->logicalDevice,
- texture->subresources[subresourceIndex].computeWriteView,
- NULL);
- }
- if (texture->subresources[subresourceIndex].depthStencilView != VK_NULL_HANDLE) {
- renderer->vkDestroyImageView(
- renderer->logicalDevice,
- texture->subresources[subresourceIndex].depthStencilView,
- NULL);
- }
- }
- SDL_free(texture->subresources);
- if (texture->fullView) {
- renderer->vkDestroyImageView(
- renderer->logicalDevice,
- texture->fullView,
- NULL);
- }
- if (texture->image) {
- renderer->vkDestroyImage(
- renderer->logicalDevice,
- texture->image,
- NULL);
- }
- if (texture->usedRegion) {
- VULKAN_INTERNAL_RemoveMemoryUsedRegion(
- renderer,
- texture->usedRegion);
- }
- SDL_free(texture);
- }
- static void VULKAN_INTERNAL_DestroyBuffer(
- VulkanRenderer *renderer,
- VulkanBuffer *buffer)
- {
- renderer->vkDestroyBuffer(
- renderer->logicalDevice,
- buffer->buffer,
- NULL);
- VULKAN_INTERNAL_RemoveMemoryUsedRegion(
- renderer,
- buffer->usedRegion);
- SDL_free(buffer);
- }
- static void VULKAN_INTERNAL_DestroyCommandPool(
- VulkanRenderer *renderer,
- VulkanCommandPool *commandPool)
- {
- Uint32 i;
- VulkanCommandBuffer *commandBuffer;
- renderer->vkDestroyCommandPool(
- renderer->logicalDevice,
- commandPool->commandPool,
- NULL);
- for (i = 0; i < commandPool->inactiveCommandBufferCount; i += 1) {
- commandBuffer = commandPool->inactiveCommandBuffers[i];
- SDL_free(commandBuffer->presentDatas);
- SDL_free(commandBuffer->waitSemaphores);
- SDL_free(commandBuffer->signalSemaphores);
- SDL_free(commandBuffer->usedBuffers);
- SDL_free(commandBuffer->usedTextures);
- SDL_free(commandBuffer->usedSamplers);
- SDL_free(commandBuffer->usedGraphicsPipelines);
- SDL_free(commandBuffer->usedComputePipelines);
- SDL_free(commandBuffer->usedFramebuffers);
- SDL_free(commandBuffer->usedUniformBuffers);
- SDL_free(commandBuffer);
- }
- SDL_free(commandPool->inactiveCommandBuffers);
- SDL_free(commandPool);
- }
- static void VULKAN_INTERNAL_DestroyDescriptorSetLayout(
- VulkanRenderer *renderer,
- DescriptorSetLayout *layout)
- {
- if (layout == NULL) {
- return;
- }
- if (layout->descriptorSetLayout != VK_NULL_HANDLE) {
- renderer->vkDestroyDescriptorSetLayout(
- renderer->logicalDevice,
- layout->descriptorSetLayout,
- NULL);
- }
- SDL_free(layout);
- }
- static void VULKAN_INTERNAL_DestroyGraphicsPipeline(
- VulkanRenderer *renderer,
- VulkanGraphicsPipeline *graphicsPipeline)
- {
- renderer->vkDestroyPipeline(
- renderer->logicalDevice,
- graphicsPipeline->pipeline,
- NULL);
- (void)SDL_AtomicDecRef(&graphicsPipeline->vertexShader->referenceCount);
- (void)SDL_AtomicDecRef(&graphicsPipeline->fragmentShader->referenceCount);
- SDL_free(graphicsPipeline);
- }
- static void VULKAN_INTERNAL_DestroyComputePipeline(
- VulkanRenderer *renderer,
- VulkanComputePipeline *computePipeline)
- {
- if (computePipeline->pipeline != VK_NULL_HANDLE) {
- renderer->vkDestroyPipeline(
- renderer->logicalDevice,
- computePipeline->pipeline,
- NULL);
- }
- if (computePipeline->shaderModule != VK_NULL_HANDLE) {
- renderer->vkDestroyShaderModule(
- renderer->logicalDevice,
- computePipeline->shaderModule,
- NULL);
- }
- SDL_free(computePipeline);
- }
- static void VULKAN_INTERNAL_DestroyShader(
- VulkanRenderer *renderer,
- VulkanShader *vulkanShader)
- {
- renderer->vkDestroyShaderModule(
- renderer->logicalDevice,
- vulkanShader->shaderModule,
- NULL);
- SDL_free((void *)vulkanShader->entrypointName);
- SDL_free(vulkanShader);
- }
- static void VULKAN_INTERNAL_DestroySampler(
- VulkanRenderer *renderer,
- VulkanSampler *vulkanSampler)
- {
- renderer->vkDestroySampler(
- renderer->logicalDevice,
- vulkanSampler->sampler,
- NULL);
- SDL_free(vulkanSampler);
- }
- static void VULKAN_INTERNAL_DestroySwapchain(
- VulkanRenderer *renderer,
- WindowData *windowData)
- {
- Uint32 i;
- VulkanSwapchainData *swapchainData;
- if (windowData == NULL) {
- return;
- }
- swapchainData = windowData->swapchainData;
- if (swapchainData == NULL) {
- return;
- }
- for (i = 0; i < swapchainData->imageCount; i += 1) {
- VULKAN_INTERNAL_RemoveFramebuffersContainingView(
- renderer,
- swapchainData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0]);
- renderer->vkDestroyImageView(
- renderer->logicalDevice,
- swapchainData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0],
- NULL);
- SDL_free(swapchainData->textureContainers[i].activeTexture->subresources[0].renderTargetViews);
- SDL_free(swapchainData->textureContainers[i].activeTexture->subresources);
- SDL_free(swapchainData->textureContainers[i].activeTexture);
- }
- SDL_free(swapchainData->textureContainers);
- renderer->vkDestroySwapchainKHR(
- renderer->logicalDevice,
- swapchainData->swapchain,
- NULL);
- renderer->vkDestroySurfaceKHR(
- renderer->instance,
- swapchainData->surface,
- NULL);
- for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
- renderer->vkDestroySemaphore(
- renderer->logicalDevice,
- swapchainData->imageAvailableSemaphore[i],
- NULL);
- renderer->vkDestroySemaphore(
- renderer->logicalDevice,
- swapchainData->renderFinishedSemaphore[i],
- NULL);
- }
- windowData->swapchainData = NULL;
- SDL_free(swapchainData);
- }
- static void VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(
- VulkanRenderer *renderer,
- VulkanGraphicsPipelineResourceLayout *resourceLayout)
- {
- if (resourceLayout->pipelineLayout != VK_NULL_HANDLE) {
- renderer->vkDestroyPipelineLayout(
- renderer->logicalDevice,
- resourceLayout->pipelineLayout,
- NULL);
- }
- SDL_free(resourceLayout);
- }
- static void VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(
- VulkanRenderer *renderer,
- VulkanComputePipelineResourceLayout *resourceLayout)
- {
- if (resourceLayout->pipelineLayout != VK_NULL_HANDLE) {
- renderer->vkDestroyPipelineLayout(
- renderer->logicalDevice,
- resourceLayout->pipelineLayout,
- NULL);
- }
- SDL_free(resourceLayout);
- }
- static void VULKAN_INTERNAL_DestroyDescriptorSetCache(
- VulkanRenderer *renderer,
- DescriptorSetCache *descriptorSetCache)
- {
- for (Uint32 i = 0; i < descriptorSetCache->poolCount; i += 1) {
- for (Uint32 j = 0; j < descriptorSetCache->pools[i].poolCount; j += 1) {
- renderer->vkDestroyDescriptorPool(
- renderer->logicalDevice,
- descriptorSetCache->pools[i].descriptorPools[j],
- NULL);
- }
- SDL_free(descriptorSetCache->pools[i].descriptorSets);
- SDL_free(descriptorSetCache->pools[i].descriptorPools);
- }
- SDL_free(descriptorSetCache);
- }
- // Hashtable functions
- static Uint32 VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashFunction(const void *key, void *data)
- {
- GraphicsPipelineResourceLayoutHashTableKey *hashTableKey = (GraphicsPipelineResourceLayoutHashTableKey *)key;
- /* The algorithm for this hashing function
- * is taken from Josh Bloch's "Effective Java".
- * (https://stackoverflow.com/a/113600/12492383)
- */
- const Uint32 hashFactor = 31;
- Uint32 result = 1;
- result = result * hashFactor + hashTableKey->vertexSamplerCount;
- result = result * hashFactor + hashTableKey->vertexStorageBufferCount;
- result = result * hashFactor + hashTableKey->vertexStorageTextureCount;
- result = result * hashFactor + hashTableKey->vertexUniformBufferCount;
- result = result * hashFactor + hashTableKey->fragmentSamplerCount;
- result = result * hashFactor + hashTableKey->fragmentStorageBufferCount;
- result = result * hashFactor + hashTableKey->fragmentStorageTextureCount;
- result = result * hashFactor + hashTableKey->fragmentUniformBufferCount;
- return result;
- }
- static bool VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashKeyMatch(const void *aKey, const void *bKey, void *data)
- {
- return SDL_memcmp(aKey, bKey, sizeof(GraphicsPipelineResourceLayoutHashTableKey)) == 0;
- }
- static void VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashNuke(const void *key, const void *value, void *data)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)data;
- VulkanGraphicsPipelineResourceLayout *resourceLayout = (VulkanGraphicsPipelineResourceLayout *)value;
- VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(renderer, resourceLayout);
- SDL_free((void*)key);
- }
- static Uint32 VULKAN_INTERNAL_ComputePipelineResourceLayoutHashFunction(const void *key, void *data)
- {
- ComputePipelineResourceLayoutHashTableKey *hashTableKey = (ComputePipelineResourceLayoutHashTableKey *)key;
- /* The algorithm for this hashing function
- * is taken from Josh Bloch's "Effective Java".
- * (https://stackoverflow.com/a/113600/12492383)
- */
- const Uint32 hashFactor = 31;
- Uint32 result = 1;
- result = result * hashFactor + hashTableKey->samplerCount;
- result = result * hashFactor + hashTableKey->readonlyStorageTextureCount;
- result = result * hashFactor + hashTableKey->readonlyStorageBufferCount;
- result = result * hashFactor + hashTableKey->readWriteStorageTextureCount;
- result = result * hashFactor + hashTableKey->readWriteStorageBufferCount;
- result = result * hashFactor + hashTableKey->uniformBufferCount;
- return result;
- }
- static bool VULKAN_INTERNAL_ComputePipelineResourceLayoutHashKeyMatch(const void *aKey, const void *bKey, void *data)
- {
- return SDL_memcmp(aKey, bKey, sizeof(ComputePipelineResourceLayoutHashTableKey)) == 0;
- }
- static void VULKAN_INTERNAL_ComputePipelineResourceLayoutHashNuke(const void *key, const void *value, void *data)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)data;
- VulkanComputePipelineResourceLayout *resourceLayout = (VulkanComputePipelineResourceLayout *)value;
- VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(renderer, resourceLayout);
- SDL_free((void*)key);
- }
- static Uint32 VULKAN_INTERNAL_DescriptorSetLayoutHashFunction(const void *key, void *data)
- {
- DescriptorSetLayoutHashTableKey *hashTableKey = (DescriptorSetLayoutHashTableKey *)key;
- /* The algorithm for this hashing function
- * is taken from Josh Bloch's "Effective Java".
- * (https://stackoverflow.com/a/113600/12492383)
- */
- const Uint32 hashFactor = 31;
- Uint32 result = 1;
- result = result * hashFactor + hashTableKey->shaderStage;
- result = result * hashFactor + hashTableKey->samplerCount;
- result = result * hashFactor + hashTableKey->storageTextureCount;
- result = result * hashFactor + hashTableKey->storageBufferCount;
- result = result * hashFactor + hashTableKey->writeStorageTextureCount;
- result = result * hashFactor + hashTableKey->writeStorageBufferCount;
- result = result * hashFactor + hashTableKey->uniformBufferCount;
- return result;
- }
- static bool VULKAN_INTERNAL_DescriptorSetLayoutHashKeyMatch(const void *aKey, const void *bKey, void *data)
- {
- return SDL_memcmp(aKey, bKey, sizeof(DescriptorSetLayoutHashTableKey)) == 0;
- }
- static void VULKAN_INTERNAL_DescriptorSetLayoutHashNuke(const void *key, const void *value, void *data)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)data;
- DescriptorSetLayout *layout = (DescriptorSetLayout *)value;
- VULKAN_INTERNAL_DestroyDescriptorSetLayout(renderer, layout);
- SDL_free((void*)key);
- }
- static Uint32 VULKAN_INTERNAL_CommandPoolHashFunction(const void *key, void *data)
- {
- return (Uint32)((CommandPoolHashTableKey *)key)->threadID;
- }
- static bool VULKAN_INTERNAL_CommandPoolHashKeyMatch(const void *aKey, const void *bKey, void *data)
- {
- CommandPoolHashTableKey *a = (CommandPoolHashTableKey *)aKey;
- CommandPoolHashTableKey *b = (CommandPoolHashTableKey *)bKey;
- return a->threadID == b->threadID;
- }
- static void VULKAN_INTERNAL_CommandPoolHashNuke(const void *key, const void *value, void *data)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)data;
- VulkanCommandPool *pool = (VulkanCommandPool *)value;
- VULKAN_INTERNAL_DestroyCommandPool(renderer, pool);
- SDL_free((void *)key);
- }
- static Uint32 VULKAN_INTERNAL_RenderPassHashFunction(
- const void *key,
- void *data)
- {
- RenderPassHashTableKey *hashTableKey = (RenderPassHashTableKey *)key;
- /* The algorithm for this hashing function
- * is taken from Josh Bloch's "Effective Java".
- * (https://stackoverflow.com/a/113600/12492383)
- */
- const Uint32 hashFactor = 31;
- Uint32 result = 1;
- for (Uint32 i = 0; i < hashTableKey->numColorTargets; i += 1) {
- result = result * hashFactor + hashTableKey->colorTargetDescriptions[i].loadOp;
- result = result * hashFactor + hashTableKey->colorTargetDescriptions[i].storeOp;
- result = result * hashFactor + hashTableKey->colorTargetDescriptions[i].format;
- }
- for (Uint32 i = 0; i < hashTableKey->numResolveTargets; i += 1) {
- result = result * hashFactor + hashTableKey->resolveTargetFormats[i];
- }
- result = result * hashFactor + hashTableKey->depthStencilTargetDescription.loadOp;
- result = result * hashFactor + hashTableKey->depthStencilTargetDescription.storeOp;
- result = result * hashFactor + hashTableKey->depthStencilTargetDescription.stencilLoadOp;
- result = result * hashFactor + hashTableKey->depthStencilTargetDescription.stencilStoreOp;
- result = result * hashFactor + hashTableKey->depthStencilTargetDescription.format;
- result = result * hashFactor + hashTableKey->sampleCount;
- return result;
- }
- static bool VULKAN_INTERNAL_RenderPassHashKeyMatch(
- const void *aKey,
- const void *bKey,
- void *data)
- {
- RenderPassHashTableKey *a = (RenderPassHashTableKey *)aKey;
- RenderPassHashTableKey *b = (RenderPassHashTableKey *)bKey;
- if (a->numColorTargets != b->numColorTargets) {
- return 0;
- }
- if (a->numResolveTargets != b->numResolveTargets) {
- return 0;
- }
- if (a->sampleCount != b->sampleCount) {
- return 0;
- }
- for (Uint32 i = 0; i < a->numColorTargets; i += 1) {
- if (a->colorTargetDescriptions[i].format != b->colorTargetDescriptions[i].format) {
- return 0;
- }
- if (a->colorTargetDescriptions[i].loadOp != b->colorTargetDescriptions[i].loadOp) {
- return 0;
- }
- if (a->colorTargetDescriptions[i].storeOp != b->colorTargetDescriptions[i].storeOp) {
- return 0;
- }
- }
- for (Uint32 i = 0; i < a->numResolveTargets; i += 1) {
- if (a->resolveTargetFormats[i] != b->resolveTargetFormats[i]) {
- return 0;
- }
- }
- if (a->depthStencilTargetDescription.format != b->depthStencilTargetDescription.format) {
- return 0;
- }
- if (a->depthStencilTargetDescription.loadOp != b->depthStencilTargetDescription.loadOp) {
- return 0;
- }
- if (a->depthStencilTargetDescription.storeOp != b->depthStencilTargetDescription.storeOp) {
- return 0;
- }
- if (a->depthStencilTargetDescription.stencilLoadOp != b->depthStencilTargetDescription.stencilLoadOp) {
- return 0;
- }
- if (a->depthStencilTargetDescription.stencilStoreOp != b->depthStencilTargetDescription.stencilStoreOp) {
- return 0;
- }
- return 1;
- }
- static void VULKAN_INTERNAL_RenderPassHashNuke(const void *key, const void *value, void *data)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)data;
- VulkanRenderPassHashTableValue *renderPassWrapper = (VulkanRenderPassHashTableValue *)value;
- renderer->vkDestroyRenderPass(
- renderer->logicalDevice,
- renderPassWrapper->handle,
- NULL);
- SDL_free(renderPassWrapper);
- SDL_free((void *)key);
- }
- static Uint32 VULKAN_INTERNAL_FramebufferHashFunction(
- const void *key,
- void *data)
- {
- FramebufferHashTableKey *hashTableKey = (FramebufferHashTableKey *)key;
- /* The algorithm for this hashing function
- * is taken from Josh Bloch's "Effective Java".
- * (https://stackoverflow.com/a/113600/12492383)
- */
- const Uint32 hashFactor = 31;
- Uint32 result = 1;
- for (Uint32 i = 0; i < hashTableKey->numColorTargets; i += 1) {
- result = result * hashFactor + (Uint32)(uintptr_t)hashTableKey->colorAttachmentViews[i];
- }
- for (Uint32 i = 0; i < hashTableKey->numResolveAttachments; i += 1) {
- result = result * hashFactor + (Uint32)(uintptr_t)hashTableKey->resolveAttachmentViews[i];
- }
- result = result * hashFactor + (Uint32)(uintptr_t)hashTableKey->depthStencilAttachmentView;
- result = result * hashFactor + hashTableKey->width;
- result = result * hashFactor + hashTableKey->height;
- return result;
- }
- static bool VULKAN_INTERNAL_FramebufferHashKeyMatch(
- const void *aKey,
- const void *bKey,
- void *data)
- {
- FramebufferHashTableKey *a = (FramebufferHashTableKey *)aKey;
- FramebufferHashTableKey *b = (FramebufferHashTableKey *)bKey;
- if (a->numColorTargets != b->numColorTargets) {
- return 0;
- }
- if (a->numResolveAttachments != b->numResolveAttachments) {
- return 0;
- }
- for (Uint32 i = 0; i < a->numColorTargets; i += 1) {
- if (a->colorAttachmentViews[i] != b->colorAttachmentViews[i]) {
- return 0;
- }
- }
- for (Uint32 i = 0; i < a->numResolveAttachments; i += 1) {
- if (a->resolveAttachmentViews[i] != b->resolveAttachmentViews[i]) {
- return 0;
- }
- }
- if (a->depthStencilAttachmentView != b->depthStencilAttachmentView) {
- return 0;
- }
- if (a->width != b->width) {
- return 0;
- }
- if (a->height != b->height) {
- return 0;
- }
- return 1;
- }
- static void VULKAN_INTERNAL_FramebufferHashNuke(const void *key, const void *value, void *data)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)data;
- VulkanFramebuffer *framebuffer = (VulkanFramebuffer *)value;
- VULKAN_INTERNAL_ReleaseFramebuffer(renderer, framebuffer);
- SDL_free((void *)key);
- }
- // Descriptor pools
- static bool VULKAN_INTERNAL_AllocateDescriptorSets(
- VulkanRenderer *renderer,
- VkDescriptorPool descriptorPool,
- VkDescriptorSetLayout descriptorSetLayout,
- Uint32 descriptorSetCount,
- VkDescriptorSet *descriptorSetArray)
- {
- VkDescriptorSetAllocateInfo descriptorSetAllocateInfo;
- VkDescriptorSetLayout *descriptorSetLayouts = SDL_stack_alloc(VkDescriptorSetLayout, descriptorSetCount);
- VkResult vulkanResult;
- Uint32 i;
- for (i = 0; i < descriptorSetCount; i += 1) {
- descriptorSetLayouts[i] = descriptorSetLayout;
- }
- descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
- descriptorSetAllocateInfo.pNext = NULL;
- descriptorSetAllocateInfo.descriptorPool = descriptorPool;
- descriptorSetAllocateInfo.descriptorSetCount = descriptorSetCount;
- descriptorSetAllocateInfo.pSetLayouts = descriptorSetLayouts;
- vulkanResult = renderer->vkAllocateDescriptorSets(
- renderer->logicalDevice,
- &descriptorSetAllocateInfo,
- descriptorSetArray);
- SDL_stack_free(descriptorSetLayouts);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkAllocateDescriptorSets, false)
- return true;
- }
- static bool VULKAN_INTERNAL_AllocateDescriptorsFromPool(
- VulkanRenderer *renderer,
- DescriptorSetLayout *descriptorSetLayout,
- DescriptorSetPool *descriptorSetPool)
- {
- VkDescriptorPoolSize descriptorPoolSizes[
- MAX_TEXTURE_SAMPLERS_PER_STAGE +
- MAX_STORAGE_TEXTURES_PER_STAGE +
- MAX_STORAGE_BUFFERS_PER_STAGE +
- MAX_COMPUTE_WRITE_TEXTURES +
- MAX_COMPUTE_WRITE_BUFFERS +
- MAX_UNIFORM_BUFFERS_PER_STAGE];
- VkDescriptorPoolCreateInfo descriptorPoolInfo;
- VkDescriptorPool pool;
- VkResult vulkanResult;
- // Category 1
- for (Uint32 i = 0; i < descriptorSetLayout->samplerCount; i += 1) {
- descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
- }
- for (Uint32 i = descriptorSetLayout->samplerCount; i < descriptorSetLayout->samplerCount + descriptorSetLayout->storageTextureCount; i += 1) {
- descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
- }
- for (Uint32 i = descriptorSetLayout->samplerCount + descriptorSetLayout->storageTextureCount; i < descriptorSetLayout->samplerCount + descriptorSetLayout->storageTextureCount + descriptorSetLayout->storageBufferCount; i += 1) {
- descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
- }
- // Category 2
- for (Uint32 i = 0; i < descriptorSetLayout->writeStorageTextureCount; i += 1) {
- descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
- }
- for (Uint32 i = descriptorSetLayout->writeStorageTextureCount; i < descriptorSetLayout->writeStorageTextureCount + descriptorSetLayout->writeStorageBufferCount; i += 1) {
- descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
- }
- // Category 3
- for (Uint32 i = 0; i < descriptorSetLayout->uniformBufferCount; i += 1) {
- descriptorPoolSizes[i].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
- descriptorPoolSizes[i].descriptorCount = DESCRIPTOR_POOL_SIZE;
- }
- descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
- descriptorPoolInfo.pNext = NULL;
- descriptorPoolInfo.flags = 0;
- descriptorPoolInfo.maxSets = DESCRIPTOR_POOL_SIZE;
- descriptorPoolInfo.poolSizeCount =
- descriptorSetLayout->samplerCount +
- descriptorSetLayout->storageTextureCount +
- descriptorSetLayout->storageBufferCount +
- descriptorSetLayout->writeStorageTextureCount +
- descriptorSetLayout->writeStorageBufferCount +
- descriptorSetLayout->uniformBufferCount;
- descriptorPoolInfo.pPoolSizes = descriptorPoolSizes;
- vulkanResult = renderer->vkCreateDescriptorPool(
- renderer->logicalDevice,
- &descriptorPoolInfo,
- NULL,
- &pool);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDescriptorPool, false)
- descriptorSetPool->poolCount += 1;
- descriptorSetPool->descriptorPools = SDL_realloc(
- descriptorSetPool->descriptorPools,
- sizeof(VkDescriptorPool) * descriptorSetPool->poolCount);
- descriptorSetPool->descriptorPools[descriptorSetPool->poolCount - 1] = pool;
- descriptorSetPool->descriptorSets = SDL_realloc(
- descriptorSetPool->descriptorSets,
- sizeof(VkDescriptorSet) * descriptorSetPool->poolCount * DESCRIPTOR_POOL_SIZE);
- if (!VULKAN_INTERNAL_AllocateDescriptorSets(
- renderer,
- pool,
- descriptorSetLayout->descriptorSetLayout,
- DESCRIPTOR_POOL_SIZE,
- &descriptorSetPool->descriptorSets[descriptorSetPool->descriptorSetCount])) {
- return false;
- }
- descriptorSetPool->descriptorSetCount += DESCRIPTOR_POOL_SIZE;
- return true;
- }
- // NOTE: these categories should be mutually exclusive
- static DescriptorSetLayout *VULKAN_INTERNAL_FetchDescriptorSetLayout(
- VulkanRenderer *renderer,
- VkShaderStageFlagBits shaderStage,
- // Category 1: read resources
- Uint32 samplerCount,
- Uint32 storageTextureCount,
- Uint32 storageBufferCount,
- // Category 2: write resources
- Uint32 writeStorageTextureCount,
- Uint32 writeStorageBufferCount,
- // Category 3: uniform buffers
- Uint32 uniformBufferCount)
- {
- DescriptorSetLayoutHashTableKey key;
- SDL_zero(key);
- DescriptorSetLayout *layout = NULL;
- key.shaderStage = shaderStage;
- key.samplerCount = samplerCount;
- key.storageTextureCount = storageTextureCount;
- key.storageBufferCount = storageBufferCount;
- key.writeStorageTextureCount = writeStorageTextureCount;
- key.writeStorageBufferCount = writeStorageBufferCount;
- key.uniformBufferCount = uniformBufferCount;
- if (SDL_FindInHashTable(
- renderer->descriptorSetLayoutHashTable,
- (const void *)&key,
- (const void **)&layout)) {
- return layout;
- }
- VkDescriptorSetLayout descriptorSetLayout;
- VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[
- MAX_TEXTURE_SAMPLERS_PER_STAGE +
- MAX_STORAGE_TEXTURES_PER_STAGE +
- MAX_STORAGE_BUFFERS_PER_STAGE +
- MAX_COMPUTE_WRITE_TEXTURES +
- MAX_COMPUTE_WRITE_BUFFERS];
- VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo;
- descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
- descriptorSetLayoutCreateInfo.pNext = NULL;
- descriptorSetLayoutCreateInfo.flags = 0;
- // Category 1
- for (Uint32 i = 0; i < samplerCount; i += 1) {
- descriptorSetLayoutBindings[i].binding = i;
- descriptorSetLayoutBindings[i].descriptorCount = 1;
- descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- descriptorSetLayoutBindings[i].stageFlags = shaderStage;
- descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
- }
- for (Uint32 i = samplerCount; i < samplerCount + storageTextureCount; i += 1) {
- descriptorSetLayoutBindings[i].binding = i;
- descriptorSetLayoutBindings[i].descriptorCount = 1;
- descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- descriptorSetLayoutBindings[i].stageFlags = shaderStage;
- descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
- }
- for (Uint32 i = samplerCount + storageTextureCount; i < samplerCount + storageTextureCount + storageBufferCount; i += 1) {
- descriptorSetLayoutBindings[i].binding = i;
- descriptorSetLayoutBindings[i].descriptorCount = 1;
- descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- descriptorSetLayoutBindings[i].stageFlags = shaderStage;
- descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
- }
- // Category 2
- for (Uint32 i = 0; i < writeStorageTextureCount; i += 1) {
- descriptorSetLayoutBindings[i].binding = i;
- descriptorSetLayoutBindings[i].descriptorCount = 1;
- descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- descriptorSetLayoutBindings[i].stageFlags = shaderStage;
- descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
- }
- for (Uint32 i = writeStorageTextureCount; i < writeStorageTextureCount + writeStorageBufferCount; i += 1) {
- descriptorSetLayoutBindings[i].binding = i;
- descriptorSetLayoutBindings[i].descriptorCount = 1;
- descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- descriptorSetLayoutBindings[i].stageFlags = shaderStage;
- descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
- }
- // Category 3
- for (Uint32 i = 0; i < uniformBufferCount; i += 1) {
- descriptorSetLayoutBindings[i].binding = i;
- descriptorSetLayoutBindings[i].descriptorCount = 1;
- descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
- descriptorSetLayoutBindings[i].stageFlags = shaderStage;
- descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
- }
- descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
- descriptorSetLayoutCreateInfo.bindingCount =
- samplerCount +
- storageTextureCount +
- storageBufferCount +
- writeStorageTextureCount +
- writeStorageBufferCount +
- uniformBufferCount;
- VkResult vulkanResult = renderer->vkCreateDescriptorSetLayout(
- renderer->logicalDevice,
- &descriptorSetLayoutCreateInfo,
- NULL,
- &descriptorSetLayout);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDescriptorSetLayout, NULL)
- layout = SDL_malloc(sizeof(DescriptorSetLayout));
- layout->descriptorSetLayout = descriptorSetLayout;
- layout->samplerCount = samplerCount;
- layout->storageBufferCount = storageBufferCount;
- layout->storageTextureCount = storageTextureCount;
- layout->writeStorageBufferCount = writeStorageBufferCount;
- layout->writeStorageTextureCount = writeStorageTextureCount;
- layout->uniformBufferCount = uniformBufferCount;
- layout->ID = SDL_AtomicIncRef(&renderer->layoutResourceID);
- DescriptorSetLayoutHashTableKey *allocedKey = SDL_malloc(sizeof(DescriptorSetLayoutHashTableKey));
- SDL_memcpy(allocedKey, &key, sizeof(DescriptorSetLayoutHashTableKey));
- SDL_InsertIntoHashTable(
- renderer->descriptorSetLayoutHashTable,
- (const void *)allocedKey,
- (const void *)layout);
- return layout;
- }
- static VulkanGraphicsPipelineResourceLayout *VULKAN_INTERNAL_FetchGraphicsPipelineResourceLayout(
- VulkanRenderer *renderer,
- VulkanShader *vertexShader,
- VulkanShader *fragmentShader)
- {
- GraphicsPipelineResourceLayoutHashTableKey key;
- SDL_zero(key);
- VulkanGraphicsPipelineResourceLayout *pipelineResourceLayout = NULL;
- key.vertexSamplerCount = vertexShader->numSamplers;
- key.vertexStorageTextureCount = vertexShader->numStorageTextures;
- key.vertexStorageBufferCount = vertexShader->numStorageBuffers;
- key.vertexUniformBufferCount = vertexShader->numUniformBuffers;
- key.fragmentSamplerCount = fragmentShader->numSamplers;
- key.fragmentStorageTextureCount = fragmentShader->numStorageTextures;
- key.fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
- key.fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
- if (SDL_FindInHashTable(
- renderer->graphicsPipelineResourceLayoutHashTable,
- (const void *)&key,
- (const void **)&pipelineResourceLayout)) {
- return pipelineResourceLayout;
- }
- VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
- VkDescriptorSetLayout descriptorSetLayouts[4];
- VkResult vulkanResult;
- pipelineResourceLayout = SDL_calloc(1, sizeof(VulkanGraphicsPipelineResourceLayout));
- pipelineResourceLayout->descriptorSetLayouts[0] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
- renderer,
- VK_SHADER_STAGE_VERTEX_BIT,
- vertexShader->numSamplers,
- vertexShader->numStorageTextures,
- vertexShader->numStorageBuffers,
- 0,
- 0,
- 0);
- pipelineResourceLayout->descriptorSetLayouts[1] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
- renderer,
- VK_SHADER_STAGE_VERTEX_BIT,
- 0,
- 0,
- 0,
- 0,
- 0,
- vertexShader->numUniformBuffers);
- pipelineResourceLayout->descriptorSetLayouts[2] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
- renderer,
- VK_SHADER_STAGE_FRAGMENT_BIT,
- fragmentShader->numSamplers,
- fragmentShader->numStorageTextures,
- fragmentShader->numStorageBuffers,
- 0,
- 0,
- 0);
- pipelineResourceLayout->descriptorSetLayouts[3] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
- renderer,
- VK_SHADER_STAGE_FRAGMENT_BIT,
- 0,
- 0,
- 0,
- 0,
- 0,
- fragmentShader->numUniformBuffers);
- descriptorSetLayouts[0] = pipelineResourceLayout->descriptorSetLayouts[0]->descriptorSetLayout;
- descriptorSetLayouts[1] = pipelineResourceLayout->descriptorSetLayouts[1]->descriptorSetLayout;
- descriptorSetLayouts[2] = pipelineResourceLayout->descriptorSetLayouts[2]->descriptorSetLayout;
- descriptorSetLayouts[3] = pipelineResourceLayout->descriptorSetLayouts[3]->descriptorSetLayout;
- pipelineResourceLayout->vertexSamplerCount = vertexShader->numSamplers;
- pipelineResourceLayout->vertexStorageTextureCount = vertexShader->numStorageTextures;
- pipelineResourceLayout->vertexStorageBufferCount = vertexShader->numStorageBuffers;
- pipelineResourceLayout->vertexUniformBufferCount = vertexShader->numUniformBuffers;
- pipelineResourceLayout->fragmentSamplerCount = fragmentShader->numSamplers;
- pipelineResourceLayout->fragmentStorageTextureCount = fragmentShader->numStorageTextures;
- pipelineResourceLayout->fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
- pipelineResourceLayout->fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
- // Create the pipeline layout
- pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- pipelineLayoutCreateInfo.pNext = NULL;
- pipelineLayoutCreateInfo.flags = 0;
- pipelineLayoutCreateInfo.setLayoutCount = 4;
- pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts;
- pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
- pipelineLayoutCreateInfo.pPushConstantRanges = NULL;
- vulkanResult = renderer->vkCreatePipelineLayout(
- renderer->logicalDevice,
- &pipelineLayoutCreateInfo,
- NULL,
- &pipelineResourceLayout->pipelineLayout);
- if (vulkanResult != VK_SUCCESS) {
- VULKAN_INTERNAL_DestroyGraphicsPipelineResourceLayout(renderer, pipelineResourceLayout);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL)
- }
- GraphicsPipelineResourceLayoutHashTableKey *allocedKey = SDL_malloc(sizeof(GraphicsPipelineResourceLayoutHashTableKey));
- SDL_memcpy(allocedKey, &key, sizeof(GraphicsPipelineResourceLayoutHashTableKey));
- SDL_InsertIntoHashTable(
- renderer->graphicsPipelineResourceLayoutHashTable,
- (const void *)allocedKey,
- (const void *)pipelineResourceLayout);
- return pipelineResourceLayout;
- }
- static VulkanComputePipelineResourceLayout *VULKAN_INTERNAL_FetchComputePipelineResourceLayout(
- VulkanRenderer *renderer,
- const SDL_GPUComputePipelineCreateInfo *createinfo)
- {
- ComputePipelineResourceLayoutHashTableKey key;
- SDL_zero(key);
- VulkanComputePipelineResourceLayout *pipelineResourceLayout = NULL;
- key.samplerCount = createinfo->num_samplers;
- key.readonlyStorageTextureCount = createinfo->num_readonly_storage_textures;
- key.readonlyStorageBufferCount = createinfo->num_readonly_storage_buffers;
- key.readWriteStorageTextureCount = createinfo->num_readwrite_storage_textures;
- key.readWriteStorageBufferCount = createinfo->num_readwrite_storage_buffers;
- key.uniformBufferCount = createinfo->num_uniform_buffers;
- if (SDL_FindInHashTable(
- renderer->computePipelineResourceLayoutHashTable,
- (const void *)&key,
- (const void **)&pipelineResourceLayout)) {
- return pipelineResourceLayout;
- }
- VkDescriptorSetLayout descriptorSetLayouts[3];
- VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
- VkResult vulkanResult;
- pipelineResourceLayout = SDL_calloc(1, sizeof(VulkanComputePipelineResourceLayout));
- pipelineResourceLayout->descriptorSetLayouts[0] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
- renderer,
- VK_SHADER_STAGE_COMPUTE_BIT,
- createinfo->num_samplers,
- createinfo->num_readonly_storage_textures,
- createinfo->num_readonly_storage_buffers,
- 0,
- 0,
- 0);
- pipelineResourceLayout->descriptorSetLayouts[1] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
- renderer,
- VK_SHADER_STAGE_COMPUTE_BIT,
- 0,
- 0,
- 0,
- createinfo->num_readwrite_storage_textures,
- createinfo->num_readwrite_storage_buffers,
- 0);
- pipelineResourceLayout->descriptorSetLayouts[2] = VULKAN_INTERNAL_FetchDescriptorSetLayout(
- renderer,
- VK_SHADER_STAGE_COMPUTE_BIT,
- 0,
- 0,
- 0,
- 0,
- 0,
- createinfo->num_uniform_buffers);
- descriptorSetLayouts[0] = pipelineResourceLayout->descriptorSetLayouts[0]->descriptorSetLayout;
- descriptorSetLayouts[1] = pipelineResourceLayout->descriptorSetLayouts[1]->descriptorSetLayout;
- descriptorSetLayouts[2] = pipelineResourceLayout->descriptorSetLayouts[2]->descriptorSetLayout;
- pipelineResourceLayout->numSamplers = createinfo->num_samplers;
- pipelineResourceLayout->numReadonlyStorageTextures = createinfo->num_readonly_storage_textures;
- pipelineResourceLayout->numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers;
- pipelineResourceLayout->numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
- pipelineResourceLayout->numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
- pipelineResourceLayout->numUniformBuffers = createinfo->num_uniform_buffers;
- // Create the pipeline layout
- pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- pipelineLayoutCreateInfo.pNext = NULL;
- pipelineLayoutCreateInfo.flags = 0;
- pipelineLayoutCreateInfo.setLayoutCount = 3;
- pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts;
- pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
- pipelineLayoutCreateInfo.pPushConstantRanges = NULL;
- vulkanResult = renderer->vkCreatePipelineLayout(
- renderer->logicalDevice,
- &pipelineLayoutCreateInfo,
- NULL,
- &pipelineResourceLayout->pipelineLayout);
- if (vulkanResult != VK_SUCCESS) {
- VULKAN_INTERNAL_DestroyComputePipelineResourceLayout(renderer, pipelineResourceLayout);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreatePipelineLayout, NULL)
- }
- ComputePipelineResourceLayoutHashTableKey *allocedKey = SDL_malloc(sizeof(ComputePipelineResourceLayoutHashTableKey));
- SDL_memcpy(allocedKey, &key, sizeof(ComputePipelineResourceLayoutHashTableKey));
- SDL_InsertIntoHashTable(
- renderer->computePipelineResourceLayoutHashTable,
- (const void *)allocedKey,
- (const void *)pipelineResourceLayout);
- return pipelineResourceLayout;
- }
- // Data Buffer
- static VulkanBuffer *VULKAN_INTERNAL_CreateBuffer(
- VulkanRenderer *renderer,
- VkDeviceSize size,
- SDL_GPUBufferUsageFlags usageFlags,
- VulkanBufferType type)
- {
- VulkanBuffer *buffer;
- VkResult vulkanResult;
- VkBufferCreateInfo createinfo;
- VkBufferUsageFlags vulkanUsageFlags = 0;
- Uint8 bindResult;
- if (usageFlags & SDL_GPU_BUFFERUSAGE_VERTEX) {
- vulkanUsageFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- }
- if (usageFlags & SDL_GPU_BUFFERUSAGE_INDEX) {
- vulkanUsageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
- }
- if (usageFlags & (SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ |
- SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ |
- SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE)) {
- vulkanUsageFlags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
- }
- if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT) {
- vulkanUsageFlags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
- }
- if (type == VULKAN_BUFFER_TYPE_UNIFORM) {
- vulkanUsageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
- } else {
- // GPU buffers need transfer bits for defrag, transfer buffers need them for transfers
- vulkanUsageFlags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- }
- buffer = SDL_malloc(sizeof(VulkanBuffer));
- buffer->size = size;
- buffer->usage = usageFlags;
- buffer->type = type;
- buffer->markedForDestroy = false;
- buffer->transitioned = false;
- createinfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- createinfo.pNext = NULL;
- createinfo.flags = 0;
- createinfo.size = size;
- createinfo.usage = vulkanUsageFlags;
- createinfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- createinfo.queueFamilyIndexCount = 1;
- createinfo.pQueueFamilyIndices = &renderer->queueFamilyIndex;
- // Set transfer bits so we can defrag
- createinfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- vulkanResult = renderer->vkCreateBuffer(
- renderer->logicalDevice,
- &createinfo,
- NULL,
- &buffer->buffer);
- if (vulkanResult != VK_SUCCESS) {
- SDL_free(buffer);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateBuffer, 0)
- }
- bindResult = VULKAN_INTERNAL_BindMemoryForBuffer(
- renderer,
- buffer->buffer,
- buffer->size,
- buffer->type,
- &buffer->usedRegion);
- if (bindResult != 1) {
- renderer->vkDestroyBuffer(
- renderer->logicalDevice,
- buffer->buffer,
- NULL);
- SDL_free(buffer);
- return NULL;
- }
- buffer->usedRegion->vulkanBuffer = buffer; // lol
- SDL_SetAtomicInt(&buffer->referenceCount, 0);
- return buffer;
- }
- static VulkanBufferContainer *VULKAN_INTERNAL_CreateBufferContainer(
- VulkanRenderer *renderer,
- VkDeviceSize size,
- SDL_GPUBufferUsageFlags usageFlags,
- VulkanBufferType type)
- {
- VulkanBufferContainer *bufferContainer;
- VulkanBuffer *buffer;
- buffer = VULKAN_INTERNAL_CreateBuffer(
- renderer,
- size,
- usageFlags,
- type);
- if (buffer == NULL) {
- return NULL;
- }
- bufferContainer = SDL_malloc(sizeof(VulkanBufferContainer));
- bufferContainer->activeBuffer = buffer;
- buffer->container = bufferContainer;
- buffer->containerIndex = 0;
- bufferContainer->bufferCapacity = 1;
- bufferContainer->bufferCount = 1;
- bufferContainer->buffers = SDL_malloc(
- bufferContainer->bufferCapacity * sizeof(VulkanBuffer *));
- bufferContainer->buffers[0] = bufferContainer->activeBuffer;
- bufferContainer->debugName = NULL;
- return bufferContainer;
- }
- // Texture Subresource Utilities
- static Uint32 VULKAN_INTERNAL_GetTextureSubresourceIndex(
- Uint32 mipLevel,
- Uint32 layer,
- Uint32 numLevels)
- {
- return mipLevel + (layer * numLevels);
- }
- static VulkanTextureSubresource *VULKAN_INTERNAL_FetchTextureSubresource(
- VulkanTextureContainer *textureContainer,
- Uint32 layer,
- Uint32 level)
- {
- Uint32 index = VULKAN_INTERNAL_GetTextureSubresourceIndex(
- level,
- layer,
- textureContainer->header.info.num_levels);
- return &textureContainer->activeTexture->subresources[index];
- }
- static bool VULKAN_INTERNAL_CreateRenderTargetView(
- VulkanRenderer *renderer,
- VulkanTexture *texture,
- Uint32 layerOrDepth,
- Uint32 level,
- VkFormat format,
- VkComponentMapping swizzle,
- VkImageView *pView)
- {
- VkResult vulkanResult;
- VkImageViewCreateInfo imageViewCreateInfo;
- // create framebuffer compatible views for RenderTarget
- imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- imageViewCreateInfo.pNext = NULL;
- imageViewCreateInfo.flags = 0;
- imageViewCreateInfo.image = texture->image;
- imageViewCreateInfo.format = format;
- imageViewCreateInfo.components = swizzle;
- imageViewCreateInfo.subresourceRange.aspectMask = texture->aspectFlags;
- imageViewCreateInfo.subresourceRange.baseMipLevel = level;
- imageViewCreateInfo.subresourceRange.levelCount = 1;
- imageViewCreateInfo.subresourceRange.baseArrayLayer = layerOrDepth;
- imageViewCreateInfo.subresourceRange.layerCount = 1;
- imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- vulkanResult = renderer->vkCreateImageView(
- renderer->logicalDevice,
- &imageViewCreateInfo,
- NULL,
- pView);
- if (vulkanResult != VK_SUCCESS) {
- *pView = (VkImageView)VK_NULL_HANDLE;
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateImageView, false)
- }
- return true;
- }
- static bool VULKAN_INTERNAL_CreateSubresourceView(
- VulkanRenderer *renderer,
- const SDL_GPUTextureCreateInfo *createinfo,
- VulkanTexture *texture,
- Uint32 layer,
- Uint32 level,
- VkComponentMapping swizzle,
- VkImageView *pView)
- {
- VkResult vulkanResult;
- VkImageViewCreateInfo imageViewCreateInfo;
- // create framebuffer compatible views for RenderTarget
- imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- imageViewCreateInfo.pNext = NULL;
- imageViewCreateInfo.flags = 0;
- imageViewCreateInfo.image = texture->image;
- imageViewCreateInfo.format = SDLToVK_TextureFormat[createinfo->format];
- imageViewCreateInfo.components = swizzle;
- imageViewCreateInfo.subresourceRange.aspectMask = texture->aspectFlags;
- imageViewCreateInfo.subresourceRange.baseMipLevel = level;
- imageViewCreateInfo.subresourceRange.levelCount = 1;
- imageViewCreateInfo.subresourceRange.baseArrayLayer = layer;
- imageViewCreateInfo.subresourceRange.layerCount = 1;
- imageViewCreateInfo.viewType = (createinfo->type == SDL_GPU_TEXTURETYPE_3D) ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D;
- vulkanResult = renderer->vkCreateImageView(
- renderer->logicalDevice,
- &imageViewCreateInfo,
- NULL,
- pView);
- if (vulkanResult != VK_SUCCESS) {
- *pView = (VkImageView)VK_NULL_HANDLE;
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateImageView, false)
- }
- return true;
- }
- // Swapchain
- static bool VULKAN_INTERNAL_QuerySwapchainSupport(
- VulkanRenderer *renderer,
- VkPhysicalDevice physicalDevice,
- VkSurfaceKHR surface,
- SwapchainSupportDetails *outputDetails)
- {
- VkResult result;
- VkBool32 supportsPresent;
- renderer->vkGetPhysicalDeviceSurfaceSupportKHR(
- physicalDevice,
- renderer->queueFamilyIndex,
- surface,
- &supportsPresent);
- // Initialize these in case anything fails
- outputDetails->formatsLength = 0;
- outputDetails->presentModesLength = 0;
- if (!supportsPresent) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "This surface does not support presenting!");
- return false;
- }
- // Run the device surface queries
- result = renderer->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
- physicalDevice,
- surface,
- &outputDetails->capabilities);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfaceCapabilitiesKHR, false)
- if (!(outputDetails->capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Opaque presentation unsupported! Expect weird transparency bugs!");
- }
- result = renderer->vkGetPhysicalDeviceSurfaceFormatsKHR(
- physicalDevice,
- surface,
- &outputDetails->formatsLength,
- NULL);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfaceFormatsKHR, false)
- result = renderer->vkGetPhysicalDeviceSurfacePresentModesKHR(
- physicalDevice,
- surface,
- &outputDetails->presentModesLength,
- NULL);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfacePresentModesKHR, false)
- // Generate the arrays, if applicable
- outputDetails->formats = NULL;
- if (outputDetails->formatsLength != 0) {
- outputDetails->formats = (VkSurfaceFormatKHR *)SDL_malloc(
- sizeof(VkSurfaceFormatKHR) * outputDetails->formatsLength);
- if (!outputDetails->formats) {
- return 0;
- }
- result = renderer->vkGetPhysicalDeviceSurfaceFormatsKHR(
- physicalDevice,
- surface,
- &outputDetails->formatsLength,
- outputDetails->formats);
- if (result != VK_SUCCESS) {
- SDL_free(outputDetails->formats);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfaceFormatsKHR, false)
- }
- }
- outputDetails->presentModes = NULL;
- if (outputDetails->presentModesLength != 0) {
- outputDetails->presentModes = (VkPresentModeKHR *)SDL_malloc(
- sizeof(VkPresentModeKHR) * outputDetails->presentModesLength);
- if (!outputDetails->presentModes) {
- SDL_free(outputDetails->formats);
- return false;
- }
- result = renderer->vkGetPhysicalDeviceSurfacePresentModesKHR(
- physicalDevice,
- surface,
- &outputDetails->presentModesLength,
- outputDetails->presentModes);
- if (result != VK_SUCCESS) {
- SDL_free(outputDetails->formats);
- SDL_free(outputDetails->presentModes);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkGetPhysicalDeviceSurfacePresentModesKHR, false)
- }
- }
- /* If we made it here, all the queries were successful. This does NOT
- * necessarily mean there are any supported formats or present modes!
- */
- return true;
- }
- static bool VULKAN_INTERNAL_VerifySwapSurfaceFormat(
- VkFormat desiredFormat,
- VkColorSpaceKHR desiredColorSpace,
- VkSurfaceFormatKHR *availableFormats,
- Uint32 availableFormatsLength)
- {
- Uint32 i;
- for (i = 0; i < availableFormatsLength; i += 1) {
- if (availableFormats[i].format == desiredFormat &&
- availableFormats[i].colorSpace == desiredColorSpace) {
- return true;
- }
- }
- return false;
- }
- static bool VULKAN_INTERNAL_VerifySwapPresentMode(
- VkPresentModeKHR presentMode,
- VkPresentModeKHR *availablePresentModes,
- Uint32 availablePresentModesLength)
- {
- Uint32 i;
- for (i = 0; i < availablePresentModesLength; i += 1) {
- if (availablePresentModes[i] == presentMode) {
- return true;
- }
- }
- return false;
- }
- static bool VULKAN_INTERNAL_CreateSwapchain(
- VulkanRenderer *renderer,
- WindowData *windowData)
- {
- VkResult vulkanResult;
- VulkanSwapchainData *swapchainData;
- VkSwapchainCreateInfoKHR swapchainCreateInfo;
- VkImage *swapchainImages;
- VkSemaphoreCreateInfo semaphoreCreateInfo;
- SwapchainSupportDetails swapchainSupportDetails;
- bool hasValidSwapchainComposition, hasValidPresentMode;
- Sint32 drawableWidth, drawableHeight;
- Uint32 i;
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- SDL_assert(_this && _this->Vulkan_CreateSurface);
- swapchainData = SDL_malloc(sizeof(VulkanSwapchainData));
- swapchainData->frameCounter = 0;
- // Each swapchain must have its own surface.
- if (!_this->Vulkan_CreateSurface(
- _this,
- windowData->window,
- renderer->instance,
- NULL, // FIXME: VAllocationCallbacks
- &swapchainData->surface)) {
- SDL_free(swapchainData);
- SDL_LogError(
- SDL_LOG_CATEGORY_GPU,
- "Vulkan_CreateSurface failed: %s",
- SDL_GetError());
- return false;
- }
- if (!VULKAN_INTERNAL_QuerySwapchainSupport(
- renderer,
- renderer->physicalDevice,
- swapchainData->surface,
- &swapchainSupportDetails)) {
- renderer->vkDestroySurfaceKHR(
- renderer->instance,
- swapchainData->surface,
- NULL);
- if (swapchainSupportDetails.formatsLength > 0) {
- SDL_free(swapchainSupportDetails.formats);
- }
- if (swapchainSupportDetails.presentModesLength > 0) {
- SDL_free(swapchainSupportDetails.presentModes);
- }
- SDL_free(swapchainData);
- return false;
- }
- if (swapchainSupportDetails.capabilities.currentExtent.width == 0 ||
- swapchainSupportDetails.capabilities.currentExtent.height == 0) {
- // Not an error, just minimize behavior!
- renderer->vkDestroySurfaceKHR(
- renderer->instance,
- swapchainData->surface,
- NULL);
- if (swapchainSupportDetails.formatsLength > 0) {
- SDL_free(swapchainSupportDetails.formats);
- }
- if (swapchainSupportDetails.presentModesLength > 0) {
- SDL_free(swapchainSupportDetails.presentModes);
- }
- SDL_free(swapchainData);
- return false;
- }
- // Verify that we can use the requested composition and present mode
- swapchainData->format = SwapchainCompositionToFormat[windowData->swapchainComposition];
- swapchainData->colorSpace = SwapchainCompositionToColorSpace[windowData->swapchainComposition];
- swapchainData->swapchainSwizzle = SwapchainCompositionSwizzle[windowData->swapchainComposition];
- swapchainData->usingFallbackFormat = false;
- hasValidSwapchainComposition = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
- swapchainData->format,
- swapchainData->colorSpace,
- swapchainSupportDetails.formats,
- swapchainSupportDetails.formatsLength);
- if (!hasValidSwapchainComposition) {
- // Let's try again with the fallback format...
- swapchainData->format = SwapchainCompositionToFallbackFormat[windowData->swapchainComposition];
- swapchainData->usingFallbackFormat = true;
- hasValidSwapchainComposition = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
- swapchainData->format,
- swapchainData->colorSpace,
- swapchainSupportDetails.formats,
- swapchainSupportDetails.formatsLength);
- }
- swapchainData->presentMode = SDLToVK_PresentMode[windowData->presentMode];
- hasValidPresentMode = VULKAN_INTERNAL_VerifySwapPresentMode(
- swapchainData->presentMode,
- swapchainSupportDetails.presentModes,
- swapchainSupportDetails.presentModesLength);
- if (!hasValidSwapchainComposition || !hasValidPresentMode) {
- renderer->vkDestroySurfaceKHR(
- renderer->instance,
- swapchainData->surface,
- NULL);
- if (swapchainSupportDetails.formatsLength > 0) {
- SDL_free(swapchainSupportDetails.formats);
- }
- if (swapchainSupportDetails.presentModesLength > 0) {
- SDL_free(swapchainSupportDetails.presentModes);
- }
- SDL_free(swapchainData);
- if (!hasValidSwapchainComposition) {
- SET_STRING_ERROR_AND_RETURN("Device does not support requested swapchain composition!", false);
- }
- if (!hasValidPresentMode) {
- SET_STRING_ERROR_AND_RETURN("Device does not support requested present_mode!", false);
- }
- return false;
- }
- // Sync now to be sure that our swapchain size is correct
- SDL_SyncWindow(windowData->window);
- SDL_GetWindowSizeInPixels(
- windowData->window,
- &drawableWidth,
- &drawableHeight);
- if (drawableWidth < (Sint32)swapchainSupportDetails.capabilities.minImageExtent.width ||
- drawableWidth > (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.width ||
- drawableHeight < (Sint32)swapchainSupportDetails.capabilities.minImageExtent.height ||
- drawableHeight > (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.height) {
- if (swapchainSupportDetails.capabilities.currentExtent.width != SDL_MAX_UINT32) {
- drawableWidth = VULKAN_INTERNAL_clamp(
- drawableWidth,
- (Sint32)swapchainSupportDetails.capabilities.minImageExtent.width,
- (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.width);
- drawableHeight = VULKAN_INTERNAL_clamp(
- drawableHeight,
- (Sint32)swapchainSupportDetails.capabilities.minImageExtent.height,
- (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.height);
- } else {
- renderer->vkDestroySurfaceKHR(
- renderer->instance,
- swapchainData->surface,
- NULL);
- if (swapchainSupportDetails.formatsLength > 0) {
- SDL_free(swapchainSupportDetails.formats);
- }
- if (swapchainSupportDetails.presentModesLength > 0) {
- SDL_free(swapchainSupportDetails.presentModes);
- }
- SDL_free(swapchainData);
- SET_STRING_ERROR_AND_RETURN("No fallback swapchain size available!", false);
- }
- }
- swapchainData->imageCount = MAX_FRAMES_IN_FLIGHT;
- if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
- swapchainData->imageCount > swapchainSupportDetails.capabilities.maxImageCount) {
- swapchainData->imageCount = swapchainSupportDetails.capabilities.maxImageCount;
- }
- if (swapchainData->imageCount < swapchainSupportDetails.capabilities.minImageCount) {
- swapchainData->imageCount = swapchainSupportDetails.capabilities.minImageCount;
- }
- if (swapchainData->presentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
- /* Required for proper triple-buffering.
- * Note that this is below the above maxImageCount check!
- * If the driver advertises MAILBOX but does not support 3 swap
- * images, it's not real mailbox support, so let it fail hard.
- * -flibit
- */
- swapchainData->imageCount = SDL_max(swapchainData->imageCount, 3);
- }
- swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
- swapchainCreateInfo.pNext = NULL;
- swapchainCreateInfo.flags = 0;
- swapchainCreateInfo.surface = swapchainData->surface;
- swapchainCreateInfo.minImageCount = swapchainData->imageCount;
- swapchainCreateInfo.imageFormat = swapchainData->format;
- swapchainCreateInfo.imageColorSpace = swapchainData->colorSpace;
- swapchainCreateInfo.imageExtent.width = drawableWidth;
- swapchainCreateInfo.imageExtent.height = drawableHeight;
- swapchainCreateInfo.imageArrayLayers = 1;
- swapchainCreateInfo.imageUsage =
- VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
- VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapchainCreateInfo.queueFamilyIndexCount = 0;
- swapchainCreateInfo.pQueueFamilyIndices = NULL;
- swapchainCreateInfo.preTransform = swapchainSupportDetails.capabilities.currentTransform;
- swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- swapchainCreateInfo.presentMode = swapchainData->presentMode;
- swapchainCreateInfo.clipped = VK_TRUE;
- swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
- vulkanResult = renderer->vkCreateSwapchainKHR(
- renderer->logicalDevice,
- &swapchainCreateInfo,
- NULL,
- &swapchainData->swapchain);
- if (swapchainSupportDetails.formatsLength > 0) {
- SDL_free(swapchainSupportDetails.formats);
- }
- if (swapchainSupportDetails.presentModesLength > 0) {
- SDL_free(swapchainSupportDetails.presentModes);
- }
- if (vulkanResult != VK_SUCCESS) {
- renderer->vkDestroySurfaceKHR(
- renderer->instance,
- swapchainData->surface,
- NULL);
- SDL_free(swapchainData);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSwapchainKHR, false)
- }
- renderer->vkGetSwapchainImagesKHR(
- renderer->logicalDevice,
- swapchainData->swapchain,
- &swapchainData->imageCount,
- NULL);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkGetSwapchainImagesKHR, false)
- swapchainData->textureContainers = SDL_malloc(
- sizeof(VulkanTextureContainer) * swapchainData->imageCount);
- if (!swapchainData->textureContainers) {
- renderer->vkDestroySurfaceKHR(
- renderer->instance,
- swapchainData->surface,
- NULL);
- SDL_free(swapchainData);
- return false;
- }
- swapchainImages = SDL_stack_alloc(VkImage, swapchainData->imageCount);
- vulkanResult = renderer->vkGetSwapchainImagesKHR(
- renderer->logicalDevice,
- swapchainData->swapchain,
- &swapchainData->imageCount,
- swapchainImages);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkGetSwapchainImagesKHR, false)
- for (i = 0; i < swapchainData->imageCount; i += 1) {
- // Initialize dummy container
- SDL_zero(swapchainData->textureContainers[i]);
- swapchainData->textureContainers[i].canBeCycled = false;
- swapchainData->textureContainers[i].header.info.width = drawableWidth;
- swapchainData->textureContainers[i].header.info.height = drawableHeight;
- swapchainData->textureContainers[i].header.info.layer_count_or_depth = 1;
- swapchainData->textureContainers[i].header.info.format = SwapchainCompositionToSDLFormat(
- windowData->swapchainComposition,
- swapchainData->usingFallbackFormat);
- swapchainData->textureContainers[i].header.info.type = SDL_GPU_TEXTURETYPE_2D;
- swapchainData->textureContainers[i].header.info.num_levels = 1;
- swapchainData->textureContainers[i].header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
- swapchainData->textureContainers[i].header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
- swapchainData->textureContainers[i].activeTexture = SDL_malloc(sizeof(VulkanTexture));
- swapchainData->textureContainers[i].activeTexture->image = swapchainImages[i];
- // Swapchain memory is managed by the driver
- swapchainData->textureContainers[i].activeTexture->usedRegion = NULL;
- swapchainData->textureContainers[i].activeTexture->swizzle = swapchainData->swapchainSwizzle;
- swapchainData->textureContainers[i].activeTexture->aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
- swapchainData->textureContainers[i].activeTexture->depth = 1;
- swapchainData->textureContainers[i].activeTexture->usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
- swapchainData->textureContainers[i].activeTexture->container = &swapchainData->textureContainers[i];
- SDL_SetAtomicInt(&swapchainData->textureContainers[i].activeTexture->referenceCount, 0);
- // Create slice
- swapchainData->textureContainers[i].activeTexture->subresourceCount = 1;
- swapchainData->textureContainers[i].activeTexture->subresources = SDL_malloc(sizeof(VulkanTextureSubresource));
- swapchainData->textureContainers[i].activeTexture->subresources[0].parent = swapchainData->textureContainers[i].activeTexture;
- swapchainData->textureContainers[i].activeTexture->subresources[0].layer = 0;
- swapchainData->textureContainers[i].activeTexture->subresources[0].level = 0;
- swapchainData->textureContainers[i].activeTexture->subresources[0].transitioned = true;
- swapchainData->textureContainers[i].activeTexture->subresources[0].renderTargetViews = SDL_malloc(sizeof(VkImageView));
- // TODO: ERROR CHECK
- if (!VULKAN_INTERNAL_CreateRenderTargetView(
- renderer,
- swapchainData->textureContainers[i].activeTexture,
- 0,
- 0,
- swapchainData->format,
- swapchainData->swapchainSwizzle,
- &swapchainData->textureContainers[i].activeTexture->subresources[0].renderTargetViews[0])) {
- SDL_free(swapchainData);
- return false;
- }
- }
- SDL_stack_free(swapchainImages);
- semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphoreCreateInfo.pNext = NULL;
- semaphoreCreateInfo.flags = 0;
- for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
- vulkanResult = renderer->vkCreateSemaphore(
- renderer->logicalDevice,
- &semaphoreCreateInfo,
- NULL,
- &swapchainData->imageAvailableSemaphore[i]);
- if (vulkanResult != VK_SUCCESS) {
- SDL_free(swapchainData);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false)
- }
- renderer->vkCreateSemaphore(
- renderer->logicalDevice,
- &semaphoreCreateInfo,
- NULL,
- &swapchainData->renderFinishedSemaphore[i]);
- if (vulkanResult != VK_SUCCESS) {
- SDL_free(swapchainData);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSemaphore, false)
- }
- swapchainData->inFlightFences[i] = NULL;
- }
- windowData->swapchainData = swapchainData;
- windowData->needsSwapchainRecreate = false;
- return true;
- }
- // Command Buffers
- static bool VULKAN_INTERNAL_BeginCommandBuffer(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer)
- {
- VkCommandBufferBeginInfo beginInfo;
- VkResult result;
- beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- beginInfo.pNext = NULL;
- beginInfo.flags = 0;
- beginInfo.pInheritanceInfo = NULL;
- beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
- result = renderer->vkBeginCommandBuffer(
- commandBuffer->commandBuffer,
- &beginInfo);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkBeginCommandBuffer, false)
- return true;
- }
- static bool VULKAN_INTERNAL_EndCommandBuffer(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer)
- {
- VkResult result = renderer->vkEndCommandBuffer(
- commandBuffer->commandBuffer);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkEndCommandBuffer, false)
- return true;
- }
- static void VULKAN_DestroyDevice(
- SDL_GPUDevice *device)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)device->driverData;
- VulkanMemorySubAllocator *allocator;
- VULKAN_Wait(device->driverData);
- for (Sint32 i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) {
- VULKAN_ReleaseWindow(device->driverData, renderer->claimedWindows[i]->window);
- }
- SDL_free(renderer->claimedWindows);
- VULKAN_Wait(device->driverData);
- SDL_free(renderer->submittedCommandBuffers);
- for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
- VULKAN_INTERNAL_DestroyBuffer(
- renderer,
- renderer->uniformBufferPool[i]->buffer);
- SDL_free(renderer->uniformBufferPool[i]);
- }
- SDL_free(renderer->uniformBufferPool);
- for (Uint32 i = 0; i < renderer->descriptorSetCachePoolCount; i += 1) {
- VULKAN_INTERNAL_DestroyDescriptorSetCache(
- renderer,
- renderer->descriptorSetCachePool[i]);
- }
- SDL_free(renderer->descriptorSetCachePool);
- for (Uint32 i = 0; i < renderer->fencePool.availableFenceCount; i += 1) {
- renderer->vkDestroyFence(
- renderer->logicalDevice,
- renderer->fencePool.availableFences[i]->fence,
- NULL);
- SDL_free(renderer->fencePool.availableFences[i]);
- }
- SDL_free(renderer->fencePool.availableFences);
- SDL_DestroyMutex(renderer->fencePool.lock);
- SDL_DestroyHashTable(renderer->commandPoolHashTable);
- SDL_DestroyHashTable(renderer->renderPassHashTable);
- SDL_DestroyHashTable(renderer->framebufferHashTable);
- SDL_DestroyHashTable(renderer->graphicsPipelineResourceLayoutHashTable);
- SDL_DestroyHashTable(renderer->computePipelineResourceLayoutHashTable);
- SDL_DestroyHashTable(renderer->descriptorSetLayoutHashTable);
- for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
- allocator = &renderer->memoryAllocator->subAllocators[i];
- for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
- for (Sint32 k = allocator->allocations[j]->usedRegionCount - 1; k >= 0; k -= 1) {
- VULKAN_INTERNAL_RemoveMemoryUsedRegion(
- renderer,
- allocator->allocations[j]->usedRegions[k]);
- }
- VULKAN_INTERNAL_DeallocateMemory(
- renderer,
- allocator,
- j);
- }
- if (renderer->memoryAllocator->subAllocators[i].allocations != NULL) {
- SDL_free(renderer->memoryAllocator->subAllocators[i].allocations);
- }
- SDL_free(renderer->memoryAllocator->subAllocators[i].sortedFreeRegions);
- }
- SDL_free(renderer->memoryAllocator);
- SDL_free(renderer->texturesToDestroy);
- SDL_free(renderer->buffersToDestroy);
- SDL_free(renderer->graphicsPipelinesToDestroy);
- SDL_free(renderer->computePipelinesToDestroy);
- SDL_free(renderer->shadersToDestroy);
- SDL_free(renderer->samplersToDestroy);
- SDL_free(renderer->framebuffersToDestroy);
- SDL_free(renderer->allocationsToDefrag);
- SDL_DestroyMutex(renderer->allocatorLock);
- SDL_DestroyMutex(renderer->disposeLock);
- SDL_DestroyMutex(renderer->submitLock);
- SDL_DestroyMutex(renderer->acquireCommandBufferLock);
- SDL_DestroyMutex(renderer->acquireUniformBufferLock);
- SDL_DestroyMutex(renderer->renderPassFetchLock);
- SDL_DestroyMutex(renderer->framebufferFetchLock);
- renderer->vkDestroyDevice(renderer->logicalDevice, NULL);
- renderer->vkDestroyInstance(renderer->instance, NULL);
- SDL_free(renderer);
- SDL_free(device);
- SDL_Vulkan_UnloadLibrary();
- }
- static DescriptorSetCache *VULKAN_INTERNAL_AcquireDescriptorSetCache(
- VulkanRenderer *renderer)
- {
- DescriptorSetCache *cache;
- if (renderer->descriptorSetCachePoolCount == 0) {
- cache = SDL_malloc(sizeof(DescriptorSetCache));
- cache->poolCount = 0;
- cache->pools = NULL;
- } else {
- cache = renderer->descriptorSetCachePool[renderer->descriptorSetCachePoolCount - 1];
- renderer->descriptorSetCachePoolCount -= 1;
- }
- return cache;
- }
- static void VULKAN_INTERNAL_ReturnDescriptorSetCacheToPool(
- VulkanRenderer *renderer,
- DescriptorSetCache *descriptorSetCache)
- {
- EXPAND_ARRAY_IF_NEEDED(
- renderer->descriptorSetCachePool,
- DescriptorSetCache *,
- renderer->descriptorSetCachePoolCount + 1,
- renderer->descriptorSetCachePoolCapacity,
- renderer->descriptorSetCachePoolCapacity * 2)
- renderer->descriptorSetCachePool[renderer->descriptorSetCachePoolCount] = descriptorSetCache;
- renderer->descriptorSetCachePoolCount += 1;
- for (Uint32 i = 0; i < descriptorSetCache->poolCount; i += 1) {
- descriptorSetCache->pools[i].descriptorSetIndex = 0;
- }
- }
- static VkDescriptorSet VULKAN_INTERNAL_FetchDescriptorSet(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *vulkanCommandBuffer,
- DescriptorSetLayout *descriptorSetLayout)
- {
- // Grow the pool to meet the descriptor set layout ID
- if (descriptorSetLayout->ID >= vulkanCommandBuffer->descriptorSetCache->poolCount) {
- vulkanCommandBuffer->descriptorSetCache->pools = SDL_realloc(
- vulkanCommandBuffer->descriptorSetCache->pools,
- sizeof(DescriptorSetPool) * (descriptorSetLayout->ID + 1));
- for (Uint32 i = vulkanCommandBuffer->descriptorSetCache->poolCount; i < descriptorSetLayout->ID + 1; i += 1) {
- SDL_zero(vulkanCommandBuffer->descriptorSetCache->pools[i]);
- }
- vulkanCommandBuffer->descriptorSetCache->poolCount = descriptorSetLayout->ID + 1;
- }
- DescriptorSetPool *pool =
- &vulkanCommandBuffer->descriptorSetCache->pools[descriptorSetLayout->ID];
- if (pool->descriptorSetIndex == pool->descriptorSetCount) {
- if (!VULKAN_INTERNAL_AllocateDescriptorsFromPool(
- renderer,
- descriptorSetLayout,
- pool)) {
- return VK_NULL_HANDLE;
- }
- }
- VkDescriptorSet descriptorSet = pool->descriptorSets[pool->descriptorSetIndex];
- pool->descriptorSetIndex += 1;
- return descriptorSet;
- }
- static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer)
- {
- VulkanGraphicsPipelineResourceLayout *resourceLayout;
- DescriptorSetLayout *descriptorSetLayout;
- VkWriteDescriptorSet writeDescriptorSets[
- (MAX_TEXTURE_SAMPLERS_PER_STAGE +
- MAX_STORAGE_TEXTURES_PER_STAGE +
- MAX_STORAGE_BUFFERS_PER_STAGE +
- MAX_UNIFORM_BUFFERS_PER_STAGE) * 2];
- VkDescriptorBufferInfo bufferInfos[MAX_STORAGE_BUFFERS_PER_STAGE * 2];
- VkDescriptorImageInfo imageInfos[(MAX_TEXTURE_SAMPLERS_PER_STAGE + MAX_STORAGE_TEXTURES_PER_STAGE) * 2];
- Uint32 dynamicOffsets[MAX_UNIFORM_BUFFERS_PER_STAGE * 2];
- Uint32 writeCount = 0;
- Uint32 bufferInfoCount = 0;
- Uint32 imageInfoCount = 0;
- Uint32 dynamicOffsetCount = 0;
- if (
- !commandBuffer->needNewVertexResourceDescriptorSet &&
- !commandBuffer->needNewVertexUniformDescriptorSet &&
- !commandBuffer->needNewVertexUniformOffsets &&
- !commandBuffer->needNewFragmentResourceDescriptorSet &&
- !commandBuffer->needNewFragmentUniformDescriptorSet &&
- !commandBuffer->needNewFragmentUniformOffsets
- ) {
- return;
- }
- resourceLayout = commandBuffer->currentGraphicsPipeline->resourceLayout;
- if (commandBuffer->needNewVertexResourceDescriptorSet) {
- descriptorSetLayout = resourceLayout->descriptorSetLayouts[0];
- commandBuffer->vertexResourceDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
- renderer,
- commandBuffer,
- descriptorSetLayout);
- for (Uint32 i = 0; i < resourceLayout->vertexSamplerCount; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = i;
- currentWriteDescriptorSet->dstSet = commandBuffer->vertexResourceDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pBufferInfo = NULL;
- imageInfos[imageInfoCount].sampler = commandBuffer->vertexSamplers[i]->sampler;
- imageInfos[imageInfoCount].imageView = commandBuffer->vertexSamplerTextures[i]->fullView;
- imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
- writeCount += 1;
- imageInfoCount += 1;
- }
- for (Uint32 i = 0; i < resourceLayout->vertexStorageTextureCount; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = resourceLayout->vertexSamplerCount + i;
- currentWriteDescriptorSet->dstSet = commandBuffer->vertexResourceDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pBufferInfo = NULL;
- imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
- imageInfos[imageInfoCount].imageView = commandBuffer->vertexStorageTextures[i]->fullView;
- imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
- currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
- writeCount += 1;
- imageInfoCount += 1;
- }
- for (Uint32 i = 0; i < resourceLayout->vertexStorageBufferCount; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = resourceLayout->vertexSamplerCount + resourceLayout->vertexStorageTextureCount + i;
- currentWriteDescriptorSet->dstSet = commandBuffer->vertexResourceDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pImageInfo = NULL;
- bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexStorageBuffers[i]->buffer;
- bufferInfos[bufferInfoCount].offset = 0;
- bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
- currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
- writeCount += 1;
- bufferInfoCount += 1;
- }
- commandBuffer->needNewVertexResourceDescriptorSet = false;
- }
- if (commandBuffer->needNewVertexUniformDescriptorSet) {
- descriptorSetLayout = resourceLayout->descriptorSetLayouts[1];
- commandBuffer->vertexUniformDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
- renderer,
- commandBuffer,
- descriptorSetLayout);
- for (Uint32 i = 0; i < resourceLayout->vertexUniformBufferCount; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = i;
- currentWriteDescriptorSet->dstSet = commandBuffer->vertexUniformDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pImageInfo = NULL;
- bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexUniformBuffers[i]->buffer->buffer;
- bufferInfos[bufferInfoCount].offset = 0;
- bufferInfos[bufferInfoCount].range = MAX_UBO_SECTION_SIZE;
- currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
- writeCount += 1;
- bufferInfoCount += 1;
- }
- commandBuffer->needNewVertexUniformDescriptorSet = false;
- }
- for (Uint32 i = 0; i < resourceLayout->vertexUniformBufferCount; i += 1) {
- dynamicOffsets[dynamicOffsetCount] = commandBuffer->vertexUniformBuffers[i]->drawOffset;
- dynamicOffsetCount += 1;
- }
- if (commandBuffer->needNewFragmentResourceDescriptorSet) {
- descriptorSetLayout = resourceLayout->descriptorSetLayouts[2];
- commandBuffer->fragmentResourceDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
- renderer,
- commandBuffer,
- descriptorSetLayout);
- for (Uint32 i = 0; i < resourceLayout->fragmentSamplerCount; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = i;
- currentWriteDescriptorSet->dstSet = commandBuffer->fragmentResourceDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pBufferInfo = NULL;
- imageInfos[imageInfoCount].sampler = commandBuffer->fragmentSamplers[i]->sampler;
- imageInfos[imageInfoCount].imageView = commandBuffer->fragmentSamplerTextures[i]->fullView;
- imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
- writeCount += 1;
- imageInfoCount += 1;
- }
- for (Uint32 i = 0; i < resourceLayout->fragmentStorageTextureCount; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = resourceLayout->fragmentSamplerCount + i;
- currentWriteDescriptorSet->dstSet = commandBuffer->fragmentResourceDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pBufferInfo = NULL;
- imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
- imageInfos[imageInfoCount].imageView = commandBuffer->fragmentStorageTextures[i]->fullView;
- imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
- currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
- writeCount += 1;
- imageInfoCount += 1;
- }
- for (Uint32 i = 0; i < resourceLayout->fragmentStorageBufferCount; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = resourceLayout->fragmentSamplerCount + resourceLayout->fragmentStorageTextureCount + i;
- currentWriteDescriptorSet->dstSet = commandBuffer->fragmentResourceDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pImageInfo = NULL;
- bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentStorageBuffers[i]->buffer;
- bufferInfos[bufferInfoCount].offset = 0;
- bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
- currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
- writeCount += 1;
- bufferInfoCount += 1;
- }
- commandBuffer->needNewFragmentResourceDescriptorSet = false;
- }
- if (commandBuffer->needNewFragmentUniformDescriptorSet) {
- descriptorSetLayout = resourceLayout->descriptorSetLayouts[3];
- commandBuffer->fragmentUniformDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
- renderer,
- commandBuffer,
- descriptorSetLayout);
- for (Uint32 i = 0; i < resourceLayout->fragmentUniformBufferCount; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = i;
- currentWriteDescriptorSet->dstSet = commandBuffer->fragmentUniformDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pImageInfo = NULL;
- bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentUniformBuffers[i]->buffer->buffer;
- bufferInfos[bufferInfoCount].offset = 0;
- bufferInfos[bufferInfoCount].range = MAX_UBO_SECTION_SIZE;
- currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
- writeCount += 1;
- bufferInfoCount += 1;
- }
- commandBuffer->needNewFragmentUniformDescriptorSet = false;
- }
- for (Uint32 i = 0; i < resourceLayout->fragmentUniformBufferCount; i += 1) {
- dynamicOffsets[dynamicOffsetCount] = commandBuffer->fragmentUniformBuffers[i]->drawOffset;
- dynamicOffsetCount += 1;
- }
- renderer->vkUpdateDescriptorSets(
- renderer->logicalDevice,
- writeCount,
- writeDescriptorSets,
- 0,
- NULL);
- VkDescriptorSet sets[4];
- sets[0] = commandBuffer->vertexResourceDescriptorSet;
- sets[1] = commandBuffer->vertexUniformDescriptorSet;
- sets[2] = commandBuffer->fragmentResourceDescriptorSet;
- sets[3] = commandBuffer->fragmentUniformDescriptorSet;
- renderer->vkCmdBindDescriptorSets(
- commandBuffer->commandBuffer,
- VK_PIPELINE_BIND_POINT_GRAPHICS,
- resourceLayout->pipelineLayout,
- 0,
- 4,
- sets,
- dynamicOffsetCount,
- dynamicOffsets);
- commandBuffer->needNewVertexUniformOffsets = false;
- commandBuffer->needNewFragmentUniformOffsets = false;
- }
- static void VULKAN_DrawIndexedPrimitives(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 numIndices,
- Uint32 numInstances,
- Uint32 firstIndex,
- Sint32 vertexOffset,
- Uint32 firstInstance)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
- renderer->vkCmdDrawIndexed(
- vulkanCommandBuffer->commandBuffer,
- numIndices,
- numInstances,
- firstIndex,
- vertexOffset,
- firstInstance);
- }
- static void VULKAN_DrawPrimitives(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 numVertices,
- Uint32 numInstances,
- Uint32 firstVertex,
- Uint32 firstInstance)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
- renderer->vkCmdDraw(
- vulkanCommandBuffer->commandBuffer,
- numVertices,
- numInstances,
- firstVertex,
- firstInstance);
- }
- static void VULKAN_DrawPrimitivesIndirect(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUBuffer *buffer,
- Uint32 offset,
- Uint32 drawCount)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)buffer)->activeBuffer;
- Uint32 pitch = sizeof(SDL_GPUIndirectDrawCommand);
- Uint32 i;
- VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
- if (renderer->supportsMultiDrawIndirect) {
- // Real multi-draw!
- renderer->vkCmdDrawIndirect(
- vulkanCommandBuffer->commandBuffer,
- vulkanBuffer->buffer,
- offset,
- drawCount,
- pitch);
- } else {
- // Fake multi-draw...
- for (i = 0; i < drawCount; i += 1) {
- renderer->vkCmdDrawIndirect(
- vulkanCommandBuffer->commandBuffer,
- vulkanBuffer->buffer,
- offset + (pitch * i),
- 1,
- pitch);
- }
- }
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
- }
- static void VULKAN_DrawIndexedPrimitivesIndirect(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUBuffer *buffer,
- Uint32 offset,
- Uint32 drawCount)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)buffer)->activeBuffer;
- Uint32 pitch = sizeof(SDL_GPUIndexedIndirectDrawCommand);
- Uint32 i;
- VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
- if (renderer->supportsMultiDrawIndirect) {
- // Real multi-draw!
- renderer->vkCmdDrawIndexedIndirect(
- vulkanCommandBuffer->commandBuffer,
- vulkanBuffer->buffer,
- offset,
- drawCount,
- pitch);
- } else {
- // Fake multi-draw...
- for (i = 0; i < drawCount; i += 1) {
- renderer->vkCmdDrawIndexedIndirect(
- vulkanCommandBuffer->commandBuffer,
- vulkanBuffer->buffer,
- offset + (pitch * i),
- 1,
- pitch);
- }
- }
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
- }
- // Debug Naming
- static void VULKAN_INTERNAL_SetBufferName(
- VulkanRenderer *renderer,
- VulkanBuffer *buffer,
- const char *text)
- {
- VkDebugUtilsObjectNameInfoEXT nameInfo;
- if (renderer->debugMode && renderer->supportsDebugUtils) {
- nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
- nameInfo.pNext = NULL;
- nameInfo.pObjectName = text;
- nameInfo.objectType = VK_OBJECT_TYPE_BUFFER;
- nameInfo.objectHandle = (uint64_t)buffer->buffer;
- renderer->vkSetDebugUtilsObjectNameEXT(
- renderer->logicalDevice,
- &nameInfo);
- }
- }
- static void VULKAN_SetBufferName(
- SDL_GPURenderer *driverData,
- SDL_GPUBuffer *buffer,
- const char *text)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanBufferContainer *container = (VulkanBufferContainer *)buffer;
- size_t textLength = SDL_strlen(text) + 1;
- if (renderer->debugMode && renderer->supportsDebugUtils) {
- container->debugName = SDL_realloc(
- container->debugName,
- textLength);
- SDL_utf8strlcpy(
- container->debugName,
- text,
- textLength);
- for (Uint32 i = 0; i < container->bufferCount; i += 1) {
- VULKAN_INTERNAL_SetBufferName(
- renderer,
- container->buffers[i],
- text);
- }
- }
- }
- static void VULKAN_INTERNAL_SetTextureName(
- VulkanRenderer *renderer,
- VulkanTexture *texture,
- const char *text)
- {
- VkDebugUtilsObjectNameInfoEXT nameInfo;
- if (renderer->debugMode && renderer->supportsDebugUtils) {
- nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
- nameInfo.pNext = NULL;
- nameInfo.pObjectName = text;
- nameInfo.objectType = VK_OBJECT_TYPE_IMAGE;
- nameInfo.objectHandle = (uint64_t)texture->image;
- renderer->vkSetDebugUtilsObjectNameEXT(
- renderer->logicalDevice,
- &nameInfo);
- }
- }
- static void VULKAN_SetTextureName(
- SDL_GPURenderer *driverData,
- SDL_GPUTexture *texture,
- const char *text)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanTextureContainer *container = (VulkanTextureContainer *)texture;
- size_t textLength = SDL_strlen(text) + 1;
- if (renderer->debugMode && renderer->supportsDebugUtils) {
- container->debugName = SDL_realloc(
- container->debugName,
- textLength);
- SDL_utf8strlcpy(
- container->debugName,
- text,
- textLength);
- for (Uint32 i = 0; i < container->textureCount; i += 1) {
- VULKAN_INTERNAL_SetTextureName(
- renderer,
- container->textures[i],
- text);
- }
- }
- }
- static void VULKAN_InsertDebugLabel(
- SDL_GPUCommandBuffer *commandBuffer,
- const char *text)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VkDebugUtilsLabelEXT labelInfo;
- if (renderer->supportsDebugUtils) {
- labelInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
- labelInfo.pNext = NULL;
- labelInfo.pLabelName = text;
- renderer->vkCmdInsertDebugUtilsLabelEXT(
- vulkanCommandBuffer->commandBuffer,
- &labelInfo);
- }
- }
- static void VULKAN_PushDebugGroup(
- SDL_GPUCommandBuffer *commandBuffer,
- const char *name)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VkDebugUtilsLabelEXT labelInfo;
- if (renderer->supportsDebugUtils) {
- labelInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
- labelInfo.pNext = NULL;
- labelInfo.pLabelName = name;
- renderer->vkCmdBeginDebugUtilsLabelEXT(
- vulkanCommandBuffer->commandBuffer,
- &labelInfo);
- }
- }
- static void VULKAN_PopDebugGroup(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- if (renderer->supportsDebugUtils) {
- renderer->vkCmdEndDebugUtilsLabelEXT(vulkanCommandBuffer->commandBuffer);
- }
- }
- static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
- VulkanRenderer *renderer,
- const SDL_GPUTextureCreateInfo *createinfo)
- {
- VkResult vulkanResult;
- VkImageCreateInfo imageCreateInfo;
- VkImageCreateFlags imageCreateFlags = 0;
- VkImageViewCreateInfo imageViewCreateInfo;
- Uint8 bindResult;
- VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- Uint32 layerCount = (createinfo->type == SDL_GPU_TEXTURETYPE_3D) ? 1 : createinfo->layer_count_or_depth;
- Uint32 depth = (createinfo->type == SDL_GPU_TEXTURETYPE_3D) ? createinfo->layer_count_or_depth : 1;
- VulkanTexture *texture = SDL_calloc(1, sizeof(VulkanTexture));
- texture->swizzle = SwizzleForSDLFormat(createinfo->format);
- texture->depth = depth;
- texture->usage = createinfo->usage;
- SDL_SetAtomicInt(&texture->referenceCount, 0);
- if (IsDepthFormat(createinfo->format)) {
- texture->aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
- if (IsStencilFormat(createinfo->format)) {
- texture->aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
- }
- } else {
- texture->aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
- }
- if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
- imageCreateFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
- } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
- imageCreateFlags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
- }
- if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) {
- vkUsageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
- }
- if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
- vkUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
- }
- if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
- vkUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
- }
- if (createinfo->usage & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ |
- SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ |
- SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE |
- SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) {
- vkUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
- }
- imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- imageCreateInfo.pNext = NULL;
- imageCreateInfo.flags = imageCreateFlags;
- imageCreateInfo.imageType = createinfo->type == SDL_GPU_TEXTURETYPE_3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
- imageCreateInfo.format = SDLToVK_TextureFormat[createinfo->format];
- imageCreateInfo.extent.width = createinfo->width;
- imageCreateInfo.extent.height = createinfo->height;
- imageCreateInfo.extent.depth = depth;
- imageCreateInfo.mipLevels = createinfo->num_levels;
- imageCreateInfo.arrayLayers = layerCount;
- imageCreateInfo.samples = SDLToVK_SampleCount[createinfo->sample_count];
- imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
- imageCreateInfo.usage = vkUsageFlags;
- imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- imageCreateInfo.queueFamilyIndexCount = 0;
- imageCreateInfo.pQueueFamilyIndices = NULL;
- imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- vulkanResult = renderer->vkCreateImage(
- renderer->logicalDevice,
- &imageCreateInfo,
- NULL,
- &texture->image);
- if (vulkanResult != VK_SUCCESS) {
- VULKAN_INTERNAL_DestroyTexture(renderer, texture);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateImage, NULL)
- }
- bindResult = VULKAN_INTERNAL_BindMemoryForImage(
- renderer,
- texture->image,
- &texture->usedRegion);
- if (bindResult != 1) {
- renderer->vkDestroyImage(
- renderer->logicalDevice,
- texture->image,
- NULL);
- VULKAN_INTERNAL_DestroyTexture(renderer, texture);
- SET_STRING_ERROR_AND_RETURN("Unable to bind memory for texture!", NULL)
- }
- texture->usedRegion->vulkanTexture = texture; // lol
- if (createinfo->usage & (SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)) {
- imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- imageViewCreateInfo.pNext = NULL;
- imageViewCreateInfo.flags = 0;
- imageViewCreateInfo.image = texture->image;
- imageViewCreateInfo.format = SDLToVK_TextureFormat[createinfo->format];
- imageViewCreateInfo.components = texture->swizzle;
- imageViewCreateInfo.subresourceRange.aspectMask = texture->aspectFlags;
- imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
- imageViewCreateInfo.subresourceRange.levelCount = createinfo->num_levels;
- imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
- imageViewCreateInfo.subresourceRange.layerCount = layerCount;
- if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
- imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
- } else if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
- imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
- } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
- imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
- } else if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
- imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
- } else {
- imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- }
- vulkanResult = renderer->vkCreateImageView(
- renderer->logicalDevice,
- &imageViewCreateInfo,
- NULL,
- &texture->fullView);
- if (vulkanResult != VK_SUCCESS) {
- VULKAN_INTERNAL_DestroyTexture(renderer, texture);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, "vkCreateImageView", NULL)
- }
- }
- // Define slices
- texture->subresourceCount = layerCount * createinfo->num_levels;
- texture->subresources = SDL_calloc(
- texture->subresourceCount,
- sizeof(VulkanTextureSubresource));
- for (Uint32 i = 0; i < layerCount; i += 1) {
- for (Uint32 j = 0; j < createinfo->num_levels; j += 1) {
- Uint32 subresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
- j,
- i,
- createinfo->num_levels);
- if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
- texture->subresources[subresourceIndex].renderTargetViews = SDL_malloc(
- depth * sizeof(VkImageView));
- if (depth > 1) {
- for (Uint32 k = 0; k < depth; k += 1) {
- if (!VULKAN_INTERNAL_CreateRenderTargetView(
- renderer,
- texture,
- k,
- j,
- SDLToVK_TextureFormat[createinfo->format],
- texture->swizzle,
- &texture->subresources[subresourceIndex].renderTargetViews[k])) {
- VULKAN_INTERNAL_DestroyTexture(renderer, texture);
- return NULL;
- }
- }
- } else {
- if (!VULKAN_INTERNAL_CreateRenderTargetView(
- renderer,
- texture,
- i,
- j,
- SDLToVK_TextureFormat[createinfo->format],
- texture->swizzle,
- &texture->subresources[subresourceIndex].renderTargetViews[0])) {
- VULKAN_INTERNAL_DestroyTexture(renderer, texture);
- return NULL;
- }
- }
- }
- if ((createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) || (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) {
- if (!VULKAN_INTERNAL_CreateSubresourceView(
- renderer,
- createinfo,
- texture,
- i,
- j,
- texture->swizzle,
- &texture->subresources[subresourceIndex].computeWriteView)) {
- VULKAN_INTERNAL_DestroyTexture(renderer, texture);
- return NULL;
- }
- }
- if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
- if (!VULKAN_INTERNAL_CreateSubresourceView(
- renderer,
- createinfo,
- texture,
- i,
- j,
- texture->swizzle,
- &texture->subresources[subresourceIndex].depthStencilView)) {
- VULKAN_INTERNAL_DestroyTexture(renderer, texture);
- return NULL;
- }
- }
- texture->subresources[subresourceIndex].parent = texture;
- texture->subresources[subresourceIndex].layer = i;
- texture->subresources[subresourceIndex].level = j;
- texture->subresources[subresourceIndex].transitioned = false;
- }
- }
- return texture;
- }
- static void VULKAN_INTERNAL_CycleActiveBuffer(
- VulkanRenderer *renderer,
- VulkanBufferContainer *container)
- {
- VulkanBuffer *buffer;
- // If a previously-cycled buffer is available, we can use that.
- for (Uint32 i = 0; i < container->bufferCount; i += 1) {
- buffer = container->buffers[i];
- if (SDL_GetAtomicInt(&buffer->referenceCount) == 0) {
- container->activeBuffer = buffer;
- return;
- }
- }
- // No buffer handle is available, create a new one.
- buffer = VULKAN_INTERNAL_CreateBuffer(
- renderer,
- container->activeBuffer->size,
- container->activeBuffer->usage,
- container->activeBuffer->type);
- if (!buffer) {
- return;
- }
- EXPAND_ARRAY_IF_NEEDED(
- container->buffers,
- VulkanBuffer *,
- container->bufferCount + 1,
- container->bufferCapacity,
- container->bufferCapacity * 2);
- container->buffers[container->bufferCount] = buffer;
- buffer->container = container;
- buffer->containerIndex = container->bufferCount;
- container->bufferCount += 1;
- container->activeBuffer = buffer;
- if (renderer->debugMode && renderer->supportsDebugUtils && container->debugName != NULL) {
- VULKAN_INTERNAL_SetBufferName(
- renderer,
- container->activeBuffer,
- container->debugName);
- }
- }
- static void VULKAN_INTERNAL_CycleActiveTexture(
- VulkanRenderer *renderer,
- VulkanTextureContainer *container)
- {
- VulkanTexture *texture;
- // If a previously-cycled texture is available, we can use that.
- for (Uint32 i = 0; i < container->textureCount; i += 1) {
- texture = container->textures[i];
- if (SDL_GetAtomicInt(&texture->referenceCount) == 0) {
- container->activeTexture = texture;
- return;
- }
- }
- // No texture is available, generate a new one.
- texture = VULKAN_INTERNAL_CreateTexture(
- renderer,
- &container->header.info);
- if (!texture) {
- return;
- }
- EXPAND_ARRAY_IF_NEEDED(
- container->textures,
- VulkanTexture *,
- container->textureCount + 1,
- container->textureCapacity,
- container->textureCapacity * 2);
- container->textures[container->textureCount] = texture;
- texture->container = container;
- texture->containerIndex = container->textureCount;
- container->textureCount += 1;
- container->activeTexture = texture;
- if (renderer->debugMode && renderer->supportsDebugUtils && container->debugName != NULL) {
- VULKAN_INTERNAL_SetTextureName(
- renderer,
- container->activeTexture,
- container->debugName);
- }
- }
- static VulkanBuffer *VULKAN_INTERNAL_PrepareBufferForWrite(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanBufferContainer *bufferContainer,
- bool cycle,
- VulkanBufferUsageMode destinationUsageMode)
- {
- if (
- cycle &&
- SDL_GetAtomicInt(&bufferContainer->activeBuffer->referenceCount) > 0) {
- VULKAN_INTERNAL_CycleActiveBuffer(
- renderer,
- bufferContainer);
- }
- VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
- renderer,
- commandBuffer,
- destinationUsageMode,
- bufferContainer->activeBuffer);
- return bufferContainer->activeBuffer;
- }
- static VulkanTextureSubresource *VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- VulkanTextureContainer *textureContainer,
- Uint32 layer,
- Uint32 level,
- bool cycle,
- VulkanTextureUsageMode destinationUsageMode)
- {
- VulkanTextureSubresource *textureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
- textureContainer,
- layer,
- level);
- if (
- cycle &&
- textureContainer->canBeCycled &&
- SDL_GetAtomicInt(&textureContainer->activeTexture->referenceCount) > 0) {
- VULKAN_INTERNAL_CycleActiveTexture(
- renderer,
- textureContainer);
- textureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
- textureContainer,
- layer,
- level);
- }
- // always do barrier because of layout transitions
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- commandBuffer,
- destinationUsageMode,
- textureSubresource);
- return textureSubresource;
- }
- static VkRenderPass VULKAN_INTERNAL_CreateRenderPass(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- const SDL_GPUColorTargetInfo *colorTargetInfos,
- Uint32 numColorTargets,
- const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo)
- {
- VkResult vulkanResult;
- VkAttachmentDescription attachmentDescriptions[2 * MAX_COLOR_TARGET_BINDINGS + 1 /* depth */];
- VkAttachmentReference colorAttachmentReferences[MAX_COLOR_TARGET_BINDINGS];
- VkAttachmentReference resolveReferences[MAX_COLOR_TARGET_BINDINGS];
- VkAttachmentReference depthStencilAttachmentReference;
- VkRenderPassCreateInfo renderPassCreateInfo;
- VkSubpassDescription subpass;
- VkRenderPass renderPass;
- Uint32 i;
- Uint32 attachmentDescriptionCount = 0;
- Uint32 colorAttachmentReferenceCount = 0;
- Uint32 resolveReferenceCount = 0;
- for (i = 0; i < numColorTargets; i += 1) {
- VulkanTextureContainer *container = (VulkanTextureContainer *)colorTargetInfos[i].texture;
- attachmentDescriptions[attachmentDescriptionCount].flags = 0;
- attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[container->header.info.format];
- attachmentDescriptions[attachmentDescriptionCount].samples = SDLToVK_SampleCount[container->header.info.sample_count];
- attachmentDescriptions[attachmentDescriptionCount].loadOp = SDLToVK_LoadOp[colorTargetInfos[i].load_op];
- attachmentDescriptions[attachmentDescriptionCount].storeOp = SDLToVK_StoreOp[colorTargetInfos[i].store_op];
- attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- colorAttachmentReferences[colorAttachmentReferenceCount].attachment = attachmentDescriptionCount;
- colorAttachmentReferences[colorAttachmentReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachmentDescriptionCount += 1;
- colorAttachmentReferenceCount += 1;
- if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
- VulkanTextureContainer *resolveContainer = (VulkanTextureContainer *)colorTargetInfos[i].resolve_texture;
- attachmentDescriptions[attachmentDescriptionCount].flags = 0;
- attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[resolveContainer->header.info.format];
- attachmentDescriptions[attachmentDescriptionCount].samples = SDLToVK_SampleCount[resolveContainer->header.info.sample_count];
- attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // The texture will be overwritten anyway
- attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // Always store the resolve texture
- attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- resolveReferences[resolveReferenceCount].attachment = attachmentDescriptionCount;
- resolveReferences[resolveReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachmentDescriptionCount += 1;
- resolveReferenceCount += 1;
- }
- }
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass.flags = 0;
- subpass.inputAttachmentCount = 0;
- subpass.pInputAttachments = NULL;
- subpass.colorAttachmentCount = numColorTargets;
- subpass.pColorAttachments = colorAttachmentReferences;
- subpass.preserveAttachmentCount = 0;
- subpass.pPreserveAttachments = NULL;
- if (depthStencilTargetInfo == NULL) {
- subpass.pDepthStencilAttachment = NULL;
- } else {
- VulkanTextureContainer *container = (VulkanTextureContainer *)depthStencilTargetInfo->texture;
- attachmentDescriptions[attachmentDescriptionCount].flags = 0;
- attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[container->header.info.format];
- attachmentDescriptions[attachmentDescriptionCount].samples = SDLToVK_SampleCount[container->header.info.sample_count];
- attachmentDescriptions[attachmentDescriptionCount].loadOp = SDLToVK_LoadOp[depthStencilTargetInfo->load_op];
- attachmentDescriptions[attachmentDescriptionCount].storeOp = SDLToVK_StoreOp[depthStencilTargetInfo->store_op];
- attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = SDLToVK_LoadOp[depthStencilTargetInfo->stencil_load_op];
- attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = SDLToVK_StoreOp[depthStencilTargetInfo->stencil_store_op];
- attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- depthStencilAttachmentReference.attachment = attachmentDescriptionCount;
- depthStencilAttachmentReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- subpass.pDepthStencilAttachment = &depthStencilAttachmentReference;
- attachmentDescriptionCount += 1;
- }
- if (resolveReferenceCount > 0) {
- subpass.pResolveAttachments = resolveReferences;
- } else {
- subpass.pResolveAttachments = NULL;
- }
- renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- renderPassCreateInfo.pNext = NULL;
- renderPassCreateInfo.flags = 0;
- renderPassCreateInfo.pAttachments = attachmentDescriptions;
- renderPassCreateInfo.attachmentCount = attachmentDescriptionCount;
- renderPassCreateInfo.subpassCount = 1;
- renderPassCreateInfo.pSubpasses = &subpass;
- renderPassCreateInfo.dependencyCount = 0;
- renderPassCreateInfo.pDependencies = NULL;
- vulkanResult = renderer->vkCreateRenderPass(
- renderer->logicalDevice,
- &renderPassCreateInfo,
- NULL,
- &renderPass);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateRenderPass, VK_NULL_HANDLE);
- return renderPass;
- }
- static VkRenderPass VULKAN_INTERNAL_CreateTransientRenderPass(
- VulkanRenderer *renderer,
- SDL_GPUGraphicsPipelineTargetInfo targetInfo,
- VkSampleCountFlagBits sampleCount)
- {
- VkAttachmentDescription attachmentDescriptions[MAX_COLOR_TARGET_BINDINGS + 1 /* depth */];
- VkAttachmentReference colorAttachmentReferences[MAX_COLOR_TARGET_BINDINGS];
- VkAttachmentReference depthStencilAttachmentReference;
- SDL_GPUColorTargetDescription attachmentDescription;
- VkSubpassDescription subpass;
- VkRenderPassCreateInfo renderPassCreateInfo;
- VkRenderPass renderPass;
- VkResult result;
- Uint32 attachmentDescriptionCount = 0;
- Uint32 colorAttachmentReferenceCount = 0;
- Uint32 i;
- for (i = 0; i < targetInfo.num_color_targets; i += 1) {
- attachmentDescription = targetInfo.color_target_descriptions[i];
- attachmentDescriptions[attachmentDescriptionCount].flags = 0;
- attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[attachmentDescription.format];
- attachmentDescriptions[attachmentDescriptionCount].samples = sampleCount;
- attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- colorAttachmentReferences[colorAttachmentReferenceCount].attachment = attachmentDescriptionCount;
- colorAttachmentReferences[colorAttachmentReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachmentDescriptionCount += 1;
- colorAttachmentReferenceCount += 1;
- }
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass.flags = 0;
- subpass.inputAttachmentCount = 0;
- subpass.pInputAttachments = NULL;
- subpass.colorAttachmentCount = targetInfo.num_color_targets;
- subpass.pColorAttachments = colorAttachmentReferences;
- subpass.preserveAttachmentCount = 0;
- subpass.pPreserveAttachments = NULL;
- if (targetInfo.has_depth_stencil_target) {
- attachmentDescriptions[attachmentDescriptionCount].flags = 0;
- attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_TextureFormat[targetInfo.depth_stencil_format];
- attachmentDescriptions[attachmentDescriptionCount].samples = sampleCount;
- attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- depthStencilAttachmentReference.attachment = attachmentDescriptionCount;
- depthStencilAttachmentReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- subpass.pDepthStencilAttachment = &depthStencilAttachmentReference;
- attachmentDescriptionCount += 1;
- } else {
- subpass.pDepthStencilAttachment = NULL;
- }
- // Resolve attachments aren't needed for transient passes
- subpass.pResolveAttachments = NULL;
- renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- renderPassCreateInfo.pNext = NULL;
- renderPassCreateInfo.flags = 0;
- renderPassCreateInfo.pAttachments = attachmentDescriptions;
- renderPassCreateInfo.attachmentCount = attachmentDescriptionCount;
- renderPassCreateInfo.subpassCount = 1;
- renderPassCreateInfo.pSubpasses = &subpass;
- renderPassCreateInfo.dependencyCount = 0;
- renderPassCreateInfo.pDependencies = NULL;
- result = renderer->vkCreateRenderPass(
- renderer->logicalDevice,
- &renderPassCreateInfo,
- NULL,
- &renderPass);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkCreateRenderPass, VK_NULL_HANDLE)
- return renderPass;
- }
- static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
- SDL_GPURenderer *driverData,
- const SDL_GPUGraphicsPipelineCreateInfo *createinfo)
- {
- VkResult vulkanResult;
- Uint32 i;
- VulkanGraphicsPipeline *graphicsPipeline = (VulkanGraphicsPipeline *)SDL_malloc(sizeof(VulkanGraphicsPipeline));
- VkGraphicsPipelineCreateInfo vkPipelineCreateInfo;
- VkPipelineShaderStageCreateInfo shaderStageCreateInfos[2];
- VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo;
- VkPipelineVertexInputDivisorStateCreateInfoEXT divisorStateCreateInfo;
- VkVertexInputBindingDescription *vertexInputBindingDescriptions = SDL_stack_alloc(VkVertexInputBindingDescription, createinfo->vertex_input_state.num_vertex_buffers);
- VkVertexInputAttributeDescription *vertexInputAttributeDescriptions = SDL_stack_alloc(VkVertexInputAttributeDescription, createinfo->vertex_input_state.num_vertex_attributes);
- VkVertexInputBindingDivisorDescriptionEXT *divisorDescriptions = SDL_stack_alloc(VkVertexInputBindingDivisorDescriptionEXT, createinfo->vertex_input_state.num_vertex_buffers);
- Uint32 divisorDescriptionCount = 0;
- VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo;
- VkPipelineViewportStateCreateInfo viewportStateCreateInfo;
- VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo;
- VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo;
- VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo;
- VkStencilOpState frontStencilState;
- VkStencilOpState backStencilState;
- VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo;
- VkPipelineColorBlendAttachmentState *colorBlendAttachmentStates = SDL_stack_alloc(
- VkPipelineColorBlendAttachmentState,
- createinfo->target_info.num_color_targets);
- static const VkDynamicState dynamicStates[] = {
- VK_DYNAMIC_STATE_VIEWPORT,
- VK_DYNAMIC_STATE_SCISSOR,
- VK_DYNAMIC_STATE_BLEND_CONSTANTS,
- VK_DYNAMIC_STATE_STENCIL_REFERENCE
- };
- VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo;
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- // Create a "compatible" render pass
- VkRenderPass transientRenderPass = VULKAN_INTERNAL_CreateTransientRenderPass(
- renderer,
- createinfo->target_info,
- SDLToVK_SampleCount[createinfo->multisample_state.sample_count]);
- // Dynamic state
- dynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
- dynamicStateCreateInfo.pNext = NULL;
- dynamicStateCreateInfo.flags = 0;
- dynamicStateCreateInfo.dynamicStateCount = SDL_arraysize(dynamicStates);
- dynamicStateCreateInfo.pDynamicStates = dynamicStates;
- // Shader stages
- graphicsPipeline->vertexShader = (VulkanShader *)createinfo->vertex_shader;
- SDL_AtomicIncRef(&graphicsPipeline->vertexShader->referenceCount);
- shaderStageCreateInfos[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- shaderStageCreateInfos[0].pNext = NULL;
- shaderStageCreateInfos[0].flags = 0;
- shaderStageCreateInfos[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
- shaderStageCreateInfos[0].module = graphicsPipeline->vertexShader->shaderModule;
- shaderStageCreateInfos[0].pName = graphicsPipeline->vertexShader->entrypointName;
- shaderStageCreateInfos[0].pSpecializationInfo = NULL;
- graphicsPipeline->fragmentShader = (VulkanShader *)createinfo->fragment_shader;
- SDL_AtomicIncRef(&graphicsPipeline->fragmentShader->referenceCount);
- shaderStageCreateInfos[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- shaderStageCreateInfos[1].pNext = NULL;
- shaderStageCreateInfos[1].flags = 0;
- shaderStageCreateInfos[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
- shaderStageCreateInfos[1].module = graphicsPipeline->fragmentShader->shaderModule;
- shaderStageCreateInfos[1].pName = graphicsPipeline->fragmentShader->entrypointName;
- shaderStageCreateInfos[1].pSpecializationInfo = NULL;
- // Vertex input
- for (i = 0; i < createinfo->vertex_input_state.num_vertex_buffers; i += 1) {
- vertexInputBindingDescriptions[i].binding = createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot;
- vertexInputBindingDescriptions[i].inputRate = SDLToVK_VertexInputRate[createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate];
- vertexInputBindingDescriptions[i].stride = createinfo->vertex_input_state.vertex_buffer_descriptions[i].pitch;
- if (createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) {
- divisorDescriptionCount += 1;
- }
- }
- for (i = 0; i < createinfo->vertex_input_state.num_vertex_attributes; i += 1) {
- vertexInputAttributeDescriptions[i].binding = createinfo->vertex_input_state.vertex_attributes[i].buffer_slot;
- vertexInputAttributeDescriptions[i].format = SDLToVK_VertexFormat[createinfo->vertex_input_state.vertex_attributes[i].format];
- vertexInputAttributeDescriptions[i].location = createinfo->vertex_input_state.vertex_attributes[i].location;
- vertexInputAttributeDescriptions[i].offset = createinfo->vertex_input_state.vertex_attributes[i].offset;
- }
- vertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- vertexInputStateCreateInfo.pNext = NULL;
- vertexInputStateCreateInfo.flags = 0;
- vertexInputStateCreateInfo.vertexBindingDescriptionCount = createinfo->vertex_input_state.num_vertex_buffers;
- vertexInputStateCreateInfo.pVertexBindingDescriptions = vertexInputBindingDescriptions;
- vertexInputStateCreateInfo.vertexAttributeDescriptionCount = createinfo->vertex_input_state.num_vertex_attributes;
- vertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions;
- if (divisorDescriptionCount > 0) {
- divisorDescriptionCount = 0;
- for (i = 0; i < createinfo->vertex_input_state.num_vertex_buffers; i += 1) {
- if (createinfo->vertex_input_state.vertex_buffer_descriptions[i].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) {
- divisorDescriptions[divisorDescriptionCount].binding = createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot;
- divisorDescriptions[divisorDescriptionCount].divisor = createinfo->vertex_input_state.vertex_buffer_descriptions[i].instance_step_rate;
- divisorDescriptionCount += 1;
- }
- }
- divisorStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
- divisorStateCreateInfo.pNext = NULL;
- divisorStateCreateInfo.vertexBindingDivisorCount = divisorDescriptionCount;
- divisorStateCreateInfo.pVertexBindingDivisors = divisorDescriptions;
- vertexInputStateCreateInfo.pNext = &divisorStateCreateInfo;
- }
- // Topology
- inputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- inputAssemblyStateCreateInfo.pNext = NULL;
- inputAssemblyStateCreateInfo.flags = 0;
- inputAssemblyStateCreateInfo.primitiveRestartEnable = VK_FALSE;
- inputAssemblyStateCreateInfo.topology = SDLToVK_PrimitiveType[createinfo->primitive_type];
- graphicsPipeline->primitiveType = createinfo->primitive_type;
- // Viewport
- // NOTE: viewport and scissor are dynamic, and must be set using the command buffer
- viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- viewportStateCreateInfo.pNext = NULL;
- viewportStateCreateInfo.flags = 0;
- viewportStateCreateInfo.viewportCount = 1;
- viewportStateCreateInfo.pViewports = NULL;
- viewportStateCreateInfo.scissorCount = 1;
- viewportStateCreateInfo.pScissors = NULL;
- // Rasterization
- rasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
- rasterizationStateCreateInfo.pNext = NULL;
- rasterizationStateCreateInfo.flags = 0;
- rasterizationStateCreateInfo.depthClampEnable = !createinfo->rasterizer_state.enable_depth_clip;
- rasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE;
- rasterizationStateCreateInfo.polygonMode = SDLToVK_PolygonMode(
- renderer,
- createinfo->rasterizer_state.fill_mode);
- rasterizationStateCreateInfo.cullMode = SDLToVK_CullMode[createinfo->rasterizer_state.cull_mode];
- rasterizationStateCreateInfo.frontFace = SDLToVK_FrontFace[createinfo->rasterizer_state.front_face];
- rasterizationStateCreateInfo.depthBiasEnable =
- createinfo->rasterizer_state.enable_depth_bias;
- rasterizationStateCreateInfo.depthBiasConstantFactor =
- createinfo->rasterizer_state.depth_bias_constant_factor;
- rasterizationStateCreateInfo.depthBiasClamp =
- createinfo->rasterizer_state.depth_bias_clamp;
- rasterizationStateCreateInfo.depthBiasSlopeFactor =
- createinfo->rasterizer_state.depth_bias_slope_factor;
- rasterizationStateCreateInfo.lineWidth = 1.0f;
- // Multisample
- Uint32 sampleMask = createinfo->multisample_state.enable_mask ?
- createinfo->multisample_state.sample_mask :
- 0xFFFFFFFF;
- multisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- multisampleStateCreateInfo.pNext = NULL;
- multisampleStateCreateInfo.flags = 0;
- multisampleStateCreateInfo.rasterizationSamples = SDLToVK_SampleCount[createinfo->multisample_state.sample_count];
- multisampleStateCreateInfo.sampleShadingEnable = VK_FALSE;
- multisampleStateCreateInfo.minSampleShading = 1.0f;
- multisampleStateCreateInfo.pSampleMask = &sampleMask;
- multisampleStateCreateInfo.alphaToCoverageEnable = VK_FALSE;
- multisampleStateCreateInfo.alphaToOneEnable = VK_FALSE;
- // Depth Stencil State
- frontStencilState.failOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.front_stencil_state.fail_op];
- frontStencilState.passOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.front_stencil_state.pass_op];
- frontStencilState.depthFailOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.front_stencil_state.depth_fail_op];
- frontStencilState.compareOp = SDLToVK_CompareOp[createinfo->depth_stencil_state.front_stencil_state.compare_op];
- frontStencilState.compareMask =
- createinfo->depth_stencil_state.compare_mask;
- frontStencilState.writeMask =
- createinfo->depth_stencil_state.write_mask;
- frontStencilState.reference = 0;
- backStencilState.failOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.back_stencil_state.fail_op];
- backStencilState.passOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.back_stencil_state.pass_op];
- backStencilState.depthFailOp = SDLToVK_StencilOp[createinfo->depth_stencil_state.back_stencil_state.depth_fail_op];
- backStencilState.compareOp = SDLToVK_CompareOp[createinfo->depth_stencil_state.back_stencil_state.compare_op];
- backStencilState.compareMask =
- createinfo->depth_stencil_state.compare_mask;
- backStencilState.writeMask =
- createinfo->depth_stencil_state.write_mask;
- backStencilState.reference = 0;
- depthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
- depthStencilStateCreateInfo.pNext = NULL;
- depthStencilStateCreateInfo.flags = 0;
- depthStencilStateCreateInfo.depthTestEnable =
- createinfo->depth_stencil_state.enable_depth_test;
- depthStencilStateCreateInfo.depthWriteEnable =
- createinfo->depth_stencil_state.enable_depth_write;
- depthStencilStateCreateInfo.depthCompareOp = SDLToVK_CompareOp[createinfo->depth_stencil_state.compare_op];
- depthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE;
- depthStencilStateCreateInfo.stencilTestEnable =
- createinfo->depth_stencil_state.enable_stencil_test;
- depthStencilStateCreateInfo.front = frontStencilState;
- depthStencilStateCreateInfo.back = backStencilState;
- depthStencilStateCreateInfo.minDepthBounds = 0; // unused
- depthStencilStateCreateInfo.maxDepthBounds = 0; // unused
- // Color Blend
- for (i = 0; i < createinfo->target_info.num_color_targets; i += 1) {
- SDL_GPUColorTargetBlendState blendState = createinfo->target_info.color_target_descriptions[i].blend_state;
- SDL_GPUColorComponentFlags colorWriteMask = blendState.enable_color_write_mask ?
- blendState.color_write_mask :
- 0xF;
- colorBlendAttachmentStates[i].blendEnable =
- blendState.enable_blend;
- colorBlendAttachmentStates[i].srcColorBlendFactor = SDLToVK_BlendFactor[blendState.src_color_blendfactor];
- colorBlendAttachmentStates[i].dstColorBlendFactor = SDLToVK_BlendFactor[blendState.dst_color_blendfactor];
- colorBlendAttachmentStates[i].colorBlendOp = SDLToVK_BlendOp[blendState.color_blend_op];
- colorBlendAttachmentStates[i].srcAlphaBlendFactor = SDLToVK_BlendFactor[blendState.src_alpha_blendfactor];
- colorBlendAttachmentStates[i].dstAlphaBlendFactor = SDLToVK_BlendFactor[blendState.dst_alpha_blendfactor];
- colorBlendAttachmentStates[i].alphaBlendOp = SDLToVK_BlendOp[blendState.alpha_blend_op];
- colorBlendAttachmentStates[i].colorWriteMask =
- colorWriteMask;
- }
- colorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
- colorBlendStateCreateInfo.pNext = NULL;
- colorBlendStateCreateInfo.flags = 0;
- colorBlendStateCreateInfo.attachmentCount =
- createinfo->target_info.num_color_targets;
- colorBlendStateCreateInfo.pAttachments =
- colorBlendAttachmentStates;
- colorBlendStateCreateInfo.blendConstants[0] = 1.0f;
- colorBlendStateCreateInfo.blendConstants[1] = 1.0f;
- colorBlendStateCreateInfo.blendConstants[2] = 1.0f;
- colorBlendStateCreateInfo.blendConstants[3] = 1.0f;
- // We don't support LogicOp, so this is easy.
- colorBlendStateCreateInfo.logicOpEnable = VK_FALSE;
- colorBlendStateCreateInfo.logicOp = 0;
- // Pipeline Layout
- graphicsPipeline->resourceLayout =
- VULKAN_INTERNAL_FetchGraphicsPipelineResourceLayout(
- renderer,
- graphicsPipeline->vertexShader,
- graphicsPipeline->fragmentShader);
- if (graphicsPipeline->resourceLayout == NULL) {
- SDL_stack_free(vertexInputBindingDescriptions);
- SDL_stack_free(vertexInputAttributeDescriptions);
- SDL_stack_free(colorBlendAttachmentStates);
- SDL_stack_free(divisorDescriptions);
- SDL_free(graphicsPipeline);
- SET_STRING_ERROR_AND_RETURN("Failed to initialize pipeline resource layout!", NULL);
- }
- // Pipeline
- vkPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- vkPipelineCreateInfo.pNext = NULL;
- vkPipelineCreateInfo.flags = 0;
- vkPipelineCreateInfo.stageCount = 2;
- vkPipelineCreateInfo.pStages = shaderStageCreateInfos;
- vkPipelineCreateInfo.pVertexInputState = &vertexInputStateCreateInfo;
- vkPipelineCreateInfo.pInputAssemblyState = &inputAssemblyStateCreateInfo;
- vkPipelineCreateInfo.pTessellationState = VK_NULL_HANDLE;
- vkPipelineCreateInfo.pViewportState = &viewportStateCreateInfo;
- vkPipelineCreateInfo.pRasterizationState = &rasterizationStateCreateInfo;
- vkPipelineCreateInfo.pMultisampleState = &multisampleStateCreateInfo;
- vkPipelineCreateInfo.pDepthStencilState = &depthStencilStateCreateInfo;
- vkPipelineCreateInfo.pColorBlendState = &colorBlendStateCreateInfo;
- vkPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
- vkPipelineCreateInfo.layout = graphicsPipeline->resourceLayout->pipelineLayout;
- vkPipelineCreateInfo.renderPass = transientRenderPass;
- vkPipelineCreateInfo.subpass = 0;
- vkPipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
- vkPipelineCreateInfo.basePipelineIndex = 0;
- // TODO: enable pipeline caching
- vulkanResult = renderer->vkCreateGraphicsPipelines(
- renderer->logicalDevice,
- VK_NULL_HANDLE,
- 1,
- &vkPipelineCreateInfo,
- NULL,
- &graphicsPipeline->pipeline);
- SDL_stack_free(vertexInputBindingDescriptions);
- SDL_stack_free(vertexInputAttributeDescriptions);
- SDL_stack_free(colorBlendAttachmentStates);
- SDL_stack_free(divisorDescriptions);
- renderer->vkDestroyRenderPass(
- renderer->logicalDevice,
- transientRenderPass,
- NULL);
- if (vulkanResult != VK_SUCCESS) {
- SDL_free(graphicsPipeline);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateGraphicsPipelines, NULL)
- }
- SDL_SetAtomicInt(&graphicsPipeline->referenceCount, 0);
- return (SDL_GPUGraphicsPipeline *)graphicsPipeline;
- }
- static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
- SDL_GPURenderer *driverData,
- const SDL_GPUComputePipelineCreateInfo *createinfo)
- {
- VkShaderModuleCreateInfo shaderModuleCreateInfo;
- VkComputePipelineCreateInfo vkShaderCreateInfo;
- VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo;
- VkResult vulkanResult;
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanComputePipeline *vulkanComputePipeline;
- if (createinfo->format != SDL_GPU_SHADERFORMAT_SPIRV) {
- SET_STRING_ERROR_AND_RETURN("Incompatible shader format for Vulkan!", NULL)
- }
- vulkanComputePipeline = SDL_malloc(sizeof(VulkanComputePipeline));
- shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
- shaderModuleCreateInfo.pNext = NULL;
- shaderModuleCreateInfo.flags = 0;
- shaderModuleCreateInfo.codeSize = createinfo->code_size;
- shaderModuleCreateInfo.pCode = (Uint32 *)createinfo->code;
- vulkanResult = renderer->vkCreateShaderModule(
- renderer->logicalDevice,
- &shaderModuleCreateInfo,
- NULL,
- &vulkanComputePipeline->shaderModule);
- if (vulkanResult != VK_SUCCESS) {
- SDL_free(vulkanComputePipeline);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateShaderModule, NULL)
- }
- pipelineShaderStageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- pipelineShaderStageCreateInfo.pNext = NULL;
- pipelineShaderStageCreateInfo.flags = 0;
- pipelineShaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
- pipelineShaderStageCreateInfo.module = vulkanComputePipeline->shaderModule;
- pipelineShaderStageCreateInfo.pName = createinfo->entrypoint;
- pipelineShaderStageCreateInfo.pSpecializationInfo = NULL;
- vulkanComputePipeline->resourceLayout = VULKAN_INTERNAL_FetchComputePipelineResourceLayout(
- renderer,
- createinfo);
- if (vulkanComputePipeline->resourceLayout == NULL) {
- renderer->vkDestroyShaderModule(
- renderer->logicalDevice,
- vulkanComputePipeline->shaderModule,
- NULL);
- SDL_free(vulkanComputePipeline);
- return NULL;
- }
- vkShaderCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
- vkShaderCreateInfo.pNext = NULL;
- vkShaderCreateInfo.flags = 0;
- vkShaderCreateInfo.stage = pipelineShaderStageCreateInfo;
- vkShaderCreateInfo.layout = vulkanComputePipeline->resourceLayout->pipelineLayout;
- vkShaderCreateInfo.basePipelineHandle = (VkPipeline)VK_NULL_HANDLE;
- vkShaderCreateInfo.basePipelineIndex = 0;
- vulkanResult = renderer->vkCreateComputePipelines(
- renderer->logicalDevice,
- (VkPipelineCache)VK_NULL_HANDLE,
- 1,
- &vkShaderCreateInfo,
- NULL,
- &vulkanComputePipeline->pipeline);
- if (vulkanResult != VK_SUCCESS) {
- VULKAN_INTERNAL_DestroyComputePipeline(renderer, vulkanComputePipeline);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateComputePipeline, NULL)
- return NULL;
- }
- SDL_SetAtomicInt(&vulkanComputePipeline->referenceCount, 0);
- return (SDL_GPUComputePipeline *)vulkanComputePipeline;
- }
- static SDL_GPUSampler *VULKAN_CreateSampler(
- SDL_GPURenderer *driverData,
- const SDL_GPUSamplerCreateInfo *createinfo)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanSampler *vulkanSampler = SDL_malloc(sizeof(VulkanSampler));
- VkResult vulkanResult;
- VkSamplerCreateInfo vkSamplerCreateInfo;
- vkSamplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
- vkSamplerCreateInfo.pNext = NULL;
- vkSamplerCreateInfo.flags = 0;
- vkSamplerCreateInfo.magFilter = SDLToVK_Filter[createinfo->mag_filter];
- vkSamplerCreateInfo.minFilter = SDLToVK_Filter[createinfo->min_filter];
- vkSamplerCreateInfo.mipmapMode = SDLToVK_SamplerMipmapMode[createinfo->mipmap_mode];
- vkSamplerCreateInfo.addressModeU = SDLToVK_SamplerAddressMode[createinfo->address_mode_u];
- vkSamplerCreateInfo.addressModeV = SDLToVK_SamplerAddressMode[createinfo->address_mode_v];
- vkSamplerCreateInfo.addressModeW = SDLToVK_SamplerAddressMode[createinfo->address_mode_w];
- vkSamplerCreateInfo.mipLodBias = createinfo->mip_lod_bias;
- vkSamplerCreateInfo.anisotropyEnable = createinfo->enable_anisotropy;
- vkSamplerCreateInfo.maxAnisotropy = createinfo->max_anisotropy;
- vkSamplerCreateInfo.compareEnable = createinfo->enable_compare;
- vkSamplerCreateInfo.compareOp = SDLToVK_CompareOp[createinfo->compare_op];
- vkSamplerCreateInfo.minLod = createinfo->min_lod;
- vkSamplerCreateInfo.maxLod = createinfo->max_lod;
- vkSamplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; // arbitrary, unused
- vkSamplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
- vulkanResult = renderer->vkCreateSampler(
- renderer->logicalDevice,
- &vkSamplerCreateInfo,
- NULL,
- &vulkanSampler->sampler);
- if (vulkanResult != VK_SUCCESS) {
- SDL_free(vulkanSampler);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateSampler, NULL)
- }
- SDL_SetAtomicInt(&vulkanSampler->referenceCount, 0);
- return (SDL_GPUSampler *)vulkanSampler;
- }
- static SDL_GPUShader *VULKAN_CreateShader(
- SDL_GPURenderer *driverData,
- const SDL_GPUShaderCreateInfo *createinfo)
- {
- VulkanShader *vulkanShader;
- VkResult vulkanResult;
- VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- size_t entryPointNameLength;
- vulkanShader = SDL_malloc(sizeof(VulkanShader));
- vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
- vkShaderModuleCreateInfo.pNext = NULL;
- vkShaderModuleCreateInfo.flags = 0;
- vkShaderModuleCreateInfo.codeSize = createinfo->code_size;
- vkShaderModuleCreateInfo.pCode = (Uint32 *)createinfo->code;
- vulkanResult = renderer->vkCreateShaderModule(
- renderer->logicalDevice,
- &vkShaderModuleCreateInfo,
- NULL,
- &vulkanShader->shaderModule);
- if (vulkanResult != VK_SUCCESS) {
- SDL_free(vulkanShader);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateShaderModule, NULL)
- }
- entryPointNameLength = SDL_strlen(createinfo->entrypoint) + 1;
- vulkanShader->entrypointName = SDL_malloc(entryPointNameLength);
- SDL_utf8strlcpy((char *)vulkanShader->entrypointName, createinfo->entrypoint, entryPointNameLength);
- vulkanShader->numSamplers = createinfo->num_samplers;
- vulkanShader->numStorageTextures = createinfo->num_storage_textures;
- vulkanShader->numStorageBuffers = createinfo->num_storage_buffers;
- vulkanShader->numUniformBuffers = createinfo->num_uniform_buffers;
- SDL_SetAtomicInt(&vulkanShader->referenceCount, 0);
- return (SDL_GPUShader *)vulkanShader;
- }
- static bool VULKAN_SupportsSampleCount(
- SDL_GPURenderer *driverData,
- SDL_GPUTextureFormat format,
- SDL_GPUSampleCount sampleCount)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VkSampleCountFlags bits = IsDepthFormat(format) ? renderer->physicalDeviceProperties.properties.limits.framebufferDepthSampleCounts : renderer->physicalDeviceProperties.properties.limits.framebufferColorSampleCounts;
- VkSampleCountFlagBits vkSampleCount = SDLToVK_SampleCount[sampleCount];
- return !!(bits & vkSampleCount);
- }
- static SDL_GPUTexture *VULKAN_CreateTexture(
- SDL_GPURenderer *driverData,
- const SDL_GPUTextureCreateInfo *createinfo)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanTexture *texture;
- VulkanTextureContainer *container;
- texture = VULKAN_INTERNAL_CreateTexture(
- renderer,
- createinfo);
- if (texture == NULL) {
- return NULL;
- }
- container = SDL_malloc(sizeof(VulkanTextureContainer));
- container->header.info = *createinfo;
- container->canBeCycled = true;
- container->activeTexture = texture;
- container->textureCapacity = 1;
- container->textureCount = 1;
- container->textures = SDL_malloc(
- container->textureCapacity * sizeof(VulkanTexture *));
- container->textures[0] = container->activeTexture;
- container->debugName = NULL;
- texture->container = container;
- texture->containerIndex = 0;
- return (SDL_GPUTexture *)container;
- }
- static SDL_GPUBuffer *VULKAN_CreateBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUBufferUsageFlags usageFlags,
- Uint32 size)
- {
- return (SDL_GPUBuffer *)VULKAN_INTERNAL_CreateBufferContainer(
- (VulkanRenderer *)driverData,
- (VkDeviceSize)size,
- usageFlags,
- VULKAN_BUFFER_TYPE_GPU);
- }
- static VulkanUniformBuffer *VULKAN_INTERNAL_CreateUniformBuffer(
- VulkanRenderer *renderer,
- Uint32 size)
- {
- VulkanUniformBuffer *uniformBuffer = SDL_malloc(sizeof(VulkanUniformBuffer));
- uniformBuffer->buffer = VULKAN_INTERNAL_CreateBuffer(
- renderer,
- (VkDeviceSize)size,
- 0,
- VULKAN_BUFFER_TYPE_UNIFORM);
- uniformBuffer->drawOffset = 0;
- uniformBuffer->writeOffset = 0;
- uniformBuffer->buffer->container = (VulkanBufferContainer *)uniformBuffer; // little hack for defrag
- return uniformBuffer;
- }
- static SDL_GPUTransferBuffer *VULKAN_CreateTransferBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUTransferBufferUsage usage, // ignored on Vulkan
- Uint32 size)
- {
- return (SDL_GPUTransferBuffer *)VULKAN_INTERNAL_CreateBufferContainer(
- (VulkanRenderer *)driverData,
- (VkDeviceSize)size,
- 0,
- VULKAN_BUFFER_TYPE_TRANSFER);
- }
- static void VULKAN_INTERNAL_ReleaseTexture(
- VulkanRenderer *renderer,
- VulkanTexture *vulkanTexture)
- {
- if (vulkanTexture->markedForDestroy) {
- return;
- }
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->texturesToDestroy,
- VulkanTexture *,
- renderer->texturesToDestroyCount + 1,
- renderer->texturesToDestroyCapacity,
- renderer->texturesToDestroyCapacity * 2)
- renderer->texturesToDestroy[renderer->texturesToDestroyCount] = vulkanTexture;
- renderer->texturesToDestroyCount += 1;
- vulkanTexture->markedForDestroy = true;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void VULKAN_ReleaseTexture(
- SDL_GPURenderer *driverData,
- SDL_GPUTexture *texture)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer *)texture;
- Uint32 i;
- SDL_LockMutex(renderer->disposeLock);
- for (i = 0; i < vulkanTextureContainer->textureCount; i += 1) {
- VULKAN_INTERNAL_ReleaseTexture(renderer, vulkanTextureContainer->textures[i]);
- }
- // Containers are just client handles, so we can destroy immediately
- if (vulkanTextureContainer->debugName != NULL) {
- SDL_free(vulkanTextureContainer->debugName);
- }
- SDL_free(vulkanTextureContainer->textures);
- SDL_free(vulkanTextureContainer);
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void VULKAN_ReleaseSampler(
- SDL_GPURenderer *driverData,
- SDL_GPUSampler *sampler)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanSampler *vulkanSampler = (VulkanSampler *)sampler;
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->samplersToDestroy,
- VulkanSampler *,
- renderer->samplersToDestroyCount + 1,
- renderer->samplersToDestroyCapacity,
- renderer->samplersToDestroyCapacity * 2)
- renderer->samplersToDestroy[renderer->samplersToDestroyCount] = vulkanSampler;
- renderer->samplersToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void VULKAN_INTERNAL_ReleaseBuffer(
- VulkanRenderer *renderer,
- VulkanBuffer *vulkanBuffer)
- {
- if (vulkanBuffer->markedForDestroy) {
- return;
- }
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->buffersToDestroy,
- VulkanBuffer *,
- renderer->buffersToDestroyCount + 1,
- renderer->buffersToDestroyCapacity,
- renderer->buffersToDestroyCapacity * 2)
- renderer->buffersToDestroy[renderer->buffersToDestroyCount] = vulkanBuffer;
- renderer->buffersToDestroyCount += 1;
- vulkanBuffer->markedForDestroy = 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void VULKAN_INTERNAL_ReleaseBufferContainer(
- VulkanRenderer *renderer,
- VulkanBufferContainer *bufferContainer)
- {
- Uint32 i;
- SDL_LockMutex(renderer->disposeLock);
- for (i = 0; i < bufferContainer->bufferCount; i += 1) {
- VULKAN_INTERNAL_ReleaseBuffer(renderer, bufferContainer->buffers[i]);
- }
- // Containers are just client handles, so we can free immediately
- if (bufferContainer->debugName != NULL) {
- SDL_free(bufferContainer->debugName);
- }
- SDL_free(bufferContainer->buffers);
- SDL_free(bufferContainer);
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void VULKAN_ReleaseBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUBuffer *buffer)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanBufferContainer *vulkanBufferContainer = (VulkanBufferContainer *)buffer;
- VULKAN_INTERNAL_ReleaseBufferContainer(
- renderer,
- vulkanBufferContainer);
- }
- static void VULKAN_ReleaseTransferBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUTransferBuffer *transferBuffer)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)transferBuffer;
- VULKAN_INTERNAL_ReleaseBufferContainer(
- renderer,
- transferBufferContainer);
- }
- static void VULKAN_ReleaseShader(
- SDL_GPURenderer *driverData,
- SDL_GPUShader *shader)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanShader *vulkanShader = (VulkanShader *)shader;
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->shadersToDestroy,
- VulkanShader *,
- renderer->shadersToDestroyCount + 1,
- renderer->shadersToDestroyCapacity,
- renderer->shadersToDestroyCapacity * 2)
- renderer->shadersToDestroy[renderer->shadersToDestroyCount] = vulkanShader;
- renderer->shadersToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void VULKAN_ReleaseComputePipeline(
- SDL_GPURenderer *driverData,
- SDL_GPUComputePipeline *computePipeline)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanComputePipeline *vulkanComputePipeline = (VulkanComputePipeline *)computePipeline;
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->computePipelinesToDestroy,
- VulkanComputePipeline *,
- renderer->computePipelinesToDestroyCount + 1,
- renderer->computePipelinesToDestroyCapacity,
- renderer->computePipelinesToDestroyCapacity * 2)
- renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount] = vulkanComputePipeline;
- renderer->computePipelinesToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void VULKAN_ReleaseGraphicsPipeline(
- SDL_GPURenderer *driverData,
- SDL_GPUGraphicsPipeline *graphicsPipeline)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanGraphicsPipeline *vulkanGraphicsPipeline = (VulkanGraphicsPipeline *)graphicsPipeline;
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->graphicsPipelinesToDestroy,
- VulkanGraphicsPipeline *,
- renderer->graphicsPipelinesToDestroyCount + 1,
- renderer->graphicsPipelinesToDestroyCapacity,
- renderer->graphicsPipelinesToDestroyCapacity * 2)
- renderer->graphicsPipelinesToDestroy[renderer->graphicsPipelinesToDestroyCount] = vulkanGraphicsPipeline;
- renderer->graphicsPipelinesToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- // Command Buffer render state
- static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer,
- const SDL_GPUColorTargetInfo *colorTargetInfos,
- Uint32 numColorTargets,
- const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo)
- {
- VulkanRenderPassHashTableValue *renderPassWrapper = NULL;
- VkRenderPass renderPassHandle;
- RenderPassHashTableKey key;
- Uint32 i;
- SDL_zero(key);
- for (i = 0; i < numColorTargets; i += 1) {
- key.colorTargetDescriptions[i].format = SDLToVK_TextureFormat[((VulkanTextureContainer *)colorTargetInfos[i].texture)->header.info.format];
- key.colorTargetDescriptions[i].loadOp = colorTargetInfos[i].load_op;
- key.colorTargetDescriptions[i].storeOp = colorTargetInfos[i].store_op;
- if (colorTargetInfos[i].resolve_texture != NULL) {
- key.resolveTargetFormats[key.numResolveTargets] = SDLToVK_TextureFormat[((VulkanTextureContainer *)colorTargetInfos[i].resolve_texture)->header.info.format];
- key.numResolveTargets += 1;
- }
- }
- key.sampleCount = VK_SAMPLE_COUNT_1_BIT;
- if (numColorTargets > 0) {
- key.sampleCount = SDLToVK_SampleCount[((VulkanTextureContainer *)colorTargetInfos[0].texture)->header.info.sample_count];
- }
- key.numColorTargets = numColorTargets;
- if (depthStencilTargetInfo == NULL) {
- key.depthStencilTargetDescription.format = 0;
- key.depthStencilTargetDescription.loadOp = SDL_GPU_LOADOP_DONT_CARE;
- key.depthStencilTargetDescription.storeOp = SDL_GPU_STOREOP_DONT_CARE;
- key.depthStencilTargetDescription.stencilLoadOp = SDL_GPU_LOADOP_DONT_CARE;
- key.depthStencilTargetDescription.stencilStoreOp = SDL_GPU_STOREOP_DONT_CARE;
- } else {
- key.depthStencilTargetDescription.format = SDLToVK_TextureFormat[((VulkanTextureContainer *)depthStencilTargetInfo->texture)->header.info.format];
- key.depthStencilTargetDescription.loadOp = depthStencilTargetInfo->load_op;
- key.depthStencilTargetDescription.storeOp = depthStencilTargetInfo->store_op;
- key.depthStencilTargetDescription.stencilLoadOp = depthStencilTargetInfo->stencil_load_op;
- key.depthStencilTargetDescription.stencilStoreOp = depthStencilTargetInfo->stencil_store_op;
- }
- SDL_LockMutex(renderer->renderPassFetchLock);
- bool result = SDL_FindInHashTable(
- renderer->renderPassHashTable,
- (const void *)&key,
- (const void **)&renderPassWrapper);
- SDL_UnlockMutex(renderer->renderPassFetchLock);
- if (result) {
- return renderPassWrapper->handle;
- }
- renderPassHandle = VULKAN_INTERNAL_CreateRenderPass(
- renderer,
- commandBuffer,
- colorTargetInfos,
- numColorTargets,
- depthStencilTargetInfo);
- if (renderPassHandle == VK_NULL_HANDLE) {
- return VK_NULL_HANDLE;
- }
- // Have to malloc the key to store it in the hashtable
- RenderPassHashTableKey *allocedKey = SDL_malloc(sizeof(RenderPassHashTableKey));
- SDL_memcpy(allocedKey, &key, sizeof(RenderPassHashTableKey));
- renderPassWrapper = SDL_malloc(sizeof(VulkanRenderPassHashTableValue));
- renderPassWrapper->handle = renderPassHandle;
- SDL_LockMutex(renderer->renderPassFetchLock);
- SDL_InsertIntoHashTable(
- renderer->renderPassHashTable,
- (const void *)allocedKey,
- (const void *)renderPassWrapper);
- SDL_UnlockMutex(renderer->renderPassFetchLock);
- return renderPassHandle;
- }
- static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
- VulkanRenderer *renderer,
- VkRenderPass renderPass,
- const SDL_GPUColorTargetInfo *colorTargetInfos,
- Uint32 numColorTargets,
- const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo,
- Uint32 width,
- Uint32 height)
- {
- VulkanFramebuffer *vulkanFramebuffer = NULL;
- VkFramebufferCreateInfo framebufferInfo;
- VkResult result;
- VkImageView imageViewAttachments[2 * MAX_COLOR_TARGET_BINDINGS + 1 /* depth */];
- FramebufferHashTableKey key;
- Uint32 attachmentCount = 0;
- Uint32 i;
- SDL_zero(imageViewAttachments);
- SDL_zero(key);
- key.numColorTargets = numColorTargets;
- for (i = 0; i < numColorTargets; i += 1) {
- VulkanTextureContainer *container = (VulkanTextureContainer *)colorTargetInfos[i].texture;
- VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
- container,
- container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorTargetInfos[i].layer_or_depth_plane,
- colorTargetInfos[i].mip_level);
- Uint32 rtvIndex =
- container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0;
- key.colorAttachmentViews[i] = subresource->renderTargetViews[rtvIndex];
- if (colorTargetInfos[i].resolve_texture != NULL) {
- VulkanTextureContainer *resolveTextureContainer = (VulkanTextureContainer *)colorTargetInfos[i].resolve_texture;
- VulkanTextureSubresource *resolveSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
- resolveTextureContainer,
- colorTargetInfos[i].layer_or_depth_plane,
- colorTargetInfos[i].mip_level);
- key.resolveAttachmentViews[key.numResolveAttachments] = resolveSubresource->renderTargetViews[0];
- key.numResolveAttachments += 1;
- }
- }
- if (depthStencilTargetInfo == NULL) {
- key.depthStencilAttachmentView = VK_NULL_HANDLE;
- } else {
- VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
- (VulkanTextureContainer *)depthStencilTargetInfo->texture,
- 0,
- 0);
- key.depthStencilAttachmentView = subresource->depthStencilView;
- }
- key.width = width;
- key.height = height;
- SDL_LockMutex(renderer->framebufferFetchLock);
- bool findResult = SDL_FindInHashTable(
- renderer->framebufferHashTable,
- (const void *)&key,
- (const void **)&vulkanFramebuffer);
- SDL_UnlockMutex(renderer->framebufferFetchLock);
- if (findResult) {
- return vulkanFramebuffer;
- }
- vulkanFramebuffer = SDL_malloc(sizeof(VulkanFramebuffer));
- SDL_SetAtomicInt(&vulkanFramebuffer->referenceCount, 0);
- // Create a new framebuffer
- for (i = 0; i < numColorTargets; i += 1) {
- VulkanTextureContainer *container = (VulkanTextureContainer *)colorTargetInfos[i].texture;
- VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
- container,
- container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorTargetInfos[i].layer_or_depth_plane,
- colorTargetInfos[i].mip_level);
- Uint32 rtvIndex =
- container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0;
- imageViewAttachments[attachmentCount] = subresource->renderTargetViews[rtvIndex];
- attachmentCount += 1;
- if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
- VulkanTextureContainer *resolveContainer = (VulkanTextureContainer *)colorTargetInfos[i].resolve_texture;
- VulkanTextureSubresource *resolveSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
- resolveContainer,
- colorTargetInfos[i].resolve_layer,
- colorTargetInfos[i].resolve_mip_level);
- imageViewAttachments[attachmentCount] = resolveSubresource->renderTargetViews[0];
- attachmentCount += 1;
- }
- }
- if (depthStencilTargetInfo != NULL) {
- VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
- (VulkanTextureContainer *)depthStencilTargetInfo->texture,
- 0,
- 0);
- imageViewAttachments[attachmentCount] = subresource->depthStencilView;
- attachmentCount += 1;
- }
- framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- framebufferInfo.pNext = NULL;
- framebufferInfo.flags = 0;
- framebufferInfo.renderPass = renderPass;
- framebufferInfo.attachmentCount = attachmentCount;
- framebufferInfo.pAttachments = imageViewAttachments;
- framebufferInfo.width = key.width;
- framebufferInfo.height = key.height;
- framebufferInfo.layers = 1;
- result = renderer->vkCreateFramebuffer(
- renderer->logicalDevice,
- &framebufferInfo,
- NULL,
- &vulkanFramebuffer->framebuffer);
- if (result == VK_SUCCESS) {
- // Have to malloc the key to store it in the hashtable
- FramebufferHashTableKey *allocedKey = SDL_malloc(sizeof(FramebufferHashTableKey));
- SDL_memcpy(allocedKey, &key, sizeof(FramebufferHashTableKey));
- SDL_LockMutex(renderer->framebufferFetchLock);
- SDL_InsertIntoHashTable(
- renderer->framebufferHashTable,
- (const void *)allocedKey,
- (const void *)vulkanFramebuffer);
- SDL_UnlockMutex(renderer->framebufferFetchLock);
- } else {
- SDL_free(vulkanFramebuffer);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkCreateFramebuffer, NULL)
- }
- return vulkanFramebuffer;
- }
- static void VULKAN_INTERNAL_SetCurrentViewport(
- VulkanCommandBuffer *commandBuffer,
- const SDL_GPUViewport *viewport)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- vulkanCommandBuffer->currentViewport.x = viewport->x;
- vulkanCommandBuffer->currentViewport.width = viewport->w;
- vulkanCommandBuffer->currentViewport.minDepth = viewport->min_depth;
- vulkanCommandBuffer->currentViewport.maxDepth = viewport->max_depth;
- // Viewport flip for consistency with other backends
- vulkanCommandBuffer->currentViewport.y = viewport->y + viewport->h;
- vulkanCommandBuffer->currentViewport.height = -viewport->h;
- renderer->vkCmdSetViewport(
- vulkanCommandBuffer->commandBuffer,
- 0,
- 1,
- &vulkanCommandBuffer->currentViewport);
- }
- static void VULKAN_SetViewport(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUViewport *viewport)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VULKAN_INTERNAL_SetCurrentViewport(
- vulkanCommandBuffer,
- viewport);
- }
- static void VULKAN_INTERNAL_SetCurrentScissor(
- VulkanCommandBuffer *vulkanCommandBuffer,
- const SDL_Rect *scissor)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- vulkanCommandBuffer->currentScissor.offset.x = scissor->x;
- vulkanCommandBuffer->currentScissor.offset.y = scissor->y;
- vulkanCommandBuffer->currentScissor.extent.width = scissor->w;
- vulkanCommandBuffer->currentScissor.extent.height = scissor->h;
- renderer->vkCmdSetScissor(
- vulkanCommandBuffer->commandBuffer,
- 0,
- 1,
- &vulkanCommandBuffer->currentScissor);
- }
- static void VULKAN_SetScissor(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_Rect *scissor)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VULKAN_INTERNAL_SetCurrentScissor(
- vulkanCommandBuffer,
- scissor);
- }
- static void VULKAN_INTERNAL_SetCurrentBlendConstants(
- VulkanCommandBuffer *vulkanCommandBuffer,
- SDL_FColor blendConstants)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- vulkanCommandBuffer->blendConstants[0] = blendConstants.r;
- vulkanCommandBuffer->blendConstants[1] = blendConstants.g;
- vulkanCommandBuffer->blendConstants[2] = blendConstants.b;
- vulkanCommandBuffer->blendConstants[3] = blendConstants.a;
- renderer->vkCmdSetBlendConstants(
- vulkanCommandBuffer->commandBuffer,
- vulkanCommandBuffer->blendConstants);
- }
- static void VULKAN_SetBlendConstants(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_FColor blendConstants)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VULKAN_INTERNAL_SetCurrentBlendConstants(
- vulkanCommandBuffer,
- blendConstants);
- }
- static void VULKAN_INTERNAL_SetCurrentStencilReference(
- VulkanCommandBuffer *vulkanCommandBuffer,
- Uint8 reference)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- vulkanCommandBuffer->stencilRef = reference;
- renderer->vkCmdSetStencilReference(
- vulkanCommandBuffer->commandBuffer,
- VK_STENCIL_FACE_FRONT_AND_BACK,
- vulkanCommandBuffer->stencilRef);
- }
- static void VULKAN_SetStencilReference(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint8 reference)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VULKAN_INTERNAL_SetCurrentStencilReference(
- vulkanCommandBuffer,
- reference);
- }
- static void VULKAN_BindVertexSamplers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
- vulkanCommandBuffer->vertexSamplerTextures[firstSlot + i] = textureContainer->activeTexture;
- vulkanCommandBuffer->vertexSamplers[firstSlot + i] = (VulkanSampler *)textureSamplerBindings[i].sampler;
- VULKAN_INTERNAL_TrackSampler(
- vulkanCommandBuffer,
- (VulkanSampler *)textureSamplerBindings[i].sampler);
- VULKAN_INTERNAL_TrackTexture(
- vulkanCommandBuffer,
- textureContainer->activeTexture);
- }
- vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
- }
- static void VULKAN_BindVertexStorageTextures(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUTexture *const *storageTextures,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
- vulkanCommandBuffer->vertexStorageTextures[firstSlot + i] = textureContainer->activeTexture;
- VULKAN_INTERNAL_TrackTexture(
- vulkanCommandBuffer,
- textureContainer->activeTexture);
- }
- vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
- }
- static void VULKAN_BindVertexStorageBuffers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUBuffer *const *storageBuffers,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanBufferContainer *bufferContainer;
- Uint32 i;
- for (i = 0; i < numBindings; i += 1) {
- bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
- vulkanCommandBuffer->vertexStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
- VULKAN_INTERNAL_TrackBuffer(
- vulkanCommandBuffer,
- bufferContainer->activeBuffer);
- }
- vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
- }
- static void VULKAN_BindFragmentSamplers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
- vulkanCommandBuffer->fragmentSamplerTextures[firstSlot + i] = textureContainer->activeTexture;
- vulkanCommandBuffer->fragmentSamplers[firstSlot + i] = (VulkanSampler *)textureSamplerBindings[i].sampler;
- VULKAN_INTERNAL_TrackSampler(
- vulkanCommandBuffer,
- (VulkanSampler *)textureSamplerBindings[i].sampler);
- VULKAN_INTERNAL_TrackTexture(
- vulkanCommandBuffer,
- textureContainer->activeTexture);
- }
- vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
- }
- static void VULKAN_BindFragmentStorageTextures(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUTexture *const *storageTextures,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
- vulkanCommandBuffer->fragmentStorageTextures[firstSlot + i] =
- textureContainer->activeTexture;
- VULKAN_INTERNAL_TrackTexture(
- vulkanCommandBuffer,
- textureContainer->activeTexture);
- }
- vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
- }
- static void VULKAN_BindFragmentStorageBuffers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUBuffer *const *storageBuffers,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanBufferContainer *bufferContainer;
- Uint32 i;
- for (i = 0; i < numBindings; i += 1) {
- bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
- vulkanCommandBuffer->fragmentStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
- VULKAN_INTERNAL_TrackBuffer(
- vulkanCommandBuffer,
- bufferContainer->activeBuffer);
- }
- vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
- }
- static VulkanUniformBuffer *VULKAN_INTERNAL_AcquireUniformBufferFromPool(
- VulkanCommandBuffer *commandBuffer)
- {
- VulkanRenderer *renderer = commandBuffer->renderer;
- VulkanUniformBuffer *uniformBuffer;
- SDL_LockMutex(renderer->acquireUniformBufferLock);
- if (renderer->uniformBufferPoolCount > 0) {
- uniformBuffer = renderer->uniformBufferPool[renderer->uniformBufferPoolCount - 1];
- renderer->uniformBufferPoolCount -= 1;
- } else {
- uniformBuffer = VULKAN_INTERNAL_CreateUniformBuffer(
- renderer,
- UNIFORM_BUFFER_SIZE);
- }
- SDL_UnlockMutex(renderer->acquireUniformBufferLock);
- VULKAN_INTERNAL_TrackUniformBuffer(commandBuffer, uniformBuffer);
- return uniformBuffer;
- }
- static void VULKAN_INTERNAL_ReturnUniformBufferToPool(
- VulkanRenderer *renderer,
- VulkanUniformBuffer *uniformBuffer)
- {
- if (renderer->uniformBufferPoolCount >= renderer->uniformBufferPoolCapacity) {
- renderer->uniformBufferPoolCapacity *= 2;
- renderer->uniformBufferPool = SDL_realloc(
- renderer->uniformBufferPool,
- renderer->uniformBufferPoolCapacity * sizeof(VulkanUniformBuffer *));
- }
- renderer->uniformBufferPool[renderer->uniformBufferPoolCount] = uniformBuffer;
- renderer->uniformBufferPoolCount += 1;
- uniformBuffer->writeOffset = 0;
- uniformBuffer->drawOffset = 0;
- }
- static void VULKAN_INTERNAL_PushUniformData(
- VulkanCommandBuffer *commandBuffer,
- VulkanUniformBufferStage uniformBufferStage,
- Uint32 slotIndex,
- const void *data,
- Uint32 length)
- {
- Uint32 blockSize =
- VULKAN_INTERNAL_NextHighestAlignment32(
- length,
- commandBuffer->renderer->minUBOAlignment);
- VulkanUniformBuffer *uniformBuffer;
- if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_VERTEX) {
- if (commandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
- commandBuffer->vertexUniformBuffers[slotIndex] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
- commandBuffer);
- }
- uniformBuffer = commandBuffer->vertexUniformBuffers[slotIndex];
- } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT) {
- if (commandBuffer->fragmentUniformBuffers[slotIndex] == NULL) {
- commandBuffer->fragmentUniformBuffers[slotIndex] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
- commandBuffer);
- }
- uniformBuffer = commandBuffer->fragmentUniformBuffers[slotIndex];
- } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE) {
- if (commandBuffer->computeUniformBuffers[slotIndex] == NULL) {
- commandBuffer->computeUniformBuffers[slotIndex] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
- commandBuffer);
- }
- uniformBuffer = commandBuffer->computeUniformBuffers[slotIndex];
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
- return;
- }
- // If there is no more room, acquire a new uniform buffer
- if (uniformBuffer->writeOffset + blockSize + MAX_UBO_SECTION_SIZE >= uniformBuffer->buffer->size) {
- uniformBuffer = VULKAN_INTERNAL_AcquireUniformBufferFromPool(commandBuffer);
- uniformBuffer->drawOffset = 0;
- uniformBuffer->writeOffset = 0;
- if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_VERTEX) {
- commandBuffer->vertexUniformBuffers[slotIndex] = uniformBuffer;
- commandBuffer->needNewVertexUniformDescriptorSet = true;
- } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT) {
- commandBuffer->fragmentUniformBuffers[slotIndex] = uniformBuffer;
- commandBuffer->needNewFragmentUniformDescriptorSet = true;
- } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE) {
- commandBuffer->computeUniformBuffers[slotIndex] = uniformBuffer;
- commandBuffer->needNewComputeUniformDescriptorSet = true;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
- return;
- }
- }
- uniformBuffer->drawOffset = uniformBuffer->writeOffset;
- Uint8 *dst =
- uniformBuffer->buffer->usedRegion->allocation->mapPointer +
- uniformBuffer->buffer->usedRegion->resourceOffset +
- uniformBuffer->writeOffset;
- SDL_memcpy(
- dst,
- data,
- length);
- uniformBuffer->writeOffset += blockSize;
- if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_VERTEX) {
- commandBuffer->needNewVertexUniformOffsets = true;
- } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT) {
- commandBuffer->needNewFragmentUniformOffsets = true;
- } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE) {
- commandBuffer->needNewComputeUniformOffsets = true;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
- return;
- }
- }
- static void VULKAN_BeginRenderPass(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUColorTargetInfo *colorTargetInfos,
- Uint32 numColorTargets,
- const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VkRenderPass renderPass;
- VulkanFramebuffer *framebuffer;
- Uint32 w, h;
- VkClearValue *clearValues;
- Uint32 clearCount = 0;
- Uint32 totalColorAttachmentCount = 0;
- Uint32 i;
- SDL_GPUViewport defaultViewport;
- SDL_Rect defaultScissor;
- SDL_FColor defaultBlendConstants;
- Uint32 framebufferWidth = SDL_MAX_UINT32;
- Uint32 framebufferHeight = SDL_MAX_UINT32;
- for (i = 0; i < numColorTargets; i += 1) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)colorTargetInfos[i].texture;
- w = textureContainer->header.info.width >> colorTargetInfos[i].mip_level;
- h = textureContainer->header.info.height >> colorTargetInfos[i].mip_level;
- // The framebuffer cannot be larger than the smallest attachment.
- if (w < framebufferWidth) {
- framebufferWidth = w;
- }
- if (h < framebufferHeight) {
- framebufferHeight = h;
- }
- }
- if (depthStencilTargetInfo != NULL) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)depthStencilTargetInfo->texture;
- w = textureContainer->header.info.width;
- h = textureContainer->header.info.height;
- // The framebuffer cannot be larger than the smallest attachment.
- if (w < framebufferWidth) {
- framebufferWidth = w;
- }
- if (h < framebufferHeight) {
- framebufferHeight = h;
- }
- }
- for (i = 0; i < numColorTargets; i += 1) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)colorTargetInfos[i].texture;
- VulkanTextureSubresource *subresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
- renderer,
- vulkanCommandBuffer,
- textureContainer,
- textureContainer->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorTargetInfos[i].layer_or_depth_plane,
- colorTargetInfos[i].mip_level,
- colorTargetInfos[i].cycle,
- VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT);
- vulkanCommandBuffer->colorAttachmentSubresources[vulkanCommandBuffer->colorAttachmentSubresourceCount] = subresource;
- vulkanCommandBuffer->colorAttachmentSubresourceCount += 1;
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, subresource->parent);
- totalColorAttachmentCount += 1;
- clearCount += 1;
- if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
- VulkanTextureContainer *resolveContainer = (VulkanTextureContainer *)colorTargetInfos[i].resolve_texture;
- VulkanTextureSubresource *resolveSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
- renderer,
- vulkanCommandBuffer,
- resolveContainer,
- colorTargetInfos[i].resolve_layer,
- colorTargetInfos[i].resolve_mip_level,
- colorTargetInfos[i].cycle_resolve_texture,
- VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT);
- vulkanCommandBuffer->resolveAttachmentSubresources[vulkanCommandBuffer->resolveAttachmentSubresourceCount] = resolveSubresource;
- vulkanCommandBuffer->resolveAttachmentSubresourceCount += 1;
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, resolveSubresource->parent);
- totalColorAttachmentCount += 1;
- clearCount += 1;
- }
- }
- if (depthStencilTargetInfo != NULL) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)depthStencilTargetInfo->texture;
- VulkanTextureSubresource *subresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
- renderer,
- vulkanCommandBuffer,
- textureContainer,
- 0,
- 0,
- depthStencilTargetInfo->cycle,
- VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT);
- vulkanCommandBuffer->depthStencilAttachmentSubresource = subresource;
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, subresource->parent);
- clearCount += 1;
- }
- // Fetch required render objects
- renderPass = VULKAN_INTERNAL_FetchRenderPass(
- renderer,
- vulkanCommandBuffer,
- colorTargetInfos,
- numColorTargets,
- depthStencilTargetInfo);
- if (renderPass == VK_NULL_HANDLE) {
- return;
- }
- framebuffer = VULKAN_INTERNAL_FetchFramebuffer(
- renderer,
- renderPass,
- colorTargetInfos,
- numColorTargets,
- depthStencilTargetInfo,
- framebufferWidth,
- framebufferHeight);
- if (framebuffer == NULL) {
- return;
- }
- VULKAN_INTERNAL_TrackFramebuffer(renderer, vulkanCommandBuffer, framebuffer);
- // Set clear values
- clearValues = SDL_stack_alloc(VkClearValue, clearCount);
- for (i = 0; i < totalColorAttachmentCount; i += 1) {
- clearValues[i].color.float32[0] = colorTargetInfos[i].clear_color.r;
- clearValues[i].color.float32[1] = colorTargetInfos[i].clear_color.g;
- clearValues[i].color.float32[2] = colorTargetInfos[i].clear_color.b;
- clearValues[i].color.float32[3] = colorTargetInfos[i].clear_color.a;
- if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
- // Skip over the resolve texture, we're not clearing it
- i += 1;
- }
- }
- if (depthStencilTargetInfo != NULL) {
- clearValues[totalColorAttachmentCount].depthStencil.depth =
- depthStencilTargetInfo->clear_depth;
- clearValues[totalColorAttachmentCount].depthStencil.stencil =
- depthStencilTargetInfo->clear_stencil;
- }
- VkRenderPassBeginInfo renderPassBeginInfo;
- renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- renderPassBeginInfo.pNext = NULL;
- renderPassBeginInfo.renderPass = renderPass;
- renderPassBeginInfo.framebuffer = framebuffer->framebuffer;
- renderPassBeginInfo.pClearValues = clearValues;
- renderPassBeginInfo.clearValueCount = clearCount;
- renderPassBeginInfo.renderArea.extent.width = framebufferWidth;
- renderPassBeginInfo.renderArea.extent.height = framebufferHeight;
- renderPassBeginInfo.renderArea.offset.x = 0;
- renderPassBeginInfo.renderArea.offset.y = 0;
- renderer->vkCmdBeginRenderPass(
- vulkanCommandBuffer->commandBuffer,
- &renderPassBeginInfo,
- VK_SUBPASS_CONTENTS_INLINE);
- SDL_stack_free(clearValues);
- // Set sensible default states
- defaultViewport.x = 0;
- defaultViewport.y = 0;
- defaultViewport.w = (float)framebufferWidth;
- defaultViewport.h = (float)framebufferHeight;
- defaultViewport.min_depth = 0;
- defaultViewport.max_depth = 1;
- VULKAN_INTERNAL_SetCurrentViewport(
- vulkanCommandBuffer,
- &defaultViewport);
- defaultScissor.x = 0;
- defaultScissor.y = 0;
- defaultScissor.w = (Sint32)framebufferWidth;
- defaultScissor.h = (Sint32)framebufferHeight;
- VULKAN_INTERNAL_SetCurrentScissor(
- vulkanCommandBuffer,
- &defaultScissor);
- defaultBlendConstants.r = 1.0f;
- defaultBlendConstants.g = 1.0f;
- defaultBlendConstants.b = 1.0f;
- defaultBlendConstants.a = 1.0f;
- VULKAN_INTERNAL_SetCurrentBlendConstants(
- vulkanCommandBuffer,
- defaultBlendConstants);
- VULKAN_INTERNAL_SetCurrentStencilReference(
- vulkanCommandBuffer,
- 0);
- }
- static void VULKAN_BindGraphicsPipeline(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUGraphicsPipeline *graphicsPipeline)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanGraphicsPipeline *pipeline = (VulkanGraphicsPipeline *)graphicsPipeline;
- renderer->vkCmdBindPipeline(
- vulkanCommandBuffer->commandBuffer,
- VK_PIPELINE_BIND_POINT_GRAPHICS,
- pipeline->pipeline);
- vulkanCommandBuffer->currentGraphicsPipeline = pipeline;
- VULKAN_INTERNAL_TrackGraphicsPipeline(vulkanCommandBuffer, pipeline);
- // Acquire uniform buffers if necessary
- for (Uint32 i = 0; i < pipeline->resourceLayout->vertexUniformBufferCount; i += 1) {
- if (vulkanCommandBuffer->vertexUniformBuffers[i] == NULL) {
- vulkanCommandBuffer->vertexUniformBuffers[i] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
- vulkanCommandBuffer);
- }
- }
- for (Uint32 i = 0; i < pipeline->resourceLayout->fragmentUniformBufferCount; i += 1) {
- if (vulkanCommandBuffer->fragmentUniformBuffers[i] == NULL) {
- vulkanCommandBuffer->fragmentUniformBuffers[i] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
- vulkanCommandBuffer);
- }
- }
- // Mark bindings as needed
- vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
- vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
- vulkanCommandBuffer->needNewVertexUniformDescriptorSet = true;
- vulkanCommandBuffer->needNewFragmentUniformDescriptorSet = true;
- vulkanCommandBuffer->needNewVertexUniformOffsets = true;
- vulkanCommandBuffer->needNewFragmentUniformOffsets = true;
- }
- static void VULKAN_BindVertexBuffers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- const SDL_GPUBufferBinding *bindings,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanBuffer *currentVulkanBuffer;
- VkBuffer *buffers = SDL_stack_alloc(VkBuffer, numBindings);
- VkDeviceSize *offsets = SDL_stack_alloc(VkDeviceSize, numBindings);
- Uint32 i;
- for (i = 0; i < numBindings; i += 1) {
- currentVulkanBuffer = ((VulkanBufferContainer *)bindings[i].buffer)->activeBuffer;
- buffers[i] = currentVulkanBuffer->buffer;
- offsets[i] = (VkDeviceSize)bindings[i].offset;
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, currentVulkanBuffer);
- }
- renderer->vkCmdBindVertexBuffers(
- vulkanCommandBuffer->commandBuffer,
- firstSlot,
- numBindings,
- buffers,
- offsets);
- SDL_stack_free(buffers);
- SDL_stack_free(offsets);
- }
- static void VULKAN_BindIndexBuffer(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUBufferBinding *binding,
- SDL_GPUIndexElementSize indexElementSize)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)binding->buffer)->activeBuffer;
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
- renderer->vkCmdBindIndexBuffer(
- vulkanCommandBuffer->commandBuffer,
- vulkanBuffer->buffer,
- (VkDeviceSize)binding->offset,
- SDLToVK_IndexType[indexElementSize]);
- }
- static void VULKAN_PushVertexUniformData(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 slotIndex,
- const void *data,
- Uint32 length)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VULKAN_INTERNAL_PushUniformData(
- vulkanCommandBuffer,
- VULKAN_UNIFORM_BUFFER_STAGE_VERTEX,
- slotIndex,
- data,
- length);
- }
- static void VULKAN_PushFragmentUniformData(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 slotIndex,
- const void *data,
- Uint32 length)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VULKAN_INTERNAL_PushUniformData(
- vulkanCommandBuffer,
- VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT,
- slotIndex,
- data,
- length);
- }
- static void VULKAN_EndRenderPass(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- Uint32 i;
- renderer->vkCmdEndRenderPass(
- vulkanCommandBuffer->commandBuffer);
- for (i = 0; i < vulkanCommandBuffer->colorAttachmentSubresourceCount; i += 1) {
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT,
- vulkanCommandBuffer->colorAttachmentSubresources[i]);
- }
- vulkanCommandBuffer->colorAttachmentSubresourceCount = 0;
- for (i = 0; i < vulkanCommandBuffer->resolveAttachmentSubresourceCount; i += 1) {
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT,
- vulkanCommandBuffer->resolveAttachmentSubresources[i]);
- }
- vulkanCommandBuffer->resolveAttachmentSubresourceCount = 0;
- if (vulkanCommandBuffer->depthStencilAttachmentSubresource != NULL) {
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT,
- vulkanCommandBuffer->depthStencilAttachmentSubresource);
- vulkanCommandBuffer->depthStencilAttachmentSubresource = NULL;
- }
- vulkanCommandBuffer->currentGraphicsPipeline = NULL;
- vulkanCommandBuffer->vertexResourceDescriptorSet = VK_NULL_HANDLE;
- vulkanCommandBuffer->vertexUniformDescriptorSet = VK_NULL_HANDLE;
- vulkanCommandBuffer->fragmentResourceDescriptorSet = VK_NULL_HANDLE;
- vulkanCommandBuffer->fragmentUniformDescriptorSet = VK_NULL_HANDLE;
- // Reset bind state
- SDL_zeroa(vulkanCommandBuffer->colorAttachmentSubresources);
- SDL_zeroa(vulkanCommandBuffer->resolveAttachmentSubresources);
- vulkanCommandBuffer->depthStencilAttachmentSubresource = NULL;
- SDL_zeroa(vulkanCommandBuffer->vertexSamplers);
- SDL_zeroa(vulkanCommandBuffer->vertexSamplerTextures);
- SDL_zeroa(vulkanCommandBuffer->vertexStorageTextures);
- SDL_zeroa(vulkanCommandBuffer->vertexStorageBuffers);
- SDL_zeroa(vulkanCommandBuffer->fragmentSamplers);
- SDL_zeroa(vulkanCommandBuffer->fragmentSamplerTextures);
- SDL_zeroa(vulkanCommandBuffer->fragmentStorageTextures);
- SDL_zeroa(vulkanCommandBuffer->fragmentStorageBuffers);
- }
- static void VULKAN_BeginComputePass(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUStorageTextureReadWriteBinding *storageTextureBindings,
- Uint32 numStorageTextureBindings,
- const SDL_GPUStorageBufferReadWriteBinding *storageBufferBindings,
- Uint32 numStorageBufferBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
- VulkanBufferContainer *bufferContainer;
- VulkanBuffer *buffer;
- Uint32 i;
- vulkanCommandBuffer->readWriteComputeStorageTextureSubresourceCount = numStorageTextureBindings;
- for (i = 0; i < numStorageTextureBindings; i += 1) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextureBindings[i].texture;
- VulkanTextureSubresource *subresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
- renderer,
- vulkanCommandBuffer,
- textureContainer,
- storageTextureBindings[i].layer,
- storageTextureBindings[i].mip_level,
- storageTextureBindings[i].cycle,
- VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
- vulkanCommandBuffer->readWriteComputeStorageTextureSubresources[i] = subresource;
- VULKAN_INTERNAL_TrackTexture(
- vulkanCommandBuffer,
- subresource->parent);
- }
- for (i = 0; i < numStorageBufferBindings; i += 1) {
- bufferContainer = (VulkanBufferContainer *)storageBufferBindings[i].buffer;
- buffer = VULKAN_INTERNAL_PrepareBufferForWrite(
- renderer,
- vulkanCommandBuffer,
- bufferContainer,
- storageBufferBindings[i].cycle,
- VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ);
- vulkanCommandBuffer->readWriteComputeStorageBuffers[i] = buffer;
- VULKAN_INTERNAL_TrackBuffer(
- vulkanCommandBuffer,
- buffer);
- }
- }
- static void VULKAN_BindComputePipeline(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUComputePipeline *computePipeline)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanComputePipeline *vulkanComputePipeline = (VulkanComputePipeline *)computePipeline;
- renderer->vkCmdBindPipeline(
- vulkanCommandBuffer->commandBuffer,
- VK_PIPELINE_BIND_POINT_COMPUTE,
- vulkanComputePipeline->pipeline);
- vulkanCommandBuffer->currentComputePipeline = vulkanComputePipeline;
- VULKAN_INTERNAL_TrackComputePipeline(vulkanCommandBuffer, vulkanComputePipeline);
- // Acquire uniform buffers if necessary
- for (Uint32 i = 0; i < vulkanComputePipeline->resourceLayout->numUniformBuffers; i += 1) {
- if (vulkanCommandBuffer->computeUniformBuffers[i] == NULL) {
- vulkanCommandBuffer->computeUniformBuffers[i] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
- vulkanCommandBuffer);
- }
- }
- // Mark binding as needed
- vulkanCommandBuffer->needNewComputeReadWriteDescriptorSet = true;
- vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
- vulkanCommandBuffer->needNewComputeUniformDescriptorSet = true;
- vulkanCommandBuffer->needNewComputeUniformOffsets = true;
- }
- static void VULKAN_BindComputeSamplers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
- vulkanCommandBuffer->computeSamplerTextures[firstSlot + i] = textureContainer->activeTexture;
- vulkanCommandBuffer->computeSamplers[firstSlot + i] = (VulkanSampler *)textureSamplerBindings[i].sampler;
- VULKAN_INTERNAL_TrackSampler(
- vulkanCommandBuffer,
- (VulkanSampler *)textureSamplerBindings[i].sampler);
- VULKAN_INTERNAL_TrackTexture(
- vulkanCommandBuffer,
- textureContainer->activeTexture);
- }
- vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
- }
- static void VULKAN_BindComputeStorageTextures(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUTexture *const *storageTextures,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- if (vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i] != NULL) {
- VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
- vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i]);
- }
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
- vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i] =
- textureContainer->activeTexture;
- VULKAN_INTERNAL_TextureTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
- textureContainer->activeTexture);
- VULKAN_INTERNAL_TrackTexture(
- vulkanCommandBuffer,
- textureContainer->activeTexture);
- }
- vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
- }
- static void VULKAN_BindComputeStorageBuffers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUBuffer *const *storageBuffers,
- Uint32 numBindings)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
- VulkanBufferContainer *bufferContainer;
- Uint32 i;
- for (i = 0; i < numBindings; i += 1) {
- if (vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i] != NULL) {
- VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
- vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i]);
- }
- bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
- vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
- VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
- bufferContainer->activeBuffer);
- VULKAN_INTERNAL_TrackBuffer(
- vulkanCommandBuffer,
- bufferContainer->activeBuffer);
- }
- vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
- }
- static void VULKAN_PushComputeUniformData(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 slotIndex,
- const void *data,
- Uint32 length)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VULKAN_INTERNAL_PushUniformData(
- vulkanCommandBuffer,
- VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE,
- slotIndex,
- data,
- length);
- }
- static void VULKAN_INTERNAL_BindComputeDescriptorSets(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer)
- {
- VulkanComputePipelineResourceLayout *resourceLayout;
- DescriptorSetLayout *descriptorSetLayout;
- VkWriteDescriptorSet writeDescriptorSets[
- MAX_TEXTURE_SAMPLERS_PER_STAGE +
- MAX_STORAGE_TEXTURES_PER_STAGE +
- MAX_STORAGE_BUFFERS_PER_STAGE +
- MAX_COMPUTE_WRITE_TEXTURES +
- MAX_COMPUTE_WRITE_BUFFERS +
- MAX_UNIFORM_BUFFERS_PER_STAGE];
- VkDescriptorBufferInfo bufferInfos[MAX_STORAGE_BUFFERS_PER_STAGE + MAX_COMPUTE_WRITE_BUFFERS + MAX_UNIFORM_BUFFERS_PER_STAGE];
- VkDescriptorImageInfo imageInfos[MAX_TEXTURE_SAMPLERS_PER_STAGE + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_COMPUTE_WRITE_TEXTURES];
- Uint32 dynamicOffsets[MAX_UNIFORM_BUFFERS_PER_STAGE];
- Uint32 writeCount = 0;
- Uint32 bufferInfoCount = 0;
- Uint32 imageInfoCount = 0;
- Uint32 dynamicOffsetCount = 0;
- if (
- !commandBuffer->needNewComputeReadOnlyDescriptorSet &&
- !commandBuffer->needNewComputeReadWriteDescriptorSet &&
- !commandBuffer->needNewComputeUniformDescriptorSet &&
- !commandBuffer->needNewComputeUniformOffsets
- ) {
- return;
- }
- resourceLayout = commandBuffer->currentComputePipeline->resourceLayout;
- if (commandBuffer->needNewComputeReadOnlyDescriptorSet) {
- descriptorSetLayout = resourceLayout->descriptorSetLayouts[0];
- commandBuffer->computeReadOnlyDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
- renderer,
- commandBuffer,
- descriptorSetLayout);
- for (Uint32 i = 0; i < resourceLayout->numSamplers; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = i;
- currentWriteDescriptorSet->dstSet = commandBuffer->computeReadOnlyDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pBufferInfo = NULL;
- imageInfos[imageInfoCount].sampler = commandBuffer->computeSamplers[i]->sampler;
- imageInfos[imageInfoCount].imageView = commandBuffer->computeSamplerTextures[i]->fullView;
- imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
- writeCount += 1;
- imageInfoCount += 1;
- }
- for (Uint32 i = 0; i < resourceLayout->numReadonlyStorageTextures; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = resourceLayout->numSamplers + i;
- currentWriteDescriptorSet->dstSet = commandBuffer->computeReadOnlyDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pBufferInfo = NULL;
- imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
- imageInfos[imageInfoCount].imageView = commandBuffer->readOnlyComputeStorageTextures[i]->fullView;
- imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
- currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
- writeCount += 1;
- imageInfoCount += 1;
- }
- for (Uint32 i = 0; i < resourceLayout->numReadonlyStorageBuffers; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = resourceLayout->numSamplers + resourceLayout->numReadonlyStorageTextures + i;
- currentWriteDescriptorSet->dstSet = commandBuffer->computeReadOnlyDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pImageInfo = NULL;
- bufferInfos[bufferInfoCount].buffer = commandBuffer->readOnlyComputeStorageBuffers[i]->buffer;
- bufferInfos[bufferInfoCount].offset = 0;
- bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
- currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
- writeCount += 1;
- bufferInfoCount += 1;
- }
- commandBuffer->needNewComputeReadOnlyDescriptorSet = false;
- }
- if (commandBuffer->needNewComputeReadWriteDescriptorSet) {
- descriptorSetLayout = resourceLayout->descriptorSetLayouts[1];
- commandBuffer->computeReadWriteDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
- renderer,
- commandBuffer,
- descriptorSetLayout);
- for (Uint32 i = 0; i < resourceLayout->numReadWriteStorageTextures; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = i;
- currentWriteDescriptorSet->dstSet = commandBuffer->computeReadWriteDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pBufferInfo = NULL;
- imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
- imageInfos[imageInfoCount].imageView = commandBuffer->readWriteComputeStorageTextureSubresources[i]->computeWriteView;
- imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
- currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
- writeCount += 1;
- imageInfoCount += 1;
- }
- for (Uint32 i = 0; i < resourceLayout->numReadWriteStorageBuffers; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = resourceLayout->numReadWriteStorageTextures + i;
- currentWriteDescriptorSet->dstSet = commandBuffer->computeReadWriteDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pImageInfo = NULL;
- bufferInfos[bufferInfoCount].buffer = commandBuffer->readWriteComputeStorageBuffers[i]->buffer;
- bufferInfos[bufferInfoCount].offset = 0;
- bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
- currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
- writeCount += 1;
- bufferInfoCount += 1;
- }
- commandBuffer->needNewComputeReadWriteDescriptorSet = false;
- }
- if (commandBuffer->needNewComputeUniformDescriptorSet) {
- descriptorSetLayout = resourceLayout->descriptorSetLayouts[2];
- commandBuffer->computeUniformDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
- renderer,
- commandBuffer,
- descriptorSetLayout);
- for (Uint32 i = 0; i < resourceLayout->numUniformBuffers; i += 1) {
- VkWriteDescriptorSet *currentWriteDescriptorSet = &writeDescriptorSets[writeCount];
- currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- currentWriteDescriptorSet->pNext = NULL;
- currentWriteDescriptorSet->descriptorCount = 1;
- currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
- currentWriteDescriptorSet->dstArrayElement = 0;
- currentWriteDescriptorSet->dstBinding = i;
- currentWriteDescriptorSet->dstSet = commandBuffer->computeUniformDescriptorSet;
- currentWriteDescriptorSet->pTexelBufferView = NULL;
- currentWriteDescriptorSet->pImageInfo = NULL;
- bufferInfos[bufferInfoCount].buffer = commandBuffer->computeUniformBuffers[i]->buffer->buffer;
- bufferInfos[bufferInfoCount].offset = 0;
- bufferInfos[bufferInfoCount].range = MAX_UBO_SECTION_SIZE;
- currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
- writeCount += 1;
- bufferInfoCount += 1;
- }
- commandBuffer->needNewComputeUniformDescriptorSet = false;
- }
- for (Uint32 i = 0; i < resourceLayout->numUniformBuffers; i += 1) {
- dynamicOffsets[i] = commandBuffer->computeUniformBuffers[i]->drawOffset;
- dynamicOffsetCount += 1;
- }
- renderer->vkUpdateDescriptorSets(
- renderer->logicalDevice,
- writeCount,
- writeDescriptorSets,
- 0,
- NULL);
- VkDescriptorSet sets[3];
- sets[0] = commandBuffer->computeReadOnlyDescriptorSet;
- sets[1] = commandBuffer->computeReadWriteDescriptorSet;
- sets[2] = commandBuffer->computeUniformDescriptorSet;
- renderer->vkCmdBindDescriptorSets(
- commandBuffer->commandBuffer,
- VK_PIPELINE_BIND_POINT_COMPUTE,
- resourceLayout->pipelineLayout,
- 0,
- 3,
- sets,
- dynamicOffsetCount,
- dynamicOffsets);
- commandBuffer->needNewVertexUniformOffsets = false;
- }
- static void VULKAN_DispatchCompute(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 groupcountX,
- Uint32 groupcountY,
- Uint32 groupcountZ)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VULKAN_INTERNAL_BindComputeDescriptorSets(renderer, vulkanCommandBuffer);
- renderer->vkCmdDispatch(
- vulkanCommandBuffer->commandBuffer,
- groupcountX,
- groupcountY,
- groupcountZ);
- }
- static void VULKAN_DispatchComputeIndirect(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUBuffer *buffer,
- Uint32 offset)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)buffer)->activeBuffer;
- VULKAN_INTERNAL_BindComputeDescriptorSets(renderer, vulkanCommandBuffer);
- renderer->vkCmdDispatchIndirect(
- vulkanCommandBuffer->commandBuffer,
- vulkanBuffer->buffer,
- offset);
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
- }
- static void VULKAN_EndComputePass(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- Uint32 i;
- for (i = 0; i < vulkanCommandBuffer->readWriteComputeStorageTextureSubresourceCount; i += 1) {
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- vulkanCommandBuffer->renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
- vulkanCommandBuffer->readWriteComputeStorageTextureSubresources[i]);
- vulkanCommandBuffer->readWriteComputeStorageTextureSubresources[i] = NULL;
- }
- vulkanCommandBuffer->readWriteComputeStorageTextureSubresourceCount = 0;
- for (i = 0; i < MAX_COMPUTE_WRITE_BUFFERS; i += 1) {
- if (vulkanCommandBuffer->readWriteComputeStorageBuffers[i] != NULL) {
- VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
- vulkanCommandBuffer->renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
- vulkanCommandBuffer->readWriteComputeStorageBuffers[i]);
- vulkanCommandBuffer->readWriteComputeStorageBuffers[i] = NULL;
- }
- }
- for (i = 0; i < MAX_STORAGE_TEXTURES_PER_STAGE; i += 1) {
- if (vulkanCommandBuffer->readOnlyComputeStorageTextures[i] != NULL) {
- VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
- vulkanCommandBuffer->renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
- vulkanCommandBuffer->readOnlyComputeStorageTextures[i]);
- vulkanCommandBuffer->readOnlyComputeStorageTextures[i] = NULL;
- }
- }
- for (i = 0; i < MAX_STORAGE_BUFFERS_PER_STAGE; i += 1) {
- if (vulkanCommandBuffer->readOnlyComputeStorageBuffers[i] != NULL) {
- VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
- vulkanCommandBuffer->renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
- vulkanCommandBuffer->readOnlyComputeStorageBuffers[i]);
- vulkanCommandBuffer->readOnlyComputeStorageBuffers[i] = NULL;
- }
- }
- // we don't need a barrier because sampler state is always the default if sampler bit is set
- SDL_zeroa(vulkanCommandBuffer->computeSamplerTextures);
- SDL_zeroa(vulkanCommandBuffer->computeSamplers);
- vulkanCommandBuffer->currentComputePipeline = NULL;
- vulkanCommandBuffer->computeReadOnlyDescriptorSet = VK_NULL_HANDLE;
- vulkanCommandBuffer->computeReadWriteDescriptorSet = VK_NULL_HANDLE;
- vulkanCommandBuffer->computeUniformDescriptorSet = VK_NULL_HANDLE;
- }
- static void *VULKAN_MapTransferBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUTransferBuffer *transferBuffer,
- bool cycle)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)transferBuffer;
- if (
- cycle &&
- SDL_GetAtomicInt(&transferBufferContainer->activeBuffer->referenceCount) > 0) {
- VULKAN_INTERNAL_CycleActiveBuffer(
- renderer,
- transferBufferContainer);
- }
- Uint8 *bufferPointer =
- transferBufferContainer->activeBuffer->usedRegion->allocation->mapPointer +
- transferBufferContainer->activeBuffer->usedRegion->resourceOffset;
- return bufferPointer;
- }
- static void VULKAN_UnmapTransferBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUTransferBuffer *transferBuffer)
- {
- // no-op because transfer buffers are persistently mapped
- (void)driverData;
- (void)transferBuffer;
- }
- static void VULKAN_BeginCopyPass(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- // no-op
- (void)commandBuffer;
- }
- static void VULKAN_UploadToTexture(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUTextureTransferInfo *source,
- const SDL_GPUTextureRegion *destination,
- bool cycle)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)source->transfer_buffer;
- VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer *)destination->texture;
- VulkanTextureSubresource *vulkanTextureSubresource;
- VkBufferImageCopy imageCopy;
- // Note that the transfer buffer does not need a barrier, as it is synced by the client
- vulkanTextureSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
- renderer,
- vulkanCommandBuffer,
- vulkanTextureContainer,
- destination->layer,
- destination->mip_level,
- cycle,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION);
- imageCopy.imageExtent.width = destination->w;
- imageCopy.imageExtent.height = destination->h;
- imageCopy.imageExtent.depth = destination->d;
- imageCopy.imageOffset.x = destination->x;
- imageCopy.imageOffset.y = destination->y;
- imageCopy.imageOffset.z = destination->z;
- imageCopy.imageSubresource.aspectMask = vulkanTextureSubresource->parent->aspectFlags;
- imageCopy.imageSubresource.baseArrayLayer = destination->layer;
- imageCopy.imageSubresource.layerCount = 1;
- imageCopy.imageSubresource.mipLevel = destination->mip_level;
- imageCopy.bufferOffset = source->offset;
- imageCopy.bufferRowLength = source->pixels_per_row;
- imageCopy.bufferImageHeight = source->rows_per_layer;
- renderer->vkCmdCopyBufferToImage(
- vulkanCommandBuffer->commandBuffer,
- transferBufferContainer->activeBuffer->buffer,
- vulkanTextureSubresource->parent->image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1,
- &imageCopy);
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
- vulkanTextureSubresource);
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, vulkanTextureSubresource->parent);
- }
- static void VULKAN_UploadToBuffer(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUTransferBufferLocation *source,
- const SDL_GPUBufferRegion *destination,
- bool cycle)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)source->transfer_buffer;
- VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)destination->buffer;
- VkBufferCopy bufferCopy;
- // Note that the transfer buffer does not need a barrier, as it is synced by the client
- VulkanBuffer *vulkanBuffer = VULKAN_INTERNAL_PrepareBufferForWrite(
- renderer,
- vulkanCommandBuffer,
- bufferContainer,
- cycle,
- VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION);
- bufferCopy.srcOffset = source->offset;
- bufferCopy.dstOffset = destination->offset;
- bufferCopy.size = destination->size;
- renderer->vkCmdCopyBuffer(
- vulkanCommandBuffer->commandBuffer,
- transferBufferContainer->activeBuffer->buffer,
- vulkanBuffer->buffer,
- 1,
- &bufferCopy);
- VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
- vulkanBuffer);
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
- }
- // Readback
- static void VULKAN_DownloadFromTexture(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUTextureRegion *source,
- const SDL_GPUTextureTransferInfo *destination)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
- VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)source->texture;
- VulkanTextureSubresource *vulkanTextureSubresource;
- VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)destination->transfer_buffer;
- VkBufferImageCopy imageCopy;
- vulkanTextureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
- textureContainer,
- source->layer,
- source->mip_level);
- // Note that the transfer buffer does not need a barrier, as it is synced by the client
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- vulkanTextureSubresource);
- imageCopy.imageExtent.width = source->w;
- imageCopy.imageExtent.height = source->h;
- imageCopy.imageExtent.depth = source->d;
- imageCopy.imageOffset.x = source->x;
- imageCopy.imageOffset.y = source->y;
- imageCopy.imageOffset.z = source->z;
- imageCopy.imageSubresource.aspectMask = vulkanTextureSubresource->parent->aspectFlags;
- imageCopy.imageSubresource.baseArrayLayer = source->layer;
- imageCopy.imageSubresource.layerCount = 1;
- imageCopy.imageSubresource.mipLevel = source->mip_level;
- imageCopy.bufferOffset = destination->offset;
- imageCopy.bufferRowLength = destination->pixels_per_row;
- imageCopy.bufferImageHeight = destination->rows_per_layer;
- renderer->vkCmdCopyImageToBuffer(
- vulkanCommandBuffer->commandBuffer,
- vulkanTextureSubresource->parent->image,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- transferBufferContainer->activeBuffer->buffer,
- 1,
- &imageCopy);
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- vulkanTextureSubresource);
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, vulkanTextureSubresource->parent);
- }
- static void VULKAN_DownloadFromBuffer(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUBufferRegion *source,
- const SDL_GPUTransferBufferLocation *destination)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
- VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)source->buffer;
- VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)destination->transfer_buffer;
- VkBufferCopy bufferCopy;
- // Note that transfer buffer does not need a barrier, as it is synced by the client
- VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
- bufferContainer->activeBuffer);
- bufferCopy.srcOffset = source->offset;
- bufferCopy.dstOffset = destination->offset;
- bufferCopy.size = source->size;
- renderer->vkCmdCopyBuffer(
- vulkanCommandBuffer->commandBuffer,
- bufferContainer->activeBuffer->buffer,
- transferBufferContainer->activeBuffer->buffer,
- 1,
- &bufferCopy);
- VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
- bufferContainer->activeBuffer);
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBuffer);
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, bufferContainer->activeBuffer);
- }
- static void VULKAN_CopyTextureToTexture(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUTextureLocation *source,
- const SDL_GPUTextureLocation *destination,
- Uint32 w,
- Uint32 h,
- Uint32 d,
- bool cycle)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanTextureSubresource *srcSubresource;
- VulkanTextureSubresource *dstSubresource;
- VkImageCopy imageCopy;
- srcSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
- (VulkanTextureContainer *)source->texture,
- source->layer,
- source->mip_level);
- dstSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
- renderer,
- vulkanCommandBuffer,
- (VulkanTextureContainer *)destination->texture,
- destination->layer,
- destination->mip_level,
- cycle,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION);
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- srcSubresource);
- imageCopy.srcOffset.x = source->x;
- imageCopy.srcOffset.y = source->y;
- imageCopy.srcOffset.z = source->z;
- imageCopy.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
- imageCopy.srcSubresource.baseArrayLayer = source->layer;
- imageCopy.srcSubresource.layerCount = 1;
- imageCopy.srcSubresource.mipLevel = source->mip_level;
- imageCopy.dstOffset.x = destination->x;
- imageCopy.dstOffset.y = destination->y;
- imageCopy.dstOffset.z = destination->z;
- imageCopy.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
- imageCopy.dstSubresource.baseArrayLayer = destination->layer;
- imageCopy.dstSubresource.layerCount = 1;
- imageCopy.dstSubresource.mipLevel = destination->mip_level;
- imageCopy.extent.width = w;
- imageCopy.extent.height = h;
- imageCopy.extent.depth = d;
- renderer->vkCmdCopyImage(
- vulkanCommandBuffer->commandBuffer,
- srcSubresource->parent->image,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- dstSubresource->parent->image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1,
- &imageCopy);
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- srcSubresource);
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
- dstSubresource);
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcSubresource->parent);
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstSubresource->parent);
- }
- static void VULKAN_CopyBufferToBuffer(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUBufferLocation *source,
- const SDL_GPUBufferLocation *destination,
- Uint32 size,
- bool cycle)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanBufferContainer *srcContainer = (VulkanBufferContainer *)source->buffer;
- VulkanBufferContainer *dstContainer = (VulkanBufferContainer *)destination->buffer;
- VkBufferCopy bufferCopy;
- VulkanBuffer *dstBuffer = VULKAN_INTERNAL_PrepareBufferForWrite(
- renderer,
- vulkanCommandBuffer,
- dstContainer,
- cycle,
- VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION);
- VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
- srcContainer->activeBuffer);
- bufferCopy.srcOffset = source->offset;
- bufferCopy.dstOffset = destination->offset;
- bufferCopy.size = size;
- renderer->vkCmdCopyBuffer(
- vulkanCommandBuffer->commandBuffer,
- srcContainer->activeBuffer->buffer,
- dstBuffer->buffer,
- 1,
- &bufferCopy);
- VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
- srcContainer->activeBuffer);
- VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
- dstBuffer);
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, srcContainer->activeBuffer);
- VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, dstBuffer);
- }
- static void VULKAN_GenerateMipmaps(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUTexture *texture)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VulkanTextureContainer *container = (VulkanTextureContainer *)texture;
- VulkanTextureSubresource *srcTextureSubresource;
- VulkanTextureSubresource *dstTextureSubresource;
- VkImageBlit blit;
- // Blit each slice sequentially. Barriers, barriers everywhere!
- for (Uint32 layerOrDepthIndex = 0; layerOrDepthIndex < container->header.info.layer_count_or_depth; layerOrDepthIndex += 1)
- for (Uint32 level = 1; level < container->header.info.num_levels; level += 1) {
- Uint32 layer = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : layerOrDepthIndex;
- Uint32 depth = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? layerOrDepthIndex : 0;
- Uint32 srcSubresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
- level - 1,
- layer,
- container->header.info.num_levels);
- Uint32 dstSubresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
- level,
- layer,
- container->header.info.num_levels);
- srcTextureSubresource = &container->activeTexture->subresources[srcSubresourceIndex];
- dstTextureSubresource = &container->activeTexture->subresources[dstSubresourceIndex];
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- srcTextureSubresource);
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
- dstTextureSubresource);
- blit.srcOffsets[0].x = 0;
- blit.srcOffsets[0].y = 0;
- blit.srcOffsets[0].z = depth;
- blit.srcOffsets[1].x = container->header.info.width >> (level - 1);
- blit.srcOffsets[1].y = container->header.info.height >> (level - 1);
- blit.srcOffsets[1].z = depth + 1;
- blit.dstOffsets[0].x = 0;
- blit.dstOffsets[0].y = 0;
- blit.dstOffsets[0].z = depth;
- blit.dstOffsets[1].x = container->header.info.width >> level;
- blit.dstOffsets[1].y = container->header.info.height >> level;
- blit.dstOffsets[1].z = depth + 1;
- blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- blit.srcSubresource.baseArrayLayer = layer;
- blit.srcSubresource.layerCount = 1;
- blit.srcSubresource.mipLevel = level - 1;
- blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- blit.dstSubresource.baseArrayLayer = layer;
- blit.dstSubresource.layerCount = 1;
- blit.dstSubresource.mipLevel = level;
- renderer->vkCmdBlitImage(
- vulkanCommandBuffer->commandBuffer,
- container->activeTexture->image,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- container->activeTexture->image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1,
- &blit,
- VK_FILTER_LINEAR);
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- srcTextureSubresource);
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
- dstTextureSubresource);
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcTextureSubresource->parent);
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstTextureSubresource->parent);
- }
- }
- static void VULKAN_EndCopyPass(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- // no-op
- (void)commandBuffer;
- }
- static void VULKAN_Blit(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUBlitInfo *info)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- TextureCommonHeader *srcHeader = (TextureCommonHeader *)info->source.texture;
- TextureCommonHeader *dstHeader = (TextureCommonHeader *)info->destination.texture;
- VkImageBlit region;
- Uint32 srcLayer = srcHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : info->source.layer_or_depth_plane;
- Uint32 srcDepth = srcHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? info->source.layer_or_depth_plane : 0;
- Uint32 dstLayer = dstHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : info->destination.layer_or_depth_plane;
- Uint32 dstDepth = dstHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? info->destination.layer_or_depth_plane : 0;
- int32_t swap;
- // Using BeginRenderPass to clear because vkCmdClearColorImage requires barriers anyway
- if (info->load_op == SDL_GPU_LOADOP_CLEAR) {
- SDL_GPUColorTargetInfo targetInfo;
- targetInfo.texture = info->destination.texture;
- targetInfo.mip_level = info->destination.mip_level;
- targetInfo.layer_or_depth_plane = info->destination.layer_or_depth_plane;
- targetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
- targetInfo.store_op = SDL_GPU_STOREOP_STORE;
- targetInfo.clear_color = info->clear_color;
- targetInfo.cycle = info->cycle;
- VULKAN_BeginRenderPass(
- commandBuffer,
- &targetInfo,
- 1,
- NULL);
- VULKAN_EndRenderPass(commandBuffer);
- }
- VulkanTextureSubresource *srcSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
- (VulkanTextureContainer *)info->source.texture,
- srcLayer,
- info->source.mip_level);
- VulkanTextureSubresource *dstSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
- renderer,
- vulkanCommandBuffer,
- (VulkanTextureContainer *)info->destination.texture,
- dstLayer,
- info->destination.mip_level,
- info->cycle,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION);
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- srcSubresource);
- region.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
- region.srcSubresource.baseArrayLayer = srcSubresource->layer;
- region.srcSubresource.layerCount = 1;
- region.srcSubresource.mipLevel = srcSubresource->level;
- region.srcOffsets[0].x = info->source.x;
- region.srcOffsets[0].y = info->source.y;
- region.srcOffsets[0].z = srcDepth;
- region.srcOffsets[1].x = info->source.x + info->source.w;
- region.srcOffsets[1].y = info->source.y + info->source.h;
- region.srcOffsets[1].z = srcDepth + 1;
- if (info->flip_mode & SDL_FLIP_HORIZONTAL) {
- // flip the x positions
- swap = region.srcOffsets[0].x;
- region.srcOffsets[0].x = region.srcOffsets[1].x;
- region.srcOffsets[1].x = swap;
- }
- if (info->flip_mode & SDL_FLIP_VERTICAL) {
- // flip the y positions
- swap = region.srcOffsets[0].y;
- region.srcOffsets[0].y = region.srcOffsets[1].y;
- region.srcOffsets[1].y = swap;
- }
- region.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
- region.dstSubresource.baseArrayLayer = dstSubresource->layer;
- region.dstSubresource.layerCount = 1;
- region.dstSubresource.mipLevel = dstSubresource->level;
- region.dstOffsets[0].x = info->destination.x;
- region.dstOffsets[0].y = info->destination.y;
- region.dstOffsets[0].z = dstDepth;
- region.dstOffsets[1].x = info->destination.x + info->destination.w;
- region.dstOffsets[1].y = info->destination.y + info->destination.h;
- region.dstOffsets[1].z = dstDepth + 1;
- renderer->vkCmdBlitImage(
- vulkanCommandBuffer->commandBuffer,
- srcSubresource->parent->image,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- dstSubresource->parent->image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1,
- ®ion,
- SDLToVK_Filter[info->filter]);
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- srcSubresource);
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
- dstSubresource);
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcSubresource->parent);
- VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstSubresource->parent);
- }
- static bool VULKAN_INTERNAL_AllocateCommandBuffer(
- VulkanRenderer *renderer,
- VulkanCommandPool *vulkanCommandPool)
- {
- VkCommandBufferAllocateInfo allocateInfo;
- VkResult vulkanResult;
- VkCommandBuffer commandBufferHandle;
- VulkanCommandBuffer *commandBuffer;
- vulkanCommandPool->inactiveCommandBufferCapacity += 1;
- vulkanCommandPool->inactiveCommandBuffers = SDL_realloc(
- vulkanCommandPool->inactiveCommandBuffers,
- sizeof(VulkanCommandBuffer *) *
- vulkanCommandPool->inactiveCommandBufferCapacity);
- allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- allocateInfo.pNext = NULL;
- allocateInfo.commandPool = vulkanCommandPool->commandPool;
- allocateInfo.commandBufferCount = 1;
- allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- vulkanResult = renderer->vkAllocateCommandBuffers(
- renderer->logicalDevice,
- &allocateInfo,
- &commandBufferHandle);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkAllocateCommandBuffers, false)
- commandBuffer = SDL_malloc(sizeof(VulkanCommandBuffer));
- commandBuffer->renderer = renderer;
- commandBuffer->commandPool = vulkanCommandPool;
- commandBuffer->commandBuffer = commandBufferHandle;
- commandBuffer->inFlightFence = VK_NULL_HANDLE;
- // Presentation tracking
- commandBuffer->presentDataCapacity = 1;
- commandBuffer->presentDataCount = 0;
- commandBuffer->presentDatas = SDL_malloc(
- commandBuffer->presentDataCapacity * sizeof(VulkanPresentData));
- commandBuffer->waitSemaphoreCapacity = 1;
- commandBuffer->waitSemaphoreCount = 0;
- commandBuffer->waitSemaphores = SDL_malloc(
- commandBuffer->waitSemaphoreCapacity * sizeof(VkSemaphore));
- commandBuffer->signalSemaphoreCapacity = 1;
- commandBuffer->signalSemaphoreCount = 0;
- commandBuffer->signalSemaphores = SDL_malloc(
- commandBuffer->signalSemaphoreCapacity * sizeof(VkSemaphore));
- // Resource bind tracking
- commandBuffer->needNewVertexResourceDescriptorSet = true;
- commandBuffer->needNewVertexUniformDescriptorSet = true;
- commandBuffer->needNewVertexUniformOffsets = true;
- commandBuffer->needNewFragmentResourceDescriptorSet = true;
- commandBuffer->needNewFragmentUniformDescriptorSet = true;
- commandBuffer->needNewFragmentUniformOffsets = true;
- commandBuffer->needNewComputeReadWriteDescriptorSet = true;
- commandBuffer->needNewComputeReadOnlyDescriptorSet = true;
- commandBuffer->needNewComputeUniformDescriptorSet = true;
- commandBuffer->needNewComputeUniformOffsets = true;
- commandBuffer->vertexResourceDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->vertexUniformDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->fragmentResourceDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->fragmentUniformDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->computeReadOnlyDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->computeReadWriteDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->computeUniformDescriptorSet = VK_NULL_HANDLE;
- // Resource tracking
- commandBuffer->usedBufferCapacity = 4;
- commandBuffer->usedBufferCount = 0;
- commandBuffer->usedBuffers = SDL_malloc(
- commandBuffer->usedBufferCapacity * sizeof(VulkanBuffer *));
- commandBuffer->usedTextureCapacity = 4;
- commandBuffer->usedTextureCount = 0;
- commandBuffer->usedTextures = SDL_malloc(
- commandBuffer->usedTextureCapacity * sizeof(VulkanTexture *));
- commandBuffer->usedSamplerCapacity = 4;
- commandBuffer->usedSamplerCount = 0;
- commandBuffer->usedSamplers = SDL_malloc(
- commandBuffer->usedSamplerCapacity * sizeof(VulkanSampler *));
- commandBuffer->usedGraphicsPipelineCapacity = 4;
- commandBuffer->usedGraphicsPipelineCount = 0;
- commandBuffer->usedGraphicsPipelines = SDL_malloc(
- commandBuffer->usedGraphicsPipelineCapacity * sizeof(VulkanGraphicsPipeline *));
- commandBuffer->usedComputePipelineCapacity = 4;
- commandBuffer->usedComputePipelineCount = 0;
- commandBuffer->usedComputePipelines = SDL_malloc(
- commandBuffer->usedComputePipelineCapacity * sizeof(VulkanComputePipeline *));
- commandBuffer->usedFramebufferCapacity = 4;
- commandBuffer->usedFramebufferCount = 0;
- commandBuffer->usedFramebuffers = SDL_malloc(
- commandBuffer->usedFramebufferCapacity * sizeof(VulkanFramebuffer *));
- commandBuffer->usedUniformBufferCapacity = 4;
- commandBuffer->usedUniformBufferCount = 0;
- commandBuffer->usedUniformBuffers = SDL_malloc(
- commandBuffer->usedUniformBufferCapacity * sizeof(VulkanUniformBuffer *));
- // Pool it!
- vulkanCommandPool->inactiveCommandBuffers[vulkanCommandPool->inactiveCommandBufferCount] = commandBuffer;
- vulkanCommandPool->inactiveCommandBufferCount += 1;
- return true;
- }
- static VulkanCommandPool *VULKAN_INTERNAL_FetchCommandPool(
- VulkanRenderer *renderer,
- SDL_ThreadID threadID)
- {
- VulkanCommandPool *vulkanCommandPool = NULL;
- VkCommandPoolCreateInfo commandPoolCreateInfo;
- VkResult vulkanResult;
- CommandPoolHashTableKey key;
- key.threadID = threadID;
- bool result = SDL_FindInHashTable(
- renderer->commandPoolHashTable,
- (const void *)&key,
- (const void **)&vulkanCommandPool);
- if (result) {
- return vulkanCommandPool;
- }
- vulkanCommandPool = (VulkanCommandPool *)SDL_malloc(sizeof(VulkanCommandPool));
- commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- commandPoolCreateInfo.pNext = NULL;
- commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- commandPoolCreateInfo.queueFamilyIndex = renderer->queueFamilyIndex;
- vulkanResult = renderer->vkCreateCommandPool(
- renderer->logicalDevice,
- &commandPoolCreateInfo,
- NULL,
- &vulkanCommandPool->commandPool);
- if (vulkanResult != VK_SUCCESS) {
- SDL_free(vulkanCommandPool);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateCommandPool, NULL)
- return NULL;
- }
- vulkanCommandPool->threadID = threadID;
- vulkanCommandPool->inactiveCommandBufferCapacity = 0;
- vulkanCommandPool->inactiveCommandBufferCount = 0;
- vulkanCommandPool->inactiveCommandBuffers = NULL;
- if (!VULKAN_INTERNAL_AllocateCommandBuffer(
- renderer,
- vulkanCommandPool)) {
- VULKAN_INTERNAL_DestroyCommandPool(renderer, vulkanCommandPool);
- return NULL;
- }
- CommandPoolHashTableKey *allocedKey = SDL_malloc(sizeof(CommandPoolHashTableKey));
- allocedKey->threadID = threadID;
- SDL_InsertIntoHashTable(
- renderer->commandPoolHashTable,
- (const void *)allocedKey,
- (const void *)vulkanCommandPool);
- return vulkanCommandPool;
- }
- static VulkanCommandBuffer *VULKAN_INTERNAL_GetInactiveCommandBufferFromPool(
- VulkanRenderer *renderer,
- SDL_ThreadID threadID)
- {
- VulkanCommandPool *commandPool =
- VULKAN_INTERNAL_FetchCommandPool(renderer, threadID);
- VulkanCommandBuffer *commandBuffer;
- if (commandPool == NULL) {
- return NULL;
- }
- if (commandPool->inactiveCommandBufferCount == 0) {
- if (!VULKAN_INTERNAL_AllocateCommandBuffer(
- renderer,
- commandPool)) {
- return NULL;
- }
- }
- commandBuffer = commandPool->inactiveCommandBuffers[commandPool->inactiveCommandBufferCount - 1];
- commandPool->inactiveCommandBufferCount -= 1;
- return commandBuffer;
- }
- static SDL_GPUCommandBuffer *VULKAN_AcquireCommandBuffer(
- SDL_GPURenderer *driverData)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VkResult result;
- Uint32 i;
- SDL_ThreadID threadID = SDL_GetCurrentThreadID();
- SDL_LockMutex(renderer->acquireCommandBufferLock);
- VulkanCommandBuffer *commandBuffer =
- VULKAN_INTERNAL_GetInactiveCommandBufferFromPool(renderer, threadID);
- commandBuffer->descriptorSetCache = VULKAN_INTERNAL_AcquireDescriptorSetCache(renderer);
- SDL_UnlockMutex(renderer->acquireCommandBufferLock);
- if (commandBuffer == NULL) {
- return NULL;
- }
- // Reset state
- commandBuffer->currentComputePipeline = NULL;
- commandBuffer->currentGraphicsPipeline = NULL;
- SDL_zeroa(commandBuffer->colorAttachmentSubresources);
- SDL_zeroa(commandBuffer->resolveAttachmentSubresources);
- commandBuffer->depthStencilAttachmentSubresource = NULL;
- commandBuffer->colorAttachmentSubresourceCount = 0;
- commandBuffer->resolveAttachmentSubresourceCount = 0;
- for (i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
- commandBuffer->vertexUniformBuffers[i] = NULL;
- commandBuffer->fragmentUniformBuffers[i] = NULL;
- commandBuffer->computeUniformBuffers[i] = NULL;
- }
- commandBuffer->needNewVertexResourceDescriptorSet = true;
- commandBuffer->needNewVertexUniformDescriptorSet = true;
- commandBuffer->needNewVertexUniformOffsets = true;
- commandBuffer->needNewFragmentResourceDescriptorSet = true;
- commandBuffer->needNewFragmentUniformDescriptorSet = true;
- commandBuffer->needNewFragmentUniformOffsets = true;
- commandBuffer->needNewComputeReadOnlyDescriptorSet = true;
- commandBuffer->needNewComputeUniformDescriptorSet = true;
- commandBuffer->needNewComputeUniformOffsets = true;
- commandBuffer->vertexResourceDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->vertexUniformDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->fragmentResourceDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->fragmentUniformDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->computeReadOnlyDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->computeReadWriteDescriptorSet = VK_NULL_HANDLE;
- commandBuffer->computeUniformDescriptorSet = VK_NULL_HANDLE;
- SDL_zeroa(commandBuffer->vertexSamplerTextures);
- SDL_zeroa(commandBuffer->vertexSamplers);
- SDL_zeroa(commandBuffer->vertexStorageTextures);
- SDL_zeroa(commandBuffer->vertexStorageBuffers);
- SDL_zeroa(commandBuffer->fragmentSamplerTextures);
- SDL_zeroa(commandBuffer->fragmentSamplers);
- SDL_zeroa(commandBuffer->fragmentStorageTextures);
- SDL_zeroa(commandBuffer->fragmentStorageBuffers);
- SDL_zeroa(commandBuffer->readWriteComputeStorageTextureSubresources);
- commandBuffer->readWriteComputeStorageTextureSubresourceCount = 0;
- SDL_zeroa(commandBuffer->readWriteComputeStorageBuffers);
- SDL_zeroa(commandBuffer->computeSamplerTextures);
- SDL_zeroa(commandBuffer->computeSamplers);
- SDL_zeroa(commandBuffer->readOnlyComputeStorageTextures);
- SDL_zeroa(commandBuffer->readOnlyComputeStorageBuffers);
- commandBuffer->autoReleaseFence = 1;
- commandBuffer->isDefrag = 0;
- /* Reset the command buffer here to avoid resets being called
- * from a separate thread than where the command buffer was acquired
- */
- result = renderer->vkResetCommandBuffer(
- commandBuffer->commandBuffer,
- VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkResetCommandBuffer, NULL)
- if (!VULKAN_INTERNAL_BeginCommandBuffer(renderer, commandBuffer)) {
- return NULL;
- }
- return (SDL_GPUCommandBuffer *)commandBuffer;
- }
- static bool VULKAN_QueryFence(
- SDL_GPURenderer *driverData,
- SDL_GPUFence *fence)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VkResult result;
- result = renderer->vkGetFenceStatus(
- renderer->logicalDevice,
- ((VulkanFenceHandle *)fence)->fence);
- if (result == VK_SUCCESS) {
- return true;
- } else if (result == VK_NOT_READY) {
- return false;
- } else {
- SET_ERROR_AND_RETURN("vkGetFenceStatus: %s", VkErrorMessages(result), false)
- }
- }
- static void VULKAN_INTERNAL_ReturnFenceToPool(
- VulkanRenderer *renderer,
- VulkanFenceHandle *fenceHandle)
- {
- SDL_LockMutex(renderer->fencePool.lock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->fencePool.availableFences,
- VulkanFenceHandle *,
- renderer->fencePool.availableFenceCount + 1,
- renderer->fencePool.availableFenceCapacity,
- renderer->fencePool.availableFenceCapacity * 2);
- renderer->fencePool.availableFences[renderer->fencePool.availableFenceCount] = fenceHandle;
- renderer->fencePool.availableFenceCount += 1;
- SDL_UnlockMutex(renderer->fencePool.lock);
- }
- static void VULKAN_ReleaseFence(
- SDL_GPURenderer *driverData,
- SDL_GPUFence *fence)
- {
- VulkanFenceHandle *handle = (VulkanFenceHandle *)fence;
- if (SDL_AtomicDecRef(&handle->referenceCount)) {
- VULKAN_INTERNAL_ReturnFenceToPool((VulkanRenderer *)driverData, handle);
- }
- }
- static WindowData *VULKAN_INTERNAL_FetchWindowData(
- SDL_Window *window)
- {
- SDL_PropertiesID properties = SDL_GetWindowProperties(window);
- return (WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
- }
- static bool VULKAN_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
- {
- SDL_Window *w = (SDL_Window *)userdata;
- WindowData *data;
- if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
- data = VULKAN_INTERNAL_FetchWindowData(w);
- data->needsSwapchainRecreate = true;
- }
- return true;
- }
- static bool VULKAN_SupportsSwapchainComposition(
- SDL_GPURenderer *driverData,
- SDL_Window *window,
- SDL_GPUSwapchainComposition swapchainComposition)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
- VkSurfaceKHR surface;
- SwapchainSupportDetails supportDetails;
- bool result = false;
- if (windowData == NULL || windowData->swapchainData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Must claim window before querying swapchain composition support!", false)
- }
- surface = windowData->swapchainData->surface;
- if (VULKAN_INTERNAL_QuerySwapchainSupport(
- renderer,
- renderer->physicalDevice,
- surface,
- &supportDetails)) {
- result = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
- SwapchainCompositionToFormat[swapchainComposition],
- SwapchainCompositionToColorSpace[swapchainComposition],
- supportDetails.formats,
- supportDetails.formatsLength);
- if (!result) {
- // Let's try again with the fallback format...
- result = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
- SwapchainCompositionToFallbackFormat[swapchainComposition],
- SwapchainCompositionToColorSpace[swapchainComposition],
- supportDetails.formats,
- supportDetails.formatsLength);
- }
- SDL_free(supportDetails.formats);
- SDL_free(supportDetails.presentModes);
- }
- return result;
- }
- static bool VULKAN_SupportsPresentMode(
- SDL_GPURenderer *driverData,
- SDL_Window *window,
- SDL_GPUPresentMode presentMode)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
- VkSurfaceKHR surface;
- SwapchainSupportDetails supportDetails;
- bool result = false;
- if (windowData == NULL || windowData->swapchainData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Must claim window before querying present mode support!", false)
- }
- surface = windowData->swapchainData->surface;
- if (VULKAN_INTERNAL_QuerySwapchainSupport(
- renderer,
- renderer->physicalDevice,
- surface,
- &supportDetails)) {
- result = VULKAN_INTERNAL_VerifySwapPresentMode(
- SDLToVK_PresentMode[presentMode],
- supportDetails.presentModes,
- supportDetails.presentModesLength);
- SDL_free(supportDetails.formats);
- SDL_free(supportDetails.presentModes);
- }
- return result;
- }
- static bool VULKAN_ClaimWindow(
- SDL_GPURenderer *driverData,
- SDL_Window *window)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- windowData = SDL_malloc(sizeof(WindowData));
- windowData->window = window;
- windowData->presentMode = SDL_GPU_PRESENTMODE_VSYNC;
- windowData->swapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR;
- if (VULKAN_INTERNAL_CreateSwapchain(renderer, windowData)) {
- SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
- if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
- renderer->claimedWindowCapacity *= 2;
- renderer->claimedWindows = SDL_realloc(
- renderer->claimedWindows,
- renderer->claimedWindowCapacity * sizeof(WindowData *));
- }
- renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
- renderer->claimedWindowCount += 1;
- SDL_AddEventWatch(VULKAN_INTERNAL_OnWindowResize, window);
- return 1;
- } else {
- SDL_free(windowData);
- SET_STRING_ERROR_AND_RETURN("Could not create swapchain, failed to claim window!", 0);
- }
- } else {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Window already claimed!");
- return 0;
- }
- }
- static void VULKAN_ReleaseWindow(
- SDL_GPURenderer *driverData,
- SDL_Window *window)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
- Uint32 i;
- if (windowData == NULL) {
- return;
- }
- if (windowData->swapchainData != NULL) {
- VULKAN_Wait(driverData);
- for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
- if (windowData->swapchainData->inFlightFences[i] != NULL) {
- VULKAN_ReleaseFence(
- driverData,
- windowData->swapchainData->inFlightFences[i]);
- }
- }
- VULKAN_INTERNAL_DestroySwapchain(
- (VulkanRenderer *)driverData,
- windowData);
- }
- for (i = 0; i < renderer->claimedWindowCount; i += 1) {
- if (renderer->claimedWindows[i]->window == window) {
- renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
- renderer->claimedWindowCount -= 1;
- break;
- }
- }
- SDL_free(windowData);
- SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
- SDL_RemoveEventWatch(VULKAN_INTERNAL_OnWindowResize, window);
- }
- static bool VULKAN_INTERNAL_RecreateSwapchain(
- VulkanRenderer *renderer,
- WindowData *windowData)
- {
- Uint32 i;
- if (windowData->swapchainData != NULL) {
- if (!VULKAN_Wait((SDL_GPURenderer *)renderer)) {
- return false;
- }
- for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
- if (windowData->swapchainData->inFlightFences[i] != NULL) {
- VULKAN_ReleaseFence(
- (SDL_GPURenderer *)renderer,
- windowData->swapchainData->inFlightFences[i]);
- }
- }
- }
- VULKAN_INTERNAL_DestroySwapchain(renderer, windowData);
- return VULKAN_INTERNAL_CreateSwapchain(renderer, windowData);
- }
- static bool VULKAN_AcquireSwapchainTexture(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_Window *window,
- SDL_GPUTexture **swapchainTexture)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- Uint32 swapchainImageIndex;
- WindowData *windowData;
- VulkanSwapchainData *swapchainData;
- VkResult acquireResult = VK_SUCCESS;
- VulkanTextureContainer *swapchainTextureContainer = NULL;
- VulkanPresentData *presentData;
- *swapchainTexture = NULL;
- windowData = VULKAN_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false)
- }
- swapchainData = windowData->swapchainData;
- // Window is claimed but swapchain is invalid!
- if (swapchainData == NULL) {
- if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) {
- // Window is minimized, don't bother
- return true;
- }
- // Let's try to recreate
- VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
- swapchainData = windowData->swapchainData;
- if (swapchainData == NULL) {
- return false;
- }
- }
- if (swapchainData->inFlightFences[swapchainData->frameCounter] != NULL) {
- if (swapchainData->presentMode == VK_PRESENT_MODE_FIFO_KHR) {
- // In VSYNC mode, block until the least recent presented frame is done
- if (!VULKAN_WaitForFences(
- (SDL_GPURenderer *)renderer,
- true,
- &swapchainData->inFlightFences[swapchainData->frameCounter],
- 1)) {
- return false;
- }
- } else {
- if (!VULKAN_QueryFence(
- (SDL_GPURenderer *)renderer,
- swapchainData->inFlightFences[swapchainData->frameCounter])) {
- /*
- * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled,
- * return true to indicate that there is no error but rendering should be skipped
- */
- return true;
- }
- }
- VULKAN_ReleaseFence(
- (SDL_GPURenderer *)renderer,
- swapchainData->inFlightFences[swapchainData->frameCounter]);
- swapchainData->inFlightFences[swapchainData->frameCounter] = NULL;
- }
- // If window data marked as needing swapchain recreate, try to recreate
- if (windowData->needsSwapchainRecreate) {
- VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
- swapchainData = windowData->swapchainData;
- if (swapchainData == NULL) {
- return false;
- }
- }
- // Finally, try to acquire!
- acquireResult = renderer->vkAcquireNextImageKHR(
- renderer->logicalDevice,
- swapchainData->swapchain,
- SDL_MAX_UINT64,
- swapchainData->imageAvailableSemaphore[swapchainData->frameCounter],
- VK_NULL_HANDLE,
- &swapchainImageIndex);
- // Acquisition is invalid, let's try to recreate
- if (acquireResult != VK_SUCCESS && acquireResult != VK_SUBOPTIMAL_KHR) {
- VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
- swapchainData = windowData->swapchainData;
- if (swapchainData == NULL) {
- return false;
- }
- acquireResult = renderer->vkAcquireNextImageKHR(
- renderer->logicalDevice,
- swapchainData->swapchain,
- SDL_MAX_UINT64,
- swapchainData->imageAvailableSemaphore[swapchainData->frameCounter],
- VK_NULL_HANDLE,
- &swapchainImageIndex);
- if (acquireResult != VK_SUCCESS && acquireResult != VK_SUBOPTIMAL_KHR) {
- return false;
- }
- }
- swapchainTextureContainer = &swapchainData->textureContainers[swapchainImageIndex];
- // We need a special execution dependency with pWaitDstStageMask or image transition can start before acquire finishes
- VkImageMemoryBarrier imageBarrier;
- imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- imageBarrier.pNext = NULL;
- imageBarrier.srcAccessMask = 0;
- imageBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- imageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- imageBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- imageBarrier.image = swapchainTextureContainer->activeTexture->image;
- imageBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- imageBarrier.subresourceRange.baseMipLevel = 0;
- imageBarrier.subresourceRange.levelCount = 1;
- imageBarrier.subresourceRange.baseArrayLayer = 0;
- imageBarrier.subresourceRange.layerCount = 1;
- renderer->vkCmdPipelineBarrier(
- vulkanCommandBuffer->commandBuffer,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
- 0,
- 0,
- NULL,
- 0,
- NULL,
- 1,
- &imageBarrier);
- // Set up present struct
- if (vulkanCommandBuffer->presentDataCount == vulkanCommandBuffer->presentDataCapacity) {
- vulkanCommandBuffer->presentDataCapacity += 1;
- vulkanCommandBuffer->presentDatas = SDL_realloc(
- vulkanCommandBuffer->presentDatas,
- vulkanCommandBuffer->presentDataCapacity * sizeof(VulkanPresentData));
- }
- presentData = &vulkanCommandBuffer->presentDatas[vulkanCommandBuffer->presentDataCount];
- vulkanCommandBuffer->presentDataCount += 1;
- presentData->windowData = windowData;
- presentData->swapchainImageIndex = swapchainImageIndex;
- // Set up present semaphores
- if (vulkanCommandBuffer->waitSemaphoreCount == vulkanCommandBuffer->waitSemaphoreCapacity) {
- vulkanCommandBuffer->waitSemaphoreCapacity += 1;
- vulkanCommandBuffer->waitSemaphores = SDL_realloc(
- vulkanCommandBuffer->waitSemaphores,
- vulkanCommandBuffer->waitSemaphoreCapacity * sizeof(VkSemaphore));
- }
- vulkanCommandBuffer->waitSemaphores[vulkanCommandBuffer->waitSemaphoreCount] =
- swapchainData->imageAvailableSemaphore[swapchainData->frameCounter];
- vulkanCommandBuffer->waitSemaphoreCount += 1;
- if (vulkanCommandBuffer->signalSemaphoreCount == vulkanCommandBuffer->signalSemaphoreCapacity) {
- vulkanCommandBuffer->signalSemaphoreCapacity += 1;
- vulkanCommandBuffer->signalSemaphores = SDL_realloc(
- vulkanCommandBuffer->signalSemaphores,
- vulkanCommandBuffer->signalSemaphoreCapacity * sizeof(VkSemaphore));
- }
- vulkanCommandBuffer->signalSemaphores[vulkanCommandBuffer->signalSemaphoreCount] =
- swapchainData->renderFinishedSemaphore[swapchainData->frameCounter];
- vulkanCommandBuffer->signalSemaphoreCount += 1;
- *swapchainTexture = (SDL_GPUTexture *)swapchainTextureContainer;
- return true;
- }
- static SDL_GPUTextureFormat VULKAN_GetSwapchainTextureFormat(
- SDL_GPURenderer *driverData,
- SDL_Window *window)
- {
- VulkanRenderer *renderer = (VulkanRenderer*)driverData;
- WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Cannot get swapchain format, window has not been claimed!", SDL_GPU_TEXTUREFORMAT_INVALID)
- }
- if (windowData->swapchainData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Cannot get swapchain format, swapchain is currently invalid!", SDL_GPU_TEXTUREFORMAT_INVALID)
- }
- return SwapchainCompositionToSDLFormat(
- windowData->swapchainComposition,
- windowData->swapchainData->usingFallbackFormat);
- }
- static bool VULKAN_SetSwapchainParameters(
- SDL_GPURenderer *driverData,
- SDL_Window *window,
- SDL_GPUSwapchainComposition swapchainComposition,
- SDL_GPUPresentMode presentMode)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Cannot set swapchain parameters on unclaimed window!", false)
- }
- if (!VULKAN_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
- SET_STRING_ERROR_AND_RETURN("Swapchain composition not supported!", false)
- }
- if (!VULKAN_SupportsPresentMode(driverData, window, presentMode)) {
- SET_STRING_ERROR_AND_RETURN("Present mode not supported!", false)
- }
- windowData->presentMode = presentMode;
- windowData->swapchainComposition = swapchainComposition;
- return VULKAN_INTERNAL_RecreateSwapchain(
- (VulkanRenderer *)driverData,
- windowData);
- }
- // Submission structure
- static VulkanFenceHandle *VULKAN_INTERNAL_AcquireFenceFromPool(
- VulkanRenderer *renderer)
- {
- VulkanFenceHandle *handle;
- VkFenceCreateInfo fenceCreateInfo;
- VkFence fence;
- VkResult vulkanResult;
- if (renderer->fencePool.availableFenceCount == 0) {
- // Create fence
- fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceCreateInfo.pNext = NULL;
- fenceCreateInfo.flags = 0;
- vulkanResult = renderer->vkCreateFence(
- renderer->logicalDevice,
- &fenceCreateInfo,
- NULL,
- &fence);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateFence, NULL)
- handle = SDL_malloc(sizeof(VulkanFenceHandle));
- handle->fence = fence;
- SDL_SetAtomicInt(&handle->referenceCount, 0);
- return handle;
- }
- SDL_LockMutex(renderer->fencePool.lock);
- handle = renderer->fencePool.availableFences[renderer->fencePool.availableFenceCount - 1];
- renderer->fencePool.availableFenceCount -= 1;
- vulkanResult = renderer->vkResetFences(
- renderer->logicalDevice,
- 1,
- &handle->fence);
- SDL_UnlockMutex(renderer->fencePool.lock);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkResetFences, NULL)
- return handle;
- }
- static void VULKAN_INTERNAL_PerformPendingDestroys(
- VulkanRenderer *renderer)
- {
- SDL_LockMutex(renderer->disposeLock);
- for (Sint32 i = renderer->texturesToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->texturesToDestroy[i]->referenceCount) == 0) {
- VULKAN_INTERNAL_DestroyTexture(
- renderer,
- renderer->texturesToDestroy[i]);
- renderer->texturesToDestroy[i] = renderer->texturesToDestroy[renderer->texturesToDestroyCount - 1];
- renderer->texturesToDestroyCount -= 1;
- }
- }
- for (Sint32 i = renderer->buffersToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->buffersToDestroy[i]->referenceCount) == 0) {
- VULKAN_INTERNAL_DestroyBuffer(
- renderer,
- renderer->buffersToDestroy[i]);
- renderer->buffersToDestroy[i] = renderer->buffersToDestroy[renderer->buffersToDestroyCount - 1];
- renderer->buffersToDestroyCount -= 1;
- }
- }
- for (Sint32 i = renderer->graphicsPipelinesToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->graphicsPipelinesToDestroy[i]->referenceCount) == 0) {
- VULKAN_INTERNAL_DestroyGraphicsPipeline(
- renderer,
- renderer->graphicsPipelinesToDestroy[i]);
- renderer->graphicsPipelinesToDestroy[i] = renderer->graphicsPipelinesToDestroy[renderer->graphicsPipelinesToDestroyCount - 1];
- renderer->graphicsPipelinesToDestroyCount -= 1;
- }
- }
- for (Sint32 i = renderer->computePipelinesToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->computePipelinesToDestroy[i]->referenceCount) == 0) {
- VULKAN_INTERNAL_DestroyComputePipeline(
- renderer,
- renderer->computePipelinesToDestroy[i]);
- renderer->computePipelinesToDestroy[i] = renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount - 1];
- renderer->computePipelinesToDestroyCount -= 1;
- }
- }
- for (Sint32 i = renderer->shadersToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->shadersToDestroy[i]->referenceCount) == 0) {
- VULKAN_INTERNAL_DestroyShader(
- renderer,
- renderer->shadersToDestroy[i]);
- renderer->shadersToDestroy[i] = renderer->shadersToDestroy[renderer->shadersToDestroyCount - 1];
- renderer->shadersToDestroyCount -= 1;
- }
- }
- for (Sint32 i = renderer->samplersToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->samplersToDestroy[i]->referenceCount) == 0) {
- VULKAN_INTERNAL_DestroySampler(
- renderer,
- renderer->samplersToDestroy[i]);
- renderer->samplersToDestroy[i] = renderer->samplersToDestroy[renderer->samplersToDestroyCount - 1];
- renderer->samplersToDestroyCount -= 1;
- }
- }
- for (Sint32 i = renderer->framebuffersToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->framebuffersToDestroy[i]->referenceCount) == 0) {
- VULKAN_INTERNAL_DestroyFramebuffer(
- renderer,
- renderer->framebuffersToDestroy[i]);
- renderer->framebuffersToDestroy[i] = renderer->framebuffersToDestroy[renderer->framebuffersToDestroyCount - 1];
- renderer->framebuffersToDestroyCount -= 1;
- }
- }
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void VULKAN_INTERNAL_CleanCommandBuffer(
- VulkanRenderer *renderer,
- VulkanCommandBuffer *commandBuffer)
- {
- if (commandBuffer->autoReleaseFence) {
- VULKAN_ReleaseFence(
- (SDL_GPURenderer *)renderer,
- (SDL_GPUFence *)commandBuffer->inFlightFence);
- commandBuffer->inFlightFence = NULL;
- }
- // Uniform buffers are now available
- SDL_LockMutex(renderer->acquireUniformBufferLock);
- for (Sint32 i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
- VULKAN_INTERNAL_ReturnUniformBufferToPool(
- renderer,
- commandBuffer->usedUniformBuffers[i]);
- }
- commandBuffer->usedUniformBufferCount = 0;
- SDL_UnlockMutex(renderer->acquireUniformBufferLock);
- // Decrement reference counts
- for (Sint32 i = 0; i < commandBuffer->usedBufferCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
- }
- commandBuffer->usedBufferCount = 0;
- for (Sint32 i = 0; i < commandBuffer->usedTextureCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
- }
- commandBuffer->usedTextureCount = 0;
- for (Sint32 i = 0; i < commandBuffer->usedSamplerCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedSamplers[i]->referenceCount);
- }
- commandBuffer->usedSamplerCount = 0;
- for (Sint32 i = 0; i < commandBuffer->usedGraphicsPipelineCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedGraphicsPipelines[i]->referenceCount);
- }
- commandBuffer->usedGraphicsPipelineCount = 0;
- for (Sint32 i = 0; i < commandBuffer->usedComputePipelineCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedComputePipelines[i]->referenceCount);
- }
- commandBuffer->usedComputePipelineCount = 0;
- for (Sint32 i = 0; i < commandBuffer->usedFramebufferCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedFramebuffers[i]->referenceCount);
- }
- commandBuffer->usedFramebufferCount = 0;
- // Reset presentation data
- commandBuffer->presentDataCount = 0;
- commandBuffer->waitSemaphoreCount = 0;
- commandBuffer->signalSemaphoreCount = 0;
- // Reset defrag state
- if (commandBuffer->isDefrag) {
- renderer->defragInProgress = 0;
- }
- // Return command buffer to pool
- SDL_LockMutex(renderer->acquireCommandBufferLock);
- if (commandBuffer->commandPool->inactiveCommandBufferCount == commandBuffer->commandPool->inactiveCommandBufferCapacity) {
- commandBuffer->commandPool->inactiveCommandBufferCapacity += 1;
- commandBuffer->commandPool->inactiveCommandBuffers = SDL_realloc(
- commandBuffer->commandPool->inactiveCommandBuffers,
- commandBuffer->commandPool->inactiveCommandBufferCapacity * sizeof(VulkanCommandBuffer *));
- }
- commandBuffer->commandPool->inactiveCommandBuffers[commandBuffer->commandPool->inactiveCommandBufferCount] = commandBuffer;
- commandBuffer->commandPool->inactiveCommandBufferCount += 1;
- // Release descriptor set cache
- VULKAN_INTERNAL_ReturnDescriptorSetCacheToPool(
- renderer,
- commandBuffer->descriptorSetCache);
- commandBuffer->descriptorSetCache = NULL;
- SDL_UnlockMutex(renderer->acquireCommandBufferLock);
- // Remove this command buffer from the submitted list
- for (Uint32 i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
- if (renderer->submittedCommandBuffers[i] == commandBuffer) {
- renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
- renderer->submittedCommandBufferCount -= 1;
- }
- }
- }
- static bool VULKAN_WaitForFences(
- SDL_GPURenderer *driverData,
- bool waitAll,
- SDL_GPUFence *const *fences,
- Uint32 numFences)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VkFence *vkFences = SDL_stack_alloc(VkFence, numFences);
- VkResult result;
- for (Uint32 i = 0; i < numFences; i += 1) {
- vkFences[i] = ((VulkanFenceHandle *)fences[i])->fence;
- }
- result = renderer->vkWaitForFences(
- renderer->logicalDevice,
- numFences,
- vkFences,
- waitAll,
- SDL_MAX_UINT64);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkWaitForFences, false)
- SDL_stack_free(vkFences);
- SDL_LockMutex(renderer->submitLock);
- for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
- result = renderer->vkGetFenceStatus(
- renderer->logicalDevice,
- renderer->submittedCommandBuffers[i]->inFlightFence->fence);
- if (result == VK_SUCCESS) {
- VULKAN_INTERNAL_CleanCommandBuffer(
- renderer,
- renderer->submittedCommandBuffers[i]);
- }
- }
- VULKAN_INTERNAL_PerformPendingDestroys(renderer);
- SDL_UnlockMutex(renderer->submitLock);
- return true;
- }
- static bool VULKAN_Wait(
- SDL_GPURenderer *driverData)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VulkanCommandBuffer *commandBuffer;
- VkResult result;
- Sint32 i;
- result = renderer->vkDeviceWaitIdle(renderer->logicalDevice);
- CHECK_VULKAN_ERROR_AND_RETURN(result, vkDeviceWaitIdle, false)
- SDL_LockMutex(renderer->submitLock);
- for (i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
- commandBuffer = renderer->submittedCommandBuffers[i];
- VULKAN_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
- }
- VULKAN_INTERNAL_PerformPendingDestroys(renderer);
- SDL_UnlockMutex(renderer->submitLock);
- return true;
- }
- static SDL_GPUFence *VULKAN_SubmitAndAcquireFence(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- VulkanCommandBuffer *vulkanCommandBuffer;
- vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- vulkanCommandBuffer->autoReleaseFence = 0;
- if (!VULKAN_Submit(commandBuffer)) {
- return NULL;
- }
- return (SDL_GPUFence *)vulkanCommandBuffer->inFlightFence;
- }
- static bool VULKAN_Submit(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
- VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
- VkSubmitInfo submitInfo;
- VkPresentInfoKHR presentInfo;
- VulkanPresentData *presentData;
- VkResult vulkanResult, presentResult = VK_SUCCESS;
- VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT];
- Uint32 swapchainImageIndex;
- VulkanTextureSubresource *swapchainTextureSubresource;
- Uint8 commandBufferCleaned = 0;
- VulkanMemorySubAllocator *allocator;
- bool presenting = false;
- SDL_LockMutex(renderer->submitLock);
- // FIXME: Can this just be permanent?
- for (Uint32 i = 0; i < MAX_PRESENT_COUNT; i += 1) {
- waitStages[i] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- }
- for (Uint32 j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) {
- swapchainImageIndex = vulkanCommandBuffer->presentDatas[j].swapchainImageIndex;
- swapchainTextureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
- &vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex],
- 0,
- 0);
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- vulkanCommandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_PRESENT,
- swapchainTextureSubresource);
- }
- if (!VULKAN_INTERNAL_EndCommandBuffer(renderer, vulkanCommandBuffer)) {
- SDL_UnlockMutex(renderer->submitLock);
- return false;
- }
- vulkanCommandBuffer->inFlightFence = VULKAN_INTERNAL_AcquireFenceFromPool(renderer);
- if (vulkanCommandBuffer->inFlightFence == NULL) {
- SDL_UnlockMutex(renderer->submitLock);
- return false;
- }
- // Command buffer has a reference to the in-flight fence
- (void)SDL_AtomicIncRef(&vulkanCommandBuffer->inFlightFence->referenceCount);
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.pNext = NULL;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &vulkanCommandBuffer->commandBuffer;
- submitInfo.pWaitDstStageMask = waitStages;
- submitInfo.pWaitSemaphores = vulkanCommandBuffer->waitSemaphores;
- submitInfo.waitSemaphoreCount = vulkanCommandBuffer->waitSemaphoreCount;
- submitInfo.pSignalSemaphores = vulkanCommandBuffer->signalSemaphores;
- submitInfo.signalSemaphoreCount = vulkanCommandBuffer->signalSemaphoreCount;
- vulkanResult = renderer->vkQueueSubmit(
- renderer->unifiedQueue,
- 1,
- &submitInfo,
- vulkanCommandBuffer->inFlightFence->fence);
- if (vulkanResult != VK_SUCCESS) {
- SDL_UnlockMutex(renderer->submitLock);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkQueueSubmit, false)
- }
- // Mark command buffers as submitted
- if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) {
- renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
- renderer->submittedCommandBuffers = SDL_realloc(
- renderer->submittedCommandBuffers,
- sizeof(VulkanCommandBuffer *) * renderer->submittedCommandBufferCapacity);
- }
- renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = vulkanCommandBuffer;
- renderer->submittedCommandBufferCount += 1;
- // Present, if applicable
- bool result = true;
- for (Uint32 j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) {
- presenting = true;
- presentData = &vulkanCommandBuffer->presentDatas[j];
- presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- presentInfo.pNext = NULL;
- presentInfo.pWaitSemaphores =
- &presentData->windowData->swapchainData->renderFinishedSemaphore[presentData->windowData->swapchainData->frameCounter];
- presentInfo.waitSemaphoreCount = 1;
- presentInfo.pSwapchains = &presentData->windowData->swapchainData->swapchain;
- presentInfo.swapchainCount = 1;
- presentInfo.pImageIndices = &presentData->swapchainImageIndex;
- presentInfo.pResults = NULL;
- presentResult = renderer->vkQueuePresentKHR(
- renderer->unifiedQueue,
- &presentInfo);
- presentData->windowData->swapchainData->frameCounter =
- (presentData->windowData->swapchainData->frameCounter + 1) % MAX_FRAMES_IN_FLIGHT;
- if (presentResult != VK_SUCCESS) {
- result = VULKAN_INTERNAL_RecreateSwapchain(
- renderer,
- presentData->windowData);
- } else {
- // If presenting, the swapchain is using the in-flight fence
- presentData->windowData->swapchainData->inFlightFences[presentData->windowData->swapchainData->frameCounter] = (SDL_GPUFence*)vulkanCommandBuffer->inFlightFence;
- (void)SDL_AtomicIncRef(&vulkanCommandBuffer->inFlightFence->referenceCount);
- }
- }
- // Check if we can perform any cleanups
- for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
- vulkanResult = renderer->vkGetFenceStatus(
- renderer->logicalDevice,
- renderer->submittedCommandBuffers[i]->inFlightFence->fence);
- if (vulkanResult == VK_SUCCESS) {
- VULKAN_INTERNAL_CleanCommandBuffer(
- renderer,
- renderer->submittedCommandBuffers[i]);
- commandBufferCleaned = 1;
- }
- }
- if (commandBufferCleaned) {
- SDL_LockMutex(renderer->allocatorLock);
- for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
- allocator = &renderer->memoryAllocator->subAllocators[i];
- for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
- if (allocator->allocations[j]->usedRegionCount == 0) {
- VULKAN_INTERNAL_DeallocateMemory(
- renderer,
- allocator,
- j);
- }
- }
- }
- SDL_UnlockMutex(renderer->allocatorLock);
- }
- // Check pending destroys
- VULKAN_INTERNAL_PerformPendingDestroys(renderer);
- // Defrag!
- if (
- presenting &&
- renderer->allocationsToDefragCount > 0 &&
- !renderer->defragInProgress) {
- result = VULKAN_INTERNAL_DefragmentMemory(renderer);
- }
- SDL_UnlockMutex(renderer->submitLock);
- return result;
- }
- static bool VULKAN_INTERNAL_DefragmentMemory(
- VulkanRenderer *renderer)
- {
- VulkanMemoryAllocation *allocation;
- VulkanMemoryUsedRegion *currentRegion;
- VulkanBuffer *newBuffer;
- VulkanTexture *newTexture;
- VkBufferCopy bufferCopy;
- VkImageCopy imageCopy;
- VulkanCommandBuffer *commandBuffer;
- VulkanTextureSubresource *srcSubresource;
- VulkanTextureSubresource *dstSubresource;
- Uint32 i, subresourceIndex;
- renderer->defragInProgress = 1;
- commandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
- if (commandBuffer == NULL) {
- return false;
- }
- commandBuffer->isDefrag = 1;
- SDL_LockMutex(renderer->allocatorLock);
- allocation = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
- renderer->allocationsToDefragCount -= 1;
- /* For each used region in the allocation
- * create a new resource, copy the data
- * and re-point the resource containers
- */
- for (i = 0; i < allocation->usedRegionCount; i += 1) {
- currentRegion = allocation->usedRegions[i];
- if (currentRegion->isBuffer && !currentRegion->vulkanBuffer->markedForDestroy) {
- currentRegion->vulkanBuffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- newBuffer = VULKAN_INTERNAL_CreateBuffer(
- renderer,
- currentRegion->vulkanBuffer->size,
- currentRegion->vulkanBuffer->usage,
- currentRegion->vulkanBuffer->type);
- if (newBuffer == NULL) {
- SDL_UnlockMutex(renderer->allocatorLock);
- return false;
- }
- if (
- renderer->debugMode &&
- renderer->supportsDebugUtils &&
- currentRegion->vulkanBuffer->container != NULL &&
- currentRegion->vulkanBuffer->container->debugName != NULL) {
- VULKAN_INTERNAL_SetBufferName(
- renderer,
- newBuffer,
- currentRegion->vulkanBuffer->container->debugName);
- }
- // Copy buffer contents if necessary
- if (
- currentRegion->vulkanBuffer->type == VULKAN_BUFFER_TYPE_GPU && currentRegion->vulkanBuffer->transitioned) {
- VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
- renderer,
- commandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
- currentRegion->vulkanBuffer);
- VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
- renderer,
- commandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
- newBuffer);
- bufferCopy.srcOffset = 0;
- bufferCopy.dstOffset = 0;
- bufferCopy.size = currentRegion->resourceSize;
- renderer->vkCmdCopyBuffer(
- commandBuffer->commandBuffer,
- currentRegion->vulkanBuffer->buffer,
- newBuffer->buffer,
- 1,
- &bufferCopy);
- VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
- renderer,
- commandBuffer,
- VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
- newBuffer);
- VULKAN_INTERNAL_TrackBuffer(commandBuffer, currentRegion->vulkanBuffer);
- VULKAN_INTERNAL_TrackBuffer(commandBuffer, newBuffer);
- }
- // re-point original container to new buffer
- newBuffer->container = currentRegion->vulkanBuffer->container;
- newBuffer->containerIndex = currentRegion->vulkanBuffer->containerIndex;
- if (newBuffer->type == VULKAN_BUFFER_TYPE_UNIFORM) {
- ((VulkanUniformBuffer *)newBuffer->container)->buffer = newBuffer;
- } else {
- newBuffer->container->buffers[newBuffer->containerIndex] = newBuffer;
- if (newBuffer->container->activeBuffer == currentRegion->vulkanBuffer) {
- newBuffer->container->activeBuffer = newBuffer;
- }
- }
- VULKAN_INTERNAL_ReleaseBuffer(renderer, currentRegion->vulkanBuffer);
- } else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) {
- newTexture = VULKAN_INTERNAL_CreateTexture(
- renderer,
- ¤tRegion->vulkanTexture->container->header.info);
- if (newTexture == NULL) {
- SDL_UnlockMutex(renderer->allocatorLock);
- return false;
- }
- SDL_GPUTextureCreateInfo info = currentRegion->vulkanTexture->container->header.info;
- for (subresourceIndex = 0; subresourceIndex < currentRegion->vulkanTexture->subresourceCount; subresourceIndex += 1) {
- // copy subresource if necessary
- srcSubresource = ¤tRegion->vulkanTexture->subresources[subresourceIndex];
- dstSubresource = &newTexture->subresources[subresourceIndex];
- // Set debug name if it exists
- if (
- renderer->debugMode &&
- renderer->supportsDebugUtils &&
- srcSubresource->parent->container != NULL &&
- srcSubresource->parent->container->debugName != NULL) {
- VULKAN_INTERNAL_SetTextureName(
- renderer,
- currentRegion->vulkanTexture,
- srcSubresource->parent->container->debugName);
- }
- if (srcSubresource->transitioned) {
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- commandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
- srcSubresource);
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- renderer,
- commandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
- dstSubresource);
- imageCopy.srcOffset.x = 0;
- imageCopy.srcOffset.y = 0;
- imageCopy.srcOffset.z = 0;
- imageCopy.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
- imageCopy.srcSubresource.baseArrayLayer = srcSubresource->layer;
- imageCopy.srcSubresource.layerCount = 1;
- imageCopy.srcSubresource.mipLevel = srcSubresource->level;
- imageCopy.extent.width = SDL_max(1, info.width >> srcSubresource->level);
- imageCopy.extent.height = SDL_max(1, info.height >> srcSubresource->level);
- imageCopy.extent.depth = info.type == SDL_GPU_TEXTURETYPE_3D ? info.layer_count_or_depth : 1;
- imageCopy.dstOffset.x = 0;
- imageCopy.dstOffset.y = 0;
- imageCopy.dstOffset.z = 0;
- imageCopy.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
- imageCopy.dstSubresource.baseArrayLayer = dstSubresource->layer;
- imageCopy.dstSubresource.layerCount = 1;
- imageCopy.dstSubresource.mipLevel = dstSubresource->level;
- renderer->vkCmdCopyImage(
- commandBuffer->commandBuffer,
- currentRegion->vulkanTexture->image,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- newTexture->image,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1,
- &imageCopy);
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- renderer,
- commandBuffer,
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
- dstSubresource);
- VULKAN_INTERNAL_TrackTexture(commandBuffer, srcSubresource->parent);
- VULKAN_INTERNAL_TrackTexture(commandBuffer, dstSubresource->parent);
- }
- }
- // re-point original container to new texture
- newTexture->container = currentRegion->vulkanTexture->container;
- newTexture->containerIndex = currentRegion->vulkanTexture->containerIndex;
- newTexture->container->textures[currentRegion->vulkanTexture->containerIndex] = newTexture;
- if (currentRegion->vulkanTexture == currentRegion->vulkanTexture->container->activeTexture) {
- newTexture->container->activeTexture = newTexture;
- }
- VULKAN_INTERNAL_ReleaseTexture(renderer, currentRegion->vulkanTexture);
- }
- }
- SDL_UnlockMutex(renderer->allocatorLock);
- return VULKAN_Submit(
- (SDL_GPUCommandBuffer *)commandBuffer);
- }
- // Format Info
- static bool VULKAN_SupportsTextureFormat(
- SDL_GPURenderer *driverData,
- SDL_GPUTextureFormat format,
- SDL_GPUTextureType type,
- SDL_GPUTextureUsageFlags usage)
- {
- VulkanRenderer *renderer = (VulkanRenderer *)driverData;
- VkFormat vulkanFormat = SDLToVK_TextureFormat[format];
- VkImageUsageFlags vulkanUsage = 0;
- VkImageCreateFlags createFlags = 0;
- VkImageFormatProperties properties;
- VkResult vulkanResult;
- if (usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) {
- vulkanUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
- }
- if (usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
- vulkanUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
- }
- if (usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
- vulkanUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
- }
- if (usage & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ |
- SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ |
- SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE |
- SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) {
- vulkanUsage |= VK_IMAGE_USAGE_STORAGE_BIT;
- }
- if (type == SDL_GPU_TEXTURETYPE_CUBE || type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
- createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
- }
- vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties(
- renderer->physicalDevice,
- vulkanFormat,
- (type == SDL_GPU_TEXTURETYPE_3D) ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D,
- VK_IMAGE_TILING_OPTIMAL,
- vulkanUsage,
- createFlags,
- &properties);
- return vulkanResult == VK_SUCCESS;
- }
- // Device instantiation
- static inline Uint8 CheckDeviceExtensions(
- VkExtensionProperties *extensions,
- Uint32 numExtensions,
- VulkanExtensions *supports)
- {
- Uint32 i;
- SDL_memset(supports, '\0', sizeof(VulkanExtensions));
- for (i = 0; i < numExtensions; i += 1) {
- const char *name = extensions[i].extensionName;
- #define CHECK(ext) \
- if (SDL_strcmp(name, "VK_" #ext) == 0) { \
- supports->ext = 1; \
- }
- CHECK(KHR_swapchain)
- else CHECK(KHR_maintenance1) else CHECK(KHR_driver_properties) else CHECK(EXT_vertex_attribute_divisor) else CHECK(KHR_portability_subset)
- #undef CHECK
- }
- return (supports->KHR_swapchain &&
- supports->KHR_maintenance1);
- }
- static inline Uint32 GetDeviceExtensionCount(VulkanExtensions *supports)
- {
- return (
- supports->KHR_swapchain +
- supports->KHR_maintenance1 +
- supports->KHR_driver_properties +
- supports->EXT_vertex_attribute_divisor +
- supports->KHR_portability_subset);
- }
- static inline void CreateDeviceExtensionArray(
- VulkanExtensions *supports,
- const char **extensions)
- {
- Uint8 cur = 0;
- #define CHECK(ext) \
- if (supports->ext) { \
- extensions[cur++] = "VK_" #ext; \
- }
- CHECK(KHR_swapchain)
- CHECK(KHR_maintenance1)
- CHECK(KHR_driver_properties)
- CHECK(EXT_vertex_attribute_divisor)
- CHECK(KHR_portability_subset)
- #undef CHECK
- }
- static inline Uint8 SupportsInstanceExtension(
- const char *ext,
- VkExtensionProperties *availableExtensions,
- Uint32 numAvailableExtensions)
- {
- Uint32 i;
- for (i = 0; i < numAvailableExtensions; i += 1) {
- if (SDL_strcmp(ext, availableExtensions[i].extensionName) == 0) {
- return 1;
- }
- }
- return 0;
- }
- static Uint8 VULKAN_INTERNAL_CheckInstanceExtensions(
- const char **requiredExtensions,
- Uint32 requiredExtensionsLength,
- bool *supportsDebugUtils,
- bool *supportsColorspace)
- {
- Uint32 extensionCount, i;
- VkExtensionProperties *availableExtensions;
- Uint8 allExtensionsSupported = 1;
- vkEnumerateInstanceExtensionProperties(
- NULL,
- &extensionCount,
- NULL);
- availableExtensions = SDL_malloc(
- extensionCount * sizeof(VkExtensionProperties));
- vkEnumerateInstanceExtensionProperties(
- NULL,
- &extensionCount,
- availableExtensions);
- for (i = 0; i < requiredExtensionsLength; i += 1) {
- if (!SupportsInstanceExtension(
- requiredExtensions[i],
- availableExtensions,
- extensionCount)) {
- allExtensionsSupported = 0;
- break;
- }
- }
- // This is optional, but nice to have!
- *supportsDebugUtils = SupportsInstanceExtension(
- VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
- availableExtensions,
- extensionCount);
- // Also optional and nice to have!
- *supportsColorspace = SupportsInstanceExtension(
- VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
- availableExtensions,
- extensionCount);
- SDL_free(availableExtensions);
- return allExtensionsSupported;
- }
- static Uint8 VULKAN_INTERNAL_CheckDeviceExtensions(
- VulkanRenderer *renderer,
- VkPhysicalDevice physicalDevice,
- VulkanExtensions *physicalDeviceExtensions)
- {
- Uint32 extensionCount;
- VkExtensionProperties *availableExtensions;
- Uint8 allExtensionsSupported;
- renderer->vkEnumerateDeviceExtensionProperties(
- physicalDevice,
- NULL,
- &extensionCount,
- NULL);
- availableExtensions = (VkExtensionProperties *)SDL_malloc(
- extensionCount * sizeof(VkExtensionProperties));
- renderer->vkEnumerateDeviceExtensionProperties(
- physicalDevice,
- NULL,
- &extensionCount,
- availableExtensions);
- allExtensionsSupported = CheckDeviceExtensions(
- availableExtensions,
- extensionCount,
- physicalDeviceExtensions);
- SDL_free(availableExtensions);
- return allExtensionsSupported;
- }
- static Uint8 VULKAN_INTERNAL_CheckValidationLayers(
- const char **validationLayers,
- Uint32 validationLayersLength)
- {
- Uint32 layerCount;
- VkLayerProperties *availableLayers;
- Uint32 i, j;
- Uint8 layerFound = 0;
- vkEnumerateInstanceLayerProperties(&layerCount, NULL);
- availableLayers = (VkLayerProperties *)SDL_malloc(
- layerCount * sizeof(VkLayerProperties));
- vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
- for (i = 0; i < validationLayersLength; i += 1) {
- layerFound = 0;
- for (j = 0; j < layerCount; j += 1) {
- if (SDL_strcmp(validationLayers[i], availableLayers[j].layerName) == 0) {
- layerFound = 1;
- break;
- }
- }
- if (!layerFound) {
- break;
- }
- }
- SDL_free(availableLayers);
- return layerFound;
- }
- static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer)
- {
- VkResult vulkanResult;
- VkApplicationInfo appInfo;
- VkInstanceCreateFlags createFlags;
- const char *const *originalInstanceExtensionNames;
- const char **instanceExtensionNames;
- Uint32 instanceExtensionCount;
- VkInstanceCreateInfo createInfo;
- static const char *layerNames[] = { "VK_LAYER_KHRONOS_validation" };
- appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- appInfo.pNext = NULL;
- appInfo.pApplicationName = NULL;
- appInfo.applicationVersion = 0;
- appInfo.pEngineName = "SDLGPU";
- appInfo.engineVersion = SDL_VERSION;
- appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0);
- createFlags = 0;
- originalInstanceExtensionNames = SDL_Vulkan_GetInstanceExtensions(&instanceExtensionCount);
- if (!originalInstanceExtensionNames) {
- SDL_LogError(
- SDL_LOG_CATEGORY_GPU,
- "SDL_Vulkan_GetInstanceExtensions(): getExtensionCount: %s",
- SDL_GetError());
- return 0;
- }
- /* Extra space for the following extensions:
- * VK_KHR_get_physical_device_properties2
- * VK_EXT_swapchain_colorspace
- * VK_EXT_debug_utils
- * VK_KHR_portability_enumeration
- */
- instanceExtensionNames = SDL_stack_alloc(
- const char *,
- instanceExtensionCount + 4);
- SDL_memcpy((void *)instanceExtensionNames, originalInstanceExtensionNames, instanceExtensionCount * sizeof(const char *));
- // Core since 1.1
- instanceExtensionNames[instanceExtensionCount++] =
- VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
- #ifdef SDL_PLATFORM_APPLE
- instanceExtensionNames[instanceExtensionCount++] =
- VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME;
- createFlags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
- #endif
- if (!VULKAN_INTERNAL_CheckInstanceExtensions(
- instanceExtensionNames,
- instanceExtensionCount,
- &renderer->supportsDebugUtils,
- &renderer->supportsColorspace)) {
- SDL_stack_free((char *)instanceExtensionNames);
- SET_STRING_ERROR_AND_RETURN("Required Vulkan instance extensions not supported", false)
- }
- if (renderer->supportsDebugUtils) {
- // Append the debug extension
- instanceExtensionNames[instanceExtensionCount++] =
- VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
- } else {
- SDL_LogWarn(
- SDL_LOG_CATEGORY_GPU,
- "%s is not supported!",
- VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
- }
- if (renderer->supportsColorspace) {
- // Append colorspace extension
- instanceExtensionNames[instanceExtensionCount++] =
- VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME;
- }
- createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- createInfo.pNext = NULL;
- createInfo.flags = createFlags;
- createInfo.pApplicationInfo = &appInfo;
- createInfo.ppEnabledLayerNames = layerNames;
- createInfo.enabledExtensionCount = instanceExtensionCount;
- createInfo.ppEnabledExtensionNames = instanceExtensionNames;
- if (renderer->debugMode) {
- createInfo.enabledLayerCount = SDL_arraysize(layerNames);
- if (!VULKAN_INTERNAL_CheckValidationLayers(
- layerNames,
- createInfo.enabledLayerCount)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Validation layers not found, continuing without validation");
- createInfo.enabledLayerCount = 0;
- } else {
- SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Validation layers enabled, expect debug level performance!");
- }
- } else {
- createInfo.enabledLayerCount = 0;
- }
- vulkanResult = vkCreateInstance(&createInfo, NULL, &renderer->instance);
- SDL_stack_free((char *)instanceExtensionNames);
- if (vulkanResult != VK_SUCCESS) {
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateInstance, 0)
- }
- return 1;
- }
- static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
- VulkanRenderer *renderer,
- VkPhysicalDevice physicalDevice,
- VulkanExtensions *physicalDeviceExtensions,
- Uint32 *queueFamilyIndex,
- Uint8 *deviceRank)
- {
- Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
- VkQueueFamilyProperties *queueProps;
- bool supportsPresent;
- VkPhysicalDeviceProperties deviceProperties;
- VkPhysicalDeviceFeatures deviceFeatures;
- Uint32 i;
- const Uint8 *devicePriority = renderer->preferLowPower ? DEVICE_PRIORITY_LOWPOWER : DEVICE_PRIORITY_HIGHPERFORMANCE;
- /* Get the device rank before doing any checks, in case one fails.
- * Note: If no dedicated device exists, one that supports our features
- * would be fine
- */
- renderer->vkGetPhysicalDeviceProperties(
- physicalDevice,
- &deviceProperties);
- if (*deviceRank < devicePriority[deviceProperties.deviceType]) {
- /* This device outranks the best device we've found so far!
- * This includes a dedicated GPU that has less features than an
- * integrated GPU, because this is a freak case that is almost
- * never intentionally desired by the end user
- */
- *deviceRank = devicePriority[deviceProperties.deviceType];
- } else if (*deviceRank > devicePriority[deviceProperties.deviceType]) {
- /* Device is outranked by a previous device, don't even try to
- * run a query and reset the rank to avoid overwrites
- */
- *deviceRank = 0;
- return 0;
- }
- renderer->vkGetPhysicalDeviceFeatures(
- physicalDevice,
- &deviceFeatures);
- if (!deviceFeatures.independentBlend ||
- !deviceFeatures.imageCubeArray ||
- !deviceFeatures.depthClamp ||
- !deviceFeatures.shaderClipDistance) {
- return 0;
- }
- if (!VULKAN_INTERNAL_CheckDeviceExtensions(
- renderer,
- physicalDevice,
- physicalDeviceExtensions)) {
- return 0;
- }
- renderer->vkGetPhysicalDeviceQueueFamilyProperties(
- physicalDevice,
- &queueFamilyCount,
- NULL);
- queueProps = (VkQueueFamilyProperties *)SDL_stack_alloc(
- VkQueueFamilyProperties,
- queueFamilyCount);
- renderer->vkGetPhysicalDeviceQueueFamilyProperties(
- physicalDevice,
- &queueFamilyCount,
- queueProps);
- queueFamilyBest = 0;
- *queueFamilyIndex = SDL_MAX_UINT32;
- for (i = 0; i < queueFamilyCount; i += 1) {
- supportsPresent = SDL_Vulkan_GetPresentationSupport(
- renderer->instance,
- physicalDevice,
- i);
- if (!supportsPresent ||
- !(queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) {
- // Not a graphics family, ignore.
- continue;
- }
- /* The queue family bitflags are kind of annoying.
- *
- * We of course need a graphics family, but we ideally want the
- * _primary_ graphics family. The spec states that at least one
- * graphics family must also be a compute family, so generally
- * drivers make that the first one. But hey, maybe something
- * genuinely can't do compute or something, and FNA doesn't
- * need it, so we'll be open to a non-compute queue family.
- *
- * Additionally, it's common to see the primary queue family
- * have the transfer bit set, which is great! But this is
- * actually optional; it's impossible to NOT have transfers in
- * graphics/compute but it _is_ possible for a graphics/compute
- * family, even the primary one, to just decide not to set the
- * bitflag. Admittedly, a driver may want to isolate transfer
- * queues to a dedicated family so that queues made solely for
- * transfers can have an optimized DMA queue.
- *
- * That, or the driver author got lazy and decided not to set
- * the bit. Looking at you, Android.
- *
- * -flibit
- */
- if (queueProps[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
- if (queueProps[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
- // Has all attribs!
- queueFamilyRank = 3;
- } else {
- // Probably has a DMA transfer queue family
- queueFamilyRank = 2;
- }
- } else {
- // Just a graphics family, probably has something better
- queueFamilyRank = 1;
- }
- if (queueFamilyRank > queueFamilyBest) {
- *queueFamilyIndex = i;
- queueFamilyBest = queueFamilyRank;
- }
- }
- SDL_stack_free(queueProps);
- if (*queueFamilyIndex == SDL_MAX_UINT32) {
- // Somehow no graphics queues existed. Compute-only device?
- return 0;
- }
- // FIXME: Need better structure for checking vs storing swapchain support details
- return 1;
- }
- static Uint8 VULKAN_INTERNAL_DeterminePhysicalDevice(VulkanRenderer *renderer)
- {
- VkResult vulkanResult;
- VkPhysicalDevice *physicalDevices;
- VulkanExtensions *physicalDeviceExtensions;
- Uint32 i, physicalDeviceCount;
- Sint32 suitableIndex;
- Uint32 queueFamilyIndex, suitableQueueFamilyIndex;
- Uint8 deviceRank, highestRank;
- vulkanResult = renderer->vkEnumeratePhysicalDevices(
- renderer->instance,
- &physicalDeviceCount,
- NULL);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkEnumeratePhysicalDevices, 0)
- if (physicalDeviceCount == 0) {
- SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Failed to find any GPUs with Vulkan support");
- return 0;
- }
- physicalDevices = SDL_stack_alloc(VkPhysicalDevice, physicalDeviceCount);
- physicalDeviceExtensions = SDL_stack_alloc(VulkanExtensions, physicalDeviceCount);
- vulkanResult = renderer->vkEnumeratePhysicalDevices(
- renderer->instance,
- &physicalDeviceCount,
- physicalDevices);
- /* This should be impossible to hit, but from what I can tell this can
- * be triggered not because the array is too small, but because there
- * were drivers that turned out to be bogus, so this is the loader's way
- * of telling us that the list is now smaller than expected :shrug:
- */
- if (vulkanResult == VK_INCOMPLETE) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "vkEnumeratePhysicalDevices returned VK_INCOMPLETE, will keep trying anyway...");
- vulkanResult = VK_SUCCESS;
- }
- if (vulkanResult != VK_SUCCESS) {
- SDL_LogWarn(
- SDL_LOG_CATEGORY_GPU,
- "vkEnumeratePhysicalDevices failed: %s",
- VkErrorMessages(vulkanResult));
- SDL_stack_free(physicalDevices);
- SDL_stack_free(physicalDeviceExtensions);
- return 0;
- }
- // Any suitable device will do, but we'd like the best
- suitableIndex = -1;
- suitableQueueFamilyIndex = 0;
- highestRank = 0;
- for (i = 0; i < physicalDeviceCount; i += 1) {
- deviceRank = highestRank;
- if (VULKAN_INTERNAL_IsDeviceSuitable(
- renderer,
- physicalDevices[i],
- &physicalDeviceExtensions[i],
- &queueFamilyIndex,
- &deviceRank)) {
- /* Use this for rendering.
- * Note that this may override a previous device that
- * supports rendering, but shares the same device rank.
- */
- suitableIndex = i;
- suitableQueueFamilyIndex = queueFamilyIndex;
- highestRank = deviceRank;
- } else if (deviceRank > highestRank) {
- /* In this case, we found a... "realer?" GPU,
- * but it doesn't actually support our Vulkan.
- * We should disqualify all devices below as a
- * result, because if we don't we end up
- * ignoring real hardware and risk using
- * something like LLVMpipe instead!
- * -flibit
- */
- suitableIndex = -1;
- highestRank = deviceRank;
- }
- }
- if (suitableIndex != -1) {
- renderer->supports = physicalDeviceExtensions[suitableIndex];
- renderer->physicalDevice = physicalDevices[suitableIndex];
- renderer->queueFamilyIndex = suitableQueueFamilyIndex;
- } else {
- SDL_stack_free(physicalDevices);
- SDL_stack_free(physicalDeviceExtensions);
- return 0;
- }
- renderer->physicalDeviceProperties.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
- if (renderer->supports.KHR_driver_properties) {
- renderer->physicalDeviceDriverProperties.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
- renderer->physicalDeviceDriverProperties.pNext = NULL;
- renderer->physicalDeviceProperties.pNext =
- &renderer->physicalDeviceDriverProperties;
- renderer->vkGetPhysicalDeviceProperties2KHR(
- renderer->physicalDevice,
- &renderer->physicalDeviceProperties);
- } else {
- renderer->physicalDeviceProperties.pNext = NULL;
- renderer->vkGetPhysicalDeviceProperties(
- renderer->physicalDevice,
- &renderer->physicalDeviceProperties.properties);
- }
- renderer->vkGetPhysicalDeviceMemoryProperties(
- renderer->physicalDevice,
- &renderer->memoryProperties);
- SDL_stack_free(physicalDevices);
- SDL_stack_free(physicalDeviceExtensions);
- return 1;
- }
- static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
- VulkanRenderer *renderer)
- {
- VkResult vulkanResult;
- VkDeviceCreateInfo deviceCreateInfo;
- VkPhysicalDeviceFeatures desiredDeviceFeatures;
- VkPhysicalDeviceFeatures haveDeviceFeatures;
- VkPhysicalDevicePortabilitySubsetFeaturesKHR portabilityFeatures;
- const char **deviceExtensions;
- VkDeviceQueueCreateInfo queueCreateInfo;
- float queuePriority = 1.0f;
- queueCreateInfo.sType =
- VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- queueCreateInfo.pNext = NULL;
- queueCreateInfo.flags = 0;
- queueCreateInfo.queueFamilyIndex = renderer->queueFamilyIndex;
- queueCreateInfo.queueCount = 1;
- queueCreateInfo.pQueuePriorities = &queuePriority;
- // check feature support
- renderer->vkGetPhysicalDeviceFeatures(
- renderer->physicalDevice,
- &haveDeviceFeatures);
- // specifying used device features
- SDL_zero(desiredDeviceFeatures);
- desiredDeviceFeatures.independentBlend = VK_TRUE;
- desiredDeviceFeatures.samplerAnisotropy = VK_TRUE;
- desiredDeviceFeatures.imageCubeArray = VK_TRUE;
- desiredDeviceFeatures.depthClamp = VK_TRUE;
- desiredDeviceFeatures.shaderClipDistance = VK_TRUE;
- if (haveDeviceFeatures.fillModeNonSolid) {
- desiredDeviceFeatures.fillModeNonSolid = VK_TRUE;
- renderer->supportsFillModeNonSolid = true;
- }
- if (haveDeviceFeatures.multiDrawIndirect) {
- desiredDeviceFeatures.multiDrawIndirect = VK_TRUE;
- renderer->supportsMultiDrawIndirect = true;
- }
- // creating the logical device
- deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
- if (renderer->supports.KHR_portability_subset) {
- portabilityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR;
- portabilityFeatures.pNext = NULL;
- portabilityFeatures.constantAlphaColorBlendFactors = VK_FALSE;
- portabilityFeatures.events = VK_FALSE;
- portabilityFeatures.imageViewFormatReinterpretation = VK_FALSE;
- portabilityFeatures.imageViewFormatSwizzle = VK_TRUE;
- portabilityFeatures.imageView2DOn3DImage = VK_FALSE;
- portabilityFeatures.multisampleArrayImage = VK_FALSE;
- portabilityFeatures.mutableComparisonSamplers = VK_FALSE;
- portabilityFeatures.pointPolygons = VK_FALSE;
- portabilityFeatures.samplerMipLodBias = VK_FALSE; // Technically should be true, but eh
- portabilityFeatures.separateStencilMaskRef = VK_FALSE;
- portabilityFeatures.shaderSampleRateInterpolationFunctions = VK_FALSE;
- portabilityFeatures.tessellationIsolines = VK_FALSE;
- portabilityFeatures.tessellationPointMode = VK_FALSE;
- portabilityFeatures.triangleFans = VK_FALSE;
- portabilityFeatures.vertexAttributeAccessBeyondStride = VK_FALSE;
- deviceCreateInfo.pNext = &portabilityFeatures;
- } else {
- deviceCreateInfo.pNext = NULL;
- }
- deviceCreateInfo.flags = 0;
- deviceCreateInfo.queueCreateInfoCount = 1;
- deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
- deviceCreateInfo.enabledLayerCount = 0;
- deviceCreateInfo.ppEnabledLayerNames = NULL;
- deviceCreateInfo.enabledExtensionCount = GetDeviceExtensionCount(
- &renderer->supports);
- deviceExtensions = SDL_stack_alloc(
- const char *,
- deviceCreateInfo.enabledExtensionCount);
- CreateDeviceExtensionArray(&renderer->supports, deviceExtensions);
- deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions;
- deviceCreateInfo.pEnabledFeatures = &desiredDeviceFeatures;
- vulkanResult = renderer->vkCreateDevice(
- renderer->physicalDevice,
- &deviceCreateInfo,
- NULL,
- &renderer->logicalDevice);
- SDL_stack_free((void *)deviceExtensions);
- CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDevice, 0)
- // Load vkDevice entry points
- #define VULKAN_DEVICE_FUNCTION(func) \
- renderer->func = (PFN_##func) \
- renderer->vkGetDeviceProcAddr( \
- renderer->logicalDevice, \
- #func);
- #include "SDL_gpu_vulkan_vkfuncs.h"
- renderer->vkGetDeviceQueue(
- renderer->logicalDevice,
- renderer->queueFamilyIndex,
- 0,
- &renderer->unifiedQueue);
- return 1;
- }
- static void VULKAN_INTERNAL_LoadEntryPoints(void)
- {
- // Required for MoltenVK support
- SDL_setenv_unsafe("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
- // Load Vulkan entry points
- if (!SDL_Vulkan_LoadLibrary(NULL)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Vulkan: SDL_Vulkan_LoadLibrary failed!");
- return;
- }
- #ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wpedantic"
- #endif
- vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr();
- #ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
- #pragma GCC diagnostic pop
- #endif
- if (vkGetInstanceProcAddr == NULL) {
- SDL_LogWarn(
- SDL_LOG_CATEGORY_GPU,
- "SDL_Vulkan_GetVkGetInstanceProcAddr(): %s",
- SDL_GetError());
- return;
- }
- #define VULKAN_GLOBAL_FUNCTION(name) \
- name = (PFN_##name)vkGetInstanceProcAddr(VK_NULL_HANDLE, #name); \
- if (name == NULL) { \
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "vkGetInstanceProcAddr(VK_NULL_HANDLE, \"" #name "\") failed"); \
- return; \
- }
- #include "SDL_gpu_vulkan_vkfuncs.h"
- }
- static bool VULKAN_INTERNAL_PrepareVulkan(
- VulkanRenderer *renderer)
- {
- VULKAN_INTERNAL_LoadEntryPoints();
- if (!VULKAN_INTERNAL_CreateInstance(renderer)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Vulkan: Could not create Vulkan instance");
- return false;
- }
- #define VULKAN_INSTANCE_FUNCTION(func) \
- renderer->func = (PFN_##func)vkGetInstanceProcAddr(renderer->instance, #func);
- #include "SDL_gpu_vulkan_vkfuncs.h"
- if (!VULKAN_INTERNAL_DeterminePhysicalDevice(renderer)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Vulkan: Failed to determine a suitable physical device");
- return false;
- }
- return true;
- }
- static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
- {
- // Set up dummy VulkanRenderer
- VulkanRenderer *renderer;
- Uint8 result;
- if (_this->Vulkan_CreateSurface == NULL) {
- return false;
- }
- if (!SDL_Vulkan_LoadLibrary(NULL)) {
- return false;
- }
- renderer = (VulkanRenderer *)SDL_malloc(sizeof(VulkanRenderer));
- SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
- result = VULKAN_INTERNAL_PrepareVulkan(renderer);
- if (result) {
- renderer->vkDestroyInstance(renderer->instance, NULL);
- }
- SDL_free(renderer);
- SDL_Vulkan_UnloadLibrary();
- return result;
- }
- static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, SDL_PropertiesID props)
- {
- VulkanRenderer *renderer;
- SDL_GPUDevice *result;
- Uint32 i;
- if (!SDL_Vulkan_LoadLibrary(NULL)) {
- SDL_assert(!"This should have failed in PrepareDevice first!");
- return NULL;
- }
- renderer = (VulkanRenderer *)SDL_malloc(sizeof(VulkanRenderer));
- SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
- renderer->debugMode = debugMode;
- renderer->preferLowPower = preferLowPower;
- if (!VULKAN_INTERNAL_PrepareVulkan(renderer)) {
- SDL_free(renderer);
- SDL_Vulkan_UnloadLibrary();
- SET_STRING_ERROR_AND_RETURN("Failed to initialize Vulkan!", NULL)
- }
- SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Vulkan");
- SDL_LogInfo(
- SDL_LOG_CATEGORY_GPU,
- "Vulkan Device: %s",
- renderer->physicalDeviceProperties.properties.deviceName);
- if (renderer->supports.KHR_driver_properties) {
- SDL_LogInfo(
- SDL_LOG_CATEGORY_GPU,
- "Vulkan Driver: %s %s",
- renderer->physicalDeviceDriverProperties.driverName,
- renderer->physicalDeviceDriverProperties.driverInfo);
- SDL_LogInfo(
- SDL_LOG_CATEGORY_GPU,
- "Vulkan Conformance: %u.%u.%u",
- renderer->physicalDeviceDriverProperties.conformanceVersion.major,
- renderer->physicalDeviceDriverProperties.conformanceVersion.minor,
- renderer->physicalDeviceDriverProperties.conformanceVersion.patch);
- } else {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "KHR_driver_properties unsupported! Bother your vendor about this!");
- }
- if (!VULKAN_INTERNAL_CreateLogicalDevice(
- renderer)) {
- SDL_free(renderer);
- SDL_Vulkan_UnloadLibrary();
- SET_STRING_ERROR_AND_RETURN("Failed to create logical device!", NULL)
- }
- // FIXME: just move this into this function
- result = (SDL_GPUDevice *)SDL_malloc(sizeof(SDL_GPUDevice));
- ASSIGN_DRIVER(VULKAN)
- result->driverData = (SDL_GPURenderer *)renderer;
- /*
- * Create initial swapchain array
- */
- renderer->claimedWindowCapacity = 1;
- renderer->claimedWindowCount = 0;
- renderer->claimedWindows = SDL_malloc(
- renderer->claimedWindowCapacity * sizeof(WindowData *));
- // Threading
- renderer->allocatorLock = SDL_CreateMutex();
- renderer->disposeLock = SDL_CreateMutex();
- renderer->submitLock = SDL_CreateMutex();
- renderer->acquireCommandBufferLock = SDL_CreateMutex();
- renderer->acquireUniformBufferLock = SDL_CreateMutex();
- renderer->renderPassFetchLock = SDL_CreateMutex();
- renderer->framebufferFetchLock = SDL_CreateMutex();
- /*
- * Create submitted command buffer list
- */
- renderer->submittedCommandBufferCapacity = 16;
- renderer->submittedCommandBufferCount = 0;
- renderer->submittedCommandBuffers = SDL_malloc(sizeof(VulkanCommandBuffer *) * renderer->submittedCommandBufferCapacity);
- // Memory Allocator
- renderer->memoryAllocator = (VulkanMemoryAllocator *)SDL_malloc(
- sizeof(VulkanMemoryAllocator));
- for (i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
- renderer->memoryAllocator->subAllocators[i].memoryTypeIndex = i;
- renderer->memoryAllocator->subAllocators[i].allocations = NULL;
- renderer->memoryAllocator->subAllocators[i].allocationCount = 0;
- renderer->memoryAllocator->subAllocators[i].sortedFreeRegions = SDL_malloc(
- sizeof(VulkanMemoryFreeRegion *) * 4);
- renderer->memoryAllocator->subAllocators[i].sortedFreeRegionCount = 0;
- renderer->memoryAllocator->subAllocators[i].sortedFreeRegionCapacity = 4;
- }
- // Create uniform buffer pool
- renderer->uniformBufferPoolCount = 32;
- renderer->uniformBufferPoolCapacity = 32;
- renderer->uniformBufferPool = SDL_malloc(
- renderer->uniformBufferPoolCapacity * sizeof(VulkanUniformBuffer *));
- for (i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
- renderer->uniformBufferPool[i] = VULKAN_INTERNAL_CreateUniformBuffer(
- renderer,
- UNIFORM_BUFFER_SIZE);
- }
- renderer->descriptorSetCachePoolCapacity = 8;
- renderer->descriptorSetCachePoolCount = 0;
- renderer->descriptorSetCachePool = SDL_calloc(renderer->descriptorSetCachePoolCapacity, sizeof(DescriptorSetCache *));
- SDL_SetAtomicInt(&renderer->layoutResourceID, 0);
- // Device limits
- renderer->minUBOAlignment = (Uint32)renderer->physicalDeviceProperties.properties.limits.minUniformBufferOffsetAlignment;
- // Initialize caches
- renderer->commandPoolHashTable = SDL_CreateHashTable(
- (void *)renderer,
- 64,
- VULKAN_INTERNAL_CommandPoolHashFunction,
- VULKAN_INTERNAL_CommandPoolHashKeyMatch,
- VULKAN_INTERNAL_CommandPoolHashNuke,
- false);
- renderer->renderPassHashTable = SDL_CreateHashTable(
- (void *)renderer,
- 64,
- VULKAN_INTERNAL_RenderPassHashFunction,
- VULKAN_INTERNAL_RenderPassHashKeyMatch,
- VULKAN_INTERNAL_RenderPassHashNuke,
- false);
- renderer->framebufferHashTable = SDL_CreateHashTable(
- (void *)renderer,
- 64,
- VULKAN_INTERNAL_FramebufferHashFunction,
- VULKAN_INTERNAL_FramebufferHashKeyMatch,
- VULKAN_INTERNAL_FramebufferHashNuke,
- false);
- renderer->graphicsPipelineResourceLayoutHashTable = SDL_CreateHashTable(
- (void *)renderer,
- 64,
- VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashFunction,
- VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashKeyMatch,
- VULKAN_INTERNAL_GraphicsPipelineResourceLayoutHashNuke,
- false);
- renderer->computePipelineResourceLayoutHashTable = SDL_CreateHashTable(
- (void *)renderer,
- 64,
- VULKAN_INTERNAL_ComputePipelineResourceLayoutHashFunction,
- VULKAN_INTERNAL_ComputePipelineResourceLayoutHashKeyMatch,
- VULKAN_INTERNAL_ComputePipelineResourceLayoutHashNuke,
- false);
- renderer->descriptorSetLayoutHashTable = SDL_CreateHashTable(
- (void *)renderer,
- 64,
- VULKAN_INTERNAL_DescriptorSetLayoutHashFunction,
- VULKAN_INTERNAL_DescriptorSetLayoutHashKeyMatch,
- VULKAN_INTERNAL_DescriptorSetLayoutHashNuke,
- false);
- // Initialize fence pool
- renderer->fencePool.lock = SDL_CreateMutex();
- renderer->fencePool.availableFenceCapacity = 4;
- renderer->fencePool.availableFenceCount = 0;
- renderer->fencePool.availableFences = SDL_malloc(
- renderer->fencePool.availableFenceCapacity * sizeof(VulkanFenceHandle *));
- // Deferred destroy storage
- renderer->texturesToDestroyCapacity = 16;
- renderer->texturesToDestroyCount = 0;
- renderer->texturesToDestroy = (VulkanTexture **)SDL_malloc(
- sizeof(VulkanTexture *) *
- renderer->texturesToDestroyCapacity);
- renderer->buffersToDestroyCapacity = 16;
- renderer->buffersToDestroyCount = 0;
- renderer->buffersToDestroy = SDL_malloc(
- sizeof(VulkanBuffer *) *
- renderer->buffersToDestroyCapacity);
- renderer->samplersToDestroyCapacity = 16;
- renderer->samplersToDestroyCount = 0;
- renderer->samplersToDestroy = SDL_malloc(
- sizeof(VulkanSampler *) *
- renderer->samplersToDestroyCapacity);
- renderer->graphicsPipelinesToDestroyCapacity = 16;
- renderer->graphicsPipelinesToDestroyCount = 0;
- renderer->graphicsPipelinesToDestroy = SDL_malloc(
- sizeof(VulkanGraphicsPipeline *) *
- renderer->graphicsPipelinesToDestroyCapacity);
- renderer->computePipelinesToDestroyCapacity = 16;
- renderer->computePipelinesToDestroyCount = 0;
- renderer->computePipelinesToDestroy = SDL_malloc(
- sizeof(VulkanComputePipeline *) *
- renderer->computePipelinesToDestroyCapacity);
- renderer->shadersToDestroyCapacity = 16;
- renderer->shadersToDestroyCount = 0;
- renderer->shadersToDestroy = SDL_malloc(
- sizeof(VulkanShader *) *
- renderer->shadersToDestroyCapacity);
- renderer->framebuffersToDestroyCapacity = 16;
- renderer->framebuffersToDestroyCount = 0;
- renderer->framebuffersToDestroy = SDL_malloc(
- sizeof(VulkanFramebuffer *) *
- renderer->framebuffersToDestroyCapacity);
- // Defrag state
- renderer->defragInProgress = 0;
- renderer->allocationsToDefragCount = 0;
- renderer->allocationsToDefragCapacity = 4;
- renderer->allocationsToDefrag = SDL_malloc(
- renderer->allocationsToDefragCapacity * sizeof(VulkanMemoryAllocation *));
- return result;
- }
- SDL_GPUBootstrap VulkanDriver = {
- "vulkan",
- SDL_GPU_SHADERFORMAT_SPIRV,
- VULKAN_PrepareDriver,
- VULKAN_CreateDevice
- };
- #endif // SDL_GPU_VULKAN
|