| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
- 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_D3D12
- #include "../../core/windows/SDL_windows.h"
- #include "../../video/directx/SDL_d3d12.h"
- #include "../SDL_sysgpu.h"
- #ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
- #define HAVE_IDXGIINFOQUEUE
- #endif
- // Built-in shaders, compiled with compile_shaders.bat
- #define g_FullscreenVert D3D12_FullscreenVert
- #define g_BlitFrom2D D3D12_BlitFrom2D
- #define g_BlitFrom2DArray D3D12_BlitFrom2DArray
- #define g_BlitFrom3D D3D12_BlitFrom3D
- #define g_BlitFromCube D3D12_BlitFromCube
- #define g_BlitFromCubeArray D3D12_BlitFromCubeArray
- #if defined(SDL_PLATFORM_XBOXSERIES)
- #include "D3D12_Blit_Series.h"
- #elif defined(SDL_PLATFORM_XBOXONE)
- #include "D3D12_Blit_One.h"
- #else
- #include "D3D12_Blit.h"
- #endif
- #undef g_FullscreenVert
- #undef g_BlitFrom2D
- #undef g_BlitFrom2DArray
- #undef g_BlitFrom3D
- #undef g_BlitFromCube
- #undef g_BlitFromCubeArray
- // Macros
- #define SET_ERROR(fmt, msg) \
- do { \
- if (renderer->debug_mode) { \
- SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
- } \
- SDL_SetError(fmt, msg); \
- } while (0)
- #define SET_ERROR_AND_RETURN(fmt, msg, ret) \
- do { \
- if (renderer->debug_mode) { \
- SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
- } \
- SDL_SetError(fmt, msg); \
- return ret; \
- } while (0)
- #define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
- #define CHECK_D3D12_ERROR_AND_RETURN(msg, ret) \
- do { \
- if (FAILED(res)) { \
- D3D12_INTERNAL_SetError(renderer, msg, res); \
- return (ret); \
- } \
- } while (0)
- // Defines
- #if defined(_WIN32)
- #if defined(SDL_PLATFORM_XBOXSERIES)
- #define D3D12_DLL "d3d12_xs.dll"
- #elif defined(SDL_PLATFORM_XBOXONE)
- #define D3D12_DLL "d3d12_x.dll"
- #else
- #define D3D12_DLL "d3d12.dll"
- #endif
- #define DXGI_DLL "dxgi.dll"
- #define DXGIDEBUG_DLL "dxgidebug.dll"
- #elif defined(__APPLE__)
- #define D3D12_DLL "libdxvk_d3d12.dylib"
- #define DXGI_DLL "libdxvk_dxgi.dylib"
- #define DXGIDEBUG_DLL "libdxvk_dxgidebug.dylib"
- #else
- #define D3D12_DLL "libdxvk_d3d12.so"
- #define DXGI_DLL "libdxvk_dxgi.so"
- #define DXGIDEBUG_DLL "libdxvk_dxgidebug.so"
- #endif
- #define D3D12_CREATE_DEVICE_FUNC "D3D12CreateDevice"
- #define D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC "D3D12SerializeRootSignature"
- #define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1"
- #define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
- #define D3D12_GET_DEBUG_INTERFACE_FUNC "D3D12GetDebugInterface"
- #define WINDOW_PROPERTY_DATA "SDL_GPUD3D12WindowPropertyData"
- #define D3D_FEATURE_LEVEL_CHOICE D3D_FEATURE_LEVEL_11_1
- #define D3D_FEATURE_LEVEL_CHOICE_STR "11_1"
- // FIXME: just use sysgpu.h defines
- #define MAX_ROOT_SIGNATURE_PARAMETERS 64
- #define VIEW_GPU_DESCRIPTOR_COUNT 65536
- #define SAMPLER_GPU_DESCRIPTOR_COUNT 2048
- #define VIEW_SAMPLER_STAGING_DESCRIPTOR_COUNT 1000000
- #define TARGET_STAGING_DESCRIPTOR_COUNT 1000000
- #define D3D12_FENCE_UNSIGNALED_VALUE 0
- #define D3D12_FENCE_SIGNAL_VALUE 1
- #define SDL_GPU_SHADERSTAGE_COMPUTE (SDL_GPUShaderStage)2
- #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)); \
- }
- #ifdef _WIN32
- #define HRESULT_FMT "(0x%08lX)"
- #else
- #define HRESULT_FMT "(0x%08X)"
- #endif
- // Function Pointer Signatures
- typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY1)(const GUID *riid, void **ppFactory);
- typedef HRESULT(WINAPI *PFN_DXGI_GET_DEBUG_INTERFACE)(const GUID *riid, void **ppDebug);
- // IIDs (from https://www.magnumdb.com/)
- static const IID D3D_IID_IDXGIFactory1 = { 0x770aae78, 0xf26f, 0x4dba, { 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87 } };
- static const IID D3D_IID_IDXGIFactory4 = { 0x1bc6ea02, 0xef36, 0x464f, { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a } };
- static const IID D3D_IID_IDXGIFactory5 = { 0x7632e1f5, 0xee65, 0x4dca, { 0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d } };
- static const IID D3D_IID_IDXGIFactory6 = { 0xc1b6694f, 0xff09, 0x44a9, { 0xb0, 0x3c, 0x77, 0x90, 0x0a, 0x0a, 0x1d, 0x17 } };
- static const IID D3D_IID_IDXGIAdapter1 = { 0x29038f61, 0x3839, 0x4626, { 0x91, 0xfd, 0x08, 0x68, 0x79, 0x01, 0x1a, 0x05 } };
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- static const IID D3D_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
- #else
- static const IID D3D_IID_IDXGIDevice = { 0x54ec77fa, 0x1377, 0x44e6, { 0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c } };
- #endif
- static const IID D3D_IID_IDXGISwapChain3 = { 0x94d99bdb, 0xf1f8, 0x4ab0, { 0xb2, 0x36, 0x7d, 0xa0, 0x17, 0x0e, 0xda, 0xb1 } };
- #ifdef HAVE_IDXGIINFOQUEUE
- static const IID D3D_IID_IDXGIDebug = { 0x119e7452, 0xde9e, 0x40fe, { 0x88, 0x06, 0x88, 0xf9, 0x0c, 0x12, 0xb4, 0x41 } };
- static const IID D3D_IID_IDXGIInfoQueue = { 0xd67441c7, 0x672a, 0x476f, { 0x9e, 0x82, 0xcd, 0x55, 0xb4, 0x49, 0x49, 0xce } };
- #endif
- static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x08 } };
- static const GUID D3D_IID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, { 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 } };
- static const IID D3D_IID_ID3D12Device = { 0x189819f1, 0x1db6, 0x4b57, { 0xbe, 0x54, 0x18, 0x21, 0x33, 0x9b, 0x85, 0xf7 } };
- static const IID D3D_IID_ID3D12CommandQueue = { 0x0ec870a6, 0x5d7e, 0x4c22, { 0x8c, 0xfc, 0x5b, 0xaa, 0xe0, 0x76, 0x16, 0xed } };
- static const IID D3D_IID_ID3D12DescriptorHeap = { 0x8efb471d, 0x616c, 0x4f49, { 0x90, 0xf7, 0x12, 0x7b, 0xb7, 0x63, 0xfa, 0x51 } };
- static const IID D3D_IID_ID3D12Resource = { 0x696442be, 0xa72e, 0x4059, { 0xbc, 0x79, 0x5b, 0x5c, 0x98, 0x04, 0x0f, 0xad } };
- static const IID D3D_IID_ID3D12CommandAllocator = { 0x6102dee4, 0xaf59, 0x4b09, { 0xb9, 0x99, 0xb4, 0x4d, 0x73, 0xf0, 0x9b, 0x24 } };
- static const IID D3D_IID_ID3D12CommandList = { 0x7116d91c, 0xe7e4, 0x47ce, { 0xb8, 0xc6, 0xec, 0x81, 0x68, 0xf4, 0x37, 0xe5 } };
- static const IID D3D_IID_ID3D12GraphicsCommandList = { 0x5b160d0f, 0xac1b, 0x4185, { 0x8b, 0xa8, 0xb3, 0xae, 0x42, 0xa5, 0xa4, 0x55 } };
- static const IID D3D_IID_ID3D12Fence = { 0x0a753dcf, 0xc4d8, 0x4b91, { 0xad, 0xf6, 0xbe, 0x5a, 0x60, 0xd9, 0x5a, 0x76 } };
- static const IID D3D_IID_ID3D12RootSignature = { 0xc54a6b66, 0x72df, 0x4ee8, { 0x8b, 0xe5, 0xa9, 0x46, 0xa1, 0x42, 0x92, 0x14 } };
- static const IID D3D_IID_ID3D12CommandSignature = { 0xc36a797c, 0xec80, 0x4f0a, { 0x89, 0x85, 0xa7, 0xb2, 0x47, 0x50, 0x82, 0xd1 } };
- static const IID D3D_IID_ID3D12PipelineState = { 0x765a30f3, 0xf624, 0x4c6f, { 0xa8, 0x28, 0xac, 0xe9, 0x48, 0x62, 0x24, 0x45 } };
- static const IID D3D_IID_ID3D12Debug = { 0x344488b7, 0x6846, 0x474b, { 0xb9, 0x89, 0xf0, 0x27, 0x44, 0x82, 0x45, 0xe0 } };
- static const IID D3D_IID_ID3D12InfoQueue = { 0x0742a90b, 0xc387, 0x483f, { 0xb9, 0x46, 0x30, 0xa7, 0xe4, 0xe6, 0x14, 0x58 } };
- static const IID D3D_IID_ID3D12InfoQueue1 = { 0x2852dd88, 0xb484, 0x4c0c, { 0xb6, 0xb1, 0x67, 0x16, 0x85, 0x00, 0xe6, 0x00 } };
- // Enums
- typedef enum D3D12BufferType
- {
- D3D12_BUFFER_TYPE_GPU,
- D3D12_BUFFER_TYPE_UNIFORM,
- D3D12_BUFFER_TYPE_UPLOAD,
- D3D12_BUFFER_TYPE_DOWNLOAD
- } D3D12BufferType;
- // Conversions
- static SDL_GPUTextureFormat SwapchainCompositionToSDLTextureFormat[] = {
- SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM, // SDR
- SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, // SDR_SRGB
- SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT, // HDR
- SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM, // HDR_ADVANCED
- };
- static DXGI_FORMAT SwapchainCompositionToTextureFormat[] = {
- DXGI_FORMAT_B8G8R8A8_UNORM, // SDR
- DXGI_FORMAT_B8G8R8A8_UNORM, /* SDR_SRGB */ // NOTE: The RTV uses the sRGB format
- DXGI_FORMAT_R16G16B16A16_FLOAT, // HDR
- DXGI_FORMAT_R10G10B10A2_UNORM, // HDR_ADVANCED
- };
- static DXGI_COLOR_SPACE_TYPE SwapchainCompositionToColorSpace[] = {
- DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, // SDR
- DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, // SDR_SRGB
- DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709, // HDR
- DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 // HDR_ADVANCED
- };
- static D3D12_BLEND SDLToD3D12_BlendFactor[] = {
- D3D12_BLEND_ZERO, // INVALID
- D3D12_BLEND_ZERO, // ZERO
- D3D12_BLEND_ONE, // ONE
- D3D12_BLEND_SRC_COLOR, // SRC_COLOR
- D3D12_BLEND_INV_SRC_COLOR, // ONE_MINUS_SRC_COLOR
- D3D12_BLEND_DEST_COLOR, // DST_COLOR
- D3D12_BLEND_INV_DEST_COLOR, // ONE_MINUS_DST_COLOR
- D3D12_BLEND_SRC_ALPHA, // SRC_ALPHA
- D3D12_BLEND_INV_SRC_ALPHA, // ONE_MINUS_SRC_ALPHA
- D3D12_BLEND_DEST_ALPHA, // DST_ALPHA
- D3D12_BLEND_INV_DEST_ALPHA, // ONE_MINUS_DST_ALPHA
- D3D12_BLEND_BLEND_FACTOR, // CONSTANT_COLOR
- D3D12_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR
- D3D12_BLEND_SRC_ALPHA_SAT, // SRC_ALPHA_SATURATE
- };
- SDL_COMPILE_TIME_ASSERT(SDLToD3D12_BlendFactor, SDL_arraysize(SDLToD3D12_BlendFactor) == SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE);
- static D3D12_BLEND SDLToD3D12_BlendFactorAlpha[] = {
- D3D12_BLEND_ZERO, // INVALID
- D3D12_BLEND_ZERO, // ZERO
- D3D12_BLEND_ONE, // ONE
- D3D12_BLEND_SRC_ALPHA, // SRC_COLOR
- D3D12_BLEND_INV_SRC_ALPHA, // ONE_MINUS_SRC_COLOR
- D3D12_BLEND_DEST_ALPHA, // DST_COLOR
- D3D12_BLEND_INV_DEST_ALPHA, // ONE_MINUS_DST_COLOR
- D3D12_BLEND_SRC_ALPHA, // SRC_ALPHA
- D3D12_BLEND_INV_SRC_ALPHA, // ONE_MINUS_SRC_ALPHA
- D3D12_BLEND_DEST_ALPHA, // DST_ALPHA
- D3D12_BLEND_INV_DEST_ALPHA, // ONE_MINUS_DST_ALPHA
- D3D12_BLEND_BLEND_FACTOR, // CONSTANT_COLOR
- D3D12_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR
- D3D12_BLEND_SRC_ALPHA_SAT, // SRC_ALPHA_SATURATE
- };
- SDL_COMPILE_TIME_ASSERT(SDLToD3D12_BlendFactorAlpha, SDL_arraysize(SDLToD3D12_BlendFactorAlpha) == SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE);
- static D3D12_BLEND_OP SDLToD3D12_BlendOp[] = {
- D3D12_BLEND_OP_ADD, // INVALID
- D3D12_BLEND_OP_ADD, // ADD
- D3D12_BLEND_OP_SUBTRACT, // SUBTRACT
- D3D12_BLEND_OP_REV_SUBTRACT, // REVERSE_SUBTRACT
- D3D12_BLEND_OP_MIN, // MIN
- D3D12_BLEND_OP_MAX // MAX
- };
- SDL_COMPILE_TIME_ASSERT(SDLToD3D12_BlendOp, SDL_arraysize(SDLToD3D12_BlendOp) == SDL_GPU_BLENDOP_MAX_ENUM_VALUE);
- // These are actually color formats.
- // For some genius reason, D3D12 splits format capabilites for depth-stencil views.
- static DXGI_FORMAT SDLToD3D12_TextureFormat[] = {
- DXGI_FORMAT_UNKNOWN, // INVALID
- DXGI_FORMAT_A8_UNORM, // A8_UNORM
- DXGI_FORMAT_R8_UNORM, // R8_UNORM
- DXGI_FORMAT_R8G8_UNORM, // R8G8_UNORM
- DXGI_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
- DXGI_FORMAT_R16_UNORM, // R16_UNORM
- DXGI_FORMAT_R16G16_UNORM, // R16G16_UNORM
- DXGI_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
- DXGI_FORMAT_R10G10B10A2_UNORM, // R10G10B10A2_UNORM
- DXGI_FORMAT_B5G6R5_UNORM, // B5G6R5_UNORM
- DXGI_FORMAT_B5G5R5A1_UNORM, // B5G5R5A1_UNORM
- DXGI_FORMAT_B4G4R4A4_UNORM, // B4G4R4A4_UNORM
- DXGI_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
- DXGI_FORMAT_BC1_UNORM, // BC1_UNORM
- DXGI_FORMAT_BC2_UNORM, // BC2_UNORM
- DXGI_FORMAT_BC3_UNORM, // BC3_UNORM
- DXGI_FORMAT_BC4_UNORM, // BC4_UNORM
- DXGI_FORMAT_BC5_UNORM, // BC5_UNORM
- DXGI_FORMAT_BC7_UNORM, // BC7_UNORM
- DXGI_FORMAT_BC6H_SF16, // BC6H_FLOAT
- DXGI_FORMAT_BC6H_UF16, // BC6H_UFLOAT
- DXGI_FORMAT_R8_SNORM, // R8_SNORM
- DXGI_FORMAT_R8G8_SNORM, // R8G8_SNORM
- DXGI_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
- DXGI_FORMAT_R16_SNORM, // R16_SNORM
- DXGI_FORMAT_R16G16_SNORM, // R16G16_SNORM
- DXGI_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
- DXGI_FORMAT_R16_FLOAT, // R16_FLOAT
- DXGI_FORMAT_R16G16_FLOAT, // R16G16_FLOAT
- DXGI_FORMAT_R16G16B16A16_FLOAT, // R16G16B16A16_FLOAT
- DXGI_FORMAT_R32_FLOAT, // R32_FLOAT
- DXGI_FORMAT_R32G32_FLOAT, // R32G32_FLOAT
- DXGI_FORMAT_R32G32B32A32_FLOAT, // R32G32B32A32_FLOAT
- DXGI_FORMAT_R11G11B10_FLOAT, // R11G11B10_UFLOAT
- DXGI_FORMAT_R8_UINT, // R8_UINT
- DXGI_FORMAT_R8G8_UINT, // R8G8_UINT
- DXGI_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
- DXGI_FORMAT_R16_UINT, // R16_UINT
- DXGI_FORMAT_R16G16_UINT, // R16G16_UINT
- DXGI_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
- DXGI_FORMAT_R32_UINT, // R32_UINT
- DXGI_FORMAT_R32G32_UINT, // R32G32_UINT
- DXGI_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
- DXGI_FORMAT_R8_SINT, // R8_INT
- DXGI_FORMAT_R8G8_SINT, // R8G8_INT
- DXGI_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
- DXGI_FORMAT_R16_SINT, // R16_INT
- DXGI_FORMAT_R16G16_SINT, // R16G16_INT
- DXGI_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
- DXGI_FORMAT_R32_SINT, // R32_INT
- DXGI_FORMAT_R32G32_SINT, // R32G32_INT
- DXGI_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, // R8G8B8A8_UNORM_SRGB
- DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, // B8G8R8A8_UNORM_SRGB
- DXGI_FORMAT_BC1_UNORM_SRGB, // BC1_UNORM_SRGB
- DXGI_FORMAT_BC2_UNORM_SRGB, // BC2_UNORM_SRGB
- DXGI_FORMAT_BC3_UNORM_SRGB, // BC3_UNORM_SRGB
- DXGI_FORMAT_BC7_UNORM_SRGB, // BC7_UNORM_SRGB
- DXGI_FORMAT_R16_UNORM, // D16_UNORM
- DXGI_FORMAT_R24_UNORM_X8_TYPELESS, // D24_UNORM
- DXGI_FORMAT_R32_FLOAT, // D32_FLOAT
- DXGI_FORMAT_R24_UNORM_X8_TYPELESS, // D24_UNORM_S8_UINT
- DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, // D32_FLOAT_S8_UINT
- DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
- };
- SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TextureFormat, SDL_arraysize(SDLToD3D12_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
- static DXGI_FORMAT SDLToD3D12_DepthFormat[] = {
- DXGI_FORMAT_UNKNOWN, // INVALID
- DXGI_FORMAT_UNKNOWN, // A8_UNORM
- DXGI_FORMAT_UNKNOWN, // R8_UNORM
- DXGI_FORMAT_UNKNOWN, // R8G8_UNORM
- DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM
- DXGI_FORMAT_UNKNOWN, // R16_UNORM
- DXGI_FORMAT_UNKNOWN, // R16G16_UNORM
- DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UNORM
- DXGI_FORMAT_UNKNOWN, // R10G10B10A2_UNORM
- DXGI_FORMAT_UNKNOWN, // B5G6R5_UNORM
- DXGI_FORMAT_UNKNOWN, // B5G5R5A1_UNORM
- DXGI_FORMAT_UNKNOWN, // B4G4R4A4_UNORM
- DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM
- DXGI_FORMAT_UNKNOWN, // BC1_UNORM
- DXGI_FORMAT_UNKNOWN, // BC2_UNORM
- DXGI_FORMAT_UNKNOWN, // BC3_UNORM
- DXGI_FORMAT_UNKNOWN, // BC4_UNORM
- DXGI_FORMAT_UNKNOWN, // BC5_UNORM
- DXGI_FORMAT_UNKNOWN, // BC7_UNORM
- DXGI_FORMAT_UNKNOWN, // BC6H_FLOAT
- DXGI_FORMAT_UNKNOWN, // BC6H_UFLOAT
- DXGI_FORMAT_UNKNOWN, // R8_SNORM
- DXGI_FORMAT_UNKNOWN, // R8G8_SNORM
- DXGI_FORMAT_UNKNOWN, // R8G8B8A8_SNORM
- DXGI_FORMAT_UNKNOWN, // R16_SNORM
- DXGI_FORMAT_UNKNOWN, // R16G16_SNORM
- DXGI_FORMAT_UNKNOWN, // R16G16B16A16_SNORM
- DXGI_FORMAT_UNKNOWN, // R16_FLOAT
- DXGI_FORMAT_UNKNOWN, // R16G16_FLOAT
- DXGI_FORMAT_UNKNOWN, // R16G16B16A16_FLOAT
- DXGI_FORMAT_UNKNOWN, // R32_FLOAT
- DXGI_FORMAT_UNKNOWN, // R32G32_FLOAT
- DXGI_FORMAT_UNKNOWN, // R32G32B32A32_FLOAT
- DXGI_FORMAT_UNKNOWN, // R11G11B10_UFLOAT
- DXGI_FORMAT_UNKNOWN, // R8_UINT
- DXGI_FORMAT_UNKNOWN, // R8G8_UINT
- DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UINT
- DXGI_FORMAT_UNKNOWN, // R16_UINT
- DXGI_FORMAT_UNKNOWN, // R16G16_UINT
- DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UINT
- DXGI_FORMAT_UNKNOWN, // R32_UINT
- DXGI_FORMAT_UNKNOWN, // R32G32_UINT
- DXGI_FORMAT_UNKNOWN, // R32G32B32A32_UINT
- DXGI_FORMAT_UNKNOWN, // R8_INT
- DXGI_FORMAT_UNKNOWN, // R8G8_INT
- DXGI_FORMAT_UNKNOWN, // R8G8B8A8_INT
- DXGI_FORMAT_UNKNOWN, // R16_INT
- DXGI_FORMAT_UNKNOWN, // R16G16_INT
- DXGI_FORMAT_UNKNOWN, // R16G16B16A16_INT
- DXGI_FORMAT_UNKNOWN, // R32_INT
- DXGI_FORMAT_UNKNOWN, // R32G32_INT
- DXGI_FORMAT_UNKNOWN, // R32G32B32A32_INT
- DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // BC1_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // BC2_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // BC3_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // BC7_UNORM_SRGB
- DXGI_FORMAT_D16_UNORM, // D16_UNORM
- DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM
- DXGI_FORMAT_D32_FLOAT, // D32_FLOAT
- DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT
- DXGI_FORMAT_D32_FLOAT_S8X24_UINT, // D32_FLOAT_S8_UINT
- DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
- DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
- DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
- DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
- };
- SDL_COMPILE_TIME_ASSERT(SDLToD3D12_DepthFormat, SDL_arraysize(SDLToD3D12_DepthFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
- static D3D12_COMPARISON_FUNC SDLToD3D12_CompareOp[] = {
- D3D12_COMPARISON_FUNC_NEVER, // INVALID
- D3D12_COMPARISON_FUNC_NEVER, // NEVER
- D3D12_COMPARISON_FUNC_LESS, // LESS
- D3D12_COMPARISON_FUNC_EQUAL, // EQUAL
- D3D12_COMPARISON_FUNC_LESS_EQUAL, // LESS_OR_EQUAL
- D3D12_COMPARISON_FUNC_GREATER, // GREATER
- D3D12_COMPARISON_FUNC_NOT_EQUAL, // NOT_EQUAL
- D3D12_COMPARISON_FUNC_GREATER_EQUAL, // GREATER_OR_EQUAL
- D3D12_COMPARISON_FUNC_ALWAYS // ALWAYS
- };
- SDL_COMPILE_TIME_ASSERT(SDLToD3D12_CompareOp, SDL_arraysize(SDLToD3D12_CompareOp) == SDL_GPU_COMPAREOP_MAX_ENUM_VALUE);
- static D3D12_STENCIL_OP SDLToD3D12_StencilOp[] = {
- D3D12_STENCIL_OP_KEEP, // INVALID
- D3D12_STENCIL_OP_KEEP, // KEEP
- D3D12_STENCIL_OP_ZERO, // ZERO
- D3D12_STENCIL_OP_REPLACE, // REPLACE
- D3D12_STENCIL_OP_INCR_SAT, // INCREMENT_AND_CLAMP
- D3D12_STENCIL_OP_DECR_SAT, // DECREMENT_AND_CLAMP
- D3D12_STENCIL_OP_INVERT, // INVERT
- D3D12_STENCIL_OP_INCR, // INCREMENT_AND_WRAP
- D3D12_STENCIL_OP_DECR // DECREMENT_AND_WRAP
- };
- SDL_COMPILE_TIME_ASSERT(SDLToD3D12_StencilOp, SDL_arraysize(SDLToD3D12_StencilOp) == SDL_GPU_STENCILOP_MAX_ENUM_VALUE);
- static D3D12_CULL_MODE SDLToD3D12_CullMode[] = {
- D3D12_CULL_MODE_NONE, // NONE
- D3D12_CULL_MODE_FRONT, // FRONT
- D3D12_CULL_MODE_BACK // BACK
- };
- static D3D12_FILL_MODE SDLToD3D12_FillMode[] = {
- D3D12_FILL_MODE_SOLID, // FILL
- D3D12_FILL_MODE_WIREFRAME // LINE
- };
- static D3D12_INPUT_CLASSIFICATION SDLToD3D12_InputRate[] = {
- D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, // VERTEX
- D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA // INSTANCE
- };
- static DXGI_FORMAT SDLToD3D12_VertexFormat[] = {
- DXGI_FORMAT_UNKNOWN, // UNKNOWN
- DXGI_FORMAT_R32_SINT, // INT
- DXGI_FORMAT_R32G32_SINT, // INT2
- DXGI_FORMAT_R32G32B32_SINT, // INT3
- DXGI_FORMAT_R32G32B32A32_SINT, // INT4
- DXGI_FORMAT_R32_UINT, // UINT
- DXGI_FORMAT_R32G32_UINT, // UINT2
- DXGI_FORMAT_R32G32B32_UINT, // UINT3
- DXGI_FORMAT_R32G32B32A32_UINT, // UINT4
- DXGI_FORMAT_R32_FLOAT, // FLOAT
- DXGI_FORMAT_R32G32_FLOAT, // FLOAT2
- DXGI_FORMAT_R32G32B32_FLOAT, // FLOAT3
- DXGI_FORMAT_R32G32B32A32_FLOAT, // FLOAT4
- DXGI_FORMAT_R8G8_SINT, // BYTE2
- DXGI_FORMAT_R8G8B8A8_SINT, // BYTE4
- DXGI_FORMAT_R8G8_UINT, // UBYTE2
- DXGI_FORMAT_R8G8B8A8_UINT, // UBYTE4
- DXGI_FORMAT_R8G8_SNORM, // BYTE2_NORM
- DXGI_FORMAT_R8G8B8A8_SNORM, // BYTE4_NORM
- DXGI_FORMAT_R8G8_UNORM, // UBYTE2_NORM
- DXGI_FORMAT_R8G8B8A8_UNORM, // UBYTE4_NORM
- DXGI_FORMAT_R16G16_SINT, // SHORT2
- DXGI_FORMAT_R16G16B16A16_SINT, // SHORT4
- DXGI_FORMAT_R16G16_UINT, // USHORT2
- DXGI_FORMAT_R16G16B16A16_UINT, // USHORT4
- DXGI_FORMAT_R16G16_SNORM, // SHORT2_NORM
- DXGI_FORMAT_R16G16B16A16_SNORM, // SHORT4_NORM
- DXGI_FORMAT_R16G16_UNORM, // USHORT2_NORM
- DXGI_FORMAT_R16G16B16A16_UNORM, // USHORT4_NORM
- DXGI_FORMAT_R16G16_FLOAT, // HALF2
- DXGI_FORMAT_R16G16B16A16_FLOAT // HALF4
- };
- SDL_COMPILE_TIME_ASSERT(SDLToD3D12_VertexFormat, SDL_arraysize(SDLToD3D12_VertexFormat) == SDL_GPU_VERTEXELEMENTFORMAT_MAX_ENUM_VALUE);
- static Uint32 SDLToD3D12_SampleCount[] = {
- 1, // SDL_GPU_SAMPLECOUNT_1
- 2, // SDL_GPU_SAMPLECOUNT_2
- 4, // SDL_GPU_SAMPLECOUNT_4
- 8, // SDL_GPU_SAMPLECOUNT_8
- };
- static D3D12_PRIMITIVE_TOPOLOGY SDLToD3D12_PrimitiveType[] = {
- D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // TRIANGLELIST
- D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, // TRIANGLESTRIP
- D3D_PRIMITIVE_TOPOLOGY_LINELIST, // LINELIST
- D3D_PRIMITIVE_TOPOLOGY_LINESTRIP, // LINESTRIP
- D3D_PRIMITIVE_TOPOLOGY_POINTLIST // POINTLIST
- };
- static D3D12_TEXTURE_ADDRESS_MODE SDLToD3D12_SamplerAddressMode[] = {
- D3D12_TEXTURE_ADDRESS_MODE_WRAP, // REPEAT
- D3D12_TEXTURE_ADDRESS_MODE_MIRROR, // MIRRORED_REPEAT
- D3D12_TEXTURE_ADDRESS_MODE_CLAMP // CLAMP_TO_EDGE
- };
- static D3D12_FILTER SDLToD3D12_Filter(
- SDL_GPUFilter minFilter,
- SDL_GPUFilter magFilter,
- SDL_GPUSamplerMipmapMode mipmapMode,
- bool comparisonEnabled,
- bool anisotropyEnabled)
- {
- D3D12_FILTER result = D3D12_ENCODE_BASIC_FILTER(
- (minFilter == SDL_GPU_FILTER_LINEAR) ? 1 : 0,
- (magFilter == SDL_GPU_FILTER_LINEAR) ? 1 : 0,
- (mipmapMode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) ? 1 : 0,
- comparisonEnabled ? 1 : 0);
- if (anisotropyEnabled) {
- result = (D3D12_FILTER)(result | D3D12_ANISOTROPIC_FILTERING_BIT);
- }
- return result;
- }
- // Structures
- typedef struct D3D12Renderer D3D12Renderer;
- typedef struct D3D12CommandBufferPool D3D12CommandBufferPool;
- typedef struct D3D12CommandBuffer D3D12CommandBuffer;
- typedef struct D3D12Texture D3D12Texture;
- typedef struct D3D12Shader D3D12Shader;
- typedef struct D3D12GraphicsPipeline D3D12GraphicsPipeline;
- typedef struct D3D12ComputePipeline D3D12ComputePipeline;
- typedef struct D3D12Buffer D3D12Buffer;
- typedef struct D3D12BufferContainer D3D12BufferContainer;
- typedef struct D3D12UniformBuffer D3D12UniformBuffer;
- typedef struct D3D12DescriptorHeap D3D12DescriptorHeap;
- typedef struct D3D12TextureDownload D3D12TextureDownload;
- typedef struct D3D12Fence
- {
- ID3D12Fence *handle;
- HANDLE event; // used for blocking
- SDL_AtomicInt referenceCount;
- } D3D12Fence;
- struct D3D12DescriptorHeap
- {
- ID3D12DescriptorHeap *handle;
- D3D12_DESCRIPTOR_HEAP_TYPE heapType;
- D3D12_CPU_DESCRIPTOR_HANDLE descriptorHeapCPUStart;
- D3D12_GPU_DESCRIPTOR_HANDLE descriptorHeapGPUStart; // only exists if staging is true
- Uint32 maxDescriptors;
- Uint32 descriptorSize;
- bool staging;
- Uint32 currentDescriptorIndex;
- Uint32 *inactiveDescriptorIndices; // only exists if staging is true
- Uint32 inactiveDescriptorCount;
- };
- typedef struct D3D12DescriptorHeapPool
- {
- Uint32 capacity;
- Uint32 count;
- D3D12DescriptorHeap **heaps;
- SDL_Mutex *lock;
- } D3D12DescriptorHeapPool;
- typedef struct D3D12CPUDescriptor
- {
- D3D12DescriptorHeap *heap;
- D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle;
- Uint32 cpuHandleIndex;
- } D3D12CPUDescriptor;
- typedef struct D3D12TextureContainer
- {
- TextureCommonHeader header;
- D3D12Texture *activeTexture;
- D3D12Texture **textures;
- Uint32 textureCapacity;
- Uint32 textureCount;
- // Swapchain images cannot be cycled
- bool canBeCycled;
- char *debugName;
- } D3D12TextureContainer;
- // Null views represent by heap = NULL
- typedef struct D3D12TextureSubresource
- {
- D3D12Texture *parent;
- Uint32 layer;
- Uint32 level;
- Uint32 depth;
- Uint32 index;
- // One per depth slice
- D3D12CPUDescriptor *rtvHandles; // NULL if not a color target
- D3D12CPUDescriptor uavHandle; // NULL if not a compute storage write texture
- D3D12CPUDescriptor dsvHandle; // NULL if not a depth stencil target
- } D3D12TextureSubresource;
- struct D3D12Texture
- {
- D3D12TextureContainer *container;
- Uint32 containerIndex;
- D3D12TextureSubresource *subresources;
- Uint32 subresourceCount; /* layerCount * num_levels */
- ID3D12Resource *resource;
- D3D12CPUDescriptor srvHandle;
- SDL_AtomicInt referenceCount;
- };
- typedef struct D3D12Sampler
- {
- SDL_GPUSamplerCreateInfo createInfo;
- D3D12CPUDescriptor handle;
- SDL_AtomicInt referenceCount;
- } D3D12Sampler;
- typedef struct D3D12WindowData
- {
- SDL_Window *window;
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- D3D12XBOX_FRAME_PIPELINE_TOKEN frameToken;
- #else
- IDXGISwapChain3 *swapchain;
- #endif
- SDL_GPUPresentMode present_mode;
- SDL_GPUSwapchainComposition swapchainComposition;
- DXGI_COLOR_SPACE_TYPE swapchainColorSpace;
- Uint32 frameCounter;
- D3D12TextureContainer textureContainers[MAX_FRAMES_IN_FLIGHT];
- Uint32 swapchainTextureCount;
- SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
- Uint32 width;
- Uint32 height;
- bool needsSwapchainRecreate;
- } D3D12WindowData;
- typedef struct D3D12PresentData
- {
- D3D12WindowData *windowData;
- Uint32 swapchainImageIndex;
- } D3D12PresentData;
- struct D3D12Renderer
- {
- // Reference to the parent device
- SDL_GPUDevice *sdlGPUDevice;
- #if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- IDXGIDebug *dxgiDebug;
- IDXGIFactory4 *factory;
- #ifdef HAVE_IDXGIINFOQUEUE
- IDXGIInfoQueue *dxgiInfoQueue;
- #endif
- IDXGIAdapter1 *adapter;
- SDL_SharedObject *dxgi_dll;
- SDL_SharedObject *dxgidebug_dll;
- #endif
- ID3D12Debug *d3d12Debug;
- BOOL supportsTearing;
- SDL_SharedObject *d3d12_dll;
- ID3D12Device *device;
- PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignature_func;
- const char *semantic;
- SDL_iconv_t iconv;
- ID3D12CommandQueue *commandQueue;
- bool debug_mode;
- bool GPUUploadHeapSupported;
- // FIXME: these might not be necessary since we're not using custom heaps
- bool UMA;
- bool UMACacheCoherent;
- Uint32 allowedFramesInFlight;
- // Indirect command signatures
- ID3D12CommandSignature *indirectDrawCommandSignature;
- ID3D12CommandSignature *indirectIndexedDrawCommandSignature;
- ID3D12CommandSignature *indirectDispatchCommandSignature;
- // Blit
- SDL_GPUShader *blitVertexShader;
- SDL_GPUShader *blitFrom2DShader;
- SDL_GPUShader *blitFrom2DArrayShader;
- SDL_GPUShader *blitFrom3DShader;
- SDL_GPUShader *blitFromCubeShader;
- SDL_GPUShader *blitFromCubeArrayShader;
- SDL_GPUSampler *blitNearestSampler;
- SDL_GPUSampler *blitLinearSampler;
- BlitPipelineCacheEntry *blitPipelines;
- Uint32 blitPipelineCount;
- Uint32 blitPipelineCapacity;
- // Resources
- D3D12CommandBuffer **availableCommandBuffers;
- Uint32 availableCommandBufferCount;
- Uint32 availableCommandBufferCapacity;
- D3D12CommandBuffer **submittedCommandBuffers;
- Uint32 submittedCommandBufferCount;
- Uint32 submittedCommandBufferCapacity;
- D3D12UniformBuffer **uniformBufferPool;
- Uint32 uniformBufferPoolCount;
- Uint32 uniformBufferPoolCapacity;
- D3D12WindowData **claimedWindows;
- Uint32 claimedWindowCount;
- Uint32 claimedWindowCapacity;
- D3D12Fence **availableFences;
- Uint32 availableFenceCount;
- Uint32 availableFenceCapacity;
- D3D12DescriptorHeap *stagingDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
- D3D12DescriptorHeapPool descriptorHeapPools[2];
- // Deferred resource releasing
- D3D12Buffer **buffersToDestroy;
- Uint32 buffersToDestroyCount;
- Uint32 buffersToDestroyCapacity;
- D3D12Texture **texturesToDestroy;
- Uint32 texturesToDestroyCount;
- Uint32 texturesToDestroyCapacity;
- D3D12Sampler **samplersToDestroy;
- Uint32 samplersToDestroyCount;
- Uint32 samplersToDestroyCapacity;
- D3D12GraphicsPipeline **graphicsPipelinesToDestroy;
- Uint32 graphicsPipelinesToDestroyCount;
- Uint32 graphicsPipelinesToDestroyCapacity;
- D3D12ComputePipeline **computePipelinesToDestroy;
- Uint32 computePipelinesToDestroyCount;
- Uint32 computePipelinesToDestroyCapacity;
- // Locks
- SDL_Mutex *stagingDescriptorHeapLock;
- SDL_Mutex *acquireCommandBufferLock;
- SDL_Mutex *acquireUniformBufferLock;
- SDL_Mutex *submitLock;
- SDL_Mutex *windowLock;
- SDL_Mutex *fenceLock;
- SDL_Mutex *disposeLock;
- };
- struct D3D12CommandBuffer
- {
- // reserved for SDL_gpu
- CommandBufferCommonHeader common;
- // non owning parent reference
- D3D12Renderer *renderer;
- ID3D12CommandAllocator *commandAllocator;
- ID3D12GraphicsCommandList *graphicsCommandList;
- D3D12Fence *inFlightFence;
- bool autoReleaseFence;
- // Presentation data
- D3D12PresentData *presentDatas;
- Uint32 presentDataCount;
- Uint32 presentDataCapacity;
- D3D12TextureSubresource *colorTargetSubresources[MAX_COLOR_TARGET_BINDINGS];
- D3D12TextureSubresource *colorResolveSubresources[MAX_COLOR_TARGET_BINDINGS];
- D3D12TextureSubresource *depthStencilTextureSubresource;
- D3D12GraphicsPipeline *currentGraphicsPipeline;
- D3D12ComputePipeline *currentComputePipeline;
- // Set at acquire time
- D3D12DescriptorHeap *gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER + 1];
- D3D12UniformBuffer **usedUniformBuffers;
- Uint32 usedUniformBufferCount;
- Uint32 usedUniformBufferCapacity;
- // Resource slot state
- bool needVertexBufferBind;
- bool needVertexSamplerBind;
- bool needVertexStorageTextureBind;
- bool needVertexStorageBufferBind;
- bool needVertexUniformBufferBind[MAX_UNIFORM_BUFFERS_PER_STAGE];
- bool needFragmentSamplerBind;
- bool needFragmentStorageTextureBind;
- bool needFragmentStorageBufferBind;
- bool needFragmentUniformBufferBind[MAX_UNIFORM_BUFFERS_PER_STAGE];
- bool needComputeSamplerBind;
- bool needComputeReadOnlyStorageTextureBind;
- bool needComputeReadOnlyStorageBufferBind;
- bool needComputeUniformBufferBind[MAX_UNIFORM_BUFFERS_PER_STAGE];
- D3D12Buffer *vertexBuffers[MAX_VERTEX_BUFFERS];
- Uint32 vertexBufferOffsets[MAX_VERTEX_BUFFERS];
- Uint32 vertexBufferCount;
- D3D12Texture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- D3D12Sampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- D3D12Texture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
- D3D12Buffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
- D3D12UniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
- D3D12Texture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- D3D12Sampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- D3D12Texture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
- D3D12Buffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
- D3D12UniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
- D3D12Texture *computeSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- D3D12Sampler *computeSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- D3D12Texture *computeReadOnlyStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
- D3D12Buffer *computeReadOnlyStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
- D3D12TextureSubresource *computeReadWriteStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
- Uint32 computeReadWriteStorageTextureSubresourceCount;
- D3D12Buffer *computeReadWriteStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
- Uint32 computeReadWriteStorageBufferCount;
- D3D12UniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
- // Resource tracking
- D3D12Texture **usedTextures;
- Uint32 usedTextureCount;
- Uint32 usedTextureCapacity;
- D3D12Buffer **usedBuffers;
- Uint32 usedBufferCount;
- Uint32 usedBufferCapacity;
- D3D12Sampler **usedSamplers;
- Uint32 usedSamplerCount;
- Uint32 usedSamplerCapacity;
- D3D12GraphicsPipeline **usedGraphicsPipelines;
- Uint32 usedGraphicsPipelineCount;
- Uint32 usedGraphicsPipelineCapacity;
- D3D12ComputePipeline **usedComputePipelines;
- Uint32 usedComputePipelineCount;
- Uint32 usedComputePipelineCapacity;
- // Used for texture pitch hack
- D3D12TextureDownload **textureDownloads;
- Uint32 textureDownloadCount;
- Uint32 textureDownloadCapacity;
- };
- struct D3D12Shader
- {
- // todo cleanup
- void *bytecode;
- size_t bytecodeSize;
- Uint32 num_samplers;
- Uint32 numUniformBuffers;
- Uint32 numStorageBuffers;
- Uint32 numStorageTextures;
- };
- typedef struct D3D12GraphicsRootSignature
- {
- ID3D12RootSignature *handle;
- Sint32 vertexSamplerRootIndex;
- Sint32 vertexSamplerTextureRootIndex;
- Sint32 vertexStorageTextureRootIndex;
- Sint32 vertexStorageBufferRootIndex;
- Sint32 vertexUniformBufferRootIndex[MAX_UNIFORM_BUFFERS_PER_STAGE];
- Sint32 fragmentSamplerRootIndex;
- Sint32 fragmentSamplerTextureRootIndex;
- Sint32 fragmentStorageTextureRootIndex;
- Sint32 fragmentStorageBufferRootIndex;
- Sint32 fragmentUniformBufferRootIndex[MAX_UNIFORM_BUFFERS_PER_STAGE];
- } D3D12GraphicsRootSignature;
- struct D3D12GraphicsPipeline
- {
- ID3D12PipelineState *pipelineState;
- D3D12GraphicsRootSignature *rootSignature;
- SDL_GPUPrimitiveType primitiveType;
- Uint32 vertexStrides[MAX_VERTEX_BUFFERS];
- Uint32 vertexSamplerCount;
- Uint32 vertexUniformBufferCount;
- Uint32 vertexStorageBufferCount;
- Uint32 vertexStorageTextureCount;
- Uint32 fragmentSamplerCount;
- Uint32 fragmentUniformBufferCount;
- Uint32 fragmentStorageBufferCount;
- Uint32 fragmentStorageTextureCount;
- SDL_AtomicInt referenceCount;
- };
- typedef struct D3D12ComputeRootSignature
- {
- ID3D12RootSignature *handle;
- Sint32 samplerRootIndex;
- Sint32 samplerTextureRootIndex;
- Sint32 readOnlyStorageTextureRootIndex;
- Sint32 readOnlyStorageBufferRootIndex;
- Sint32 readWriteStorageTextureRootIndex;
- Sint32 readWriteStorageBufferRootIndex;
- Sint32 uniformBufferRootIndex[MAX_UNIFORM_BUFFERS_PER_STAGE];
- } D3D12ComputeRootSignature;
- struct D3D12ComputePipeline
- {
- ID3D12PipelineState *pipelineState;
- D3D12ComputeRootSignature *rootSignature;
- Uint32 numSamplers;
- Uint32 numReadOnlyStorageTextures;
- Uint32 numReadOnlyStorageBuffers;
- Uint32 numReadWriteStorageTextures;
- Uint32 numReadWriteStorageBuffers;
- Uint32 numUniformBuffers;
- SDL_AtomicInt referenceCount;
- };
- struct D3D12TextureDownload
- {
- D3D12Buffer *destinationBuffer;
- D3D12Buffer *temporaryBuffer;
- Uint32 width;
- Uint32 height;
- Uint32 depth;
- Uint32 bufferOffset;
- Uint32 bytesPerRow;
- Uint32 bytesPerDepthSlice;
- Uint32 alignedBytesPerRow;
- };
- struct D3D12Buffer
- {
- D3D12BufferContainer *container;
- Uint32 containerIndex;
- ID3D12Resource *handle;
- D3D12CPUDescriptor uavDescriptor;
- D3D12CPUDescriptor srvDescriptor;
- D3D12CPUDescriptor cbvDescriptor;
- D3D12_GPU_VIRTUAL_ADDRESS virtualAddress;
- Uint8 *mapPointer; // NULL except for upload buffers and fast uniform buffers
- SDL_AtomicInt referenceCount;
- bool transitioned; // used for initial resource barrier
- };
- struct D3D12BufferContainer
- {
- SDL_GPUBufferUsageFlags usage;
- Uint32 size;
- D3D12BufferType type;
- D3D12Buffer *activeBuffer;
- D3D12Buffer **buffers;
- Uint32 bufferCapacity;
- Uint32 bufferCount;
- D3D12_RESOURCE_DESC bufferDesc;
- char *debugName;
- };
- struct D3D12UniformBuffer
- {
- D3D12Buffer *buffer;
- Uint32 writeOffset;
- Uint32 drawOffset;
- Uint32 currentBlockSize;
- };
- // Forward function declarations
- static void D3D12_ReleaseWindow(SDL_GPURenderer *driverData, SDL_Window *window);
- static bool D3D12_Wait(SDL_GPURenderer *driverData);
- static bool D3D12_WaitForFences(SDL_GPURenderer *driverData, bool waitAll, SDL_GPUFence *const *fences, Uint32 numFences);
- static void D3D12_INTERNAL_ReleaseBlitPipelines(SDL_GPURenderer *driverData);
- // Helpers
- static Uint32 D3D12_INTERNAL_Align(Uint32 location, Uint32 alignment)
- {
- return (location + (alignment - 1)) & ~(alignment - 1);
- }
- // Xbox Hack
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- // FIXME: This is purely to work around a presentation bug when recreating the device/command queue.
- static ID3D12Device *s_Device;
- static ID3D12CommandQueue *s_CommandQueue;
- #endif
- #if defined(SDL_PLATFORM_XBOXONE)
- // These are not defined in d3d12_x.h.
- typedef HRESULT (D3DAPI* PFN_D3D12_XBOX_CREATE_DEVICE)(_In_opt_ IGraphicsUnknown*, _In_ const D3D12XBOX_CREATE_DEVICE_PARAMETERS*, _In_ REFIID, _Outptr_opt_ void**);
- #define D3D12_STANDARD_MULTISAMPLE_PATTERN DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN
- #endif
- // Logging
- static void D3D12_INTERNAL_SetError(
- D3D12Renderer *renderer,
- const char *msg,
- HRESULT res)
- {
- #define MAX_ERROR_LEN 1024 // FIXME: Arbitrary!
- // Buffer for text, ensure space for \0 terminator after buffer
- char wszMsgBuff[MAX_ERROR_LEN + 1];
- DWORD dwChars; // Number of chars returned.
- if (res == DXGI_ERROR_DEVICE_REMOVED) {
- if (renderer->device) {
- res = ID3D12Device_GetDeviceRemovedReason(renderer->device);
- }
- }
- // Try to get the message from the system errors.
- dwChars = FormatMessageA(
- FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- res,
- 0,
- wszMsgBuff,
- MAX_ERROR_LEN,
- NULL);
- // No message? Screw it, just post the code.
- if (dwChars == 0) {
- if (renderer->debug_mode) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: " HRESULT_FMT, msg, res);
- }
- SDL_SetError("%s! Error Code: " HRESULT_FMT, msg, res);
- return;
- }
- // Ensure valid range
- dwChars = SDL_min(dwChars, MAX_ERROR_LEN);
- // Trim whitespace from tail of message
- while (dwChars > 0) {
- if (wszMsgBuff[dwChars - 1] <= ' ') {
- dwChars--;
- } else {
- break;
- }
- }
- // Ensure null-terminated string
- wszMsgBuff[dwChars] = '\0';
- if (renderer->debug_mode) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
- }
- SDL_SetError("%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
- }
- // Debug Naming
- static void D3D12_INTERNAL_SetResourceName(
- D3D12Renderer *renderer,
- ID3D12Resource *resource,
- const char *text)
- {
- if (renderer->debug_mode) {
- ID3D12DeviceChild_SetPrivateData(
- resource,
- D3D_GUID(D3D_IID_D3DDebugObjectName),
- (UINT)SDL_strlen(text),
- text);
- }
- }
- // Release / Cleanup
- // TODO: call this when releasing resources
- static void D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- D3D12Renderer *renderer,
- D3D12CPUDescriptor *cpuDescriptor)
- {
- D3D12DescriptorHeap *heap = cpuDescriptor->heap;
- if (heap != NULL) {
- SDL_LockMutex(renderer->stagingDescriptorHeapLock);
- heap->inactiveDescriptorIndices[heap->inactiveDescriptorCount] = cpuDescriptor->cpuHandleIndex;
- heap->inactiveDescriptorCount += 1;
- SDL_UnlockMutex(renderer->stagingDescriptorHeapLock);
- }
- cpuDescriptor->heap = NULL;
- cpuDescriptor->cpuHandle.ptr = 0;
- cpuDescriptor->cpuHandleIndex = SDL_MAX_UINT32;
- }
- static void D3D12_INTERNAL_DestroyBuffer(
- D3D12Renderer *renderer,
- D3D12Buffer *buffer)
- {
- if (!buffer) {
- return;
- }
- if (buffer->mapPointer != NULL) {
- ID3D12Resource_Unmap(
- buffer->handle,
- 0,
- NULL);
- }
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &buffer->srvDescriptor);
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &buffer->uavDescriptor);
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &buffer->cbvDescriptor);
- if (buffer->handle) {
- ID3D12Resource_Release(buffer->handle);
- }
- SDL_free(buffer);
- }
- static void D3D12_INTERNAL_ReleaseBuffer(
- D3D12Renderer *renderer,
- D3D12Buffer *buffer)
- {
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->buffersToDestroy,
- D3D12Buffer *,
- renderer->buffersToDestroyCount + 1,
- renderer->buffersToDestroyCapacity,
- renderer->buffersToDestroyCapacity * 2);
- renderer->buffersToDestroy[renderer->buffersToDestroyCount] = buffer;
- renderer->buffersToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void D3D12_INTERNAL_ReleaseBufferContainer(
- D3D12Renderer *renderer,
- D3D12BufferContainer *container)
- {
- SDL_LockMutex(renderer->disposeLock);
- for (Uint32 i = 0; i < container->bufferCount; i += 1) {
- D3D12_INTERNAL_ReleaseBuffer(
- renderer,
- container->buffers[i]);
- }
- // Containers are just client handles, so we can free immediately
- if (container->debugName) {
- SDL_free(container->debugName);
- }
- SDL_free(container->buffers);
- SDL_free(container);
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void D3D12_INTERNAL_DestroyTexture(
- D3D12Renderer *renderer,
- D3D12Texture *texture)
- {
- if (!texture) {
- return;
- }
- for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
- D3D12TextureSubresource *subresource = &texture->subresources[i];
- if (subresource->rtvHandles) {
- for (Uint32 depthIndex = 0; depthIndex < subresource->depth; depthIndex += 1) {
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &subresource->rtvHandles[depthIndex]);
- }
- SDL_free(subresource->rtvHandles);
- }
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &subresource->uavHandle);
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &subresource->dsvHandle);
- }
- SDL_free(texture->subresources);
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &texture->srvHandle);
- if (texture->resource) {
- ID3D12Resource_Release(texture->resource);
- }
- SDL_free(texture);
- }
- static void D3D12_INTERNAL_ReleaseTexture(
- D3D12Renderer *renderer,
- D3D12Texture *texture)
- {
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->texturesToDestroy,
- D3D12Texture *,
- renderer->texturesToDestroyCount + 1,
- renderer->texturesToDestroyCapacity,
- renderer->texturesToDestroyCapacity * 2);
- renderer->texturesToDestroy[renderer->texturesToDestroyCount] = texture;
- renderer->texturesToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void D3D12_INTERNAL_ReleaseTextureContainer(
- D3D12Renderer *renderer,
- D3D12TextureContainer *container)
- {
- SDL_LockMutex(renderer->disposeLock);
- for (Uint32 i = 0; i < container->textureCount; i += 1) {
- D3D12_INTERNAL_ReleaseTexture(
- renderer,
- container->textures[i]);
- }
- // Containers are just client handles, so we can destroy immediately
- if (container->debugName) {
- SDL_free(container->debugName);
- }
- SDL_free(container->textures);
- SDL_free(container);
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void D3D12_INTERNAL_DestroySampler(
- D3D12Renderer *renderer,
- D3D12Sampler *sampler)
- {
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &sampler->handle);
- SDL_free(sampler);
- }
- static void D3D12_INTERNAL_DestroyGraphicsRootSignature(
- D3D12GraphicsRootSignature *rootSignature)
- {
- if (!rootSignature) {
- return;
- }
- if (rootSignature->handle) {
- ID3D12RootSignature_Release(rootSignature->handle);
- }
- SDL_free(rootSignature);
- }
- static void D3D12_INTERNAL_DestroyGraphicsPipeline(
- D3D12GraphicsPipeline *graphicsPipeline)
- {
- if (graphicsPipeline->pipelineState) {
- ID3D12PipelineState_Release(graphicsPipeline->pipelineState);
- }
- D3D12_INTERNAL_DestroyGraphicsRootSignature(graphicsPipeline->rootSignature);
- SDL_free(graphicsPipeline);
- }
- static void D3D12_INTERNAL_DestroyComputeRootSignature(
- D3D12ComputeRootSignature *rootSignature)
- {
- if (!rootSignature) {
- return;
- }
- if (rootSignature->handle) {
- ID3D12RootSignature_Release(rootSignature->handle);
- }
- SDL_free(rootSignature);
- }
- static void D3D12_INTERNAL_DestroyComputePipeline(
- D3D12ComputePipeline *computePipeline)
- {
- if (computePipeline->pipelineState) {
- ID3D12PipelineState_Release(computePipeline->pipelineState);
- }
- D3D12_INTERNAL_DestroyComputeRootSignature(computePipeline->rootSignature);
- SDL_free(computePipeline);
- }
- static void D3D12_INTERNAL_ReleaseFenceToPool(
- D3D12Renderer *renderer,
- D3D12Fence *fence)
- {
- SDL_LockMutex(renderer->fenceLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->availableFences,
- D3D12Fence *,
- renderer->availableFenceCount + 1,
- renderer->availableFenceCapacity,
- renderer->availableFenceCapacity * 2);
- renderer->availableFences[renderer->availableFenceCount] = fence;
- renderer->availableFenceCount += 1;
- SDL_UnlockMutex(renderer->fenceLock);
- }
- static void D3D12_ReleaseFence(
- SDL_GPURenderer *driverData,
- SDL_GPUFence *fence)
- {
- D3D12Fence *d3d12Fence = (D3D12Fence *)fence;
- if (SDL_AtomicDecRef(&d3d12Fence->referenceCount)) {
- D3D12_INTERNAL_ReleaseFenceToPool(
- (D3D12Renderer *)driverData,
- d3d12Fence);
- }
- }
- static bool D3D12_QueryFence(
- SDL_GPURenderer *driverData,
- SDL_GPUFence *fence)
- {
- D3D12Fence *d3d12Fence = (D3D12Fence *)fence;
- return ID3D12Fence_GetCompletedValue(d3d12Fence->handle) == D3D12_FENCE_SIGNAL_VALUE;
- }
- static void D3D12_INTERNAL_DestroyDescriptorHeap(D3D12DescriptorHeap *descriptorHeap)
- {
- if (!descriptorHeap) {
- return;
- }
- SDL_free(descriptorHeap->inactiveDescriptorIndices);
- if (descriptorHeap->handle) {
- ID3D12DescriptorHeap_Release(descriptorHeap->handle);
- }
- SDL_free(descriptorHeap);
- }
- static void D3D12_INTERNAL_DestroyCommandBuffer(D3D12CommandBuffer *commandBuffer)
- {
- if (!commandBuffer) {
- return;
- }
- if (commandBuffer->graphicsCommandList) {
- ID3D12GraphicsCommandList_Release(commandBuffer->graphicsCommandList);
- }
- if (commandBuffer->commandAllocator) {
- ID3D12CommandAllocator_Release(commandBuffer->commandAllocator);
- }
- SDL_free(commandBuffer->presentDatas);
- SDL_free(commandBuffer->usedTextures);
- SDL_free(commandBuffer->usedBuffers);
- SDL_free(commandBuffer->usedSamplers);
- SDL_free(commandBuffer->usedGraphicsPipelines);
- SDL_free(commandBuffer->usedComputePipelines);
- SDL_free(commandBuffer->usedUniformBuffers);
- SDL_free(commandBuffer->textureDownloads);
- SDL_free(commandBuffer);
- }
- static void D3D12_INTERNAL_DestroyFence(D3D12Fence *fence)
- {
- if (!fence) {
- return;
- }
- if (fence->handle) {
- ID3D12Fence_Release(fence->handle);
- }
- if (fence->event) {
- CloseHandle(fence->event);
- }
- SDL_free(fence);
- }
- static void D3D12_INTERNAL_DestroyRenderer(D3D12Renderer *renderer)
- {
- // Release uniform buffers
- for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
- D3D12_INTERNAL_DestroyBuffer(
- renderer,
- renderer->uniformBufferPool[i]->buffer);
- SDL_free(renderer->uniformBufferPool[i]);
- }
- // Clean up descriptor heaps
- for (Uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1) {
- if (renderer->stagingDescriptorHeaps[i]) {
- D3D12_INTERNAL_DestroyDescriptorHeap(renderer->stagingDescriptorHeaps[i]);
- renderer->stagingDescriptorHeaps[i] = NULL;
- }
- }
- for (Uint32 i = 0; i < 2; i += 1) {
- if (renderer->descriptorHeapPools[i].heaps) {
- for (Uint32 j = 0; j < renderer->descriptorHeapPools[i].count; j += 1) {
- if (renderer->descriptorHeapPools[i].heaps[j]) {
- D3D12_INTERNAL_DestroyDescriptorHeap(renderer->descriptorHeapPools[i].heaps[j]);
- renderer->descriptorHeapPools[i].heaps[j] = NULL;
- }
- }
- SDL_free(renderer->descriptorHeapPools[i].heaps);
- }
- if (renderer->descriptorHeapPools[i].lock) {
- SDL_DestroyMutex(renderer->descriptorHeapPools[i].lock);
- renderer->descriptorHeapPools[i].lock = NULL;
- }
- }
- // Release command buffers
- for (Uint32 i = 0; i < renderer->availableCommandBufferCount; i += 1) {
- if (renderer->availableCommandBuffers[i]) {
- D3D12_INTERNAL_DestroyCommandBuffer(renderer->availableCommandBuffers[i]);
- renderer->availableCommandBuffers[i] = NULL;
- }
- }
- // Release fences
- for (Uint32 i = 0; i < renderer->availableFenceCount; i += 1) {
- if (renderer->availableFences[i]) {
- D3D12_INTERNAL_DestroyFence(renderer->availableFences[i]);
- renderer->availableFences[i] = NULL;
- }
- }
- // Clean up allocations
- SDL_free(renderer->availableCommandBuffers);
- SDL_free(renderer->submittedCommandBuffers);
- SDL_free(renderer->uniformBufferPool);
- SDL_free(renderer->claimedWindows);
- SDL_free(renderer->availableFences);
- SDL_free(renderer->buffersToDestroy);
- SDL_free(renderer->texturesToDestroy);
- SDL_free(renderer->samplersToDestroy);
- SDL_free(renderer->graphicsPipelinesToDestroy);
- SDL_free(renderer->computePipelinesToDestroy);
- // Tear down D3D12 objects
- if (renderer->indirectDrawCommandSignature) {
- ID3D12CommandSignature_Release(renderer->indirectDrawCommandSignature);
- renderer->indirectDrawCommandSignature = NULL;
- }
- if (renderer->indirectIndexedDrawCommandSignature) {
- ID3D12CommandSignature_Release(renderer->indirectIndexedDrawCommandSignature);
- renderer->indirectIndexedDrawCommandSignature = NULL;
- }
- if (renderer->indirectDispatchCommandSignature) {
- ID3D12CommandSignature_Release(renderer->indirectDispatchCommandSignature);
- renderer->indirectDispatchCommandSignature = NULL;
- }
- #if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- if (renderer->commandQueue) {
- ID3D12CommandQueue_Release(renderer->commandQueue);
- renderer->commandQueue = NULL;
- }
- if (renderer->device) {
- ID3D12Device_Release(renderer->device);
- renderer->device = NULL;
- }
- if (renderer->adapter) {
- IDXGIAdapter1_Release(renderer->adapter);
- renderer->adapter = NULL;
- }
- if (renderer->factory) {
- IDXGIFactory4_Release(renderer->factory);
- renderer->factory = NULL;
- }
- if (renderer->dxgiDebug) {
- IDXGIDebug_ReportLiveObjects(
- renderer->dxgiDebug,
- D3D_IID_DXGI_DEBUG_ALL,
- (DXGI_DEBUG_RLO_FLAGS)(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL));
- IDXGIDebug_Release(renderer->dxgiDebug);
- renderer->dxgiDebug = NULL;
- }
- #endif
- if (renderer->d3d12_dll) {
- SDL_UnloadObject(renderer->d3d12_dll);
- renderer->d3d12_dll = NULL;
- }
- #if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- if (renderer->dxgi_dll) {
- SDL_UnloadObject(renderer->dxgi_dll);
- renderer->dxgi_dll = NULL;
- }
- if (renderer->dxgidebug_dll) {
- SDL_UnloadObject(renderer->dxgidebug_dll);
- renderer->dxgidebug_dll = NULL;
- }
- #endif
- renderer->D3D12SerializeRootSignature_func = NULL;
- if (renderer->iconv) {
- SDL_iconv_close(renderer->iconv);
- }
- SDL_DestroyMutex(renderer->stagingDescriptorHeapLock);
- SDL_DestroyMutex(renderer->acquireCommandBufferLock);
- SDL_DestroyMutex(renderer->acquireUniformBufferLock);
- SDL_DestroyMutex(renderer->submitLock);
- SDL_DestroyMutex(renderer->windowLock);
- SDL_DestroyMutex(renderer->fenceLock);
- SDL_DestroyMutex(renderer->disposeLock);
- SDL_free(renderer);
- }
- static void D3D12_DestroyDevice(SDL_GPUDevice *device)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)device->driverData;
- // Release blit pipeline structures
- D3D12_INTERNAL_ReleaseBlitPipelines((SDL_GPURenderer *)renderer);
- // Flush any remaining GPU work...
- D3D12_Wait((SDL_GPURenderer *)renderer);
- // Release window data
- for (Sint32 i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) {
- D3D12_ReleaseWindow((SDL_GPURenderer *)renderer, renderer->claimedWindows[i]->window);
- }
- D3D12_INTERNAL_DestroyRenderer(renderer);
- SDL_free(device);
- }
- // Barriers
- static inline Uint32 D3D12_INTERNAL_CalcSubresource(
- Uint32 mipLevel,
- Uint32 layer,
- Uint32 numLevels)
- {
- return mipLevel + (layer * numLevels);
- }
- static void D3D12_INTERNAL_ResourceBarrier(
- D3D12CommandBuffer *commandBuffer,
- D3D12_RESOURCE_STATES sourceState,
- D3D12_RESOURCE_STATES destinationState,
- ID3D12Resource *resource,
- Uint32 subresourceIndex,
- bool needsUavBarrier)
- {
- D3D12_RESOURCE_BARRIER barrierDesc[2];
- Uint32 numBarriers = 0;
- // No transition barrier is needed if the state is not changing.
- if (sourceState != destinationState) {
- barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
- barrierDesc[numBarriers].Flags = (D3D12_RESOURCE_BARRIER_FLAGS)0;
- barrierDesc[numBarriers].Transition.StateBefore = sourceState;
- barrierDesc[numBarriers].Transition.StateAfter = destinationState;
- barrierDesc[numBarriers].Transition.pResource = resource;
- barrierDesc[numBarriers].Transition.Subresource = subresourceIndex;
- numBarriers += 1;
- }
- if (needsUavBarrier) {
- barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
- barrierDesc[numBarriers].Flags = (D3D12_RESOURCE_BARRIER_FLAGS)0;
- barrierDesc[numBarriers].UAV.pResource = resource;
- numBarriers += 1;
- }
- if (numBarriers > 0) {
- ID3D12GraphicsCommandList_ResourceBarrier(
- commandBuffer->graphicsCommandList,
- numBarriers,
- barrierDesc);
- }
- }
- static void D3D12_INTERNAL_TextureSubresourceBarrier(
- D3D12CommandBuffer *commandBuffer,
- D3D12_RESOURCE_STATES sourceState,
- D3D12_RESOURCE_STATES destinationState,
- D3D12TextureSubresource *textureSubresource)
- {
- bool needsUAVBarrier =
- (textureSubresource->parent->container->header.info.usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) ||
- (textureSubresource->parent->container->header.info.usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE);
- D3D12_INTERNAL_ResourceBarrier(
- commandBuffer,
- sourceState,
- destinationState,
- textureSubresource->parent->resource,
- textureSubresource->index,
- needsUAVBarrier);
- }
- static D3D12_RESOURCE_STATES D3D12_INTERNAL_DefaultTextureResourceState(
- SDL_GPUTextureUsageFlags usageFlags)
- {
- // NOTE: order matters here!
- if (usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER) {
- return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
- } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) {
- return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
- } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
- return D3D12_RESOURCE_STATE_RENDER_TARGET;
- } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
- return D3D12_RESOURCE_STATE_DEPTH_WRITE;
- } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ) {
- return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
- } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) {
- return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
- } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE) {
- return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Texture has no default usage mode!");
- return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
- }
- }
- static void D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- D3D12CommandBuffer *commandBuffer,
- D3D12_RESOURCE_STATES destinationUsageMode,
- D3D12TextureSubresource *textureSubresource)
- {
- D3D12_INTERNAL_TextureSubresourceBarrier(
- commandBuffer,
- D3D12_INTERNAL_DefaultTextureResourceState(textureSubresource->parent->container->header.info.usage),
- destinationUsageMode,
- textureSubresource);
- }
- static void D3D12_INTERNAL_TextureTransitionFromDefaultUsage(
- D3D12CommandBuffer *commandBuffer,
- D3D12_RESOURCE_STATES destinationUsageMode,
- D3D12Texture *texture)
- {
- for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
- D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- commandBuffer,
- destinationUsageMode,
- &texture->subresources[i]);
- }
- }
- static void D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- D3D12CommandBuffer *commandBuffer,
- D3D12_RESOURCE_STATES sourceUsageMode,
- D3D12TextureSubresource *textureSubresource)
- {
- D3D12_INTERNAL_TextureSubresourceBarrier(
- commandBuffer,
- sourceUsageMode,
- D3D12_INTERNAL_DefaultTextureResourceState(textureSubresource->parent->container->header.info.usage),
- textureSubresource);
- }
- static void D3D12_INTERNAL_TextureTransitionToDefaultUsage(
- D3D12CommandBuffer *commandBuffer,
- D3D12_RESOURCE_STATES sourceUsageMode,
- D3D12Texture *texture)
- {
- for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- commandBuffer,
- sourceUsageMode,
- &texture->subresources[i]);
- }
- }
- static D3D12_RESOURCE_STATES D3D12_INTERNAL_DefaultBufferResourceState(
- D3D12Buffer *buffer)
- {
- if (buffer->container->usage & SDL_GPU_BUFFERUSAGE_VERTEX) {
- return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
- } else if (buffer->container->usage & SDL_GPU_BUFFERUSAGE_INDEX) {
- return D3D12_RESOURCE_STATE_INDEX_BUFFER;
- } else if (buffer->container->usage & SDL_GPU_BUFFERUSAGE_INDIRECT) {
- return D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
- } else if (buffer->container->usage & SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ) {
- return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
- } else if (buffer->container->usage & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ) {
- return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
- } else if (buffer->container->usage & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE) {
- return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Buffer has no default usage mode!");
- return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
- }
- }
- static void D3D12_INTERNAL_BufferBarrier(
- D3D12CommandBuffer *commandBuffer,
- D3D12_RESOURCE_STATES sourceState,
- D3D12_RESOURCE_STATES destinationState,
- D3D12Buffer *buffer)
- {
- D3D12_INTERNAL_ResourceBarrier(
- commandBuffer,
- buffer->transitioned ? sourceState : D3D12_RESOURCE_STATE_COMMON,
- destinationState,
- buffer->handle,
- 0,
- buffer->container->usage & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE);
- buffer->transitioned = true;
- }
- static void D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
- D3D12CommandBuffer *commandBuffer,
- D3D12_RESOURCE_STATES destinationState,
- D3D12Buffer *buffer)
- {
- D3D12_INTERNAL_BufferBarrier(
- commandBuffer,
- D3D12_INTERNAL_DefaultBufferResourceState(buffer),
- destinationState,
- buffer);
- }
- static void D3D12_INTERNAL_BufferTransitionToDefaultUsage(
- D3D12CommandBuffer *commandBuffer,
- D3D12_RESOURCE_STATES sourceState,
- D3D12Buffer *buffer)
- {
- D3D12_INTERNAL_BufferBarrier(
- commandBuffer,
- sourceState,
- D3D12_INTERNAL_DefaultBufferResourceState(buffer),
- buffer);
- }
- // Resource tracking
- #define TRACK_RESOURCE(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 = (type *)SDL_realloc( \
- commandBuffer->array, \
- commandBuffer->capacity * sizeof(type)); \
- } \
- commandBuffer->array[commandBuffer->count] = resource; \
- commandBuffer->count += 1; \
- SDL_AtomicIncRef(&resource->referenceCount);
- static void D3D12_INTERNAL_TrackTexture(
- D3D12CommandBuffer *commandBuffer,
- D3D12Texture *texture)
- {
- TRACK_RESOURCE(
- texture,
- D3D12Texture *,
- usedTextures,
- usedTextureCount,
- usedTextureCapacity)
- }
- static void D3D12_INTERNAL_TrackBuffer(
- D3D12CommandBuffer *commandBuffer,
- D3D12Buffer *buffer)
- {
- TRACK_RESOURCE(
- buffer,
- D3D12Buffer *,
- usedBuffers,
- usedBufferCount,
- usedBufferCapacity)
- }
- static void D3D12_INTERNAL_TrackSampler(
- D3D12CommandBuffer *commandBuffer,
- D3D12Sampler *sampler)
- {
- TRACK_RESOURCE(
- sampler,
- D3D12Sampler *,
- usedSamplers,
- usedSamplerCount,
- usedSamplerCapacity)
- }
- static void D3D12_INTERNAL_TrackGraphicsPipeline(
- D3D12CommandBuffer *commandBuffer,
- D3D12GraphicsPipeline *graphicsPipeline)
- {
- TRACK_RESOURCE(
- graphicsPipeline,
- D3D12GraphicsPipeline *,
- usedGraphicsPipelines,
- usedGraphicsPipelineCount,
- usedGraphicsPipelineCapacity)
- }
- static void D3D12_INTERNAL_TrackComputePipeline(
- D3D12CommandBuffer *commandBuffer,
- D3D12ComputePipeline *computePipeline)
- {
- TRACK_RESOURCE(
- computePipeline,
- D3D12ComputePipeline *,
- usedComputePipelines,
- usedComputePipelineCount,
- usedComputePipelineCapacity)
- }
- #undef TRACK_RESOURCE
- // State Creation
- static D3D12DescriptorHeap *D3D12_INTERNAL_CreateDescriptorHeap(
- D3D12Renderer *renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE type,
- Uint32 descriptorCount,
- bool staging)
- {
- D3D12DescriptorHeap *heap;
- ID3D12DescriptorHeap *handle;
- D3D12_DESCRIPTOR_HEAP_DESC heapDesc;
- HRESULT res;
- heap = (D3D12DescriptorHeap *)SDL_calloc(1, sizeof(D3D12DescriptorHeap));
- if (!heap) {
- return NULL;
- }
- heap->currentDescriptorIndex = 0;
- heap->inactiveDescriptorCount = 0;
- heap->inactiveDescriptorIndices = NULL;
- if (staging) {
- heap->inactiveDescriptorIndices = (Uint32 *)SDL_calloc(descriptorCount, sizeof(Uint32));
- if (!heap->inactiveDescriptorIndices) {
- D3D12_INTERNAL_DestroyDescriptorHeap(heap);
- return NULL;
- }
- }
- heapDesc.NumDescriptors = descriptorCount;
- heapDesc.Type = type;
- heapDesc.Flags = staging ? D3D12_DESCRIPTOR_HEAP_FLAG_NONE : D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
- heapDesc.NodeMask = 0;
- res = ID3D12Device_CreateDescriptorHeap(
- renderer->device,
- &heapDesc,
- D3D_GUID(D3D_IID_ID3D12DescriptorHeap),
- (void **)&handle);
- if (FAILED(res)) {
- D3D12_INTERNAL_SetError(renderer, "Failed to create descriptor heap!", res);
- D3D12_INTERNAL_DestroyDescriptorHeap(heap);
- return NULL;
- }
- heap->handle = handle;
- heap->heapType = type;
- heap->maxDescriptors = descriptorCount;
- heap->staging = staging;
- heap->descriptorSize = ID3D12Device_GetDescriptorHandleIncrementSize(renderer->device, type);
- D3D_CALL_RET(handle, GetCPUDescriptorHandleForHeapStart, &heap->descriptorHeapCPUStart);
- if (!staging) {
- D3D_CALL_RET(handle, GetGPUDescriptorHandleForHeapStart, &heap->descriptorHeapGPUStart);
- }
- return heap;
- }
- static D3D12DescriptorHeap *D3D12_INTERNAL_AcquireDescriptorHeapFromPool(
- D3D12CommandBuffer *commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE descriptorHeapType)
- {
- D3D12DescriptorHeap *result;
- D3D12Renderer *renderer = commandBuffer->renderer;
- D3D12DescriptorHeapPool *pool = &renderer->descriptorHeapPools[descriptorHeapType];
- SDL_LockMutex(pool->lock);
- if (pool->count > 0) {
- result = pool->heaps[pool->count - 1];
- pool->count -= 1;
- } else {
- result = D3D12_INTERNAL_CreateDescriptorHeap(
- renderer,
- descriptorHeapType,
- descriptorHeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ? VIEW_GPU_DESCRIPTOR_COUNT : SAMPLER_GPU_DESCRIPTOR_COUNT,
- false);
- }
- SDL_UnlockMutex(pool->lock);
- return result;
- }
- static void D3D12_INTERNAL_ReturnDescriptorHeapToPool(
- D3D12Renderer *renderer,
- D3D12DescriptorHeap *heap)
- {
- D3D12DescriptorHeapPool *pool = &renderer->descriptorHeapPools[heap->heapType];
- heap->currentDescriptorIndex = 0;
- SDL_LockMutex(pool->lock);
- if (pool->count >= pool->capacity) {
- pool->capacity *= 2;
- pool->heaps = (D3D12DescriptorHeap **)SDL_realloc(
- pool->heaps,
- pool->capacity * sizeof(D3D12DescriptorHeap *));
- }
- pool->heaps[pool->count] = heap;
- pool->count += 1;
- SDL_UnlockMutex(pool->lock);
- }
- /*
- * The root signature lets us define "root parameters" which are essentially bind points for resources.
- * These let us define the register ranges as well as the register "space".
- * The register space is akin to the descriptor set index in Vulkan, which allows us to group resources
- * by stage so that the registers from the vertex and fragment shaders don't clobber each other.
- *
- * Most of our root parameters are implemented as "descriptor tables" so we can
- * copy and then point to contiguous descriptor regions.
- * Uniform buffers are the exception - these have to be implemented as raw "root descriptors" so
- * that we can dynamically update the address that the constant buffer view points to.
- *
- * The root signature has a maximum size of 64 DWORDs.
- * A descriptor table uses 1 DWORD.
- * A root descriptor uses 2 DWORDS.
- * This means our biggest root signature uses 24 DWORDs total, well under the limit.
- *
- * The root parameter indices are created dynamically and stored in the D3D12GraphicsRootSignature struct.
- */
- static D3D12GraphicsRootSignature *D3D12_INTERNAL_CreateGraphicsRootSignature(
- D3D12Renderer *renderer,
- D3D12Shader *vertexShader,
- D3D12Shader *fragmentShader)
- {
- // FIXME: I think the max can be smaller...
- D3D12_ROOT_PARAMETER rootParameters[MAX_ROOT_SIGNATURE_PARAMETERS];
- D3D12_DESCRIPTOR_RANGE descriptorRanges[MAX_ROOT_SIGNATURE_PARAMETERS];
- Uint32 parameterCount = 0;
- Uint32 rangeCount = 0;
- D3D12_DESCRIPTOR_RANGE descriptorRange;
- D3D12_ROOT_PARAMETER rootParameter;
- D3D12GraphicsRootSignature *d3d12GraphicsRootSignature =
- (D3D12GraphicsRootSignature *)SDL_calloc(1, sizeof(D3D12GraphicsRootSignature));
- if (!d3d12GraphicsRootSignature) {
- return NULL;
- }
- SDL_zeroa(rootParameters);
- SDL_zeroa(descriptorRanges);
- SDL_zero(rootParameter);
- d3d12GraphicsRootSignature->vertexSamplerRootIndex = -1;
- d3d12GraphicsRootSignature->vertexSamplerTextureRootIndex = -1;
- d3d12GraphicsRootSignature->vertexStorageTextureRootIndex = -1;
- d3d12GraphicsRootSignature->vertexStorageBufferRootIndex = -1;
- d3d12GraphicsRootSignature->fragmentSamplerRootIndex = -1;
- d3d12GraphicsRootSignature->fragmentSamplerTextureRootIndex = -1;
- d3d12GraphicsRootSignature->fragmentStorageTextureRootIndex = -1;
- d3d12GraphicsRootSignature->fragmentStorageBufferRootIndex = -1;
- for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
- d3d12GraphicsRootSignature->vertexUniformBufferRootIndex[i] = -1;
- d3d12GraphicsRootSignature->fragmentUniformBufferRootIndex[i] = -1;
- }
- if (vertexShader->num_samplers > 0) {
- // Vertex Samplers
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
- descriptorRange.NumDescriptors = vertexShader->num_samplers;
- descriptorRange.BaseShaderRegister = 0;
- descriptorRange.RegisterSpace = 0;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->vertexSamplerRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- descriptorRange.NumDescriptors = vertexShader->num_samplers;
- descriptorRange.BaseShaderRegister = 0;
- descriptorRange.RegisterSpace = 0;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->vertexSamplerTextureRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- if (vertexShader->numStorageTextures) {
- // Vertex storage textures
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- descriptorRange.NumDescriptors = vertexShader->numStorageTextures;
- descriptorRange.BaseShaderRegister = vertexShader->num_samplers;
- descriptorRange.RegisterSpace = 0;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->vertexStorageTextureRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- if (vertexShader->numStorageBuffers) {
- // Vertex storage buffers
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- descriptorRange.NumDescriptors = vertexShader->numStorageBuffers;
- descriptorRange.BaseShaderRegister = vertexShader->num_samplers + vertexShader->numStorageTextures;
- descriptorRange.RegisterSpace = 0;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->vertexStorageBufferRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- // Vertex Uniforms
- for (Uint32 i = 0; i < vertexShader->numUniformBuffers; i += 1) {
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
- rootParameter.Descriptor.ShaderRegister = i;
- rootParameter.Descriptor.RegisterSpace = 1;
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->vertexUniformBufferRootIndex[i] = parameterCount;
- parameterCount += 1;
- }
- if (fragmentShader->num_samplers) {
- // Fragment Samplers
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
- descriptorRange.NumDescriptors = fragmentShader->num_samplers;
- descriptorRange.BaseShaderRegister = 0;
- descriptorRange.RegisterSpace = 2;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->fragmentSamplerRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- descriptorRange.NumDescriptors = fragmentShader->num_samplers;
- descriptorRange.BaseShaderRegister = 0;
- descriptorRange.RegisterSpace = 2;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->fragmentSamplerTextureRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- if (fragmentShader->numStorageTextures) {
- // Fragment Storage Textures
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- descriptorRange.NumDescriptors = fragmentShader->numStorageTextures;
- descriptorRange.BaseShaderRegister = fragmentShader->num_samplers;
- descriptorRange.RegisterSpace = 2;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->fragmentStorageTextureRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- if (fragmentShader->numStorageBuffers) {
- // Fragment Storage Buffers
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- descriptorRange.NumDescriptors = fragmentShader->numStorageBuffers;
- descriptorRange.BaseShaderRegister = fragmentShader->num_samplers + fragmentShader->numStorageTextures;
- descriptorRange.RegisterSpace = 2;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->fragmentStorageBufferRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- // Fragment Uniforms
- for (Uint32 i = 0; i < fragmentShader->numUniformBuffers; i += 1) {
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
- rootParameter.Descriptor.ShaderRegister = i;
- rootParameter.Descriptor.RegisterSpace = 3;
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
- rootParameters[parameterCount] = rootParameter;
- d3d12GraphicsRootSignature->fragmentUniformBufferRootIndex[i] = parameterCount;
- parameterCount += 1;
- }
- // FIXME: shouldn't have to assert here
- SDL_assert(parameterCount <= MAX_ROOT_SIGNATURE_PARAMETERS);
- SDL_assert(rangeCount <= MAX_ROOT_SIGNATURE_PARAMETERS);
- // Create the root signature description
- D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
- rootSignatureDesc.NumParameters = parameterCount;
- rootSignatureDesc.pParameters = rootParameters;
- rootSignatureDesc.NumStaticSamplers = 0;
- rootSignatureDesc.pStaticSamplers = NULL;
- rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
- // Serialize the root signature
- ID3DBlob *serializedRootSignature;
- ID3DBlob *errorBlob;
- HRESULT res = renderer->D3D12SerializeRootSignature_func(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &serializedRootSignature, &errorBlob);
- if (FAILED(res)) {
- if (errorBlob) {
- SET_ERROR("Failed to serialize RootSignature: %s", (const char *)ID3D10Blob_GetBufferPointer(errorBlob));
- ID3D10Blob_Release(errorBlob);
- }
- D3D12_INTERNAL_DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
- return NULL;
- }
- // Create the root signature
- ID3D12RootSignature *rootSignature;
- res = ID3D12Device_CreateRootSignature(
- renderer->device,
- 0,
- ID3D10Blob_GetBufferPointer(serializedRootSignature),
- ID3D10Blob_GetBufferSize(serializedRootSignature),
- D3D_GUID(D3D_IID_ID3D12RootSignature),
- (void **)&rootSignature);
- if (FAILED(res)) {
- if (errorBlob) {
- SET_ERROR("Failed to create RootSignature: %s", (const char *)ID3D10Blob_GetBufferPointer(errorBlob));
- ID3D10Blob_Release(errorBlob);
- }
- D3D12_INTERNAL_DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
- return NULL;
- }
- d3d12GraphicsRootSignature->handle = rootSignature;
- return d3d12GraphicsRootSignature;
- }
- static bool D3D12_INTERNAL_CreateShaderBytecode(
- D3D12Renderer *renderer,
- Uint32 stage,
- SDL_GPUShaderFormat format,
- const Uint8 *code,
- size_t codeSize,
- const char *entrypointName,
- void **pBytecode,
- size_t *pBytecodeSize)
- {
- if (pBytecode != NULL) {
- *pBytecode = SDL_malloc(codeSize);
- if (!*pBytecode) {
- return false;
- }
- SDL_memcpy(*pBytecode, code, codeSize);
- *pBytecodeSize = codeSize;
- }
- return true;
- }
- static D3D12ComputeRootSignature *D3D12_INTERNAL_CreateComputeRootSignature(
- D3D12Renderer *renderer,
- const SDL_GPUComputePipelineCreateInfo *createInfo)
- {
- // FIXME: I think the max can be smaller...
- D3D12_ROOT_PARAMETER rootParameters[MAX_ROOT_SIGNATURE_PARAMETERS];
- D3D12_DESCRIPTOR_RANGE descriptorRanges[MAX_ROOT_SIGNATURE_PARAMETERS];
- Uint32 parameterCount = 0;
- Uint32 rangeCount = 0;
- D3D12_DESCRIPTOR_RANGE descriptorRange;
- D3D12_ROOT_PARAMETER rootParameter;
- D3D12ComputeRootSignature *d3d12ComputeRootSignature =
- (D3D12ComputeRootSignature *)SDL_calloc(1, sizeof(D3D12ComputeRootSignature));
- if (!d3d12ComputeRootSignature) {
- return NULL;
- }
- SDL_zeroa(rootParameters);
- SDL_zeroa(descriptorRanges);
- SDL_zero(rootParameter);
- d3d12ComputeRootSignature->samplerRootIndex = -1;
- d3d12ComputeRootSignature->samplerTextureRootIndex = -1;
- d3d12ComputeRootSignature->readOnlyStorageTextureRootIndex = -1;
- d3d12ComputeRootSignature->readOnlyStorageBufferRootIndex = -1;
- d3d12ComputeRootSignature->readWriteStorageTextureRootIndex = -1;
- d3d12ComputeRootSignature->readWriteStorageBufferRootIndex = -1;
- for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
- d3d12ComputeRootSignature->uniformBufferRootIndex[i] = -1;
- }
- if (createInfo->num_samplers) {
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
- descriptorRange.NumDescriptors = createInfo->num_samplers;
- descriptorRange.BaseShaderRegister = 0;
- descriptorRange.RegisterSpace = 0;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
- rootParameters[parameterCount] = rootParameter;
- d3d12ComputeRootSignature->samplerRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- descriptorRange.NumDescriptors = createInfo->num_samplers;
- descriptorRange.BaseShaderRegister = 0;
- descriptorRange.RegisterSpace = 0;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
- rootParameters[parameterCount] = rootParameter;
- d3d12ComputeRootSignature->samplerTextureRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- if (createInfo->num_readonly_storage_textures) {
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- descriptorRange.NumDescriptors = createInfo->num_readonly_storage_textures;
- descriptorRange.BaseShaderRegister = createInfo->num_samplers;
- descriptorRange.RegisterSpace = 0;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
- rootParameters[parameterCount] = rootParameter;
- d3d12ComputeRootSignature->readOnlyStorageTextureRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- if (createInfo->num_readonly_storage_buffers) {
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- descriptorRange.NumDescriptors = createInfo->num_readonly_storage_buffers;
- descriptorRange.BaseShaderRegister = createInfo->num_samplers + createInfo->num_readonly_storage_textures;
- descriptorRange.RegisterSpace = 0;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
- rootParameters[parameterCount] = rootParameter;
- d3d12ComputeRootSignature->readOnlyStorageBufferRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- if (createInfo->num_readwrite_storage_textures) {
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
- descriptorRange.NumDescriptors = createInfo->num_readwrite_storage_textures;
- descriptorRange.BaseShaderRegister = 0;
- descriptorRange.RegisterSpace = 1;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
- rootParameters[parameterCount] = rootParameter;
- d3d12ComputeRootSignature->readWriteStorageTextureRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- if (createInfo->num_readwrite_storage_buffers) {
- descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
- descriptorRange.NumDescriptors = createInfo->num_readwrite_storage_buffers;
- descriptorRange.BaseShaderRegister = createInfo->num_readwrite_storage_textures;
- descriptorRange.RegisterSpace = 1;
- descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- descriptorRanges[rangeCount] = descriptorRange;
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- rootParameter.DescriptorTable.NumDescriptorRanges = 1;
- rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
- rootParameters[parameterCount] = rootParameter;
- d3d12ComputeRootSignature->readWriteStorageBufferRootIndex = parameterCount;
- rangeCount += 1;
- parameterCount += 1;
- }
- for (Uint32 i = 0; i < createInfo->num_uniform_buffers; i += 1) {
- rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
- rootParameter.Descriptor.ShaderRegister = i;
- rootParameter.Descriptor.RegisterSpace = 2;
- rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
- rootParameters[parameterCount] = rootParameter;
- d3d12ComputeRootSignature->uniformBufferRootIndex[i] = parameterCount;
- parameterCount += 1;
- }
- D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
- rootSignatureDesc.NumParameters = parameterCount;
- rootSignatureDesc.pParameters = rootParameters;
- rootSignatureDesc.NumStaticSamplers = 0;
- rootSignatureDesc.pStaticSamplers = NULL;
- rootSignatureDesc.Flags = (D3D12_ROOT_SIGNATURE_FLAGS)0;
- ID3DBlob *serializedRootSignature;
- ID3DBlob *errorBlob;
- HRESULT res = renderer->D3D12SerializeRootSignature_func(
- &rootSignatureDesc,
- D3D_ROOT_SIGNATURE_VERSION_1,
- &serializedRootSignature,
- &errorBlob);
- if (FAILED(res)) {
- if (errorBlob) {
- SET_ERROR("Failed to serialize RootSignature: %s", (const char *)ID3D10Blob_GetBufferPointer(errorBlob));
- ID3D10Blob_Release(errorBlob);
- }
- D3D12_INTERNAL_DestroyComputeRootSignature(d3d12ComputeRootSignature);
- return NULL;
- }
- ID3D12RootSignature *rootSignature;
- res = ID3D12Device_CreateRootSignature(
- renderer->device,
- 0,
- ID3D10Blob_GetBufferPointer(serializedRootSignature),
- ID3D10Blob_GetBufferSize(serializedRootSignature),
- D3D_GUID(D3D_IID_ID3D12RootSignature),
- (void **)&rootSignature);
- if (FAILED(res)) {
- if (errorBlob) {
- SET_ERROR("Failed to create RootSignature: %s", (const char *)ID3D10Blob_GetBufferPointer(errorBlob));
- ID3D10Blob_Release(errorBlob);
- }
- D3D12_INTERNAL_DestroyComputeRootSignature(d3d12ComputeRootSignature);
- return NULL;
- }
- d3d12ComputeRootSignature->handle = rootSignature;
- return d3d12ComputeRootSignature;
- }
- static SDL_GPUComputePipeline *D3D12_CreateComputePipeline(
- SDL_GPURenderer *driverData,
- const SDL_GPUComputePipelineCreateInfo *createinfo)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- void *bytecode;
- size_t bytecodeSize;
- ID3D12PipelineState *pipelineState;
- if (!D3D12_INTERNAL_CreateShaderBytecode(
- renderer,
- SDL_GPU_SHADERSTAGE_COMPUTE,
- createinfo->format,
- createinfo->code,
- createinfo->code_size,
- createinfo->entrypoint,
- &bytecode,
- &bytecodeSize)) {
- return NULL;
- }
- D3D12ComputeRootSignature *rootSignature = D3D12_INTERNAL_CreateComputeRootSignature(
- renderer,
- createinfo);
- if (rootSignature == NULL) {
- SDL_free(bytecode);
- SET_STRING_ERROR_AND_RETURN("Could not create root signature!", NULL);
- }
- D3D12_COMPUTE_PIPELINE_STATE_DESC pipelineDesc;
- pipelineDesc.CS.pShaderBytecode = bytecode;
- pipelineDesc.CS.BytecodeLength = bytecodeSize;
- pipelineDesc.pRootSignature = rootSignature->handle;
- pipelineDesc.CachedPSO.CachedBlobSizeInBytes = 0;
- pipelineDesc.CachedPSO.pCachedBlob = NULL;
- pipelineDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
- pipelineDesc.NodeMask = 0;
- HRESULT res = ID3D12Device_CreateComputePipelineState(
- renderer->device,
- &pipelineDesc,
- D3D_GUID(D3D_IID_ID3D12PipelineState),
- (void **)&pipelineState);
- if (FAILED(res)) {
- D3D12_INTERNAL_SetError(renderer, "Could not create compute pipeline state", res);
- SDL_free(bytecode);
- return NULL;
- }
- D3D12ComputePipeline *computePipeline =
- (D3D12ComputePipeline *)SDL_calloc(1, sizeof(D3D12ComputePipeline));
- if (!computePipeline) {
- ID3D12PipelineState_Release(pipelineState);
- SDL_free(bytecode);
- return NULL;
- }
- computePipeline->pipelineState = pipelineState;
- computePipeline->rootSignature = rootSignature;
- computePipeline->numSamplers = createinfo->num_samplers;
- computePipeline->numReadOnlyStorageTextures = createinfo->num_readonly_storage_textures;
- computePipeline->numReadOnlyStorageBuffers = createinfo->num_readonly_storage_buffers;
- computePipeline->numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
- computePipeline->numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
- computePipeline->numUniformBuffers = createinfo->num_uniform_buffers;
- SDL_SetAtomicInt(&computePipeline->referenceCount, 0);
- return (SDL_GPUComputePipeline *)computePipeline;
- }
- static bool D3D12_INTERNAL_ConvertRasterizerState(SDL_GPURasterizerState rasterizerState, D3D12_RASTERIZER_DESC *desc)
- {
- if (!desc) {
- return false;
- }
- desc->FillMode = SDLToD3D12_FillMode[rasterizerState.fill_mode];
- desc->CullMode = SDLToD3D12_CullMode[rasterizerState.cull_mode];
- switch (rasterizerState.front_face) {
- case SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE:
- desc->FrontCounterClockwise = TRUE;
- break;
- case SDL_GPU_FRONTFACE_CLOCKWISE:
- desc->FrontCounterClockwise = FALSE;
- break;
- default:
- return false;
- }
- if (rasterizerState.enable_depth_bias) {
- desc->DepthBias = SDL_lroundf(rasterizerState.depth_bias_constant_factor);
- desc->DepthBiasClamp = rasterizerState.depth_bias_clamp;
- desc->SlopeScaledDepthBias = rasterizerState.depth_bias_slope_factor;
- } else {
- desc->DepthBias = 0;
- desc->DepthBiasClamp = 0.0f;
- desc->SlopeScaledDepthBias = 0.0f;
- }
- desc->DepthClipEnable = rasterizerState.enable_depth_clip;
- desc->MultisampleEnable = FALSE;
- desc->AntialiasedLineEnable = FALSE;
- desc->ForcedSampleCount = 0;
- desc->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
- return true;
- }
- static bool D3D12_INTERNAL_ConvertBlendState(
- const SDL_GPUGraphicsPipelineCreateInfo *pipelineInfo,
- D3D12_BLEND_DESC *blendDesc)
- {
- if (!blendDesc) {
- return false;
- }
- SDL_zerop(blendDesc);
- blendDesc->AlphaToCoverageEnable = FALSE;
- blendDesc->IndependentBlendEnable = FALSE;
- for (UINT i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
- D3D12_RENDER_TARGET_BLEND_DESC rtBlendDesc;
- rtBlendDesc.BlendEnable = FALSE;
- rtBlendDesc.LogicOpEnable = FALSE;
- rtBlendDesc.SrcBlend = D3D12_BLEND_ONE;
- rtBlendDesc.DestBlend = D3D12_BLEND_ZERO;
- rtBlendDesc.BlendOp = D3D12_BLEND_OP_ADD;
- rtBlendDesc.SrcBlendAlpha = D3D12_BLEND_ONE;
- rtBlendDesc.DestBlendAlpha = D3D12_BLEND_ZERO;
- rtBlendDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
- rtBlendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
- rtBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
- // If target_info has more blend states, you can set IndependentBlendEnable to TRUE and assign different blend states to each render target slot
- if (i < pipelineInfo->target_info.num_color_targets) {
- SDL_GPUColorTargetBlendState sdlBlendState = pipelineInfo->target_info.color_target_descriptions[i].blend_state;
- SDL_GPUColorComponentFlags colorWriteMask = sdlBlendState.enable_color_write_mask ?
- sdlBlendState.color_write_mask :
- 0xF;
- rtBlendDesc.BlendEnable = sdlBlendState.enable_blend;
- rtBlendDesc.SrcBlend = SDLToD3D12_BlendFactor[sdlBlendState.src_color_blendfactor];
- rtBlendDesc.DestBlend = SDLToD3D12_BlendFactor[sdlBlendState.dst_color_blendfactor];
- rtBlendDesc.BlendOp = SDLToD3D12_BlendOp[sdlBlendState.color_blend_op];
- rtBlendDesc.SrcBlendAlpha = SDLToD3D12_BlendFactorAlpha[sdlBlendState.src_alpha_blendfactor];
- rtBlendDesc.DestBlendAlpha = SDLToD3D12_BlendFactorAlpha[sdlBlendState.dst_alpha_blendfactor];
- rtBlendDesc.BlendOpAlpha = SDLToD3D12_BlendOp[sdlBlendState.alpha_blend_op];
- rtBlendDesc.RenderTargetWriteMask = colorWriteMask;
- if (i > 0) {
- blendDesc->IndependentBlendEnable = TRUE;
- }
- }
- blendDesc->RenderTarget[i] = rtBlendDesc;
- }
- return true;
- }
- static bool D3D12_INTERNAL_ConvertDepthStencilState(SDL_GPUDepthStencilState depthStencilState, D3D12_DEPTH_STENCIL_DESC *desc)
- {
- if (desc == NULL) {
- return false;
- }
- desc->DepthEnable = depthStencilState.enable_depth_test == true ? TRUE : FALSE;
- desc->DepthWriteMask = depthStencilState.enable_depth_write == true ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
- desc->DepthFunc = SDLToD3D12_CompareOp[depthStencilState.compare_op];
- desc->StencilEnable = depthStencilState.enable_stencil_test == true ? TRUE : FALSE;
- desc->StencilReadMask = depthStencilState.compare_mask;
- desc->StencilWriteMask = depthStencilState.write_mask;
- desc->FrontFace.StencilFailOp = SDLToD3D12_StencilOp[depthStencilState.front_stencil_state.fail_op];
- desc->FrontFace.StencilDepthFailOp = SDLToD3D12_StencilOp[depthStencilState.front_stencil_state.depth_fail_op];
- desc->FrontFace.StencilPassOp = SDLToD3D12_StencilOp[depthStencilState.front_stencil_state.pass_op];
- desc->FrontFace.StencilFunc = SDLToD3D12_CompareOp[depthStencilState.front_stencil_state.compare_op];
- desc->BackFace.StencilFailOp = SDLToD3D12_StencilOp[depthStencilState.back_stencil_state.fail_op];
- desc->BackFace.StencilDepthFailOp = SDLToD3D12_StencilOp[depthStencilState.back_stencil_state.depth_fail_op];
- desc->BackFace.StencilPassOp = SDLToD3D12_StencilOp[depthStencilState.back_stencil_state.pass_op];
- desc->BackFace.StencilFunc = SDLToD3D12_CompareOp[depthStencilState.back_stencil_state.compare_op];
- return true;
- }
- static bool D3D12_INTERNAL_ConvertVertexInputState(SDL_GPUVertexInputState vertexInputState, D3D12_INPUT_ELEMENT_DESC *desc, const char *semantic)
- {
- if (desc == NULL || vertexInputState.num_vertex_attributes == 0) {
- return false;
- }
- for (Uint32 i = 0; i < vertexInputState.num_vertex_attributes; i += 1) {
- SDL_GPUVertexAttribute attribute = vertexInputState.vertex_attributes[i];
- desc[i].SemanticName = semantic;
- desc[i].SemanticIndex = attribute.location;
- desc[i].Format = SDLToD3D12_VertexFormat[attribute.format];
- desc[i].InputSlot = attribute.buffer_slot;
- desc[i].AlignedByteOffset = attribute.offset;
- desc[i].InputSlotClass = SDLToD3D12_InputRate[vertexInputState.vertex_buffer_descriptions[attribute.buffer_slot].input_rate];
- desc[i].InstanceDataStepRate = (vertexInputState.vertex_buffer_descriptions[attribute.buffer_slot].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE)
- ? vertexInputState.vertex_buffer_descriptions[attribute.buffer_slot].instance_step_rate
- : 0;
- }
- return true;
- }
- static void D3D12_INTERNAL_AssignCpuDescriptorHandle(
- D3D12Renderer *renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE heapType,
- D3D12CPUDescriptor *cpuDescriptor)
- {
- D3D12DescriptorHeap *heap = renderer->stagingDescriptorHeaps[heapType];
- Uint32 descriptorIndex;
- cpuDescriptor->heap = heap;
- SDL_LockMutex(renderer->stagingDescriptorHeapLock);
- if (heap->inactiveDescriptorCount > 0) {
- descriptorIndex = heap->inactiveDescriptorIndices[heap->inactiveDescriptorCount - 1];
- heap->inactiveDescriptorCount -= 1;
- } else if (heap->currentDescriptorIndex < heap->maxDescriptors) {
- descriptorIndex = heap->currentDescriptorIndex;
- heap->currentDescriptorIndex += 1;
- } else {
- cpuDescriptor->cpuHandleIndex = SDL_MAX_UINT32;
- cpuDescriptor->cpuHandle.ptr = 0;
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Out of CPU descriptor handles, many bad things are going to happen!");
- SDL_UnlockMutex(renderer->stagingDescriptorHeapLock);
- return;
- }
- SDL_UnlockMutex(renderer->stagingDescriptorHeapLock);
- cpuDescriptor->cpuHandleIndex = descriptorIndex;
- cpuDescriptor->cpuHandle.ptr = heap->descriptorHeapCPUStart.ptr + (descriptorIndex * heap->descriptorSize);
- }
- static SDL_GPUGraphicsPipeline *D3D12_CreateGraphicsPipeline(
- SDL_GPURenderer *driverData,
- const SDL_GPUGraphicsPipelineCreateInfo *createinfo)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12Shader *vertShader = (D3D12Shader *)createinfo->vertex_shader;
- D3D12Shader *fragShader = (D3D12Shader *)createinfo->fragment_shader;
- D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
- SDL_zero(psoDesc);
- psoDesc.VS.pShaderBytecode = vertShader->bytecode;
- psoDesc.VS.BytecodeLength = vertShader->bytecodeSize;
- psoDesc.PS.pShaderBytecode = fragShader->bytecode;
- psoDesc.PS.BytecodeLength = fragShader->bytecodeSize;
- D3D12_INPUT_ELEMENT_DESC inputElementDescs[D3D12_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
- if (createinfo->vertex_input_state.num_vertex_attributes > 0) {
- psoDesc.InputLayout.pInputElementDescs = inputElementDescs;
- psoDesc.InputLayout.NumElements = createinfo->vertex_input_state.num_vertex_attributes;
- D3D12_INTERNAL_ConvertVertexInputState(createinfo->vertex_input_state, inputElementDescs, renderer->semantic);
- }
- psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
- if (!D3D12_INTERNAL_ConvertRasterizerState(createinfo->rasterizer_state, &psoDesc.RasterizerState)) {
- return NULL;
- }
- if (!D3D12_INTERNAL_ConvertBlendState(createinfo, &psoDesc.BlendState)) {
- return NULL;
- }
- if (!D3D12_INTERNAL_ConvertDepthStencilState(createinfo->depth_stencil_state, &psoDesc.DepthStencilState)) {
- return NULL;
- }
- D3D12GraphicsPipeline *pipeline = (D3D12GraphicsPipeline *)SDL_calloc(1, sizeof(D3D12GraphicsPipeline));
- if (!pipeline) {
- return NULL;
- }
- Uint32 sampleMask = createinfo->multisample_state.enable_mask ?
- createinfo->multisample_state.sample_mask :
- 0xFFFFFFFF;
- psoDesc.SampleMask = sampleMask;
- psoDesc.SampleDesc.Count = SDLToD3D12_SampleCount[createinfo->multisample_state.sample_count];
- psoDesc.SampleDesc.Quality = (createinfo->multisample_state.sample_count > SDL_GPU_SAMPLECOUNT_1) ? D3D12_STANDARD_MULTISAMPLE_PATTERN : 0;
- psoDesc.DSVFormat = SDLToD3D12_DepthFormat[createinfo->target_info.depth_stencil_format];
- psoDesc.NumRenderTargets = createinfo->target_info.num_color_targets;
- for (uint32_t i = 0; i < createinfo->target_info.num_color_targets; i += 1) {
- psoDesc.RTVFormats[i] = SDLToD3D12_TextureFormat[createinfo->target_info.color_target_descriptions[i].format];
- }
- // Assuming some default values or further initialization
- psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
- psoDesc.CachedPSO.CachedBlobSizeInBytes = 0;
- psoDesc.CachedPSO.pCachedBlob = NULL;
- psoDesc.NodeMask = 0;
- D3D12GraphicsRootSignature *rootSignature = D3D12_INTERNAL_CreateGraphicsRootSignature(
- renderer,
- vertShader,
- fragShader);
- if (rootSignature == NULL) {
- D3D12_INTERNAL_DestroyGraphicsPipeline(pipeline);
- return NULL;
- }
- pipeline->rootSignature = rootSignature;
- psoDesc.pRootSignature = rootSignature->handle;
- ID3D12PipelineState *pipelineState;
- HRESULT res = ID3D12Device_CreateGraphicsPipelineState(
- renderer->device,
- &psoDesc,
- D3D_GUID(D3D_IID_ID3D12PipelineState),
- (void **)&pipelineState);
- if (FAILED(res)) {
- D3D12_INTERNAL_SetError(renderer, "Could not create graphics pipeline state", res);
- D3D12_INTERNAL_DestroyGraphicsPipeline(pipeline);
- return NULL;
- }
- pipeline->pipelineState = pipelineState;
- for (Uint32 i = 0; i < createinfo->vertex_input_state.num_vertex_buffers; i += 1) {
- pipeline->vertexStrides[createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot] =
- createinfo->vertex_input_state.vertex_buffer_descriptions[i].pitch;
- }
- pipeline->primitiveType = createinfo->primitive_type;
- pipeline->vertexSamplerCount = vertShader->num_samplers;
- pipeline->vertexStorageTextureCount = vertShader->numStorageTextures;
- pipeline->vertexStorageBufferCount = vertShader->numStorageBuffers;
- pipeline->vertexUniformBufferCount = vertShader->numUniformBuffers;
- pipeline->fragmentSamplerCount = fragShader->num_samplers;
- pipeline->fragmentStorageTextureCount = fragShader->numStorageTextures;
- pipeline->fragmentStorageBufferCount = fragShader->numStorageBuffers;
- pipeline->fragmentUniformBufferCount = fragShader->numUniformBuffers;
- SDL_SetAtomicInt(&pipeline->referenceCount, 0);
- return (SDL_GPUGraphicsPipeline *)pipeline;
- }
- static SDL_GPUSampler *D3D12_CreateSampler(
- SDL_GPURenderer *driverData,
- const SDL_GPUSamplerCreateInfo *createinfo)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12Sampler *sampler = (D3D12Sampler *)SDL_calloc(1, sizeof(D3D12Sampler));
- if (!sampler) {
- return NULL;
- }
- D3D12_SAMPLER_DESC samplerDesc;
- samplerDesc.Filter = SDLToD3D12_Filter(
- createinfo->min_filter,
- createinfo->mag_filter,
- createinfo->mipmap_mode,
- createinfo->enable_compare,
- createinfo->enable_anisotropy);
- samplerDesc.AddressU = SDLToD3D12_SamplerAddressMode[createinfo->address_mode_u];
- samplerDesc.AddressV = SDLToD3D12_SamplerAddressMode[createinfo->address_mode_v];
- samplerDesc.AddressW = SDLToD3D12_SamplerAddressMode[createinfo->address_mode_w];
- samplerDesc.MaxAnisotropy = (Uint32)createinfo->max_anisotropy;
- samplerDesc.ComparisonFunc = SDLToD3D12_CompareOp[createinfo->compare_op];
- samplerDesc.MinLOD = createinfo->min_lod;
- samplerDesc.MaxLOD = createinfo->max_lod;
- samplerDesc.MipLODBias = createinfo->mip_lod_bias;
- samplerDesc.BorderColor[0] = 0;
- samplerDesc.BorderColor[1] = 0;
- samplerDesc.BorderColor[2] = 0;
- samplerDesc.BorderColor[3] = 0;
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
- &sampler->handle);
- ID3D12Device_CreateSampler(
- renderer->device,
- &samplerDesc,
- sampler->handle.cpuHandle);
- sampler->createInfo = *createinfo;
- SDL_SetAtomicInt(&sampler->referenceCount, 0);
- return (SDL_GPUSampler *)sampler;
- }
- static SDL_GPUShader *D3D12_CreateShader(
- SDL_GPURenderer *driverData,
- const SDL_GPUShaderCreateInfo *createinfo)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- void *bytecode;
- size_t bytecodeSize;
- D3D12Shader *shader;
- if (!D3D12_INTERNAL_CreateShaderBytecode(
- renderer,
- createinfo->stage,
- createinfo->format,
- createinfo->code,
- createinfo->code_size,
- createinfo->entrypoint,
- &bytecode,
- &bytecodeSize)) {
- return NULL;
- }
- shader = (D3D12Shader *)SDL_calloc(1, sizeof(D3D12Shader));
- if (!shader) {
- SDL_free(bytecode);
- return NULL;
- }
- shader->num_samplers = createinfo->num_samplers;
- shader->numStorageBuffers = createinfo->num_storage_buffers;
- shader->numStorageTextures = createinfo->num_storage_textures;
- shader->numUniformBuffers = createinfo->num_uniform_buffers;
- shader->bytecode = bytecode;
- shader->bytecodeSize = bytecodeSize;
- return (SDL_GPUShader *)shader;
- }
- static D3D12Texture *D3D12_INTERNAL_CreateTexture(
- D3D12Renderer *renderer,
- const SDL_GPUTextureCreateInfo *createinfo,
- bool isSwapchainTexture)
- {
- D3D12Texture *texture;
- ID3D12Resource *handle;
- D3D12_HEAP_PROPERTIES heapProperties;
- D3D12_HEAP_FLAGS heapFlags = (D3D12_HEAP_FLAGS)0;
- D3D12_RESOURCE_DESC desc;
- D3D12_RESOURCE_FLAGS resourceFlags = (D3D12_RESOURCE_FLAGS)0;
- D3D12_RESOURCE_STATES initialState = (D3D12_RESOURCE_STATES)0;
- D3D12_CLEAR_VALUE clearValue;
- DXGI_FORMAT format;
- bool useClearValue = false;
- bool needsUAV =
- (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) ||
- (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE);
- HRESULT res;
- texture = (D3D12Texture *)SDL_calloc(1, sizeof(D3D12Texture));
- if (!texture) {
- return NULL;
- }
- 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;
- bool isMultisample = createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1;
- format = SDLToD3D12_TextureFormat[createinfo->format];
- if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
- resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
- useClearValue = true;
- clearValue.Color[0] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_R_FLOAT, 0);
- clearValue.Color[1] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_G_FLOAT, 0);
- clearValue.Color[2] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_B_FLOAT, 0);
- clearValue.Color[3] = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_A_FLOAT, 0);
- }
- if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
- resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
- useClearValue = true;
- clearValue.DepthStencil.Depth = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_DEPTH_FLOAT, 0);
- clearValue.DepthStencil.Stencil = (UINT8)SDL_GetNumberProperty(createinfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_STENCIL_UINT8, 0);
- format = SDLToD3D12_DepthFormat[createinfo->format];
- }
- if (needsUAV) {
- resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
- }
- heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProperties.CreationNodeMask = 0; // We don't do multi-adapter operation
- heapProperties.VisibleNodeMask = 0; // We don't do multi-adapter operation
- heapFlags = isSwapchainTexture ? D3D12_HEAP_FLAG_ALLOW_DISPLAY : D3D12_HEAP_FLAG_NONE;
- if (createinfo->type != SDL_GPU_TEXTURETYPE_3D) {
- desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- desc.Alignment = isSwapchainTexture ? 0 : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
- desc.Width = createinfo->width;
- desc.Height = createinfo->height;
- desc.DepthOrArraySize = (UINT16)createinfo->layer_count_or_depth;
- desc.MipLevels = (UINT16)createinfo->num_levels;
- desc.Format = format;
- desc.SampleDesc.Count = SDLToD3D12_SampleCount[createinfo->sample_count];
- desc.SampleDesc.Quality = isMultisample ? D3D12_STANDARD_MULTISAMPLE_PATTERN : 0;
- desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // Apparently this is the most efficient choice
- desc.Flags = resourceFlags;
- } else {
- desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
- desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
- desc.Width = createinfo->width;
- desc.Height = createinfo->height;
- desc.DepthOrArraySize = (UINT16)createinfo->layer_count_or_depth;
- desc.MipLevels = (UINT16)createinfo->num_levels;
- desc.Format = format;
- desc.SampleDesc.Count = 1;
- desc.SampleDesc.Quality = 0;
- desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
- desc.Flags = resourceFlags;
- }
- initialState = isSwapchainTexture ? D3D12_RESOURCE_STATE_PRESENT : D3D12_INTERNAL_DefaultTextureResourceState(createinfo->usage);
- clearValue.Format = desc.Format;
- res = ID3D12Device_CreateCommittedResource(
- renderer->device,
- &heapProperties,
- heapFlags,
- &desc,
- initialState,
- useClearValue ? &clearValue : NULL,
- D3D_GUID(D3D_IID_ID3D12Resource),
- (void **)&handle);
- if (FAILED(res)) {
- D3D12_INTERNAL_SetError(renderer, "Failed to create texture!", res);
- D3D12_INTERNAL_DestroyTexture(renderer, texture);
- return NULL;
- }
- texture->resource = handle;
- // Create the SRV if applicable
- if ((createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) ||
- (createinfo->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) ||
- (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)) {
- D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- &texture->srvHandle);
- srvDesc.Format = SDLToD3D12_TextureFormat[createinfo->format];
- srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
- if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
- srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
- srvDesc.TextureCube.MipLevels = createinfo->num_levels;
- srvDesc.TextureCube.MostDetailedMip = 0;
- srvDesc.TextureCube.ResourceMinLODClamp = 0;
- } else if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
- srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
- srvDesc.TextureCubeArray.MipLevels = createinfo->num_levels;
- srvDesc.TextureCubeArray.MostDetailedMip = 0;
- srvDesc.TextureCubeArray.First2DArrayFace = 0;
- srvDesc.TextureCubeArray.NumCubes = createinfo->layer_count_or_depth / 6;
- srvDesc.TextureCubeArray.ResourceMinLODClamp = 0;
- } else if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
- srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
- srvDesc.Texture2DArray.MipLevels = createinfo->num_levels;
- srvDesc.Texture2DArray.MostDetailedMip = 0;
- srvDesc.Texture2DArray.FirstArraySlice = 0;
- srvDesc.Texture2DArray.ArraySize = layerCount;
- srvDesc.Texture2DArray.ResourceMinLODClamp = 0;
- srvDesc.Texture2DArray.PlaneSlice = 0;
- } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
- srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
- srvDesc.Texture3D.MipLevels = createinfo->num_levels;
- srvDesc.Texture3D.MostDetailedMip = 0;
- srvDesc.Texture3D.ResourceMinLODClamp = 0; // default behavior
- } else {
- srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
- srvDesc.Texture2D.MipLevels = createinfo->num_levels;
- srvDesc.Texture2D.MostDetailedMip = 0;
- srvDesc.Texture2D.PlaneSlice = 0;
- srvDesc.Texture2D.ResourceMinLODClamp = 0; // default behavior
- }
- ID3D12Device_CreateShaderResourceView(
- renderer->device,
- handle,
- &srvDesc,
- texture->srvHandle.cpuHandle);
- }
- SDL_SetAtomicInt(&texture->referenceCount, 0);
- texture->subresourceCount = createinfo->num_levels * layerCount;
- texture->subresources = (D3D12TextureSubresource *)SDL_calloc(
- texture->subresourceCount, sizeof(D3D12TextureSubresource));
- if (!texture->subresources) {
- D3D12_INTERNAL_DestroyTexture(renderer, texture);
- return NULL;
- }
- for (Uint32 layerIndex = 0; layerIndex < layerCount; layerIndex += 1) {
- for (Uint32 levelIndex = 0; levelIndex < createinfo->num_levels; levelIndex += 1) {
- Uint32 subresourceIndex = D3D12_INTERNAL_CalcSubresource(
- levelIndex,
- layerIndex,
- createinfo->num_levels);
- texture->subresources[subresourceIndex].parent = texture;
- texture->subresources[subresourceIndex].layer = layerIndex;
- texture->subresources[subresourceIndex].level = levelIndex;
- texture->subresources[subresourceIndex].depth = depth;
- texture->subresources[subresourceIndex].index = subresourceIndex;
- texture->subresources[subresourceIndex].rtvHandles = NULL;
- texture->subresources[subresourceIndex].uavHandle.heap = NULL;
- texture->subresources[subresourceIndex].dsvHandle.heap = NULL;
- // Create RTV if needed
- if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
- texture->subresources[subresourceIndex].rtvHandles = (D3D12CPUDescriptor *)SDL_calloc(depth, sizeof(D3D12CPUDescriptor));
- for (Uint32 depthIndex = 0; depthIndex < depth; depthIndex += 1) {
- D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
- &texture->subresources[subresourceIndex].rtvHandles[depthIndex]);
- rtvDesc.Format = SDLToD3D12_TextureFormat[createinfo->format];
- if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
- rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
- rtvDesc.Texture2DArray.MipSlice = levelIndex;
- rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
- rtvDesc.Texture2DArray.ArraySize = 1;
- rtvDesc.Texture2DArray.PlaneSlice = 0;
- } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
- rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
- rtvDesc.Texture3D.MipSlice = levelIndex;
- rtvDesc.Texture3D.FirstWSlice = depthIndex;
- rtvDesc.Texture3D.WSize = 1;
- } else if (isMultisample) {
- rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
- } else {
- rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
- rtvDesc.Texture2D.MipSlice = levelIndex;
- rtvDesc.Texture2D.PlaneSlice = 0;
- }
- ID3D12Device_CreateRenderTargetView(
- renderer->device,
- texture->resource,
- &rtvDesc,
- texture->subresources[subresourceIndex].rtvHandles[depthIndex].cpuHandle);
- }
- }
- // Create DSV if needed
- if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) {
- D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
- &texture->subresources[subresourceIndex].dsvHandle);
- dsvDesc.Format = SDLToD3D12_DepthFormat[createinfo->format];
- dsvDesc.Flags = (D3D12_DSV_FLAGS)0;
- if (isMultisample) {
- dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS;
- } else {
- dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
- dsvDesc.Texture2D.MipSlice = levelIndex;
- }
- ID3D12Device_CreateDepthStencilView(
- renderer->device,
- texture->resource,
- &dsvDesc,
- texture->subresources[subresourceIndex].dsvHandle.cpuHandle);
- }
- // Create subresource UAV if necessary
- if (needsUAV) {
- D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc;
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- &texture->subresources[subresourceIndex].uavHandle);
- uavDesc.Format = SDLToD3D12_TextureFormat[createinfo->format];
- if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
- uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
- uavDesc.Texture2DArray.MipSlice = levelIndex;
- uavDesc.Texture2DArray.FirstArraySlice = layerIndex;
- uavDesc.Texture2DArray.ArraySize = 1;
- } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
- uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
- uavDesc.Texture3D.MipSlice = levelIndex;
- uavDesc.Texture3D.FirstWSlice = 0;
- uavDesc.Texture3D.WSize = depth;
- } else {
- uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
- uavDesc.Texture2D.MipSlice = levelIndex;
- uavDesc.Texture2D.PlaneSlice = 0;
- }
- ID3D12Device_CreateUnorderedAccessView(
- renderer->device,
- texture->resource,
- NULL,
- &uavDesc,
- texture->subresources[subresourceIndex].uavHandle.cpuHandle);
- }
- }
- }
- return texture;
- }
- static SDL_GPUTexture *D3D12_CreateTexture(
- SDL_GPURenderer *driverData,
- const SDL_GPUTextureCreateInfo *createinfo)
- {
- D3D12TextureContainer *container = (D3D12TextureContainer *)SDL_calloc(1, sizeof(D3D12TextureContainer));
- if (!container) {
- return NULL;
- }
- container->header.info = *createinfo;
- container->textureCapacity = 1;
- container->textureCount = 1;
- container->textures = (D3D12Texture **)SDL_calloc(
- container->textureCapacity, sizeof(D3D12Texture *));
- if (!container->textures) {
- SDL_free(container);
- return NULL;
- }
- container->debugName = NULL;
- container->canBeCycled = true;
- D3D12Texture *texture = D3D12_INTERNAL_CreateTexture(
- (D3D12Renderer *)driverData,
- createinfo,
- false);
- if (!texture) {
- SDL_free(container->textures);
- SDL_free(container);
- return NULL;
- }
- container->textures[0] = texture;
- container->activeTexture = texture;
- texture->container = container;
- texture->containerIndex = 0;
- return (SDL_GPUTexture *)container;
- }
- static D3D12Buffer *D3D12_INTERNAL_CreateBuffer(
- D3D12Renderer *renderer,
- SDL_GPUBufferUsageFlags usageFlags,
- Uint32 size,
- D3D12BufferType type)
- {
- D3D12Buffer *buffer;
- ID3D12Resource *handle;
- D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc;
- D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
- D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc;
- D3D12_HEAP_PROPERTIES heapProperties;
- D3D12_RESOURCE_DESC desc;
- D3D12_HEAP_FLAGS heapFlags = (D3D12_HEAP_FLAGS)0;
- D3D12_RESOURCE_FLAGS resourceFlags = (D3D12_RESOURCE_FLAGS)0;
- D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON;
- HRESULT res;
- buffer = (D3D12Buffer *)SDL_calloc(1, sizeof(D3D12Buffer));
- if (!buffer) {
- return NULL;
- }
- if (usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE) {
- resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
- }
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT) {
- resourceFlags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_INDIRECT_BUFFER;
- }
- #endif
- heapProperties.CreationNodeMask = 0; // We don't do multi-adapter operation
- heapProperties.VisibleNodeMask = 0; // We don't do multi-adapter operation
- if (type == D3D12_BUFFER_TYPE_GPU) {
- heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapFlags = D3D12_HEAP_FLAG_NONE;
- } else if (type == D3D12_BUFFER_TYPE_UPLOAD) {
- heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
- heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapFlags = D3D12_HEAP_FLAG_NONE;
- initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
- } else if (type == D3D12_BUFFER_TYPE_DOWNLOAD) {
- heapProperties.Type = D3D12_HEAP_TYPE_READBACK;
- heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapFlags = D3D12_HEAP_FLAG_NONE;
- initialState = D3D12_RESOURCE_STATE_COPY_DEST;
- } else if (type == D3D12_BUFFER_TYPE_UNIFORM) {
- // D3D12 is badly designed, so we have to check if the fast path for uniform buffers is enabled
- if (renderer->GPUUploadHeapSupported) {
- heapProperties.Type = D3D12_HEAP_TYPE_GPU_UPLOAD;
- heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- } else {
- heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
- heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
- }
- heapFlags = D3D12_HEAP_FLAG_NONE;
- } else {
- SET_STRING_ERROR_AND_RETURN("Unrecognized buffer type!", NULL);
- }
- desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
- desc.Width = size;
- desc.Height = 1;
- desc.DepthOrArraySize = 1;
- desc.MipLevels = 1;
- desc.Format = DXGI_FORMAT_UNKNOWN;
- desc.SampleDesc.Count = 1;
- desc.SampleDesc.Quality = 0;
- desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- desc.Flags = resourceFlags;
- res = ID3D12Device_CreateCommittedResource(
- renderer->device,
- &heapProperties,
- heapFlags,
- &desc,
- initialState,
- NULL,
- D3D_GUID(D3D_IID_ID3D12Resource),
- (void **)&handle);
- if (FAILED(res)) {
- D3D12_INTERNAL_SetError(renderer, "Could not create buffer!", res);
- D3D12_INTERNAL_DestroyBuffer(renderer, buffer);
- return NULL;
- }
- buffer->handle = handle;
- SDL_SetAtomicInt(&buffer->referenceCount, 0);
- buffer->uavDescriptor.heap = NULL;
- buffer->srvDescriptor.heap = NULL;
- buffer->cbvDescriptor.heap = NULL;
- if (usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE) {
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- &buffer->uavDescriptor);
- uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
- uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
- uavDesc.Buffer.FirstElement = 0;
- uavDesc.Buffer.NumElements = size / sizeof(Uint32);
- uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
- uavDesc.Buffer.CounterOffsetInBytes = 0; // TODO: support counters?
- uavDesc.Buffer.StructureByteStride = 0;
- // Create UAV
- ID3D12Device_CreateUnorderedAccessView(
- renderer->device,
- handle,
- NULL, // TODO: support counters?
- &uavDesc,
- buffer->uavDescriptor.cpuHandle);
- }
- if (
- (usageFlags & SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ) ||
- (usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ)) {
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- &buffer->srvDescriptor);
- srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
- srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
- srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
- srvDesc.Buffer.FirstElement = 0;
- srvDesc.Buffer.NumElements = size / sizeof(Uint32);
- srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
- srvDesc.Buffer.StructureByteStride = 0;
- // Create SRV
- ID3D12Device_CreateShaderResourceView(
- renderer->device,
- handle,
- &srvDesc,
- buffer->srvDescriptor.cpuHandle);
- }
- // FIXME: we may not need a CBV since we use root descriptors
- if (type == D3D12_BUFFER_TYPE_UNIFORM) {
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- &buffer->cbvDescriptor);
- cbvDesc.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(handle);
- cbvDesc.SizeInBytes = size;
- // Create CBV
- ID3D12Device_CreateConstantBufferView(
- renderer->device,
- &cbvDesc,
- buffer->cbvDescriptor.cpuHandle);
- }
- buffer->virtualAddress = 0;
- if (type == D3D12_BUFFER_TYPE_GPU || type == D3D12_BUFFER_TYPE_UNIFORM) {
- buffer->virtualAddress = ID3D12Resource_GetGPUVirtualAddress(buffer->handle);
- }
- buffer->mapPointer = NULL;
- // Persistently map upload buffers
- if (type == D3D12_BUFFER_TYPE_UPLOAD) {
- res = ID3D12Resource_Map(
- buffer->handle,
- 0,
- NULL,
- (void **)&buffer->mapPointer);
- if (FAILED(res)) {
- D3D12_INTERNAL_SetError(renderer, "Failed to map upload buffer!", res);
- D3D12_INTERNAL_DestroyBuffer(renderer, buffer);
- return NULL;
- }
- }
- buffer->container = NULL;
- buffer->containerIndex = 0;
- buffer->transitioned = initialState != D3D12_RESOURCE_STATE_COMMON;
- SDL_SetAtomicInt(&buffer->referenceCount, 0);
- return buffer;
- }
- static D3D12BufferContainer *D3D12_INTERNAL_CreateBufferContainer(
- D3D12Renderer *renderer,
- SDL_GPUBufferUsageFlags usageFlags,
- Uint32 size,
- D3D12BufferType type)
- {
- D3D12BufferContainer *container;
- D3D12Buffer *buffer;
- container = (D3D12BufferContainer *)SDL_calloc(1, sizeof(D3D12BufferContainer));
- if (!container) {
- return NULL;
- }
- container->usage = usageFlags;
- container->size = size;
- container->type = type;
- container->bufferCapacity = 1;
- container->bufferCount = 1;
- container->buffers = (D3D12Buffer **)SDL_calloc(
- container->bufferCapacity, sizeof(D3D12Buffer *));
- if (!container->buffers) {
- SDL_free(container);
- return NULL;
- }
- container->debugName = NULL;
- buffer = D3D12_INTERNAL_CreateBuffer(
- renderer,
- usageFlags,
- size,
- type);
- if (buffer == NULL) {
- SDL_free(container->buffers);
- SDL_free(container);
- return NULL;
- }
- container->activeBuffer = buffer;
- container->buffers[0] = buffer;
- buffer->container = container;
- buffer->containerIndex = 0;
- return container;
- }
- static SDL_GPUBuffer *D3D12_CreateBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUBufferUsageFlags usageFlags,
- Uint32 size)
- {
- return (SDL_GPUBuffer *)D3D12_INTERNAL_CreateBufferContainer(
- (D3D12Renderer *)driverData,
- usageFlags,
- size,
- D3D12_BUFFER_TYPE_GPU);
- }
- static SDL_GPUTransferBuffer *D3D12_CreateTransferBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUTransferBufferUsage usage,
- Uint32 size)
- {
- return (SDL_GPUTransferBuffer *)D3D12_INTERNAL_CreateBufferContainer(
- (D3D12Renderer *)driverData,
- 0,
- size,
- usage == SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD ? D3D12_BUFFER_TYPE_UPLOAD : D3D12_BUFFER_TYPE_DOWNLOAD);
- }
- // Debug Naming
- static void D3D12_SetBufferName(
- SDL_GPURenderer *driverData,
- SDL_GPUBuffer *buffer,
- const char *text)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12BufferContainer *container = (D3D12BufferContainer *)buffer;
- size_t textLength = SDL_strlen(text) + 1;
- if (renderer->debug_mode) {
- container->debugName = (char *)SDL_realloc(
- container->debugName,
- textLength);
- SDL_utf8strlcpy(
- container->debugName,
- text,
- textLength);
- for (Uint32 i = 0; i < container->bufferCount; i += 1) {
- D3D12_INTERNAL_SetResourceName(
- renderer,
- container->buffers[i]->handle,
- text);
- }
- }
- }
- static void D3D12_SetTextureName(
- SDL_GPURenderer *driverData,
- SDL_GPUTexture *texture,
- const char *text)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12TextureContainer *container = (D3D12TextureContainer *)texture;
- size_t textLength = SDL_strlen(text) + 1;
- if (renderer->debug_mode) {
- container->debugName = (char *)SDL_realloc(
- container->debugName,
- textLength);
- SDL_utf8strlcpy(
- container->debugName,
- text,
- textLength);
- for (Uint32 i = 0; i < container->textureCount; i += 1) {
- D3D12_INTERNAL_SetResourceName(
- renderer,
- container->textures[i]->resource,
- text);
- }
- }
- }
- /* These debug functions are all marked as "for internal usage only"
- * on D3D12... works on renderdoc!
- */
- static bool D3D12_INTERNAL_StrToWStr(
- D3D12Renderer *renderer,
- const char *str,
- wchar_t *wstr,
- size_t wstrSize,
- Uint32 *outSize)
- {
- size_t inlen, result;
- size_t outBytesLeft = wstrSize;
- *outSize = 0;
- if (renderer->iconv == NULL) {
- renderer->iconv = SDL_iconv_open("WCHAR_T", "UTF-8");
- SDL_assert(renderer->iconv);
- }
- // Convert...
- inlen = SDL_strlen(str) + 1;
- result = SDL_iconv(
- renderer->iconv,
- &str,
- &inlen,
- (char **)&wstr,
- &outBytesLeft);
- // Check...
- switch (result) {
- case SDL_ICONV_ERROR:
- case SDL_ICONV_E2BIG:
- case SDL_ICONV_EILSEQ:
- case SDL_ICONV_EINVAL:
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to convert string to wchar_t!");
- return false;
- default:
- break;
- }
- *outSize = (Uint32)(wstrSize - outBytesLeft);
- return true;
- }
- static void D3D12_InsertDebugLabel(
- SDL_GPUCommandBuffer *commandBuffer,
- const char *text)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- wchar_t wstr[256];
- Uint32 convSize;
- if (!D3D12_INTERNAL_StrToWStr(
- d3d12CommandBuffer->renderer,
- text,
- wstr,
- sizeof(wstr),
- &convSize)) {
- return;
- }
- ID3D12GraphicsCommandList_SetMarker(
- d3d12CommandBuffer->graphicsCommandList,
- 0,
- wstr,
- convSize);
- }
- static void D3D12_PushDebugGroup(
- SDL_GPUCommandBuffer *commandBuffer,
- const char *name)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- wchar_t wstr[256];
- Uint32 convSize;
- if (!D3D12_INTERNAL_StrToWStr(
- d3d12CommandBuffer->renderer,
- name,
- wstr,
- sizeof(wstr),
- &convSize)) {
- return;
- }
- ID3D12GraphicsCommandList_BeginEvent(
- d3d12CommandBuffer->graphicsCommandList,
- 0,
- wstr,
- convSize);
- }
- static void D3D12_PopDebugGroup(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- ID3D12GraphicsCommandList_EndEvent(d3d12CommandBuffer->graphicsCommandList);
- }
- // Disposal
- static void D3D12_ReleaseTexture(
- SDL_GPURenderer *driverData,
- SDL_GPUTexture *texture)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12TextureContainer *container = (D3D12TextureContainer *)texture;
- D3D12_INTERNAL_ReleaseTextureContainer(
- renderer,
- container);
- }
- static void D3D12_ReleaseSampler(
- SDL_GPURenderer *driverData,
- SDL_GPUSampler *sampler)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12Sampler *d3d12Sampler = (D3D12Sampler *)sampler;
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->samplersToDestroy,
- D3D12Sampler *,
- renderer->samplersToDestroyCount + 1,
- renderer->samplersToDestroyCapacity,
- renderer->samplersToDestroyCapacity * 2);
- renderer->samplersToDestroy[renderer->samplersToDestroyCount] = d3d12Sampler;
- renderer->samplersToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void D3D12_ReleaseBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUBuffer *buffer)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12BufferContainer *bufferContainer = (D3D12BufferContainer *)buffer;
- D3D12_INTERNAL_ReleaseBufferContainer(
- renderer,
- bufferContainer);
- }
- static void D3D12_ReleaseTransferBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUTransferBuffer *transferBuffer)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12BufferContainer *transferBufferContainer = (D3D12BufferContainer *)transferBuffer;
- D3D12_INTERNAL_ReleaseBufferContainer(
- renderer,
- transferBufferContainer);
- }
- static void D3D12_ReleaseShader(
- SDL_GPURenderer *driverData,
- SDL_GPUShader *shader)
- {
- /* D3D12Renderer *renderer = (D3D12Renderer *)driverData; */
- D3D12Shader *d3d12shader = (D3D12Shader *)shader;
- if (d3d12shader->bytecode) {
- SDL_free(d3d12shader->bytecode);
- d3d12shader->bytecode = NULL;
- }
- SDL_free(d3d12shader);
- }
- static void D3D12_ReleaseComputePipeline(
- SDL_GPURenderer *driverData,
- SDL_GPUComputePipeline *computePipeline)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12ComputePipeline *d3d12ComputePipeline = (D3D12ComputePipeline *)computePipeline;
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->computePipelinesToDestroy,
- D3D12ComputePipeline *,
- renderer->computePipelinesToDestroyCount + 1,
- renderer->computePipelinesToDestroyCapacity,
- renderer->computePipelinesToDestroyCapacity * 2);
- renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount] = d3d12ComputePipeline;
- renderer->computePipelinesToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void D3D12_ReleaseGraphicsPipeline(
- SDL_GPURenderer *driverData,
- SDL_GPUGraphicsPipeline *graphicsPipeline)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12GraphicsPipeline *d3d12GraphicsPipeline = (D3D12GraphicsPipeline *)graphicsPipeline;
- SDL_LockMutex(renderer->disposeLock);
- EXPAND_ARRAY_IF_NEEDED(
- renderer->graphicsPipelinesToDestroy,
- D3D12GraphicsPipeline *,
- renderer->graphicsPipelinesToDestroyCount + 1,
- renderer->graphicsPipelinesToDestroyCapacity,
- renderer->graphicsPipelinesToDestroyCapacity * 2);
- renderer->graphicsPipelinesToDestroy[renderer->graphicsPipelinesToDestroyCount] = d3d12GraphicsPipeline;
- renderer->graphicsPipelinesToDestroyCount += 1;
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static void D3D12_INTERNAL_ReleaseBlitPipelines(SDL_GPURenderer *driverData)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12_ReleaseSampler(driverData, renderer->blitLinearSampler);
- D3D12_ReleaseSampler(driverData, renderer->blitNearestSampler);
- D3D12_ReleaseShader(driverData, renderer->blitVertexShader);
- D3D12_ReleaseShader(driverData, renderer->blitFrom2DShader);
- D3D12_ReleaseShader(driverData, renderer->blitFrom2DArrayShader);
- D3D12_ReleaseShader(driverData, renderer->blitFrom3DShader);
- D3D12_ReleaseShader(driverData, renderer->blitFromCubeShader);
- D3D12_ReleaseShader(driverData, renderer->blitFromCubeArrayShader);
- for (Uint32 i = 0; i < renderer->blitPipelineCount; i += 1) {
- D3D12_ReleaseGraphicsPipeline(driverData, renderer->blitPipelines[i].pipeline);
- }
- SDL_free(renderer->blitPipelines);
- }
- // Render Pass
- static void D3D12_SetViewport(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUViewport *viewport)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_VIEWPORT d3d12Viewport;
- d3d12Viewport.TopLeftX = viewport->x;
- d3d12Viewport.TopLeftY = viewport->y;
- d3d12Viewport.Width = viewport->w;
- d3d12Viewport.Height = viewport->h;
- d3d12Viewport.MinDepth = viewport->min_depth;
- d3d12Viewport.MaxDepth = viewport->max_depth;
- ID3D12GraphicsCommandList_RSSetViewports(d3d12CommandBuffer->graphicsCommandList, 1, &d3d12Viewport);
- }
- static void D3D12_SetScissor(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_Rect *scissor)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_RECT scissorRect;
- scissorRect.left = scissor->x;
- scissorRect.top = scissor->y;
- scissorRect.right = scissor->x + scissor->w;
- scissorRect.bottom = scissor->y + scissor->h;
- ID3D12GraphicsCommandList_RSSetScissorRects(d3d12CommandBuffer->graphicsCommandList, 1, &scissorRect);
- }
- static void D3D12_SetBlendConstants(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_FColor blendConstants)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- FLOAT blendFactor[4] = { blendConstants.r, blendConstants.g, blendConstants.b, blendConstants.a };
- ID3D12GraphicsCommandList_OMSetBlendFactor(d3d12CommandBuffer->graphicsCommandList, blendFactor);
- }
- static void D3D12_SetStencilReference(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint8 reference
- ) {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- ID3D12GraphicsCommandList_OMSetStencilRef(d3d12CommandBuffer->graphicsCommandList, reference);
- }
- static D3D12TextureSubresource *D3D12_INTERNAL_FetchTextureSubresource(
- D3D12TextureContainer *container,
- Uint32 layer,
- Uint32 level)
- {
- Uint32 index = D3D12_INTERNAL_CalcSubresource(
- level,
- layer,
- container->header.info.num_levels);
- return &container->activeTexture->subresources[index];
- }
- static void D3D12_INTERNAL_CycleActiveTexture(
- D3D12Renderer *renderer,
- D3D12TextureContainer *container)
- {
- D3D12Texture *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 = D3D12_INTERNAL_CreateTexture(
- renderer,
- &container->header.info,
- false);
- if (!texture) {
- return;
- }
- EXPAND_ARRAY_IF_NEEDED(
- container->textures,
- D3D12Texture *,
- 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->debug_mode && container->debugName != NULL) {
- D3D12_INTERNAL_SetResourceName(
- renderer,
- container->activeTexture->resource,
- container->debugName);
- }
- }
- static D3D12TextureSubresource *D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
- D3D12CommandBuffer *commandBuffer,
- D3D12TextureContainer *container,
- Uint32 layer,
- Uint32 level,
- bool cycle,
- D3D12_RESOURCE_STATES destinationUsageMode)
- {
- D3D12TextureSubresource *subresource = D3D12_INTERNAL_FetchTextureSubresource(
- container,
- layer,
- level);
- if (
- container->canBeCycled &&
- cycle &&
- SDL_GetAtomicInt(&subresource->parent->referenceCount) > 0) {
- D3D12_INTERNAL_CycleActiveTexture(
- commandBuffer->renderer,
- container);
- subresource = D3D12_INTERNAL_FetchTextureSubresource(
- container,
- layer,
- level);
- }
- D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- commandBuffer,
- destinationUsageMode,
- subresource);
- return subresource;
- }
- static void D3D12_INTERNAL_CycleActiveBuffer(
- D3D12Renderer *renderer,
- D3D12BufferContainer *container)
- {
- // If a previously-cycled buffer is available, we can use that.
- for (Uint32 i = 0; i < container->bufferCount; i += 1) {
- D3D12Buffer *buffer = container->buffers[i];
- if (SDL_GetAtomicInt(&buffer->referenceCount) == 0) {
- container->activeBuffer = buffer;
- return;
- }
- }
- // No buffer handle is available, create a new one.
- D3D12Buffer *buffer = D3D12_INTERNAL_CreateBuffer(
- renderer,
- container->usage,
- container->size,
- container->type);
- if (!buffer) {
- return;
- }
- EXPAND_ARRAY_IF_NEEDED(
- container->buffers,
- D3D12Buffer *,
- 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->debug_mode && container->debugName != NULL) {
- D3D12_INTERNAL_SetResourceName(
- renderer,
- container->activeBuffer->handle,
- container->debugName);
- }
- }
- static D3D12Buffer *D3D12_INTERNAL_PrepareBufferForWrite(
- D3D12CommandBuffer *commandBuffer,
- D3D12BufferContainer *container,
- bool cycle,
- D3D12_RESOURCE_STATES destinationState)
- {
- if (
- cycle &&
- SDL_GetAtomicInt(&container->activeBuffer->referenceCount) > 0) {
- D3D12_INTERNAL_CycleActiveBuffer(
- commandBuffer->renderer,
- container);
- }
- D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
- commandBuffer,
- destinationState,
- container->activeBuffer);
- return container->activeBuffer;
- }
- static void D3D12_BeginRenderPass(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUColorTargetInfo *colorTargetInfos,
- Uint32 numColorTargets,
- const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- Uint32 framebufferWidth = SDL_MAX_UINT32;
- Uint32 framebufferHeight = SDL_MAX_UINT32;
- for (Uint32 i = 0; i < numColorTargets; i += 1) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)colorTargetInfos[i].texture;
- Uint32 h = container->header.info.height >> colorTargetInfos[i].mip_level;
- Uint32 w = container->header.info.width >> colorTargetInfos[i].mip_level;
- // The framebuffer cannot be larger than the smallest target.
- if (w < framebufferWidth) {
- framebufferWidth = w;
- }
- if (h < framebufferHeight) {
- framebufferHeight = h;
- }
- }
- if (depthStencilTargetInfo != NULL) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)depthStencilTargetInfo->texture;
- Uint32 h = container->header.info.height;
- Uint32 w = container->header.info.width;
- // The framebuffer cannot be larger than the smallest target.
- if (w < framebufferWidth) {
- framebufferWidth = w;
- }
- if (h < framebufferHeight) {
- framebufferHeight = h;
- }
- }
- D3D12_CPU_DESCRIPTOR_HANDLE rtvs[MAX_COLOR_TARGET_BINDINGS];
- for (Uint32 i = 0; i < numColorTargets; i += 1) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)colorTargetInfos[i].texture;
- D3D12TextureSubresource *subresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
- d3d12CommandBuffer,
- container,
- container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorTargetInfos[i].layer_or_depth_plane,
- colorTargetInfos[i].mip_level,
- colorTargetInfos[i].cycle,
- D3D12_RESOURCE_STATE_RENDER_TARGET);
- Uint32 rtvIndex = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0;
- D3D12_CPU_DESCRIPTOR_HANDLE rtv = subresource->rtvHandles[rtvIndex].cpuHandle;
- if (colorTargetInfos[i].load_op == SDL_GPU_LOADOP_CLEAR) {
- float clearColor[4];
- clearColor[0] = colorTargetInfos[i].clear_color.r;
- clearColor[1] = colorTargetInfos[i].clear_color.g;
- clearColor[2] = colorTargetInfos[i].clear_color.b;
- clearColor[3] = colorTargetInfos[i].clear_color.a;
- ID3D12GraphicsCommandList_ClearRenderTargetView(
- d3d12CommandBuffer->graphicsCommandList,
- rtv,
- clearColor,
- 0,
- NULL);
- }
- rtvs[i] = rtv;
- d3d12CommandBuffer->colorTargetSubresources[i] = subresource;
- D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, subresource->parent);
- if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
- D3D12TextureContainer *resolveContainer = (D3D12TextureContainer *)colorTargetInfos[i].resolve_texture;
- D3D12TextureSubresource *resolveSubresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
- d3d12CommandBuffer,
- resolveContainer,
- colorTargetInfos[i].resolve_layer,
- colorTargetInfos[i].resolve_mip_level,
- colorTargetInfos[i].cycle_resolve_texture,
- D3D12_RESOURCE_STATE_RESOLVE_DEST);
- d3d12CommandBuffer->colorResolveSubresources[i] = resolveSubresource;
- D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, resolveSubresource->parent);
- }
- }
- D3D12_CPU_DESCRIPTOR_HANDLE dsv;
- if (depthStencilTargetInfo != NULL) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)depthStencilTargetInfo->texture;
- D3D12TextureSubresource *subresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
- d3d12CommandBuffer,
- container,
- 0,
- 0,
- depthStencilTargetInfo->cycle,
- D3D12_RESOURCE_STATE_DEPTH_WRITE);
- if (
- depthStencilTargetInfo->load_op == SDL_GPU_LOADOP_CLEAR ||
- depthStencilTargetInfo->stencil_load_op == SDL_GPU_LOADOP_CLEAR) {
- D3D12_CLEAR_FLAGS clearFlags = (D3D12_CLEAR_FLAGS)0;
- if (depthStencilTargetInfo->load_op == SDL_GPU_LOADOP_CLEAR) {
- clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
- }
- if (depthStencilTargetInfo->stencil_load_op == SDL_GPU_LOADOP_CLEAR) {
- clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
- }
- ID3D12GraphicsCommandList_ClearDepthStencilView(
- d3d12CommandBuffer->graphicsCommandList,
- subresource->dsvHandle.cpuHandle,
- clearFlags,
- depthStencilTargetInfo->clear_depth,
- depthStencilTargetInfo->clear_stencil,
- 0,
- NULL);
- }
- dsv = subresource->dsvHandle.cpuHandle;
- d3d12CommandBuffer->depthStencilTextureSubresource = subresource;
- D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, subresource->parent);
- }
- ID3D12GraphicsCommandList_OMSetRenderTargets(
- d3d12CommandBuffer->graphicsCommandList,
- numColorTargets,
- rtvs,
- false,
- (depthStencilTargetInfo == NULL) ? NULL : &dsv);
- // Set sensible default states
- SDL_GPUViewport defaultViewport;
- defaultViewport.x = 0;
- defaultViewport.y = 0;
- defaultViewport.w = (float)framebufferWidth;
- defaultViewport.h = (float)framebufferHeight;
- defaultViewport.min_depth = 0;
- defaultViewport.max_depth = 1;
- D3D12_SetViewport(
- commandBuffer,
- &defaultViewport);
- SDL_Rect defaultScissor;
- defaultScissor.x = 0;
- defaultScissor.y = 0;
- defaultScissor.w = (Sint32)framebufferWidth;
- defaultScissor.h = (Sint32)framebufferHeight;
- D3D12_SetScissor(
- commandBuffer,
- &defaultScissor);
- D3D12_SetStencilReference(
- commandBuffer,
- 0);
- SDL_FColor blendConstants;
- blendConstants.r = 1.0f;
- blendConstants.g = 1.0f;
- blendConstants.b = 1.0f;
- blendConstants.a = 1.0f;
- D3D12_SetBlendConstants(
- commandBuffer,
- blendConstants);
- }
- static void D3D12_INTERNAL_TrackUniformBuffer(
- D3D12CommandBuffer *commandBuffer,
- D3D12UniformBuffer *uniformBuffer)
- {
- Uint32 i;
- for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
- if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) {
- return;
- }
- }
- if (commandBuffer->usedUniformBufferCount == commandBuffer->usedUniformBufferCapacity) {
- commandBuffer->usedUniformBufferCapacity += 1;
- commandBuffer->usedUniformBuffers = (D3D12UniformBuffer **)SDL_realloc(
- commandBuffer->usedUniformBuffers,
- commandBuffer->usedUniformBufferCapacity * sizeof(D3D12UniformBuffer *));
- }
- commandBuffer->usedUniformBuffers[commandBuffer->usedUniformBufferCount] = uniformBuffer;
- commandBuffer->usedUniformBufferCount += 1;
- D3D12_INTERNAL_TrackBuffer(
- commandBuffer,
- uniformBuffer->buffer);
- }
- static D3D12UniformBuffer *D3D12_INTERNAL_AcquireUniformBufferFromPool(
- D3D12CommandBuffer *commandBuffer)
- {
- D3D12Renderer *renderer = commandBuffer->renderer;
- D3D12UniformBuffer *uniformBuffer;
- SDL_LockMutex(renderer->acquireUniformBufferLock);
- if (renderer->uniformBufferPoolCount > 0) {
- uniformBuffer = renderer->uniformBufferPool[renderer->uniformBufferPoolCount - 1];
- renderer->uniformBufferPoolCount -= 1;
- } else {
- uniformBuffer = (D3D12UniformBuffer *)SDL_calloc(1, sizeof(D3D12UniformBuffer));
- if (!uniformBuffer) {
- SDL_UnlockMutex(renderer->acquireUniformBufferLock);
- return NULL;
- }
- uniformBuffer->buffer = D3D12_INTERNAL_CreateBuffer(
- renderer,
- 0,
- UNIFORM_BUFFER_SIZE,
- D3D12_BUFFER_TYPE_UNIFORM);
- if (!uniformBuffer->buffer) {
- SDL_UnlockMutex(renderer->acquireUniformBufferLock);
- return NULL;
- }
- }
- SDL_UnlockMutex(renderer->acquireUniformBufferLock);
- uniformBuffer->currentBlockSize = 0;
- uniformBuffer->drawOffset = 0;
- uniformBuffer->writeOffset = 0;
- HRESULT res = ID3D12Resource_Map(
- uniformBuffer->buffer->handle,
- 0,
- NULL,
- (void **)&uniformBuffer->buffer->mapPointer);
- CHECK_D3D12_ERROR_AND_RETURN("Failed to map buffer pool!", NULL);
- D3D12_INTERNAL_TrackUniformBuffer(commandBuffer, uniformBuffer);
- return uniformBuffer;
- }
- static void D3D12_INTERNAL_ReturnUniformBufferToPool(
- D3D12Renderer *renderer,
- D3D12UniformBuffer *uniformBuffer)
- {
- if (renderer->uniformBufferPoolCount >= renderer->uniformBufferPoolCapacity) {
- renderer->uniformBufferPoolCapacity *= 2;
- renderer->uniformBufferPool = (D3D12UniformBuffer **)SDL_realloc(
- renderer->uniformBufferPool,
- renderer->uniformBufferPoolCapacity * sizeof(D3D12UniformBuffer *));
- }
- renderer->uniformBufferPool[renderer->uniformBufferPoolCount] = uniformBuffer;
- renderer->uniformBufferPoolCount += 1;
- }
- static void D3D12_INTERNAL_PushUniformData(
- D3D12CommandBuffer *commandBuffer,
- SDL_GPUShaderStage shaderStage,
- Uint32 slotIndex,
- const void *data,
- Uint32 length)
- {
- D3D12UniformBuffer *uniformBuffer;
- if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
- if (commandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
- commandBuffer->vertexUniformBuffers[slotIndex] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
- commandBuffer);
- }
- uniformBuffer = commandBuffer->vertexUniformBuffers[slotIndex];
- } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
- if (commandBuffer->fragmentUniformBuffers[slotIndex] == NULL) {
- commandBuffer->fragmentUniformBuffers[slotIndex] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
- commandBuffer);
- }
- uniformBuffer = commandBuffer->fragmentUniformBuffers[slotIndex];
- } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
- if (commandBuffer->computeUniformBuffers[slotIndex] == NULL) {
- commandBuffer->computeUniformBuffers[slotIndex] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
- commandBuffer);
- }
- uniformBuffer = commandBuffer->computeUniformBuffers[slotIndex];
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
- return;
- }
- uniformBuffer->currentBlockSize =
- D3D12_INTERNAL_Align(
- length,
- 256);
- // If there is no more room, acquire a new uniform buffer
- if (uniformBuffer->writeOffset + uniformBuffer->currentBlockSize >= UNIFORM_BUFFER_SIZE) {
- ID3D12Resource_Unmap(
- uniformBuffer->buffer->handle,
- 0,
- NULL);
- uniformBuffer->buffer->mapPointer = NULL;
- uniformBuffer = D3D12_INTERNAL_AcquireUniformBufferFromPool(commandBuffer);
- uniformBuffer->drawOffset = 0;
- uniformBuffer->writeOffset = 0;
- if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
- commandBuffer->vertexUniformBuffers[slotIndex] = uniformBuffer;
- } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
- commandBuffer->fragmentUniformBuffers[slotIndex] = uniformBuffer;
- } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
- commandBuffer->computeUniformBuffers[slotIndex] = uniformBuffer;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
- }
- }
- uniformBuffer->drawOffset = uniformBuffer->writeOffset;
- SDL_memcpy(
- (Uint8 *)uniformBuffer->buffer->mapPointer + uniformBuffer->writeOffset,
- data,
- length);
- uniformBuffer->writeOffset += uniformBuffer->currentBlockSize;
- if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
- commandBuffer->needVertexUniformBufferBind[slotIndex] = true;
- } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
- commandBuffer->needFragmentUniformBufferBind[slotIndex] = true;
- } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
- commandBuffer->needComputeUniformBufferBind[slotIndex] = true;
- } else {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
- }
- }
- static void D3D12_BindGraphicsPipeline(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUGraphicsPipeline *graphicsPipeline)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12GraphicsPipeline *pipeline = (D3D12GraphicsPipeline *)graphicsPipeline;
- Uint32 i;
- d3d12CommandBuffer->currentGraphicsPipeline = pipeline;
- // Set the pipeline state
- ID3D12GraphicsCommandList_SetPipelineState(d3d12CommandBuffer->graphicsCommandList, pipeline->pipelineState);
- ID3D12GraphicsCommandList_SetGraphicsRootSignature(d3d12CommandBuffer->graphicsCommandList, pipeline->rootSignature->handle);
- ID3D12GraphicsCommandList_IASetPrimitiveTopology(d3d12CommandBuffer->graphicsCommandList, SDLToD3D12_PrimitiveType[pipeline->primitiveType]);
- // Mark that bindings are needed
- d3d12CommandBuffer->needVertexSamplerBind = true;
- d3d12CommandBuffer->needVertexStorageTextureBind = true;
- d3d12CommandBuffer->needVertexStorageBufferBind = true;
- d3d12CommandBuffer->needFragmentSamplerBind = true;
- d3d12CommandBuffer->needFragmentStorageTextureBind = true;
- d3d12CommandBuffer->needFragmentStorageBufferBind = true;
- for (i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
- d3d12CommandBuffer->needVertexUniformBufferBind[i] = true;
- d3d12CommandBuffer->needFragmentUniformBufferBind[i] = true;
- }
- for (i = 0; i < pipeline->vertexUniformBufferCount; i += 1) {
- if (d3d12CommandBuffer->vertexUniformBuffers[i] == NULL) {
- d3d12CommandBuffer->vertexUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
- d3d12CommandBuffer);
- }
- }
- for (i = 0; i < pipeline->fragmentUniformBufferCount; i += 1) {
- if (d3d12CommandBuffer->fragmentUniformBuffers[i] == NULL) {
- d3d12CommandBuffer->fragmentUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
- d3d12CommandBuffer);
- }
- }
- D3D12_INTERNAL_TrackGraphicsPipeline(d3d12CommandBuffer, pipeline);
- }
- static void D3D12_BindVertexBuffers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- const SDL_GPUBufferBinding *bindings,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- D3D12Buffer *currentBuffer = ((D3D12BufferContainer *)bindings[i].buffer)->activeBuffer;
- d3d12CommandBuffer->vertexBuffers[firstSlot + i] = currentBuffer;
- d3d12CommandBuffer->vertexBufferOffsets[firstSlot + i] = bindings[i].offset;
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, currentBuffer);
- }
- d3d12CommandBuffer->vertexBufferCount =
- SDL_max(d3d12CommandBuffer->vertexBufferCount, firstSlot + numBindings);
- d3d12CommandBuffer->needVertexBufferBind = true;
- }
- static void D3D12_BindIndexBuffer(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUBufferBinding *binding,
- SDL_GPUIndexElementSize indexElementSize)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Buffer *buffer = ((D3D12BufferContainer *)binding->buffer)->activeBuffer;
- D3D12_INDEX_BUFFER_VIEW view;
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, buffer);
- view.BufferLocation = buffer->virtualAddress + binding->offset;
- view.SizeInBytes = buffer->container->size - binding->offset;
- view.Format =
- indexElementSize == SDL_GPU_INDEXELEMENTSIZE_16BIT ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
- ID3D12GraphicsCommandList_IASetIndexBuffer(
- d3d12CommandBuffer->graphicsCommandList,
- &view);
- }
- static void D3D12_BindVertexSamplers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
- D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
- D3D12_INTERNAL_TrackTexture(
- d3d12CommandBuffer,
- container->activeTexture);
- D3D12_INTERNAL_TrackSampler(
- d3d12CommandBuffer,
- sampler);
- d3d12CommandBuffer->vertexSamplers[firstSlot + i] = sampler;
- d3d12CommandBuffer->vertexSamplerTextures[firstSlot + i] = container->activeTexture;
- }
- d3d12CommandBuffer->needVertexSamplerBind = true;
- }
- static void D3D12_BindVertexStorageTextures(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUTexture *const *storageTextures,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
- D3D12Texture *texture = container->activeTexture;
- D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, texture);
- d3d12CommandBuffer->vertexStorageTextures[firstSlot + i] = texture;
- }
- d3d12CommandBuffer->needVertexStorageTextureBind = true;
- }
- static void D3D12_BindVertexStorageBuffers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUBuffer *const *storageBuffers,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
- D3D12_INTERNAL_TrackBuffer(
- d3d12CommandBuffer,
- container->activeBuffer);
- d3d12CommandBuffer->vertexStorageBuffers[firstSlot + i] = container->activeBuffer;
- }
- d3d12CommandBuffer->needVertexStorageBufferBind = true;
- }
- static void D3D12_BindFragmentSamplers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
- D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
- D3D12_INTERNAL_TrackTexture(
- d3d12CommandBuffer,
- container->activeTexture);
- D3D12_INTERNAL_TrackSampler(
- d3d12CommandBuffer,
- sampler);
- d3d12CommandBuffer->fragmentSamplers[firstSlot + i] = sampler;
- d3d12CommandBuffer->fragmentSamplerTextures[firstSlot + i] = container->activeTexture;
- }
- d3d12CommandBuffer->needFragmentSamplerBind = true;
- }
- static void D3D12_BindFragmentStorageTextures(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUTexture *const *storageTextures,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
- D3D12Texture *texture = container->activeTexture;
- D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, texture);
- d3d12CommandBuffer->fragmentStorageTextures[firstSlot + i] = texture;
- }
- d3d12CommandBuffer->needFragmentStorageTextureBind = true;
- }
- static void D3D12_BindFragmentStorageBuffers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUBuffer *const *storageBuffers,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
- D3D12_INTERNAL_TrackBuffer(
- d3d12CommandBuffer,
- container->activeBuffer);
- d3d12CommandBuffer->fragmentStorageBuffers[firstSlot + i] = container->activeBuffer;
- }
- d3d12CommandBuffer->needFragmentStorageBufferBind = true;
- }
- static void D3D12_PushVertexUniformData(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 slotIndex,
- const void *data,
- Uint32 length)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_INTERNAL_PushUniformData(
- d3d12CommandBuffer,
- SDL_GPU_SHADERSTAGE_VERTEX,
- slotIndex,
- data,
- length);
- }
- static void D3D12_PushFragmentUniformData(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 slotIndex,
- const void *data,
- Uint32 length)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_INTERNAL_PushUniformData(
- d3d12CommandBuffer,
- SDL_GPU_SHADERSTAGE_FRAGMENT,
- slotIndex,
- data,
- length);
- }
- static void D3D12_INTERNAL_WriteGPUDescriptors(
- D3D12CommandBuffer *commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE heapType,
- D3D12_CPU_DESCRIPTOR_HANDLE *resourceDescriptorHandles,
- Uint32 resourceHandleCount,
- D3D12_GPU_DESCRIPTOR_HANDLE *gpuBaseDescriptor)
- {
- D3D12DescriptorHeap *heap = commandBuffer->gpuDescriptorHeaps[heapType];
- D3D12_CPU_DESCRIPTOR_HANDLE gpuHeapCpuHandle;
- // FIXME: need to error on overflow
- gpuHeapCpuHandle.ptr = heap->descriptorHeapCPUStart.ptr + (heap->currentDescriptorIndex * heap->descriptorSize);
- gpuBaseDescriptor->ptr = heap->descriptorHeapGPUStart.ptr + (heap->currentDescriptorIndex * heap->descriptorSize);
- for (Uint32 i = 0; i < resourceHandleCount; i += 1) {
- ID3D12Device_CopyDescriptorsSimple(
- commandBuffer->renderer->device,
- 1,
- gpuHeapCpuHandle,
- resourceDescriptorHandles[i],
- heapType);
- heap->currentDescriptorIndex += 1;
- gpuHeapCpuHandle.ptr += heap->descriptorSize;
- }
- }
- static void D3D12_INTERNAL_BindGraphicsResources(
- D3D12CommandBuffer *commandBuffer)
- {
- D3D12GraphicsPipeline *graphicsPipeline = commandBuffer->currentGraphicsPipeline;
- D3D12_CPU_DESCRIPTOR_HANDLE cpuHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorHandle;
- D3D12_VERTEX_BUFFER_VIEW vertexBufferViews[MAX_VERTEX_BUFFERS];
- if (commandBuffer->needVertexBufferBind) {
- for (Uint32 i = 0; i < commandBuffer->vertexBufferCount; i += 1) {
- vertexBufferViews[i].BufferLocation = commandBuffer->vertexBuffers[i]->virtualAddress + commandBuffer->vertexBufferOffsets[i];
- vertexBufferViews[i].SizeInBytes = commandBuffer->vertexBuffers[i]->container->size - commandBuffer->vertexBufferOffsets[i];
- vertexBufferViews[i].StrideInBytes = graphicsPipeline->vertexStrides[i];
- }
- ID3D12GraphicsCommandList_IASetVertexBuffers(
- commandBuffer->graphicsCommandList,
- 0,
- commandBuffer->vertexBufferCount,
- vertexBufferViews);
- }
- if (commandBuffer->needVertexSamplerBind) {
- if (graphicsPipeline->vertexSamplerCount > 0) {
- for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) {
- cpuHandles[i] = commandBuffer->vertexSamplers[i]->handle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
- cpuHandles,
- graphicsPipeline->vertexSamplerCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->vertexSamplerRootIndex,
- gpuDescriptorHandle);
- for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) {
- cpuHandles[i] = commandBuffer->vertexSamplerTextures[i]->srvHandle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- graphicsPipeline->vertexSamplerCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->vertexSamplerTextureRootIndex,
- gpuDescriptorHandle);
- }
- commandBuffer->needVertexSamplerBind = false;
- }
- if (commandBuffer->needVertexStorageTextureBind) {
- if (graphicsPipeline->vertexStorageTextureCount > 0) {
- for (Uint32 i = 0; i < graphicsPipeline->vertexStorageTextureCount; i += 1) {
- cpuHandles[i] = commandBuffer->vertexStorageTextures[i]->srvHandle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- graphicsPipeline->vertexStorageTextureCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->vertexStorageTextureRootIndex,
- gpuDescriptorHandle);
- }
- commandBuffer->needVertexStorageTextureBind = false;
- }
- if (commandBuffer->needVertexStorageBufferBind) {
- if (graphicsPipeline->vertexStorageBufferCount > 0) {
- for (Uint32 i = 0; i < graphicsPipeline->vertexStorageBufferCount; i += 1) {
- cpuHandles[i] = commandBuffer->vertexStorageBuffers[i]->srvDescriptor.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- graphicsPipeline->vertexStorageBufferCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->vertexStorageBufferRootIndex,
- gpuDescriptorHandle);
- }
- commandBuffer->needVertexStorageBufferBind = false;
- }
- for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
- if (commandBuffer->needVertexUniformBufferBind[i]) {
- if (graphicsPipeline->vertexUniformBufferCount > i) {
- ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->vertexUniformBufferRootIndex[i],
- commandBuffer->vertexUniformBuffers[i]->buffer->virtualAddress + commandBuffer->vertexUniformBuffers[i]->drawOffset);
- }
- commandBuffer->needVertexUniformBufferBind[i] = false;
- }
- }
- if (commandBuffer->needFragmentSamplerBind) {
- if (graphicsPipeline->fragmentSamplerCount > 0) {
- for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) {
- cpuHandles[i] = commandBuffer->fragmentSamplers[i]->handle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
- cpuHandles,
- graphicsPipeline->fragmentSamplerCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->fragmentSamplerRootIndex,
- gpuDescriptorHandle);
- for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) {
- cpuHandles[i] = commandBuffer->fragmentSamplerTextures[i]->srvHandle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- graphicsPipeline->fragmentSamplerCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->fragmentSamplerTextureRootIndex,
- gpuDescriptorHandle);
- }
- commandBuffer->needFragmentSamplerBind = false;
- }
- if (commandBuffer->needFragmentStorageTextureBind) {
- if (graphicsPipeline->fragmentStorageTextureCount > 0) {
- for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageTextureCount; i += 1) {
- cpuHandles[i] = commandBuffer->fragmentStorageTextures[i]->srvHandle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- graphicsPipeline->fragmentStorageTextureCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->fragmentStorageTextureRootIndex,
- gpuDescriptorHandle);
- }
- commandBuffer->needFragmentStorageTextureBind = false;
- }
- if (commandBuffer->needFragmentStorageBufferBind) {
- if (graphicsPipeline->fragmentStorageBufferCount > 0) {
- for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageBufferCount; i += 1) {
- cpuHandles[i] = commandBuffer->fragmentStorageBuffers[i]->srvDescriptor.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- graphicsPipeline->fragmentStorageBufferCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->fragmentStorageBufferRootIndex,
- gpuDescriptorHandle);
- }
- commandBuffer->needFragmentStorageBufferBind = false;
- }
- for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
- if (commandBuffer->needFragmentUniformBufferBind[i]) {
- if (graphicsPipeline->fragmentUniformBufferCount > i) {
- ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(
- commandBuffer->graphicsCommandList,
- graphicsPipeline->rootSignature->fragmentUniformBufferRootIndex[i],
- commandBuffer->fragmentUniformBuffers[i]->buffer->virtualAddress + commandBuffer->fragmentUniformBuffers[i]->drawOffset);
- }
- commandBuffer->needFragmentUniformBufferBind[i] = false;
- }
- }
- }
- static void D3D12_DrawIndexedPrimitives(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 numIndices,
- Uint32 numInstances,
- Uint32 firstIndex,
- Sint32 vertexOffset,
- Uint32 firstInstance)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer);
- ID3D12GraphicsCommandList_DrawIndexedInstanced(
- d3d12CommandBuffer->graphicsCommandList,
- numIndices,
- numInstances,
- firstIndex,
- vertexOffset,
- firstInstance);
- }
- static void D3D12_DrawPrimitives(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 numVertices,
- Uint32 numInstances,
- Uint32 firstVertex,
- Uint32 firstInstance)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer);
- ID3D12GraphicsCommandList_DrawInstanced(
- d3d12CommandBuffer->graphicsCommandList,
- numVertices,
- numInstances,
- firstVertex,
- firstInstance);
- }
- static void D3D12_DrawPrimitivesIndirect(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUBuffer *buffer,
- Uint32 offset,
- Uint32 drawCount)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Buffer *d3d12Buffer = ((D3D12BufferContainer *)buffer)->activeBuffer;
- D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer);
- ID3D12GraphicsCommandList_ExecuteIndirect(
- d3d12CommandBuffer->graphicsCommandList,
- d3d12CommandBuffer->renderer->indirectDrawCommandSignature,
- drawCount,
- d3d12Buffer->handle,
- offset,
- NULL,
- 0);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, d3d12Buffer);
- }
- static void D3D12_DrawIndexedPrimitivesIndirect(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUBuffer *buffer,
- Uint32 offset,
- Uint32 drawCount)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Buffer *d3d12Buffer = ((D3D12BufferContainer *)buffer)->activeBuffer;
- D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer);
- ID3D12GraphicsCommandList_ExecuteIndirect(
- d3d12CommandBuffer->graphicsCommandList,
- d3d12CommandBuffer->renderer->indirectIndexedDrawCommandSignature,
- drawCount,
- d3d12Buffer->handle,
- offset,
- NULL,
- 0);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, d3d12Buffer);
- }
- static void D3D12_EndRenderPass(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- Uint32 i;
- for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
- if (d3d12CommandBuffer->colorTargetSubresources[i] != NULL) {
- if (d3d12CommandBuffer->colorResolveSubresources[i] != NULL) {
- // Resolving requires some extra barriers
- D3D12_INTERNAL_TextureSubresourceBarrier(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_RENDER_TARGET,
- D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
- d3d12CommandBuffer->colorTargetSubresources[i]
- );
- ID3D12GraphicsCommandList_ResolveSubresource(
- d3d12CommandBuffer->graphicsCommandList,
- d3d12CommandBuffer->colorResolveSubresources[i]->parent->resource,
- d3d12CommandBuffer->colorResolveSubresources[i]->index,
- d3d12CommandBuffer->colorTargetSubresources[i]->parent->resource,
- d3d12CommandBuffer->colorTargetSubresources[i]->index,
- SDLToD3D12_TextureFormat[d3d12CommandBuffer->colorTargetSubresources[i]->parent->container->header.info.format]);
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
- d3d12CommandBuffer->colorTargetSubresources[i]);
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_RESOLVE_DEST,
- d3d12CommandBuffer->colorResolveSubresources[i]);
- } else {
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_RENDER_TARGET,
- d3d12CommandBuffer->colorTargetSubresources[i]);
- }
- }
- }
- if (d3d12CommandBuffer->depthStencilTextureSubresource != NULL) {
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_DEPTH_WRITE,
- d3d12CommandBuffer->depthStencilTextureSubresource);
- d3d12CommandBuffer->depthStencilTextureSubresource = NULL;
- }
- d3d12CommandBuffer->currentGraphicsPipeline = NULL;
- ID3D12GraphicsCommandList_OMSetRenderTargets(
- d3d12CommandBuffer->graphicsCommandList,
- 0,
- NULL,
- false,
- NULL);
- // Reset bind state
- SDL_zeroa(d3d12CommandBuffer->colorTargetSubresources);
- SDL_zeroa(d3d12CommandBuffer->colorResolveSubresources);
- d3d12CommandBuffer->depthStencilTextureSubresource = NULL;
- SDL_zeroa(d3d12CommandBuffer->vertexBuffers);
- SDL_zeroa(d3d12CommandBuffer->vertexBufferOffsets);
- d3d12CommandBuffer->vertexBufferCount = 0;
- SDL_zeroa(d3d12CommandBuffer->vertexSamplerTextures);
- SDL_zeroa(d3d12CommandBuffer->vertexSamplers);
- SDL_zeroa(d3d12CommandBuffer->vertexStorageTextures);
- SDL_zeroa(d3d12CommandBuffer->vertexStorageBuffers);
- SDL_zeroa(d3d12CommandBuffer->fragmentSamplerTextures);
- SDL_zeroa(d3d12CommandBuffer->fragmentSamplers);
- SDL_zeroa(d3d12CommandBuffer->fragmentStorageTextures);
- SDL_zeroa(d3d12CommandBuffer->fragmentStorageBuffers);
- }
- // Compute Pass
- static void D3D12_BeginComputePass(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUStorageTextureReadWriteBinding *storageTextureBindings,
- Uint32 numStorageTextureBindings,
- const SDL_GPUStorageBufferReadWriteBinding *storageBufferBindings,
- Uint32 numStorageBufferBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- d3d12CommandBuffer->computeReadWriteStorageTextureSubresourceCount = numStorageTextureBindings;
- d3d12CommandBuffer->computeReadWriteStorageBufferCount = numStorageBufferBindings;
- /* Read-write resources will be actually bound in BindComputePipeline
- * after the root signature is set.
- * We also have to scan to see which barriers we actually need because depth slices aren't separate subresources
- */
- if (numStorageTextureBindings > 0) {
- for (Uint32 i = 0; i < numStorageTextureBindings; i += 1) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextureBindings[i].texture;
- D3D12TextureSubresource *subresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
- d3d12CommandBuffer,
- container,
- storageTextureBindings[i].layer,
- storageTextureBindings[i].mip_level,
- storageTextureBindings[i].cycle,
- D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
- d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i] = subresource;
- D3D12_INTERNAL_TrackTexture(
- d3d12CommandBuffer,
- subresource->parent);
- }
- }
- if (numStorageBufferBindings > 0) {
- for (Uint32 i = 0; i < numStorageBufferBindings; i += 1) {
- D3D12BufferContainer *container = (D3D12BufferContainer *)storageBufferBindings[i].buffer;
- D3D12Buffer *buffer = D3D12_INTERNAL_PrepareBufferForWrite(
- d3d12CommandBuffer,
- container,
- storageBufferBindings[i].cycle,
- D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
- d3d12CommandBuffer->computeReadWriteStorageBuffers[i] = buffer;
- D3D12_INTERNAL_TrackBuffer(
- d3d12CommandBuffer,
- buffer);
- }
- }
- }
- static void D3D12_BindComputePipeline(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUComputePipeline *computePipeline)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12ComputePipeline *pipeline = (D3D12ComputePipeline *)computePipeline;
- D3D12_CPU_DESCRIPTOR_HANDLE cpuHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorHandle;
- ID3D12GraphicsCommandList_SetPipelineState(
- d3d12CommandBuffer->graphicsCommandList,
- pipeline->pipelineState);
- ID3D12GraphicsCommandList_SetComputeRootSignature(
- d3d12CommandBuffer->graphicsCommandList,
- pipeline->rootSignature->handle);
- d3d12CommandBuffer->currentComputePipeline = pipeline;
- d3d12CommandBuffer->needComputeSamplerBind = true;
- d3d12CommandBuffer->needComputeReadOnlyStorageTextureBind = true;
- d3d12CommandBuffer->needComputeReadOnlyStorageBufferBind = true;
- for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
- d3d12CommandBuffer->needComputeUniformBufferBind[i] = true;
- }
- for (Uint32 i = 0; i < pipeline->numUniformBuffers; i += 1) {
- if (d3d12CommandBuffer->computeUniformBuffers[i] == NULL) {
- d3d12CommandBuffer->computeUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
- d3d12CommandBuffer);
- }
- }
- D3D12_INTERNAL_TrackComputePipeline(d3d12CommandBuffer, pipeline);
- // Bind write-only resources after setting root signature
- if (pipeline->numReadWriteStorageTextures > 0) {
- for (Uint32 i = 0; i < pipeline->numReadWriteStorageTextures; i += 1) {
- cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i]->uavHandle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- d3d12CommandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- d3d12CommandBuffer->computeReadWriteStorageTextureSubresourceCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
- d3d12CommandBuffer->graphicsCommandList,
- d3d12CommandBuffer->currentComputePipeline->rootSignature->readWriteStorageTextureRootIndex,
- gpuDescriptorHandle);
- }
- if (pipeline->numReadWriteStorageBuffers > 0) {
- for (Uint32 i = 0; i < pipeline->numReadWriteStorageBuffers; i += 1) {
- cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageBuffers[i]->uavDescriptor.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- d3d12CommandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- d3d12CommandBuffer->computeReadWriteStorageBufferCount,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
- d3d12CommandBuffer->graphicsCommandList,
- d3d12CommandBuffer->currentComputePipeline->rootSignature->readWriteStorageBufferRootIndex,
- gpuDescriptorHandle);
- }
- }
- static void D3D12_BindComputeSamplers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
- D3D12_INTERNAL_TrackSampler(
- d3d12CommandBuffer,
- (D3D12Sampler *)textureSamplerBindings[i].sampler);
- D3D12_INTERNAL_TrackTexture(
- d3d12CommandBuffer,
- container->activeTexture);
- d3d12CommandBuffer->computeSamplerTextures[firstSlot + i] = container->activeTexture;
- d3d12CommandBuffer->computeSamplers[firstSlot + i] = (D3D12Sampler *)textureSamplerBindings[i].sampler;
- }
- d3d12CommandBuffer->needComputeSamplerBind = true;
- }
- static void D3D12_BindComputeStorageTextures(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUTexture *const *storageTextures,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- if (d3d12CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i] != NULL) {
- D3D12_INTERNAL_TextureTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
- d3d12CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i]);
- }
- D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
- d3d12CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i] = container->activeTexture;
- D3D12_INTERNAL_TextureTransitionFromDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
- container->activeTexture);
- D3D12_INTERNAL_TrackTexture(
- d3d12CommandBuffer,
- container->activeTexture);
- }
- d3d12CommandBuffer->needComputeReadOnlyStorageTextureBind = true;
- }
- static void D3D12_BindComputeStorageBuffers(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 firstSlot,
- SDL_GPUBuffer *const *storageBuffers,
- Uint32 numBindings)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < numBindings; i += 1) {
- if (d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] != NULL) {
- D3D12_INTERNAL_BufferTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
- d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i]);
- }
- D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
- D3D12Buffer *buffer = container->activeBuffer;
- d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] = buffer;
- D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
- buffer);
- D3D12_INTERNAL_TrackBuffer(
- d3d12CommandBuffer,
- buffer);
- }
- d3d12CommandBuffer->needComputeReadOnlyStorageBufferBind = true;
- }
- static void D3D12_PushComputeUniformData(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 slotIndex,
- const void *data,
- Uint32 length)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_INTERNAL_PushUniformData(
- d3d12CommandBuffer,
- SDL_GPU_SHADERSTAGE_COMPUTE,
- slotIndex,
- data,
- length);
- }
- static void D3D12_INTERNAL_BindComputeResources(
- D3D12CommandBuffer *commandBuffer)
- {
- D3D12ComputePipeline *computePipeline = commandBuffer->currentComputePipeline;
- D3D12_CPU_DESCRIPTOR_HANDLE cpuHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
- D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorHandle;
- if (commandBuffer->needComputeSamplerBind) {
- if (computePipeline->numSamplers > 0) {
- for (Uint32 i = 0; i < computePipeline->numSamplers; i += 1) {
- cpuHandles[i] = commandBuffer->computeSamplers[i]->handle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
- cpuHandles,
- computePipeline->numSamplers,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- computePipeline->rootSignature->samplerRootIndex,
- gpuDescriptorHandle);
- for (Uint32 i = 0; i < computePipeline->numSamplers; i += 1) {
- cpuHandles[i] = commandBuffer->computeSamplerTextures[i]->srvHandle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- computePipeline->numSamplers,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- computePipeline->rootSignature->samplerTextureRootIndex,
- gpuDescriptorHandle);
- }
- commandBuffer->needComputeSamplerBind = false;
- }
- if (commandBuffer->needComputeReadOnlyStorageTextureBind) {
- if (computePipeline->numReadOnlyStorageTextures > 0) {
- for (Uint32 i = 0; i < computePipeline->numReadOnlyStorageTextures; i += 1) {
- cpuHandles[i] = commandBuffer->computeReadOnlyStorageTextures[i]->srvHandle.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- computePipeline->numReadOnlyStorageTextures,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- computePipeline->rootSignature->readOnlyStorageTextureRootIndex,
- gpuDescriptorHandle);
- }
- commandBuffer->needComputeReadOnlyStorageTextureBind = false;
- }
- if (commandBuffer->needComputeReadOnlyStorageBufferBind) {
- if (computePipeline->numReadOnlyStorageBuffers > 0) {
- for (Uint32 i = 0; i < computePipeline->numReadOnlyStorageBuffers; i += 1) {
- cpuHandles[i] = commandBuffer->computeReadOnlyStorageBuffers[i]->srvDescriptor.cpuHandle;
- }
- D3D12_INTERNAL_WriteGPUDescriptors(
- commandBuffer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- cpuHandles,
- computePipeline->numReadOnlyStorageBuffers,
- &gpuDescriptorHandle);
- ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
- commandBuffer->graphicsCommandList,
- computePipeline->rootSignature->readOnlyStorageBufferRootIndex,
- gpuDescriptorHandle);
- }
- commandBuffer->needComputeReadOnlyStorageBufferBind = false;
- }
- for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
- if (commandBuffer->needComputeUniformBufferBind[i]) {
- if (computePipeline->numUniformBuffers > i) {
- ID3D12GraphicsCommandList_SetComputeRootConstantBufferView(
- commandBuffer->graphicsCommandList,
- computePipeline->rootSignature->uniformBufferRootIndex[i],
- commandBuffer->computeUniformBuffers[i]->buffer->virtualAddress + commandBuffer->computeUniformBuffers[i]->drawOffset);
- }
- }
- commandBuffer->needComputeUniformBufferBind[i] = false;
- }
- }
- static void D3D12_DispatchCompute(
- SDL_GPUCommandBuffer *commandBuffer,
- Uint32 groupcountX,
- Uint32 groupcountY,
- Uint32 groupcountZ)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_INTERNAL_BindComputeResources(d3d12CommandBuffer);
- ID3D12GraphicsCommandList_Dispatch(
- d3d12CommandBuffer->graphicsCommandList,
- groupcountX,
- groupcountY,
- groupcountZ);
- }
- static void D3D12_DispatchComputeIndirect(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUBuffer *buffer,
- Uint32 offset)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Buffer *d3d12Buffer = ((D3D12BufferContainer *)buffer)->activeBuffer;
- D3D12_INTERNAL_BindComputeResources(d3d12CommandBuffer);
- ID3D12GraphicsCommandList_ExecuteIndirect(
- d3d12CommandBuffer->graphicsCommandList,
- d3d12CommandBuffer->renderer->indirectDispatchCommandSignature,
- 1,
- d3d12Buffer->handle,
- offset,
- NULL,
- 0);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, d3d12Buffer);
- }
- static void D3D12_EndComputePass(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- for (Uint32 i = 0; i < d3d12CommandBuffer->computeReadWriteStorageTextureSubresourceCount; i += 1) {
- if (d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i]) {
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
- d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i]);
- d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i] = NULL;
- }
- }
- d3d12CommandBuffer->computeReadWriteStorageTextureSubresourceCount = 0;
- for (Uint32 i = 0; i < d3d12CommandBuffer->computeReadWriteStorageBufferCount; i += 1) {
- if (d3d12CommandBuffer->computeReadWriteStorageBuffers[i]) {
- D3D12_INTERNAL_BufferTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
- d3d12CommandBuffer->computeReadWriteStorageBuffers[i]);
- d3d12CommandBuffer->computeReadWriteStorageBuffers[i] = NULL;
- }
- }
- d3d12CommandBuffer->computeReadWriteStorageBufferCount = 0;
- for (Uint32 i = 0; i < MAX_STORAGE_TEXTURES_PER_STAGE; i += 1) {
- if (d3d12CommandBuffer->computeReadOnlyStorageTextures[i]) {
- D3D12_INTERNAL_TextureTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
- d3d12CommandBuffer->computeReadOnlyStorageTextures[i]);
- d3d12CommandBuffer->computeReadOnlyStorageTextures[i] = NULL;
- }
- }
- for (Uint32 i = 0; i < MAX_STORAGE_BUFFERS_PER_STAGE; i += 1) {
- if (d3d12CommandBuffer->computeReadOnlyStorageBuffers[i]) {
- D3D12_INTERNAL_BufferTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
- d3d12CommandBuffer->computeReadOnlyStorageBuffers[i]);
- d3d12CommandBuffer->computeReadOnlyStorageBuffers[i] = NULL;
- }
- }
- SDL_zeroa(d3d12CommandBuffer->computeSamplerTextures);
- SDL_zeroa(d3d12CommandBuffer->computeSamplers);
- d3d12CommandBuffer->currentComputePipeline = NULL;
- }
- // TransferBuffer Data
- static void *D3D12_MapTransferBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUTransferBuffer *transferBuffer,
- bool cycle)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12BufferContainer *container = (D3D12BufferContainer *)transferBuffer;
- void *dataPointer;
- if (
- cycle &&
- SDL_GetAtomicInt(&container->activeBuffer->referenceCount) > 0) {
- D3D12_INTERNAL_CycleActiveBuffer(
- renderer,
- container);
- }
- // Upload buffers are persistently mapped, download buffers are not
- if (container->type == D3D12_BUFFER_TYPE_UPLOAD) {
- dataPointer = container->activeBuffer->mapPointer;
- } else {
- ID3D12Resource_Map(
- container->activeBuffer->handle,
- 0,
- NULL,
- (void **)&dataPointer);
- }
- return dataPointer;
- }
- static void D3D12_UnmapTransferBuffer(
- SDL_GPURenderer *driverData,
- SDL_GPUTransferBuffer *transferBuffer)
- {
- (void)driverData;
- D3D12BufferContainer *container = (D3D12BufferContainer *)transferBuffer;
- // Upload buffers are persistently mapped, download buffers are not
- if (container->type == D3D12_BUFFER_TYPE_DOWNLOAD) {
- ID3D12Resource_Unmap(
- container->activeBuffer->handle,
- 0,
- NULL);
- }
- }
- // Copy Pass
- static void D3D12_BeginCopyPass(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- // no-op
- (void)commandBuffer;
- }
- static void D3D12_UploadToTexture(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUTextureTransferInfo *source,
- const SDL_GPUTextureRegion *destination,
- bool cycle)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12BufferContainer *transferBufferContainer = (D3D12BufferContainer *)source->transfer_buffer;
- D3D12Buffer *temporaryBuffer = NULL;
- D3D12_TEXTURE_COPY_LOCATION sourceLocation;
- D3D12_TEXTURE_COPY_LOCATION destinationLocation;
- Uint32 pixelsPerRow = source->pixels_per_row;
- Uint32 rowPitch;
- Uint32 alignedRowPitch;
- Uint32 rowsPerSlice = source->rows_per_layer;
- Uint32 bytesPerSlice;
- bool needsRealignment;
- bool needsPlacementCopy;
- // Note that the transfer buffer does not need a barrier, as it is synced by the client.
- D3D12TextureContainer *textureContainer = (D3D12TextureContainer *)destination->texture;
- D3D12TextureSubresource *textureSubresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
- d3d12CommandBuffer,
- textureContainer,
- destination->layer,
- destination->mip_level,
- cycle,
- D3D12_RESOURCE_STATE_COPY_DEST);
- /* D3D12 requires texture data row pitch to be 256 byte aligned, which is obviously insane.
- * Instead of exposing that restriction to the client, which is a huge rake to step on,
- * and a restriction that no other backend requires, we're going to copy data to a temporary buffer,
- * copy THAT data to the texture, and then get rid of the temporary buffer ASAP.
- * If we're lucky and the row pitch and depth pitch are already aligned, we can skip all of that.
- *
- * D3D12 also requires offsets to be 512 byte aligned. We'll fix that for the client and warn them as well.
- *
- * And just for some extra fun, D3D12 doesn't actually support depth pitch, so we have to realign that too!
- */
- if (pixelsPerRow == 0) {
- pixelsPerRow = destination->w;
- }
- rowPitch = BytesPerRow(pixelsPerRow, textureContainer->header.info.format);
- if (rowsPerSlice == 0) {
- rowsPerSlice = destination->h;
- }
- bytesPerSlice = rowsPerSlice * rowPitch;
- alignedRowPitch = D3D12_INTERNAL_Align(rowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
- needsRealignment = rowsPerSlice != destination->h || rowPitch != alignedRowPitch;
- needsPlacementCopy = source->offset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT != 0;
- sourceLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- sourceLocation.PlacedFootprint.Footprint.Format = SDLToD3D12_TextureFormat[textureContainer->header.info.format];
- sourceLocation.PlacedFootprint.Footprint.RowPitch = alignedRowPitch;
- destinationLocation.pResource = textureContainer->activeTexture->resource;
- destinationLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- destinationLocation.SubresourceIndex = textureSubresource->index;
- if (needsRealignment) {
- temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
- d3d12CommandBuffer->renderer,
- 0,
- alignedRowPitch * destination->h * destination->d,
- D3D12_BUFFER_TYPE_UPLOAD);
- if (!temporaryBuffer) {
- return;
- }
- sourceLocation.pResource = temporaryBuffer->handle;
- for (Uint32 sliceIndex = 0; sliceIndex < destination->d; sliceIndex += 1) {
- // copy row count minus one to avoid overread
- for (Uint32 rowIndex = 0; rowIndex < rowsPerSlice - 1; rowIndex += 1) {
- SDL_memcpy(
- temporaryBuffer->mapPointer + (sliceIndex * rowsPerSlice) + (rowIndex * alignedRowPitch),
- transferBufferContainer->activeBuffer->mapPointer + source->offset + (sliceIndex * bytesPerSlice) + (rowIndex * rowPitch),
- alignedRowPitch);
- }
- Uint32 offset = source->offset + (sliceIndex * bytesPerSlice) + ((rowsPerSlice - 1) * rowPitch);
- SDL_memcpy(
- temporaryBuffer->mapPointer + (sliceIndex * rowsPerSlice) + ((rowsPerSlice - 1) * alignedRowPitch),
- transferBufferContainer->activeBuffer->mapPointer + offset,
- SDL_min(alignedRowPitch, transferBufferContainer->size - offset));
- sourceLocation.PlacedFootprint.Footprint.Width = destination->w;
- sourceLocation.PlacedFootprint.Footprint.Height = rowsPerSlice;
- sourceLocation.PlacedFootprint.Footprint.Depth = 1;
- sourceLocation.PlacedFootprint.Offset = (sliceIndex * bytesPerSlice);
- ID3D12GraphicsCommandList_CopyTextureRegion(
- d3d12CommandBuffer->graphicsCommandList,
- &destinationLocation,
- destination->x,
- destination->y,
- sliceIndex,
- &sourceLocation,
- NULL);
- }
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, temporaryBuffer);
- D3D12_INTERNAL_ReleaseBuffer(
- d3d12CommandBuffer->renderer,
- temporaryBuffer);
- } else if (needsPlacementCopy) {
- temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
- d3d12CommandBuffer->renderer,
- 0,
- alignedRowPitch * destination->h * destination->d,
- D3D12_BUFFER_TYPE_UPLOAD);
- if (!temporaryBuffer) {
- return;
- }
- SDL_memcpy(
- temporaryBuffer->mapPointer,
- transferBufferContainer->activeBuffer->mapPointer + source->offset,
- alignedRowPitch * destination->h * destination->d);
- sourceLocation.pResource = temporaryBuffer->handle;
- sourceLocation.PlacedFootprint.Offset = 0;
- sourceLocation.PlacedFootprint.Footprint.Width = destination->w;
- sourceLocation.PlacedFootprint.Footprint.Height = destination->h;
- sourceLocation.PlacedFootprint.Footprint.Depth = 1;
- ID3D12GraphicsCommandList_CopyTextureRegion(
- d3d12CommandBuffer->graphicsCommandList,
- &destinationLocation,
- destination->x,
- destination->y,
- destination->z,
- &sourceLocation,
- NULL);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, temporaryBuffer);
- D3D12_INTERNAL_ReleaseBuffer(
- d3d12CommandBuffer->renderer,
- temporaryBuffer);
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Texture upload offset not aligned to 512 bytes! This is suboptimal on D3D12!");
- } else {
- sourceLocation.pResource = transferBufferContainer->activeBuffer->handle;
- sourceLocation.PlacedFootprint.Offset = source->offset;
- sourceLocation.PlacedFootprint.Footprint.Width = destination->w;
- sourceLocation.PlacedFootprint.Footprint.Height = destination->h;
- sourceLocation.PlacedFootprint.Footprint.Depth = destination->d;
- ID3D12GraphicsCommandList_CopyTextureRegion(
- d3d12CommandBuffer->graphicsCommandList,
- &destinationLocation,
- destination->x,
- destination->y,
- destination->z,
- &sourceLocation,
- NULL);
- }
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_DEST,
- textureSubresource);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, transferBufferContainer->activeBuffer);
- D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, textureSubresource->parent);
- }
- static void D3D12_UploadToBuffer(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUTransferBufferLocation *source,
- const SDL_GPUBufferRegion *destination,
- bool cycle)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12BufferContainer *transferBufferContainer = (D3D12BufferContainer *)source->transfer_buffer;
- D3D12BufferContainer *bufferContainer = (D3D12BufferContainer *)destination->buffer;
- // The transfer buffer does not need a barrier, it is synced by the client.
- D3D12Buffer *buffer = D3D12_INTERNAL_PrepareBufferForWrite(
- d3d12CommandBuffer,
- bufferContainer,
- cycle,
- D3D12_RESOURCE_STATE_COPY_DEST);
- ID3D12GraphicsCommandList_CopyBufferRegion(
- d3d12CommandBuffer->graphicsCommandList,
- buffer->handle,
- destination->offset,
- transferBufferContainer->activeBuffer->handle,
- source->offset,
- destination->size);
- D3D12_INTERNAL_BufferTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_DEST,
- buffer);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, transferBufferContainer->activeBuffer);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, buffer);
- }
- static void D3D12_CopyTextureToTexture(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUTextureLocation *source,
- const SDL_GPUTextureLocation *destination,
- Uint32 w,
- Uint32 h,
- Uint32 d,
- bool cycle)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_TEXTURE_COPY_LOCATION sourceLocation;
- D3D12_TEXTURE_COPY_LOCATION destinationLocation;
- D3D12TextureSubresource *sourceSubresource = D3D12_INTERNAL_FetchTextureSubresource(
- (D3D12TextureContainer *)source->texture,
- source->layer,
- source->mip_level);
- D3D12TextureSubresource *destinationSubresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
- d3d12CommandBuffer,
- (D3D12TextureContainer *)destination->texture,
- destination->layer,
- destination->mip_level,
- cycle,
- D3D12_RESOURCE_STATE_COPY_DEST);
- D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_SOURCE,
- sourceSubresource);
- sourceLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- sourceLocation.SubresourceIndex = sourceSubresource->index;
- sourceLocation.pResource = sourceSubresource->parent->resource;
- destinationLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- destinationLocation.SubresourceIndex = destinationSubresource->index;
- destinationLocation.pResource = destinationSubresource->parent->resource;
- D3D12_BOX sourceBox = { source->x, source->y, source->z, source->x + w, source->y + h, source->z + d };
- ID3D12GraphicsCommandList_CopyTextureRegion(
- d3d12CommandBuffer->graphicsCommandList,
- &destinationLocation,
- destination->x,
- destination->y,
- destination->z,
- &sourceLocation,
- &sourceBox);
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_SOURCE,
- sourceSubresource);
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_DEST,
- destinationSubresource);
- D3D12_INTERNAL_TrackTexture(
- d3d12CommandBuffer,
- sourceSubresource->parent);
- D3D12_INTERNAL_TrackTexture(
- d3d12CommandBuffer,
- destinationSubresource->parent);
- }
- static void D3D12_CopyBufferToBuffer(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUBufferLocation *source,
- const SDL_GPUBufferLocation *destination,
- Uint32 size,
- bool cycle)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12BufferContainer *sourceContainer = (D3D12BufferContainer *)source->buffer;
- D3D12BufferContainer *destinationContainer = (D3D12BufferContainer *)destination->buffer;
- D3D12Buffer *sourceBuffer = sourceContainer->activeBuffer;
- D3D12Buffer *destinationBuffer = D3D12_INTERNAL_PrepareBufferForWrite(
- d3d12CommandBuffer,
- destinationContainer,
- cycle,
- D3D12_RESOURCE_STATE_COPY_DEST);
- D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_SOURCE,
- sourceBuffer);
- ID3D12GraphicsCommandList_CopyBufferRegion(
- d3d12CommandBuffer->graphicsCommandList,
- destinationBuffer->handle,
- destination->offset,
- sourceBuffer->handle,
- source->offset,
- size);
- D3D12_INTERNAL_BufferTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_SOURCE,
- sourceBuffer);
- D3D12_INTERNAL_BufferTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_DEST,
- destinationBuffer);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, sourceBuffer);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, destinationBuffer);
- }
- static void D3D12_DownloadFromTexture(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUTextureRegion *source,
- const SDL_GPUTextureTransferInfo *destination)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12_TEXTURE_COPY_LOCATION sourceLocation;
- D3D12_TEXTURE_COPY_LOCATION destinationLocation;
- Uint32 pixelsPerRow = destination->pixels_per_row;
- Uint32 rowPitch;
- Uint32 alignedRowPitch;
- Uint32 rowsPerSlice = destination->rows_per_layer;
- bool needsRealignment;
- bool needsPlacementCopy;
- D3D12TextureDownload *textureDownload = NULL;
- D3D12TextureContainer *sourceContainer = (D3D12TextureContainer *)source->texture;
- D3D12TextureSubresource *sourceSubresource = D3D12_INTERNAL_FetchTextureSubresource(
- sourceContainer,
- source->layer,
- source->mip_level);
- D3D12BufferContainer *destinationContainer = (D3D12BufferContainer *)destination->transfer_buffer;
- D3D12Buffer *destinationBuffer = destinationContainer->activeBuffer;
- /* D3D12 requires texture data row pitch to be 256 byte aligned, which is obviously insane.
- * Instead of exposing that restriction to the client, which is a huge rake to step on,
- * and a restriction that no other backend requires, we're going to copy data to a temporary buffer,
- * copy THAT data to the texture, and then get rid of the temporary buffer ASAP.
- * If we're lucky and the row pitch and depth pitch are already aligned, we can skip all of that.
- *
- * D3D12 also requires offsets to be 512 byte aligned. We'll fix that for the client and warn them as well.
- *
- * And just for some extra fun, D3D12 doesn't actually support depth pitch, so we have to realign that too!
- *
- * Since this is an async download we have to do all these fixups after the command is finished,
- * so we'll cache the metadata and map and copy it when the command buffer is cleaned.
- */
- if (pixelsPerRow == 0) {
- pixelsPerRow = source->w;
- }
- rowPitch = BytesPerRow(pixelsPerRow, sourceContainer->header.info.format);
- if (rowsPerSlice == 0) {
- rowsPerSlice = source->h;
- }
- alignedRowPitch = D3D12_INTERNAL_Align(rowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
- needsRealignment = rowsPerSlice != source->h || rowPitch != alignedRowPitch;
- needsPlacementCopy = destination->offset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT != 0;
- sourceLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- sourceLocation.SubresourceIndex = sourceSubresource->index;
- sourceLocation.pResource = sourceSubresource->parent->resource;
- D3D12_BOX sourceBox = { source->x, source->y, source->z, source->x + source->w, source->y + rowsPerSlice, source->z + source->d };
- destinationLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- destinationLocation.PlacedFootprint.Footprint.Format = SDLToD3D12_TextureFormat[sourceContainer->header.info.format];
- destinationLocation.PlacedFootprint.Footprint.Width = source->w;
- destinationLocation.PlacedFootprint.Footprint.Height = rowsPerSlice;
- destinationLocation.PlacedFootprint.Footprint.Depth = source->d;
- destinationLocation.PlacedFootprint.Footprint.RowPitch = alignedRowPitch;
- if (needsRealignment || needsPlacementCopy) {
- textureDownload = (D3D12TextureDownload *)SDL_malloc(sizeof(D3D12TextureDownload));
- if (!textureDownload) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create texture download structure!");
- return;
- }
- textureDownload->temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
- d3d12CommandBuffer->renderer,
- 0,
- alignedRowPitch * rowsPerSlice * source->d,
- D3D12_BUFFER_TYPE_DOWNLOAD);
- if (!textureDownload->temporaryBuffer) {
- SDL_free(textureDownload);
- return;
- }
- textureDownload->destinationBuffer = destinationBuffer;
- textureDownload->bufferOffset = destination->offset;
- textureDownload->width = source->w;
- textureDownload->height = rowsPerSlice;
- textureDownload->depth = source->d;
- textureDownload->bytesPerRow = rowPitch;
- textureDownload->bytesPerDepthSlice = rowPitch * rowsPerSlice;
- textureDownload->alignedBytesPerRow = alignedRowPitch;
- destinationLocation.pResource = textureDownload->temporaryBuffer->handle;
- destinationLocation.PlacedFootprint.Offset = 0;
- } else {
- destinationLocation.pResource = destinationBuffer->handle;
- destinationLocation.PlacedFootprint.Offset = destination->offset;
- }
- D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_SOURCE,
- sourceSubresource);
- ID3D12GraphicsCommandList_CopyTextureRegion(
- d3d12CommandBuffer->graphicsCommandList,
- &destinationLocation,
- 0,
- 0,
- 0,
- &sourceLocation,
- &sourceBox);
- D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_SOURCE,
- sourceSubresource);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, destinationBuffer);
- D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, sourceSubresource->parent);
- if (textureDownload != NULL) {
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, textureDownload->temporaryBuffer);
- if (d3d12CommandBuffer->textureDownloadCount >= d3d12CommandBuffer->textureDownloadCapacity) {
- d3d12CommandBuffer->textureDownloadCapacity *= 2;
- d3d12CommandBuffer->textureDownloads = (D3D12TextureDownload **)SDL_realloc(
- d3d12CommandBuffer->textureDownloads,
- d3d12CommandBuffer->textureDownloadCapacity * sizeof(D3D12TextureDownload *));
- }
- d3d12CommandBuffer->textureDownloads[d3d12CommandBuffer->textureDownloadCount] = textureDownload;
- d3d12CommandBuffer->textureDownloadCount += 1;
- D3D12_INTERNAL_ReleaseBuffer(d3d12CommandBuffer->renderer, textureDownload->temporaryBuffer);
- }
- }
- static void D3D12_DownloadFromBuffer(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUBufferRegion *source,
- const SDL_GPUTransferBufferLocation *destination)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12BufferContainer *sourceContainer = (D3D12BufferContainer *)source->buffer;
- D3D12BufferContainer *destinationContainer = (D3D12BufferContainer *)destination->transfer_buffer;
- D3D12Buffer *sourceBuffer = sourceContainer->activeBuffer;
- D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_SOURCE,
- sourceBuffer);
- D3D12Buffer *destinationBuffer = destinationContainer->activeBuffer;
- ID3D12GraphicsCommandList_CopyBufferRegion(
- d3d12CommandBuffer->graphicsCommandList,
- destinationBuffer->handle,
- destination->offset,
- sourceBuffer->handle,
- source->offset,
- source->size);
- D3D12_INTERNAL_BufferTransitionToDefaultUsage(
- d3d12CommandBuffer,
- D3D12_RESOURCE_STATE_COPY_SOURCE,
- sourceBuffer);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, sourceBuffer);
- D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, destinationBuffer);
- }
- static void D3D12_EndCopyPass(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- // no-op
- (void)commandBuffer;
- }
- static void D3D12_GenerateMipmaps(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_GPUTexture *texture)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
- D3D12TextureContainer *container = (D3D12TextureContainer *)texture;
- SDL_GPUGraphicsPipeline *blitPipeline;
- blitPipeline = SDL_GPU_FetchBlitPipeline(
- renderer->sdlGPUDevice,
- container->header.info.type,
- container->header.info.format,
- renderer->blitVertexShader,
- renderer->blitFrom2DShader,
- renderer->blitFrom2DArrayShader,
- renderer->blitFrom3DShader,
- renderer->blitFromCubeShader,
- renderer->blitFromCubeArrayShader,
- &renderer->blitPipelines,
- &renderer->blitPipelineCount,
- &renderer->blitPipelineCapacity);
- if (blitPipeline == NULL) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not fetch blit pipeline");
- return;
- }
- // We have to do this one subresource at a time
- for (Uint32 layerOrDepthIndex = 0; layerOrDepthIndex < container->header.info.layer_count_or_depth; layerOrDepthIndex += 1) {
- for (Uint32 levelIndex = 1; levelIndex < container->header.info.num_levels; levelIndex += 1) {
- SDL_GPUBlitInfo blitInfo;
- SDL_zero(blitInfo);
- blitInfo.source.texture = texture;
- blitInfo.source.mip_level = levelIndex - 1;
- blitInfo.source.layer_or_depth_plane = layerOrDepthIndex;
- blitInfo.source.x = 0;
- blitInfo.source.y = 0;
- blitInfo.source.w = container->header.info.width >> (levelIndex - 1);
- blitInfo.source.h = container->header.info.height >> (levelIndex - 1);
- blitInfo.destination.texture = texture;
- blitInfo.destination.mip_level = levelIndex;
- blitInfo.destination.layer_or_depth_plane = layerOrDepthIndex;
- blitInfo.destination.x = 0;
- blitInfo.destination.y = 0;
- blitInfo.destination.w = container->header.info.width >> levelIndex;
- blitInfo.destination.h = container->header.info.height >> levelIndex;
- blitInfo.load_op = SDL_GPU_LOADOP_DONT_CARE;
- blitInfo.filter = SDL_GPU_FILTER_LINEAR;
- SDL_BlitGPUTexture(
- commandBuffer,
- &blitInfo);
- }
- }
- D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, container->activeTexture);
- }
- static void D3D12_Blit(
- SDL_GPUCommandBuffer *commandBuffer,
- const SDL_GPUBlitInfo *info)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Renderer *renderer = (D3D12Renderer *)d3d12CommandBuffer->renderer;
- SDL_GPU_BlitCommon(
- commandBuffer,
- info,
- renderer->blitLinearSampler,
- renderer->blitNearestSampler,
- renderer->blitVertexShader,
- renderer->blitFrom2DShader,
- renderer->blitFrom2DArrayShader,
- renderer->blitFrom3DShader,
- renderer->blitFromCubeShader,
- renderer->blitFromCubeArrayShader,
- &renderer->blitPipelines,
- &renderer->blitPipelineCount,
- &renderer->blitPipelineCapacity);
- }
- // Submission/Presentation
- static D3D12WindowData *D3D12_INTERNAL_FetchWindowData(
- SDL_Window *window)
- {
- SDL_PropertiesID properties = SDL_GetWindowProperties(window);
- return (D3D12WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
- }
- static bool D3D12_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
- {
- SDL_Window *w = (SDL_Window *)userdata;
- D3D12WindowData *data;
- if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
- data = D3D12_INTERNAL_FetchWindowData(w);
- data->needsSwapchainRecreate = true;
- }
- return true;
- }
- static bool D3D12_SupportsSwapchainComposition(
- SDL_GPURenderer *driverData,
- SDL_Window *window,
- SDL_GPUSwapchainComposition swapchainComposition)
- {
- #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
- // FIXME: HDR support would be nice to add, but it seems complicated...
- return swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR ||
- swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR;
- #else
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- DXGI_FORMAT format;
- D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport;
- Uint32 colorSpaceSupport;
- HRESULT res;
- format = SwapchainCompositionToTextureFormat[swapchainComposition];
- formatSupport.Format = format;
- res = ID3D12Device_CheckFeatureSupport(
- renderer->device,
- D3D12_FEATURE_FORMAT_SUPPORT,
- &formatSupport,
- sizeof(formatSupport));
- if (FAILED(res)) {
- // Format is apparently unknown
- return false;
- }
- if (!(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_DISPLAY)) {
- return false;
- }
- D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Must claim window before querying swapchain composition support!", false);
- }
- // Check the color space support if necessary
- if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) {
- IDXGISwapChain3_CheckColorSpaceSupport(
- windowData->swapchain,
- SwapchainCompositionToColorSpace[swapchainComposition],
- &colorSpaceSupport);
- if (!(colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) {
- return false;
- }
- }
- #endif
- return true;
- }
- static bool D3D12_SupportsPresentMode(
- SDL_GPURenderer *driverData,
- SDL_Window *window,
- SDL_GPUPresentMode presentMode)
- {
- (void)driverData;
- (void)window;
- switch (presentMode) {
- case SDL_GPU_PRESENTMODE_IMMEDIATE:
- case SDL_GPU_PRESENTMODE_VSYNC:
- return true;
- case SDL_GPU_PRESENTMODE_MAILBOX:
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- return false;
- #else
- return true;
- #endif
- default:
- SDL_assert(!"Unrecognized present mode");
- return false;
- }
- }
- #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
- static bool D3D12_INTERNAL_CreateSwapchain(
- D3D12Renderer *renderer,
- D3D12WindowData *windowData,
- SDL_GPUSwapchainComposition swapchain_composition,
- SDL_GPUPresentMode present_mode)
- {
- int width, height;
- SDL_GPUTextureCreateInfo createInfo;
- D3D12Texture *texture;
- // Get the swapchain size
- SDL_SyncWindow(windowData->window);
- SDL_GetWindowSizeInPixels(windowData->window, &width, &height);
- // Create the swapchain textures
- SDL_zero(createInfo);
- createInfo.type = SDL_GPU_TEXTURETYPE_2D;
- createInfo.width = width;
- createInfo.height = height;
- createInfo.format = SwapchainCompositionToSDLTextureFormat[swapchain_composition];
- createInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
- createInfo.layer_count_or_depth = 1;
- createInfo.num_levels = 1;
- for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
- texture = D3D12_INTERNAL_CreateTexture(renderer, &createInfo, true);
- texture->container = &windowData->textureContainers[i];
- windowData->textureContainers[i].activeTexture = texture;
- windowData->textureContainers[i].canBeCycled = false;
- windowData->textureContainers[i].header.info = createInfo;
- windowData->textureContainers[i].textureCapacity = 1;
- windowData->textureContainers[i].textureCount = 1;
- windowData->textureContainers[i].textures = &windowData->textureContainers[i].activeTexture;
- }
- // Initialize the swapchain data
- windowData->present_mode = present_mode;
- windowData->swapchainComposition = swapchain_composition;
- windowData->swapchainColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
- windowData->frameCounter = 0;
- windowData->width = width;
- windowData->height = height;
- // Precache blit pipelines for the swapchain format
- for (Uint32 i = 0; i < 5; i += 1) {
- SDL_GPU_FetchBlitPipeline(
- renderer->sdlGPUDevice,
- (SDL_GPUTextureType)i,
- createInfo.format,
- renderer->blitVertexShader,
- renderer->blitFrom2DShader,
- renderer->blitFrom2DArrayShader,
- renderer->blitFrom3DShader,
- renderer->blitFromCubeShader,
- renderer->blitFromCubeArrayShader,
- &renderer->blitPipelines,
- &renderer->blitPipelineCount,
- &renderer->blitPipelineCapacity);
- }
- return true;
- }
- static void D3D12_INTERNAL_DestroySwapchain(
- D3D12Renderer *renderer,
- D3D12WindowData *windowData)
- {
- renderer->commandQueue->PresentX(0, NULL, NULL);
- for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
- D3D12_INTERNAL_DestroyTexture(
- renderer,
- windowData->textureContainers[i].activeTexture);
- }
- }
- static bool D3D12_INTERNAL_ResizeSwapchain(
- D3D12Renderer *renderer,
- D3D12WindowData *windowData)
- {
- // Wait so we don't release in-flight views
- D3D12_Wait((SDL_GPURenderer *)renderer);
- // Present a black screen
- renderer->commandQueue->PresentX(0, NULL, NULL);
- // Clean up the previous swapchain textures
- for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
- D3D12_INTERNAL_DestroyTexture(
- renderer,
- windowData->textureContainers[i].activeTexture);
- }
- // Create a new swapchain
- D3D12_INTERNAL_CreateSwapchain(
- renderer,
- windowData,
- windowData->swapchainComposition,
- windowData->present_mode);
- windowData->needsSwapchainRecreate = false;
- return true;
- }
- #else
- static bool D3D12_INTERNAL_InitializeSwapchainTexture(
- D3D12Renderer *renderer,
- IDXGISwapChain3 *swapchain,
- SDL_GPUSwapchainComposition composition,
- Uint32 index,
- D3D12TextureContainer *pTextureContainer)
- {
- D3D12Texture *pTexture;
- ID3D12Resource *swapchainTexture;
- D3D12_RESOURCE_DESC textureDesc;
- D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
- D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
- DXGI_FORMAT swapchainFormat = SwapchainCompositionToTextureFormat[composition];
- HRESULT res;
- res = IDXGISwapChain_GetBuffer(
- swapchain,
- index,
- D3D_GUID(D3D_IID_ID3D12Resource),
- (void **)&swapchainTexture);
- CHECK_D3D12_ERROR_AND_RETURN("Could not get buffer from swapchain!", false);
- pTexture = (D3D12Texture *)SDL_calloc(1, sizeof(D3D12Texture));
- if (!pTexture) {
- ID3D12Resource_Release(swapchainTexture);
- return false;
- }
- pTexture->resource = NULL; // This will be set in AcquireSwapchainTexture
- SDL_SetAtomicInt(&pTexture->referenceCount, 0);
- pTexture->subresourceCount = 1;
- pTexture->subresources = (D3D12TextureSubresource *)SDL_calloc(1, sizeof(D3D12TextureSubresource));
- if (!pTexture->subresources) {
- SDL_free(pTexture);
- ID3D12Resource_Release(swapchainTexture);
- return false;
- }
- pTexture->subresources[0].rtvHandles = SDL_calloc(1, sizeof(D3D12CPUDescriptor));
- pTexture->subresources[0].uavHandle.heap = NULL;
- pTexture->subresources[0].dsvHandle.heap = NULL;
- pTexture->subresources[0].parent = pTexture;
- pTexture->subresources[0].index = 0;
- pTexture->subresources[0].layer = 0;
- pTexture->subresources[0].depth = 1;
- pTexture->subresources[0].level = 0;
- ID3D12Resource_GetDesc(swapchainTexture, &textureDesc);
- pTextureContainer->header.info.width = (Uint32)textureDesc.Width;
- pTextureContainer->header.info.height = (Uint32)textureDesc.Height;
- pTextureContainer->header.info.layer_count_or_depth = 1;
- pTextureContainer->header.info.num_levels = 1;
- pTextureContainer->header.info.type = SDL_GPU_TEXTURETYPE_2D;
- pTextureContainer->header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
- pTextureContainer->header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
- pTextureContainer->header.info.format = SwapchainCompositionToSDLTextureFormat[composition];
- pTextureContainer->debugName = NULL;
- pTextureContainer->textures = (D3D12Texture **)SDL_calloc(1, sizeof(D3D12Texture *));
- if (!pTextureContainer->textures) {
- SDL_free(pTexture->subresources);
- SDL_free(pTexture);
- ID3D12Resource_Release(swapchainTexture);
- return false;
- }
- pTextureContainer->textureCapacity = 1;
- pTextureContainer->textureCount = 1;
- pTextureContainer->textures[0] = pTexture;
- pTextureContainer->activeTexture = pTexture;
- pTextureContainer->canBeCycled = false;
- pTexture->container = pTextureContainer;
- pTexture->containerIndex = 0;
- // Create the SRV for the swapchain
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
- &pTexture->srvHandle);
- srvDesc.Format = SwapchainCompositionToTextureFormat[composition];
- srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
- srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
- srvDesc.Texture2D.MipLevels = 1;
- srvDesc.Texture2D.MostDetailedMip = 0;
- srvDesc.Texture2D.ResourceMinLODClamp = 0;
- srvDesc.Texture2D.PlaneSlice = 0;
- ID3D12Device_CreateShaderResourceView(
- renderer->device,
- swapchainTexture,
- &srvDesc,
- pTexture->srvHandle.cpuHandle);
- // Create the RTV for the swapchain
- D3D12_INTERNAL_AssignCpuDescriptorHandle(
- renderer,
- D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
- &pTexture->subresources[0].rtvHandles[0]);
- rtvDesc.Format = (composition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : swapchainFormat;
- rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
- rtvDesc.Texture2D.MipSlice = 0;
- rtvDesc.Texture2D.PlaneSlice = 0;
- ID3D12Device_CreateRenderTargetView(
- renderer->device,
- swapchainTexture,
- &rtvDesc,
- pTexture->subresources[0].rtvHandles[0].cpuHandle);
- ID3D12Resource_Release(swapchainTexture);
- return true;
- }
- static bool D3D12_INTERNAL_ResizeSwapchain(
- D3D12Renderer *renderer,
- D3D12WindowData *windowData)
- {
- // Wait so we don't release in-flight views
- D3D12_Wait((SDL_GPURenderer *)renderer);
- // Release views and clean up
- for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &windowData->textureContainers[i].activeTexture->srvHandle);
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles[0]);
- SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles);
- SDL_free(windowData->textureContainers[i].activeTexture->subresources);
- SDL_free(windowData->textureContainers[i].activeTexture);
- SDL_free(windowData->textureContainers[i].textures);
- }
- // Resize the swapchain
- HRESULT res = IDXGISwapChain_ResizeBuffers(
- windowData->swapchain,
- 0, // Keep buffer count the same
- 0, // use client window width
- 0, // use client window height
- DXGI_FORMAT_UNKNOWN, // Keep the old format
- renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
- CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain buffers", false);
- // Create texture object for the swapchain
- for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
- if (!D3D12_INTERNAL_InitializeSwapchainTexture(
- renderer,
- windowData->swapchain,
- windowData->swapchainComposition,
- i,
- &windowData->textureContainers[i])) {
- return false;
- }
- }
- DXGI_SWAP_CHAIN_DESC1 swapchainDesc;
- IDXGISwapChain3_GetDesc1(windowData->swapchain, &swapchainDesc);
- CHECK_D3D12_ERROR_AND_RETURN("Failed to retrieve swapchain descriptor!", false);
- windowData->width = swapchainDesc.Width;
- windowData->height = swapchainDesc.Height;
- windowData->needsSwapchainRecreate = false;
- return true;
- }
- static void D3D12_INTERNAL_DestroySwapchain(
- D3D12Renderer *renderer,
- D3D12WindowData *windowData)
- {
- // Release views and clean up
- for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &windowData->textureContainers[i].activeTexture->srvHandle);
- D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
- renderer,
- &windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles[0]);
- SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles);
- SDL_free(windowData->textureContainers[i].activeTexture->subresources);
- SDL_free(windowData->textureContainers[i].activeTexture);
- SDL_free(windowData->textureContainers[i].textures);
- }
- IDXGISwapChain_Release(windowData->swapchain);
- windowData->swapchain = NULL;
- }
- static bool D3D12_INTERNAL_CreateSwapchain(
- D3D12Renderer *renderer,
- D3D12WindowData *windowData,
- SDL_GPUSwapchainComposition swapchainComposition,
- SDL_GPUPresentMode presentMode)
- {
- HWND dxgiHandle;
- DXGI_SWAP_CHAIN_DESC1 swapchainDesc;
- DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc;
- DXGI_FORMAT swapchainFormat;
- IDXGIFactory1 *pParent;
- IDXGISwapChain1 *swapchain;
- IDXGISwapChain3 *swapchain3;
- HRESULT res;
- // Get the DXGI handle
- #ifdef _WIN32
- dxgiHandle = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(windowData->window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
- #else
- dxgiHandle = (HWND)windowData->window;
- #endif
- swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
- // Min swapchain image count is 2
- windowData->swapchainTextureCount = SDL_clamp(renderer->allowedFramesInFlight, 2, 3);
- // Initialize the swapchain buffer descriptor
- swapchainDesc.Width = 0; // use client window width
- swapchainDesc.Height = 0; // use client window height
- swapchainDesc.Format = swapchainFormat;
- swapchainDesc.SampleDesc.Count = 1;
- swapchainDesc.SampleDesc.Quality = 0;
- swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapchainDesc.BufferCount = windowData->swapchainTextureCount;
- swapchainDesc.Scaling = DXGI_SCALING_STRETCH;
- swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
- swapchainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
- swapchainDesc.Flags = 0;
- swapchainDesc.Stereo = 0;
- // Initialize the fullscreen descriptor (if needed)
- fullscreenDesc.RefreshRate.Numerator = 0;
- fullscreenDesc.RefreshRate.Denominator = 0;
- fullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
- fullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
- fullscreenDesc.Windowed = true;
- if (renderer->supportsTearing) {
- swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
- } else {
- swapchainDesc.Flags = 0;
- }
- if (!IsWindow(dxgiHandle)) {
- return false;
- }
- // Create the swapchain!
- res = IDXGIFactory4_CreateSwapChainForHwnd(
- renderer->factory,
- (IUnknown *)renderer->commandQueue,
- dxgiHandle,
- &swapchainDesc,
- &fullscreenDesc,
- NULL,
- &swapchain);
- CHECK_D3D12_ERROR_AND_RETURN("Could not create swapchain", false);
- res = IDXGISwapChain1_QueryInterface(
- swapchain,
- D3D_GUID(D3D_IID_IDXGISwapChain3),
- (void **)&swapchain3);
- IDXGISwapChain1_Release(swapchain);
- CHECK_D3D12_ERROR_AND_RETURN("Could not create IDXGISwapChain3", false);
- if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) {
- // Support already verified if we hit this block
- IDXGISwapChain3_SetColorSpace1(
- swapchain3,
- SwapchainCompositionToColorSpace[swapchainComposition]);
- }
- /*
- * The swapchain's parent is a separate factory from the factory that
- * we used to create the swapchain, and only that parent can be used to
- * set the window association. Trying to set an association on our factory
- * will silently fail and doesn't even verify arguments or return errors.
- * See https://gamedev.net/forums/topic/634235-dxgidisabling-altenter/4999955/
- */
- res = IDXGISwapChain3_GetParent(
- swapchain3,
- D3D_GUID(D3D_IID_IDXGIFactory1),
- (void **)&pParent);
- if (FAILED(res)) {
- SDL_LogWarn(
- SDL_LOG_CATEGORY_GPU,
- "Could not get swapchain parent! Error Code: " HRESULT_FMT,
- res);
- } else {
- // Disable DXGI window crap
- res = IDXGIFactory1_MakeWindowAssociation(
- pParent,
- dxgiHandle,
- DXGI_MWA_NO_WINDOW_CHANGES);
- if (FAILED(res)) {
- SDL_LogWarn(
- SDL_LOG_CATEGORY_GPU,
- "MakeWindowAssociation failed! Error Code: " HRESULT_FMT,
- res);
- }
- // We're done with the parent now
- IDXGIFactory1_Release(pParent);
- }
- IDXGISwapChain3_GetDesc1(swapchain3, &swapchainDesc);
- CHECK_D3D12_ERROR_AND_RETURN("Failed to retrieve swapchain descriptor!", false);
- // Initialize the swapchain data
- windowData->swapchain = swapchain3;
- windowData->present_mode = presentMode;
- windowData->swapchainComposition = swapchainComposition;
- windowData->swapchainColorSpace = SwapchainCompositionToColorSpace[swapchainComposition];
- windowData->frameCounter = 0;
- windowData->width = swapchainDesc.Width;
- windowData->height = swapchainDesc.Height;
- // Precache blit pipelines for the swapchain format
- for (Uint32 i = 0; i < 5; i += 1) {
- SDL_GPU_FetchBlitPipeline(
- renderer->sdlGPUDevice,
- (SDL_GPUTextureType)i,
- SwapchainCompositionToSDLTextureFormat[swapchainComposition],
- renderer->blitVertexShader,
- renderer->blitFrom2DShader,
- renderer->blitFrom2DArrayShader,
- renderer->blitFrom3DShader,
- renderer->blitFromCubeShader,
- renderer->blitFromCubeArrayShader,
- &renderer->blitPipelines,
- &renderer->blitPipelineCount,
- &renderer->blitPipelineCapacity);
- }
- /* If a you are using a FLIP model format you can't create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM_SRGB.
- * You have to create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM and then set the render target view's format to DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
- */
- for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
- if (!D3D12_INTERNAL_InitializeSwapchainTexture(
- renderer,
- swapchain3,
- swapchainComposition,
- i,
- &windowData->textureContainers[i])) {
- IDXGISwapChain3_Release(swapchain3);
- return false;
- }
- }
- return true;
- }
- #endif
- static bool D3D12_ClaimWindow(
- SDL_GPURenderer *driverData,
- SDL_Window *window)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- windowData = (D3D12WindowData *)SDL_calloc(1, sizeof(D3D12WindowData));
- if (!windowData) {
- return false;
- }
- windowData->window = window;
- if (D3D12_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
- SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
- SDL_LockMutex(renderer->windowLock);
- if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
- renderer->claimedWindowCapacity *= 2;
- renderer->claimedWindows = (D3D12WindowData **)SDL_realloc(
- renderer->claimedWindows,
- renderer->claimedWindowCapacity * sizeof(D3D12WindowData *));
- }
- renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
- renderer->claimedWindowCount += 1;
- SDL_UnlockMutex(renderer->windowLock);
- SDL_AddEventWatch(D3D12_INTERNAL_OnWindowResize, window);
- return true;
- } else {
- SDL_free(windowData);
- SET_STRING_ERROR_AND_RETURN("Could not create swapchain, failed to claim window!", false);
- }
- } else {
- SET_STRING_ERROR_AND_RETURN("Window already claimed", false);
- return false;
- }
- }
- static void D3D12_ReleaseWindow(
- SDL_GPURenderer *driverData,
- SDL_Window *window)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Window already unclaimed!", );
- }
- D3D12_Wait(driverData);
- for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
- if (windowData->inFlightFences[i] != NULL) {
- D3D12_ReleaseFence(
- driverData,
- windowData->inFlightFences[i]);
- windowData->inFlightFences[i] = NULL;
- }
- }
- D3D12_INTERNAL_DestroySwapchain(renderer, windowData);
- SDL_LockMutex(renderer->windowLock);
- for (Uint32 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_UnlockMutex(renderer->windowLock);
- SDL_free(windowData);
- SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
- SDL_RemoveEventWatch(D3D12_INTERNAL_OnWindowResize, window);
- }
- static bool D3D12_SetSwapchainParameters(
- SDL_GPURenderer *driverData,
- SDL_Window *window,
- SDL_GPUSwapchainComposition swapchainComposition,
- SDL_GPUPresentMode presentMode)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Cannot set swapchain parameters on unclaimed window!", false);
- }
- if (!D3D12_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
- SET_STRING_ERROR_AND_RETURN("Swapchain composition not supported!", false);
- }
- if (!D3D12_SupportsPresentMode(driverData, window, presentMode)) {
- SET_STRING_ERROR_AND_RETURN("Present mode not supported!", false);
- }
- if (
- swapchainComposition != windowData->swapchainComposition ||
- presentMode != windowData->present_mode) {
- D3D12_Wait(driverData);
- // Recreate the swapchain
- D3D12_INTERNAL_DestroySwapchain(
- renderer,
- windowData);
- return D3D12_INTERNAL_CreateSwapchain(
- renderer,
- windowData,
- swapchainComposition,
- presentMode);
- }
- return true;
- }
- static bool D3D12_SetAllowedFramesInFlight(
- SDL_GPURenderer *driverData,
- Uint32 allowedFramesInFlight)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- if (!D3D12_Wait(driverData)) {
- return false;
- }
- // Destroy all swapchains
- for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
- D3D12WindowData *windowData = renderer->claimedWindows[i];
- D3D12_INTERNAL_DestroySwapchain(renderer, windowData);
- }
- // Set the frames in flight value
- renderer->allowedFramesInFlight = allowedFramesInFlight;
- // Recreate all swapchains
- for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
- D3D12WindowData *windowData = renderer->claimedWindows[i];
- if (!D3D12_INTERNAL_CreateSwapchain(
- renderer,
- windowData,
- windowData->swapchainComposition,
- windowData->present_mode)) {
- return false;
- }
- }
- return true;
- }
- static SDL_GPUTextureFormat D3D12_GetSwapchainTextureFormat(
- SDL_GPURenderer *driverData,
- SDL_Window *window)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Cannot get swapchain format, window has not been claimed!", SDL_GPU_TEXTUREFORMAT_INVALID);
- }
- return windowData->textureContainers[windowData->frameCounter].header.info.format;
- }
- static D3D12Fence *D3D12_INTERNAL_AcquireFence(
- D3D12Renderer *renderer)
- {
- D3D12Fence *fence;
- ID3D12Fence *handle;
- HRESULT res;
- SDL_LockMutex(renderer->fenceLock);
- if (renderer->availableFenceCount == 0) {
- res = ID3D12Device_CreateFence(
- renderer->device,
- D3D12_FENCE_UNSIGNALED_VALUE,
- D3D12_FENCE_FLAG_NONE,
- D3D_GUID(D3D_IID_ID3D12Fence),
- (void **)&handle);
- if (FAILED(res)) {
- D3D12_INTERNAL_SetError(renderer, "Failed to create fence!", res);
- SDL_UnlockMutex(renderer->fenceLock);
- return NULL;
- }
- fence = (D3D12Fence *)SDL_calloc(1, sizeof(D3D12Fence));
- if (!fence) {
- ID3D12Fence_Release(handle);
- SDL_UnlockMutex(renderer->fenceLock);
- return NULL;
- }
- fence->handle = handle;
- fence->event = CreateEvent(NULL, FALSE, FALSE, NULL);
- SDL_SetAtomicInt(&fence->referenceCount, 0);
- } else {
- fence = renderer->availableFences[renderer->availableFenceCount - 1];
- renderer->availableFenceCount -= 1;
- ID3D12Fence_Signal(fence->handle, D3D12_FENCE_UNSIGNALED_VALUE);
- }
- SDL_UnlockMutex(renderer->fenceLock);
- (void)SDL_AtomicIncRef(&fence->referenceCount);
- return fence;
- }
- static bool D3D12_INTERNAL_AllocateCommandBuffer(
- D3D12Renderer *renderer)
- {
- D3D12CommandBuffer *commandBuffer;
- HRESULT res;
- ID3D12CommandAllocator *commandAllocator;
- ID3D12GraphicsCommandList *commandList;
- commandBuffer = (D3D12CommandBuffer *)SDL_calloc(1, sizeof(D3D12CommandBuffer));
- if (!commandBuffer) {
- SET_STRING_ERROR_AND_RETURN("Failed to create ID3D12CommandList. Out of Memory", false);
- }
- res = ID3D12Device_CreateCommandAllocator(
- renderer->device,
- D3D12_COMMAND_LIST_TYPE_DIRECT,
- D3D_GUID(D3D_IID_ID3D12CommandAllocator),
- (void **)&commandAllocator);
- if (FAILED(res)) {
- D3D12_INTERNAL_SetError(renderer, "Failed to create ID3D12CommandAllocator", res);
- D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
- return false;
- }
- commandBuffer->commandAllocator = commandAllocator;
- res = ID3D12Device_CreateCommandList(
- renderer->device,
- 0,
- D3D12_COMMAND_LIST_TYPE_DIRECT,
- commandAllocator,
- NULL,
- D3D_GUID(D3D_IID_ID3D12GraphicsCommandList),
- (void **)&commandList);
- if (FAILED(res)) {
- D3D12_INTERNAL_SetError(renderer, "Failed to create ID3D12CommandList", res);
- D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
- return false;
- }
- commandBuffer->graphicsCommandList = commandList;
- commandBuffer->renderer = renderer;
- commandBuffer->inFlightFence = NULL;
- // Window handling
- commandBuffer->presentDataCapacity = 1;
- commandBuffer->presentDataCount = 0;
- commandBuffer->presentDatas = (D3D12PresentData *)SDL_calloc(
- commandBuffer->presentDataCapacity, sizeof(D3D12PresentData));
- // Resource tracking
- commandBuffer->usedTextureCapacity = 4;
- commandBuffer->usedTextureCount = 0;
- commandBuffer->usedTextures = (D3D12Texture **)SDL_calloc(
- commandBuffer->usedTextureCapacity, sizeof(D3D12Texture *));
- commandBuffer->usedBufferCapacity = 4;
- commandBuffer->usedBufferCount = 0;
- commandBuffer->usedBuffers = (D3D12Buffer **)SDL_calloc(
- commandBuffer->usedBufferCapacity, sizeof(D3D12Buffer *));
- commandBuffer->usedSamplerCapacity = 4;
- commandBuffer->usedSamplerCount = 0;
- commandBuffer->usedSamplers = (D3D12Sampler **)SDL_calloc(
- commandBuffer->usedSamplerCapacity, sizeof(D3D12Sampler *));
- commandBuffer->usedGraphicsPipelineCapacity = 4;
- commandBuffer->usedGraphicsPipelineCount = 0;
- commandBuffer->usedGraphicsPipelines = (D3D12GraphicsPipeline **)SDL_calloc(
- commandBuffer->usedGraphicsPipelineCapacity, sizeof(D3D12GraphicsPipeline *));
- commandBuffer->usedComputePipelineCapacity = 4;
- commandBuffer->usedComputePipelineCount = 0;
- commandBuffer->usedComputePipelines = (D3D12ComputePipeline **)SDL_calloc(
- commandBuffer->usedComputePipelineCapacity, sizeof(D3D12ComputePipeline *));
- commandBuffer->usedUniformBufferCapacity = 4;
- commandBuffer->usedUniformBufferCount = 0;
- commandBuffer->usedUniformBuffers = (D3D12UniformBuffer **)SDL_calloc(
- commandBuffer->usedUniformBufferCapacity, sizeof(D3D12UniformBuffer *));
- commandBuffer->textureDownloadCapacity = 4;
- commandBuffer->textureDownloadCount = 0;
- commandBuffer->textureDownloads = (D3D12TextureDownload **)SDL_calloc(
- commandBuffer->textureDownloadCapacity, sizeof(D3D12TextureDownload *));
- if (
- (!commandBuffer->presentDatas) ||
- (!commandBuffer->usedTextures) ||
- (!commandBuffer->usedBuffers) ||
- (!commandBuffer->usedSamplers) ||
- (!commandBuffer->usedGraphicsPipelines) ||
- (!commandBuffer->usedComputePipelines) ||
- (!commandBuffer->usedUniformBuffers) ||
- (!commandBuffer->textureDownloads)) {
- D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
- SET_STRING_ERROR_AND_RETURN("Failed to create ID3D12CommandList. Out of Memory", false);
- }
- D3D12CommandBuffer **resizedAvailableCommandBuffers = (D3D12CommandBuffer **)SDL_realloc(
- renderer->availableCommandBuffers,
- sizeof(D3D12CommandBuffer *) * (renderer->availableCommandBufferCapacity + 1));
- if (!resizedAvailableCommandBuffers) {
- D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
- SET_STRING_ERROR_AND_RETURN("Failed to create ID3D12CommandList. Out of Memory", false);
- }
- // Add to inactive command buffer array
- renderer->availableCommandBufferCapacity += 1;
- renderer->availableCommandBuffers = resizedAvailableCommandBuffers;
- renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
- renderer->availableCommandBufferCount += 1;
- return true;
- }
- static D3D12CommandBuffer *D3D12_INTERNAL_AcquireCommandBufferFromPool(
- D3D12Renderer *renderer)
- {
- D3D12CommandBuffer *commandBuffer;
- if (renderer->availableCommandBufferCount == 0) {
- if (!D3D12_INTERNAL_AllocateCommandBuffer(renderer)) {
- return NULL;
- }
- }
- commandBuffer = renderer->availableCommandBuffers[renderer->availableCommandBufferCount - 1];
- renderer->availableCommandBufferCount -= 1;
- return commandBuffer;
- }
- static SDL_GPUCommandBuffer *D3D12_AcquireCommandBuffer(
- SDL_GPURenderer *driverData)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12CommandBuffer *commandBuffer;
- ID3D12DescriptorHeap *heaps[2];
- SDL_zeroa(heaps);
- SDL_LockMutex(renderer->acquireCommandBufferLock);
- commandBuffer = D3D12_INTERNAL_AcquireCommandBufferFromPool(renderer);
- SDL_UnlockMutex(renderer->acquireCommandBufferLock);
- if (commandBuffer == NULL) {
- return NULL;
- }
- // Set the descriptor heaps!
- commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] =
- D3D12_INTERNAL_AcquireDescriptorHeapFromPool(commandBuffer, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
- if (!commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]) {
- D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
- return NULL;
- }
- commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] =
- D3D12_INTERNAL_AcquireDescriptorHeapFromPool(commandBuffer, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
- if (!commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]) {
- D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
- return NULL;
- }
- heaps[0] = commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]->handle;
- heaps[1] = commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]->handle;
- ID3D12GraphicsCommandList_SetDescriptorHeaps(
- commandBuffer->graphicsCommandList,
- 2,
- heaps);
- // Set the bind state
- commandBuffer->currentGraphicsPipeline = NULL;
- SDL_zeroa(commandBuffer->colorTargetSubresources);
- SDL_zeroa(commandBuffer->colorResolveSubresources);
- commandBuffer->depthStencilTextureSubresource = NULL;
- SDL_zeroa(commandBuffer->vertexBuffers);
- SDL_zeroa(commandBuffer->vertexBufferOffsets);
- commandBuffer->vertexBufferCount = 0;
- SDL_zeroa(commandBuffer->vertexSamplerTextures);
- SDL_zeroa(commandBuffer->vertexSamplers);
- SDL_zeroa(commandBuffer->vertexStorageTextures);
- SDL_zeroa(commandBuffer->vertexStorageBuffers);
- SDL_zeroa(commandBuffer->vertexUniformBuffers);
- SDL_zeroa(commandBuffer->fragmentSamplerTextures);
- SDL_zeroa(commandBuffer->fragmentSamplers);
- SDL_zeroa(commandBuffer->fragmentStorageTextures);
- SDL_zeroa(commandBuffer->fragmentStorageBuffers);
- SDL_zeroa(commandBuffer->fragmentUniformBuffers);
- SDL_zeroa(commandBuffer->computeSamplerTextures);
- SDL_zeroa(commandBuffer->computeSamplers);
- SDL_zeroa(commandBuffer->computeReadOnlyStorageTextures);
- SDL_zeroa(commandBuffer->computeReadOnlyStorageBuffers);
- SDL_zeroa(commandBuffer->computeReadWriteStorageTextureSubresources);
- SDL_zeroa(commandBuffer->computeReadWriteStorageBuffers);
- SDL_zeroa(commandBuffer->computeUniformBuffers);
- commandBuffer->autoReleaseFence = true;
- return (SDL_GPUCommandBuffer *)commandBuffer;
- }
- static bool D3D12_WaitForSwapchain(
- SDL_GPURenderer *driverData,
- SDL_Window *window)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Cannot wait for a swapchain from an unclaimed window!", false);
- }
- if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
- if (!D3D12_WaitForFences(
- driverData,
- true,
- &windowData->inFlightFences[windowData->frameCounter],
- 1)) {
- return false;
- }
- }
- return true;
- }
- static bool D3D12_INTERNAL_AcquireSwapchainTexture(
- bool block,
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_Window *window,
- SDL_GPUTexture **swapchainTexture,
- Uint32 *swapchainTextureWidth,
- Uint32 *swapchainTextureHeight)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
- D3D12WindowData *windowData;
- Uint32 swapchainIndex;
- HRESULT res;
- *swapchainTexture = NULL;
- if (swapchainTextureWidth) {
- *swapchainTextureWidth = 0;
- }
- if (swapchainTextureHeight) {
- *swapchainTextureHeight = 0;
- }
- windowData = D3D12_INTERNAL_FetchWindowData(window);
- if (windowData == NULL) {
- SET_STRING_ERROR_AND_RETURN("Cannot acquire swapchain texture from an unclaimed window!", false);
- }
- if (windowData->needsSwapchainRecreate) {
- if (!D3D12_INTERNAL_ResizeSwapchain(renderer, windowData)) {
- return false;
- }
- }
- if (swapchainTextureWidth) {
- *swapchainTextureWidth = windowData->width;
- }
- if (swapchainTextureHeight) {
- *swapchainTextureHeight = windowData->height;
- }
- if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
- if (block) {
- // In VSYNC mode, block until the least recent presented frame is done
- if (!D3D12_WaitForFences(
- (SDL_GPURenderer *)renderer,
- true,
- &windowData->inFlightFences[windowData->frameCounter],
- 1)) {
- return false;
- }
- } else {
- // If we are not blocking and the least recent fence is not signaled,
- // return true to indicate that there is no error but rendering should be skipped.
- if (!D3D12_QueryFence(
- (SDL_GPURenderer *)renderer,
- windowData->inFlightFences[windowData->frameCounter])) {
- return true;
- }
- }
- D3D12_ReleaseFence(
- (SDL_GPURenderer *)renderer,
- windowData->inFlightFences[windowData->frameCounter]);
- windowData->inFlightFences[windowData->frameCounter] = NULL;
- }
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- // FIXME: Should this happen before the inFlightFences stuff above?
- windowData->frameToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL;
- renderer->device->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, NULL, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &windowData->frameToken);
- swapchainIndex = windowData->frameCounter;
- #else
- swapchainIndex = IDXGISwapChain3_GetCurrentBackBufferIndex(windowData->swapchain);
- // Set the handle on the windowData texture data.
- res = IDXGISwapChain_GetBuffer(
- windowData->swapchain,
- swapchainIndex,
- D3D_GUID(D3D_IID_ID3D12Resource),
- (void **)&windowData->textureContainers[swapchainIndex].activeTexture->resource);
- CHECK_D3D12_ERROR_AND_RETURN("Could not acquire swapchain!", false);
- #endif
- // Set up presentation
- if (d3d12CommandBuffer->presentDataCount == d3d12CommandBuffer->presentDataCapacity) {
- d3d12CommandBuffer->presentDataCapacity += 1;
- d3d12CommandBuffer->presentDatas = (D3D12PresentData *)SDL_realloc(
- d3d12CommandBuffer->presentDatas,
- d3d12CommandBuffer->presentDataCapacity * sizeof(D3D12PresentData));
- }
- d3d12CommandBuffer->presentDatas[d3d12CommandBuffer->presentDataCount].windowData = windowData;
- d3d12CommandBuffer->presentDatas[d3d12CommandBuffer->presentDataCount].swapchainImageIndex = swapchainIndex;
- d3d12CommandBuffer->presentDataCount += 1;
- // Set up resource barrier
- D3D12_RESOURCE_BARRIER barrierDesc;
- barrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
- barrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
- barrierDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
- barrierDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
- barrierDesc.Transition.pResource = windowData->textureContainers[swapchainIndex].activeTexture->resource;
- barrierDesc.Transition.Subresource = 0;
- ID3D12GraphicsCommandList_ResourceBarrier(
- d3d12CommandBuffer->graphicsCommandList,
- 1,
- &barrierDesc);
- *swapchainTexture = (SDL_GPUTexture*)&windowData->textureContainers[swapchainIndex];
- return true;
- }
- static bool D3D12_AcquireSwapchainTexture(
- SDL_GPUCommandBuffer *command_buffer,
- SDL_Window *window,
- SDL_GPUTexture **swapchain_texture,
- Uint32 *swapchain_texture_width,
- Uint32 *swapchain_texture_height
- ) {
- return D3D12_INTERNAL_AcquireSwapchainTexture(
- false,
- command_buffer,
- window,
- swapchain_texture,
- swapchain_texture_width,
- swapchain_texture_height);
- }
- static bool D3D12_WaitAndAcquireSwapchainTexture(
- SDL_GPUCommandBuffer *command_buffer,
- SDL_Window *window,
- SDL_GPUTexture **swapchain_texture,
- Uint32 *swapchain_texture_width,
- Uint32 *swapchain_texture_height
- ) {
- return D3D12_INTERNAL_AcquireSwapchainTexture(
- true,
- command_buffer,
- window,
- swapchain_texture,
- swapchain_texture_width,
- swapchain_texture_height);
- }
- static void D3D12_INTERNAL_PerformPendingDestroys(D3D12Renderer *renderer)
- {
- SDL_LockMutex(renderer->disposeLock);
- for (Sint32 i = renderer->buffersToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->buffersToDestroy[i]->referenceCount) == 0) {
- D3D12_INTERNAL_DestroyBuffer(
- renderer,
- renderer->buffersToDestroy[i]);
- renderer->buffersToDestroy[i] = renderer->buffersToDestroy[renderer->buffersToDestroyCount - 1];
- renderer->buffersToDestroyCount -= 1;
- }
- }
- for (Sint32 i = renderer->texturesToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->texturesToDestroy[i]->referenceCount) == 0) {
- D3D12_INTERNAL_DestroyTexture(
- renderer,
- renderer->texturesToDestroy[i]);
- renderer->texturesToDestroy[i] = renderer->texturesToDestroy[renderer->texturesToDestroyCount - 1];
- renderer->texturesToDestroyCount -= 1;
- }
- }
- for (Sint32 i = renderer->samplersToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->samplersToDestroy[i]->referenceCount) == 0) {
- D3D12_INTERNAL_DestroySampler(
- renderer,
- renderer->samplersToDestroy[i]);
- renderer->samplersToDestroy[i] = renderer->samplersToDestroy[renderer->samplersToDestroyCount - 1];
- renderer->samplersToDestroyCount -= 1;
- }
- }
- for (Sint32 i = renderer->graphicsPipelinesToDestroyCount - 1; i >= 0; i -= 1) {
- if (SDL_GetAtomicInt(&renderer->graphicsPipelinesToDestroy[i]->referenceCount) == 0) {
- D3D12_INTERNAL_DestroyGraphicsPipeline(
- 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) {
- D3D12_INTERNAL_DestroyComputePipeline(
- renderer->computePipelinesToDestroy[i]);
- renderer->computePipelinesToDestroy[i] = renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount - 1];
- renderer->computePipelinesToDestroyCount -= 1;
- }
- }
- SDL_UnlockMutex(renderer->disposeLock);
- }
- static bool D3D12_INTERNAL_CopyTextureDownload(
- D3D12CommandBuffer *commandBuffer,
- D3D12TextureDownload *download)
- {
- D3D12Renderer *renderer = commandBuffer->renderer;
- Uint8 *sourcePtr;
- Uint8 *destPtr;
- HRESULT res;
- res = ID3D12Resource_Map(
- download->temporaryBuffer->handle,
- 0,
- NULL,
- (void **)&sourcePtr);
- CHECK_D3D12_ERROR_AND_RETURN("Failed to map temporary buffer", false);
- res = ID3D12Resource_Map(
- download->destinationBuffer->handle,
- 0,
- NULL,
- (void **)&destPtr);
- CHECK_D3D12_ERROR_AND_RETURN("Failed to map destination buffer", false);
- for (Uint32 sliceIndex = 0; sliceIndex < download->depth; sliceIndex += 1) {
- for (Uint32 rowIndex = 0; rowIndex < download->height; rowIndex += 1) {
- SDL_memcpy(
- destPtr + download->bufferOffset + (sliceIndex * download->bytesPerDepthSlice) + (rowIndex * download->bytesPerRow),
- sourcePtr + (sliceIndex * download->height) + (rowIndex * download->alignedBytesPerRow),
- download->bytesPerRow);
- }
- }
- ID3D12Resource_Unmap(
- download->temporaryBuffer->handle,
- 0,
- NULL);
- ID3D12Resource_Unmap(
- download->destinationBuffer->handle,
- 0,
- NULL);
- return true;
- }
- static bool D3D12_INTERNAL_CleanCommandBuffer(
- D3D12Renderer *renderer,
- D3D12CommandBuffer *commandBuffer,
- bool cancel)
- {
- Uint32 i;
- HRESULT res;
- bool result = true;
- // Perform deferred texture data copies
- for (i = 0; i < commandBuffer->textureDownloadCount; i += 1) {
- if (!cancel) {
- result &= D3D12_INTERNAL_CopyTextureDownload(
- commandBuffer,
- commandBuffer->textureDownloads[i]);
- }
- SDL_free(commandBuffer->textureDownloads[i]);
- }
- commandBuffer->textureDownloadCount = 0;
- if (!result) {
- return false;
- }
- res = ID3D12CommandAllocator_Reset(commandBuffer->commandAllocator);
- CHECK_D3D12_ERROR_AND_RETURN("Could not reset command allocator", false);
- res = ID3D12GraphicsCommandList_Reset(
- commandBuffer->graphicsCommandList,
- commandBuffer->commandAllocator,
- NULL);
- CHECK_D3D12_ERROR_AND_RETURN("Could not reset command list", false);
- // Return descriptor heaps to pool
- D3D12_INTERNAL_ReturnDescriptorHeapToPool(
- renderer,
- commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]);
- D3D12_INTERNAL_ReturnDescriptorHeapToPool(
- renderer,
- commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]);
- // Uniform buffers are now available
- SDL_LockMutex(renderer->acquireUniformBufferLock);
- for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
- D3D12_INTERNAL_ReturnUniformBufferToPool(
- renderer,
- commandBuffer->usedUniformBuffers[i]);
- }
- commandBuffer->usedUniformBufferCount = 0;
- SDL_UnlockMutex(renderer->acquireUniformBufferLock);
- // TODO: More reference counting
- for (i = 0; i < commandBuffer->usedTextureCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
- }
- commandBuffer->usedTextureCount = 0;
- for (i = 0; i < commandBuffer->usedBufferCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
- }
- commandBuffer->usedBufferCount = 0;
- for (i = 0; i < commandBuffer->usedSamplerCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedSamplers[i]->referenceCount);
- }
- commandBuffer->usedSamplerCount = 0;
- for (i = 0; i < commandBuffer->usedGraphicsPipelineCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedGraphicsPipelines[i]->referenceCount);
- }
- commandBuffer->usedGraphicsPipelineCount = 0;
- for (i = 0; i < commandBuffer->usedComputePipelineCount; i += 1) {
- (void)SDL_AtomicDecRef(&commandBuffer->usedComputePipelines[i]->referenceCount);
- }
- commandBuffer->usedComputePipelineCount = 0;
- // Reset presentation
- commandBuffer->presentDataCount = 0;
- // The fence is now available (unless SubmitAndAcquireFence was called)
- if (commandBuffer->autoReleaseFence) {
- D3D12_ReleaseFence(
- (SDL_GPURenderer *)renderer,
- (SDL_GPUFence *)commandBuffer->inFlightFence);
- commandBuffer->inFlightFence = NULL;
- }
- // Return command buffer to pool
- SDL_LockMutex(renderer->acquireCommandBufferLock);
- if (renderer->availableCommandBufferCount == renderer->availableCommandBufferCapacity) {
- renderer->availableCommandBufferCapacity += 1;
- renderer->availableCommandBuffers = (D3D12CommandBuffer **)SDL_realloc(
- renderer->availableCommandBuffers,
- renderer->availableCommandBufferCapacity * sizeof(D3D12CommandBuffer *));
- }
- renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
- renderer->availableCommandBufferCount += 1;
- SDL_UnlockMutex(renderer->acquireCommandBufferLock);
- // Remove this command buffer from the submitted list
- if (!cancel) {
- for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
- if (renderer->submittedCommandBuffers[i] == commandBuffer) {
- renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
- renderer->submittedCommandBufferCount -= 1;
- }
- }
- }
- return true;
- }
- static bool D3D12_Submit(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
- ID3D12CommandList *commandLists[1];
- HRESULT res;
- SDL_LockMutex(renderer->submitLock);
- // Unmap uniform buffers
- for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
- if (d3d12CommandBuffer->vertexUniformBuffers[i] != NULL) {
- ID3D12Resource_Unmap(
- d3d12CommandBuffer->vertexUniformBuffers[i]->buffer->handle,
- 0,
- NULL);
- d3d12CommandBuffer->vertexUniformBuffers[i]->buffer->mapPointer = NULL;
- }
- if (d3d12CommandBuffer->fragmentUniformBuffers[i] != NULL) {
- ID3D12Resource_Unmap(
- d3d12CommandBuffer->fragmentUniformBuffers[i]->buffer->handle,
- 0,
- NULL);
- d3d12CommandBuffer->fragmentUniformBuffers[i]->buffer->mapPointer = NULL;
- }
- // TODO: compute uniforms
- }
- // Transition present textures to present mode
- for (Uint32 i = 0; i < d3d12CommandBuffer->presentDataCount; i += 1) {
- Uint32 swapchainIndex = d3d12CommandBuffer->presentDatas[i].swapchainImageIndex;
- D3D12TextureContainer *container = &d3d12CommandBuffer->presentDatas[i].windowData->textureContainers[swapchainIndex];
- D3D12TextureSubresource *subresource = D3D12_INTERNAL_FetchTextureSubresource(container, 0, 0);
- D3D12_RESOURCE_BARRIER barrierDesc;
- barrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
- barrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
- barrierDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
- barrierDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
- barrierDesc.Transition.pResource = subresource->parent->resource;
- barrierDesc.Transition.Subresource = subresource->index;
- ID3D12GraphicsCommandList_ResourceBarrier(
- d3d12CommandBuffer->graphicsCommandList,
- 1,
- &barrierDesc);
- }
- // Notify the command buffer that we have completed recording
- res = ID3D12GraphicsCommandList_Close(d3d12CommandBuffer->graphicsCommandList);
- CHECK_D3D12_ERROR_AND_RETURN("Failed to close command list!", false);
- res = ID3D12GraphicsCommandList_QueryInterface(
- d3d12CommandBuffer->graphicsCommandList,
- D3D_GUID(D3D_IID_ID3D12CommandList),
- (void **)&commandLists[0]);
- if (FAILED(res)) {
- SDL_UnlockMutex(renderer->submitLock);
- CHECK_D3D12_ERROR_AND_RETURN("Failed to convert command list!", false);
- }
- // Submit the command list to the queue
- ID3D12CommandQueue_ExecuteCommandLists(
- renderer->commandQueue,
- 1,
- commandLists);
- ID3D12CommandList_Release(commandLists[0]);
- // Acquire a fence and set it to the in-flight fence
- d3d12CommandBuffer->inFlightFence = D3D12_INTERNAL_AcquireFence(renderer);
- if (!d3d12CommandBuffer->inFlightFence) {
- SDL_UnlockMutex(renderer->submitLock);
- return false;
- }
- // Mark that a fence should be signaled after command list execution
- res = ID3D12CommandQueue_Signal(
- renderer->commandQueue,
- d3d12CommandBuffer->inFlightFence->handle,
- D3D12_FENCE_SIGNAL_VALUE);
- if (FAILED(res)) {
- SDL_UnlockMutex(renderer->submitLock);
- CHECK_D3D12_ERROR_AND_RETURN("Failed to enqueue fence signal!", false);
- }
- // Mark the command buffer as submitted
- if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) {
- renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
- renderer->submittedCommandBuffers = (D3D12CommandBuffer **)SDL_realloc(
- renderer->submittedCommandBuffers,
- sizeof(D3D12CommandBuffer *) * renderer->submittedCommandBufferCapacity);
- }
- renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = d3d12CommandBuffer;
- renderer->submittedCommandBufferCount += 1;
- bool result = true;
- // Present, if applicable
- for (Uint32 i = 0; i < d3d12CommandBuffer->presentDataCount; i += 1) {
- D3D12PresentData *presentData = &d3d12CommandBuffer->presentDatas[i];
- D3D12WindowData *windowData = presentData->windowData;
- #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
- D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParams;
- SDL_zero(planeParams);
- planeParams.Token = windowData->frameToken;
- planeParams.ResourceCount = 1;
- planeParams.ppResources = &windowData->textureContainers[windowData->frameCounter].activeTexture->resource;
- planeParams.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; // FIXME
- D3D12XBOX_PRESENT_PARAMETERS presentParams;
- SDL_zero(presentParams);
- presentParams.Flags = (windowData->present_mode == SDL_GPU_PRESENTMODE_IMMEDIATE) ? D3D12XBOX_PRESENT_FLAG_IMMEDIATE : D3D12XBOX_PRESENT_FLAG_NONE;
- renderer->commandQueue->PresentX(1, &planeParams, &presentParams);
- if (FAILED(res)) {
- result = false;
- }
- #else
- // NOTE: flip discard always supported since DXGI 1.4 is required
- Uint32 syncInterval = 1;
- if (windowData->present_mode == SDL_GPU_PRESENTMODE_IMMEDIATE ||
- windowData->present_mode == SDL_GPU_PRESENTMODE_MAILBOX) {
- syncInterval = 0;
- }
- Uint32 presentFlags = 0;
- if (renderer->supportsTearing &&
- windowData->present_mode == SDL_GPU_PRESENTMODE_IMMEDIATE) {
- presentFlags = DXGI_PRESENT_ALLOW_TEARING;
- }
- res = IDXGISwapChain_Present(
- windowData->swapchain,
- syncInterval,
- presentFlags);
- if (FAILED(res)) {
- result = false;
- }
- ID3D12Resource_Release(windowData->textureContainers[presentData->swapchainImageIndex].activeTexture->resource);
- #endif
- windowData->inFlightFences[windowData->frameCounter] = (SDL_GPUFence*)d3d12CommandBuffer->inFlightFence;
- (void)SDL_AtomicIncRef(&d3d12CommandBuffer->inFlightFence->referenceCount);
- windowData->frameCounter = (windowData->frameCounter + 1) % renderer->allowedFramesInFlight;
- }
- // Check for cleanups
- for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
- Uint64 fenceValue = ID3D12Fence_GetCompletedValue(
- renderer->submittedCommandBuffers[i]->inFlightFence->handle);
- if (fenceValue == D3D12_FENCE_SIGNAL_VALUE) {
- result &= D3D12_INTERNAL_CleanCommandBuffer(
- renderer,
- renderer->submittedCommandBuffers[i],
- false);
- }
- }
- D3D12_INTERNAL_PerformPendingDestroys(renderer);
- SDL_UnlockMutex(renderer->submitLock);
- return result;
- }
- static SDL_GPUFence *D3D12_SubmitAndAcquireFence(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- d3d12CommandBuffer->autoReleaseFence = false;
- if (!D3D12_Submit(commandBuffer)) {
- return NULL;
- }
- return (SDL_GPUFence *)d3d12CommandBuffer->inFlightFence;
- }
- static bool D3D12_Cancel(
- SDL_GPUCommandBuffer *commandBuffer)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
- bool result;
- HRESULT res;
- // Notify the command buffer that we have completed recording
- res = ID3D12GraphicsCommandList_Close(d3d12CommandBuffer->graphicsCommandList);
- CHECK_D3D12_ERROR_AND_RETURN("Failed to close command list!", false);
- d3d12CommandBuffer->autoReleaseFence = false;
- SDL_LockMutex(renderer->submitLock);
- result = D3D12_INTERNAL_CleanCommandBuffer(renderer, d3d12CommandBuffer, true);
- SDL_UnlockMutex(renderer->submitLock);
- return result;
- }
- static bool D3D12_Wait(
- SDL_GPURenderer *driverData)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12Fence *fence = D3D12_INTERNAL_AcquireFence(renderer);
- if (!fence) {
- return false;
- }
- HRESULT res;
- SDL_LockMutex(renderer->submitLock);
- if (renderer->commandQueue) {
- // Insert a signal into the end of the command queue...
- ID3D12CommandQueue_Signal(
- renderer->commandQueue,
- fence->handle,
- D3D12_FENCE_SIGNAL_VALUE);
- // ...and then block on it.
- if (ID3D12Fence_GetCompletedValue(fence->handle) != D3D12_FENCE_SIGNAL_VALUE) {
- res = ID3D12Fence_SetEventOnCompletion(
- fence->handle,
- D3D12_FENCE_SIGNAL_VALUE,
- fence->event);
- CHECK_D3D12_ERROR_AND_RETURN("Setting fence event failed", false);
- DWORD waitResult = WaitForSingleObject(fence->event, INFINITE);
- if (waitResult == WAIT_FAILED) {
- SDL_UnlockMutex(renderer->submitLock);
- SET_STRING_ERROR_AND_RETURN("Wait failed", false); // TODO: is there a better way to report this?
- }
- }
- }
- D3D12_ReleaseFence(
- (SDL_GPURenderer *)renderer,
- (SDL_GPUFence *)fence);
- bool result = true;
- // Clean up
- for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
- result &= D3D12_INTERNAL_CleanCommandBuffer(renderer, renderer->submittedCommandBuffers[i], false);
- }
- D3D12_INTERNAL_PerformPendingDestroys(renderer);
- SDL_UnlockMutex(renderer->submitLock);
- return result;
- }
- static bool D3D12_WaitForFences(
- SDL_GPURenderer *driverData,
- bool waitAll,
- SDL_GPUFence *const *fences,
- Uint32 numFences)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12Fence *fence;
- HANDLE *events = SDL_stack_alloc(HANDLE, numFences);
- HRESULT res;
- SDL_LockMutex(renderer->submitLock);
- for (Uint32 i = 0; i < numFences; i += 1) {
- fence = (D3D12Fence *)fences[i];
- res = ID3D12Fence_SetEventOnCompletion(
- fence->handle,
- D3D12_FENCE_SIGNAL_VALUE,
- fence->event);
- CHECK_D3D12_ERROR_AND_RETURN("Setting fence event failed", false);
- events[i] = fence->event;
- }
- DWORD waitResult = WaitForMultipleObjects(
- numFences,
- events,
- waitAll,
- INFINITE);
- if (waitResult == WAIT_FAILED) {
- SDL_UnlockMutex(renderer->submitLock);
- SET_STRING_ERROR_AND_RETURN("Wait failed", false); // TODO: is there a better way to report this?
- }
- bool result = true;
- // Check for cleanups
- for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
- Uint64 fenceValue = ID3D12Fence_GetCompletedValue(
- renderer->submittedCommandBuffers[i]->inFlightFence->handle);
- if (fenceValue == D3D12_FENCE_SIGNAL_VALUE) {
- result &= D3D12_INTERNAL_CleanCommandBuffer(
- renderer,
- renderer->submittedCommandBuffers[i],
- false);
- }
- }
- D3D12_INTERNAL_PerformPendingDestroys(renderer);
- SDL_stack_free(events);
- SDL_UnlockMutex(renderer->submitLock);
- return result;
- }
- // Feature Queries
- static bool D3D12_SupportsTextureFormat(
- SDL_GPURenderer *driverData,
- SDL_GPUTextureFormat format,
- SDL_GPUTextureType type,
- SDL_GPUTextureUsageFlags usage)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- DXGI_FORMAT dxgiFormat = SDLToD3D12_TextureFormat[format];
- D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport = { dxgiFormat, D3D12_FORMAT_SUPPORT1_NONE, D3D12_FORMAT_SUPPORT2_NONE };
- HRESULT res;
- res = ID3D12Device_CheckFeatureSupport(
- renderer->device,
- D3D12_FEATURE_FORMAT_SUPPORT,
- &formatSupport,
- sizeof(formatSupport));
- if (FAILED(res)) {
- // Format is apparently unknown
- return false;
- }
- // Is the texture type supported?
- if (type == SDL_GPU_TEXTURETYPE_2D && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D)) {
- return false;
- }
- if (type == SDL_GPU_TEXTURETYPE_2D_ARRAY && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D)) {
- return false;
- }
- if (type == SDL_GPU_TEXTURETYPE_3D && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE3D)) {
- return false;
- }
- if (type == SDL_GPU_TEXTURETYPE_CUBE && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURECUBE)) {
- return false;
- }
- if (type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURECUBE)) {
- return false;
- }
- // Are the usage flags supported?
- if ((usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE)) {
- return false;
- }
- if ((usage & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD)) {
- return false;
- }
- if ((usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) && !(formatSupport.Support2 & D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE)) {
- return false;
- }
- if ((usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE) && !(formatSupport.Support2 & D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD)) {
- return false;
- }
- if ((usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET)) {
- return false;
- }
- // Special case check for depth, because D3D12 is great.
- formatSupport.Format = SDLToD3D12_DepthFormat[format];
- formatSupport.Support1 = D3D12_FORMAT_SUPPORT1_NONE;
- formatSupport.Support2 = D3D12_FORMAT_SUPPORT2_NONE;
- res = ID3D12Device_CheckFeatureSupport(
- renderer->device,
- D3D12_FEATURE_FORMAT_SUPPORT,
- &formatSupport,
- sizeof(formatSupport));
- if (FAILED(res)) {
- // Format is apparently unknown
- return false;
- }
- if ((usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL)) {
- return false;
- }
- return true;
- }
- static bool D3D12_SupportsSampleCount(
- SDL_GPURenderer *driverData,
- SDL_GPUTextureFormat format,
- SDL_GPUSampleCount sampleCount)
- {
- D3D12Renderer *renderer = (D3D12Renderer *)driverData;
- D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS featureData;
- HRESULT res;
- #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
- featureData.Flags = (D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG)0;
- #else
- featureData.Flags = (D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS)0;
- #endif
- featureData.Format = SDLToD3D12_TextureFormat[format];
- featureData.SampleCount = SDLToD3D12_SampleCount[sampleCount];
- res = ID3D12Device_CheckFeatureSupport(
- renderer->device,
- D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
- &featureData,
- sizeof(featureData));
- return SUCCEEDED(res) && featureData.NumQualityLevels > 0;
- }
- static void D3D12_INTERNAL_InitBlitResources(
- D3D12Renderer *renderer)
- {
- SDL_GPUShaderCreateInfo shaderCreateInfo;
- SDL_GPUSamplerCreateInfo samplerCreateInfo;
- renderer->blitPipelineCapacity = 2;
- renderer->blitPipelineCount = 0;
- renderer->blitPipelines = (BlitPipelineCacheEntry *)SDL_malloc(
- renderer->blitPipelineCapacity * sizeof(BlitPipelineCacheEntry));
- // Fullscreen vertex shader
- SDL_zero(shaderCreateInfo);
- shaderCreateInfo.code = (Uint8 *)D3D12_FullscreenVert;
- shaderCreateInfo.code_size = sizeof(D3D12_FullscreenVert);
- shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX;
- shaderCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
- shaderCreateInfo.entrypoint = "main";
- renderer->blitVertexShader = D3D12_CreateShader(
- (SDL_GPURenderer *)renderer,
- &shaderCreateInfo);
- if (renderer->blitVertexShader == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile vertex shader for blit!");
- }
- // BlitFrom2D pixel shader
- shaderCreateInfo.code = (Uint8 *)D3D12_BlitFrom2D;
- shaderCreateInfo.code_size = sizeof(D3D12_BlitFrom2D);
- shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
- shaderCreateInfo.num_samplers = 1;
- shaderCreateInfo.num_uniform_buffers = 1;
- renderer->blitFrom2DShader = D3D12_CreateShader(
- (SDL_GPURenderer *)renderer,
- &shaderCreateInfo);
- if (renderer->blitFrom2DShader == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2D pixel shader!");
- }
- // BlitFrom2DArray pixel shader
- shaderCreateInfo.code = (Uint8 *)D3D12_BlitFrom2DArray;
- shaderCreateInfo.code_size = sizeof(D3D12_BlitFrom2DArray);
- renderer->blitFrom2DArrayShader = D3D12_CreateShader(
- (SDL_GPURenderer *)renderer,
- &shaderCreateInfo);
- if (renderer->blitFrom2DArrayShader == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2DArray pixel shader!");
- }
- // BlitFrom3D pixel shader
- shaderCreateInfo.code = (Uint8 *)D3D12_BlitFrom3D;
- shaderCreateInfo.code_size = sizeof(D3D12_BlitFrom3D);
- renderer->blitFrom3DShader = D3D12_CreateShader(
- (SDL_GPURenderer *)renderer,
- &shaderCreateInfo);
- if (renderer->blitFrom3DShader == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom3D pixel shader!");
- }
- // BlitFromCube pixel shader
- shaderCreateInfo.code = (Uint8 *)D3D12_BlitFromCube;
- shaderCreateInfo.code_size = sizeof(D3D12_BlitFromCube);
- renderer->blitFromCubeShader = D3D12_CreateShader(
- (SDL_GPURenderer *)renderer,
- &shaderCreateInfo);
- if (renderer->blitFromCubeShader == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCube pixel shader!");
- }
- // BlitFromCubeArray pixel shader
- shaderCreateInfo.code = (Uint8 *)D3D12_BlitFromCubeArray;
- shaderCreateInfo.code_size = sizeof(D3D12_BlitFromCubeArray);
- renderer->blitFromCubeArrayShader = D3D12_CreateShader(
- (SDL_GPURenderer *)renderer,
- &shaderCreateInfo);
- if (renderer->blitFromCubeArrayShader == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCubeArray pixel shader!");
- }
- // Create samplers
- samplerCreateInfo.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
- samplerCreateInfo.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
- samplerCreateInfo.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
- samplerCreateInfo.enable_anisotropy = 0;
- samplerCreateInfo.enable_compare = 0;
- samplerCreateInfo.mag_filter = SDL_GPU_FILTER_NEAREST;
- samplerCreateInfo.min_filter = SDL_GPU_FILTER_NEAREST;
- samplerCreateInfo.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
- samplerCreateInfo.mip_lod_bias = 0.0f;
- samplerCreateInfo.min_lod = 0;
- samplerCreateInfo.max_lod = 1000;
- samplerCreateInfo.max_anisotropy = 1.0f;
- samplerCreateInfo.compare_op = SDL_GPU_COMPAREOP_NEVER;
- renderer->blitNearestSampler = D3D12_CreateSampler(
- (SDL_GPURenderer *)renderer,
- &samplerCreateInfo);
- if (renderer->blitNearestSampler == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit nearest sampler!");
- }
- samplerCreateInfo.mag_filter = SDL_GPU_FILTER_LINEAR;
- samplerCreateInfo.min_filter = SDL_GPU_FILTER_LINEAR;
- samplerCreateInfo.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
- renderer->blitLinearSampler = D3D12_CreateSampler(
- (SDL_GPURenderer *)renderer,
- &samplerCreateInfo);
- if (renderer->blitLinearSampler == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit linear sampler!");
- }
- }
- static bool D3D12_PrepareDriver(SDL_VideoDevice *_this)
- {
- #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
- return true;
- #else
- SDL_SharedObject *d3d12Dll;
- SDL_SharedObject *dxgiDll;
- PFN_D3D12_CREATE_DEVICE D3D12CreateDeviceFunc;
- PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc;
- HRESULT res;
- ID3D12Device *device;
- IDXGIFactory1 *factory;
- IDXGIFactory4 *factory4;
- IDXGIFactory6 *factory6;
- IDXGIAdapter1 *adapter;
- // Can we load D3D12?
- d3d12Dll = SDL_LoadObject(D3D12_DLL);
- if (d3d12Dll == NULL) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Could not find " D3D12_DLL);
- return false;
- }
- D3D12CreateDeviceFunc = (PFN_D3D12_CREATE_DEVICE)SDL_LoadFunction(
- d3d12Dll,
- D3D12_CREATE_DEVICE_FUNC);
- if (D3D12CreateDeviceFunc == NULL) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Could not find function " D3D12_CREATE_DEVICE_FUNC " in " D3D12_DLL);
- SDL_UnloadObject(d3d12Dll);
- return false;
- }
- // Can we load DXGI?
- dxgiDll = SDL_LoadObject(DXGI_DLL);
- if (dxgiDll == NULL) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Could not find " DXGI_DLL);
- return false;
- }
- CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction(
- dxgiDll,
- CREATE_DXGI_FACTORY1_FUNC);
- if (CreateDXGIFactoryFunc == NULL) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Could not find function " CREATE_DXGI_FACTORY1_FUNC " in " DXGI_DLL);
- SDL_UnloadObject(dxgiDll);
- return false;
- }
- // Can we create a device?
- // Create the DXGI factory
- res = CreateDXGIFactoryFunc(
- &D3D_IID_IDXGIFactory1,
- (void **)&factory);
- if (FAILED(res)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Could not create DXGIFactory");
- SDL_UnloadObject(d3d12Dll);
- SDL_UnloadObject(dxgiDll);
- return false;
- }
- // Check for DXGI 1.4 support
- res = IDXGIFactory1_QueryInterface(
- factory,
- D3D_GUID(D3D_IID_IDXGIFactory4),
- (void **)&factory4);
- if (FAILED(res)) {
- IDXGIFactory1_Release(factory);
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Failed to find DXGI1.4 support, required for DX12");
- SDL_UnloadObject(d3d12Dll);
- SDL_UnloadObject(dxgiDll);
- return false;
- }
- IDXGIFactory4_Release(factory4);
- res = IDXGIFactory1_QueryInterface(
- factory,
- D3D_GUID(D3D_IID_IDXGIFactory6),
- (void **)&factory6);
- if (SUCCEEDED(res)) {
- res = IDXGIFactory6_EnumAdapterByGpuPreference(
- factory6,
- 0,
- DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
- D3D_GUID(D3D_IID_IDXGIAdapter1),
- (void **)&adapter);
- IDXGIFactory6_Release(factory6);
- } else {
- res = IDXGIFactory1_EnumAdapters1(
- factory,
- 0,
- &adapter);
- }
- if (FAILED(res)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Failed to find adapter for D3D12Device");
- IDXGIFactory1_Release(factory);
- SDL_UnloadObject(d3d12Dll);
- SDL_UnloadObject(dxgiDll);
- return false;
- }
- res = D3D12CreateDeviceFunc(
- (IUnknown *)adapter,
- D3D_FEATURE_LEVEL_CHOICE,
- D3D_GUID(D3D_IID_ID3D12Device),
- (void **)&device);
- if (SUCCEEDED(res)) {
- ID3D12Device_Release(device);
- }
- IDXGIAdapter1_Release(adapter);
- IDXGIFactory1_Release(factory);
- SDL_UnloadObject(d3d12Dll);
- SDL_UnloadObject(dxgiDll);
- if (FAILED(res)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Could not create D3D12Device with feature level " D3D_FEATURE_LEVEL_CHOICE_STR);
- return false;
- }
- return true;
- #endif
- }
- #if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) && defined(HAVE_IDXGIINFOQUEUE)
- static void D3D12_INTERNAL_TryInitializeDXGIDebug(D3D12Renderer *renderer)
- {
- PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc;
- HRESULT res;
- renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL);
- if (renderer->dxgidebug_dll == NULL) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not find " DXGIDEBUG_DLL);
- return;
- }
- DXGIGetDebugInterfaceFunc = (PFN_DXGI_GET_DEBUG_INTERFACE)SDL_LoadFunction(
- renderer->dxgidebug_dll,
- DXGI_GET_DEBUG_INTERFACE_FUNC);
- if (DXGIGetDebugInterfaceFunc == NULL) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " DXGI_GET_DEBUG_INTERFACE_FUNC);
- return;
- }
- res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, (void **)&renderer->dxgiDebug);
- if (FAILED(res)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIDebug interface");
- }
- res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, (void **)&renderer->dxgiInfoQueue);
- if (FAILED(res)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIInfoQueue interface");
- }
- }
- #endif
- static void D3D12_INTERNAL_TryInitializeD3D12Debug(D3D12Renderer *renderer)
- {
- PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterfaceFunc;
- HRESULT res;
- D3D12GetDebugInterfaceFunc = (PFN_D3D12_GET_DEBUG_INTERFACE)SDL_LoadFunction(
- renderer->d3d12_dll,
- D3D12_GET_DEBUG_INTERFACE_FUNC);
- if (D3D12GetDebugInterfaceFunc == NULL) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " D3D12_GET_DEBUG_INTERFACE_FUNC);
- return;
- }
- res = D3D12GetDebugInterfaceFunc(D3D_GUID(D3D_IID_ID3D12Debug), (void **)&renderer->d3d12Debug);
- if (FAILED(res)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get ID3D12Debug interface");
- return;
- }
- ID3D12Debug_EnableDebugLayer(renderer->d3d12Debug);
- }
- #if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- static bool D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *renderer)
- {
- ID3D12InfoQueue *infoQueue = NULL;
- D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO };
- D3D12_INFO_QUEUE_FILTER filter;
- HRESULT res;
- res = ID3D12Device_QueryInterface(
- renderer->device,
- D3D_GUID(D3D_IID_ID3D12InfoQueue),
- (void **)&infoQueue);
- if (FAILED(res)) {
- CHECK_D3D12_ERROR_AND_RETURN("Failed to convert ID3D12Device to ID3D12InfoQueue", false);
- }
- SDL_zero(filter);
- filter.DenyList.NumSeverities = 1;
- filter.DenyList.pSeverityList = severities;
- ID3D12InfoQueue_PushStorageFilter(
- infoQueue,
- &filter);
- ID3D12InfoQueue_SetBreakOnSeverity(
- infoQueue,
- D3D12_MESSAGE_SEVERITY_CORRUPTION,
- true);
- ID3D12InfoQueue_Release(infoQueue);
- return true;
- }
- static void WINAPI D3D12_INTERNAL_OnD3D12DebugInfoMsg(
- D3D12_MESSAGE_CATEGORY category,
- D3D12_MESSAGE_SEVERITY severity,
- D3D12_MESSAGE_ID id,
- LPCSTR description,
- void *context)
- {
- char *catStr;
- char *sevStr;
- switch (category) {
- case D3D12_MESSAGE_CATEGORY_APPLICATION_DEFINED:
- catStr = "APPLICATION_DEFINED";
- break;
- case D3D12_MESSAGE_CATEGORY_MISCELLANEOUS:
- catStr = "MISCELLANEOUS";
- break;
- case D3D12_MESSAGE_CATEGORY_INITIALIZATION:
- catStr = "INITIALIZATION";
- break;
- case D3D12_MESSAGE_CATEGORY_CLEANUP:
- catStr = "CLEANUP";
- break;
- case D3D12_MESSAGE_CATEGORY_COMPILATION:
- catStr = "COMPILATION";
- break;
- case D3D12_MESSAGE_CATEGORY_STATE_CREATION:
- catStr = "STATE_CREATION";
- break;
- case D3D12_MESSAGE_CATEGORY_STATE_SETTING:
- catStr = "STATE_SETTING";
- break;
- case D3D12_MESSAGE_CATEGORY_STATE_GETTING:
- catStr = "STATE_GETTING";
- break;
- case D3D12_MESSAGE_CATEGORY_RESOURCE_MANIPULATION:
- catStr = "RESOURCE_MANIPULATION";
- break;
- case D3D12_MESSAGE_CATEGORY_EXECUTION:
- catStr = "EXECUTION";
- break;
- case D3D12_MESSAGE_CATEGORY_SHADER:
- catStr = "SHADER";
- break;
- default:
- catStr = "UNKNOWN";
- break;
- }
- switch (severity) {
- case D3D12_MESSAGE_SEVERITY_CORRUPTION:
- sevStr = "CORRUPTION";
- break;
- case D3D12_MESSAGE_SEVERITY_ERROR:
- sevStr = "ERROR";
- break;
- case D3D12_MESSAGE_SEVERITY_WARNING:
- sevStr = "WARNING";
- break;
- case D3D12_MESSAGE_SEVERITY_INFO:
- sevStr = "INFO";
- break;
- case D3D12_MESSAGE_SEVERITY_MESSAGE:
- sevStr = "MESSAGE";
- break;
- default:
- sevStr = "UNKNOWN";
- break;
- }
- if (severity <= D3D12_MESSAGE_SEVERITY_ERROR) {
- SDL_LogError(
- SDL_LOG_CATEGORY_GPU,
- "D3D12 ERROR: %s [%s %s #%d]",
- description,
- catStr,
- sevStr,
- id);
- } else {
- SDL_LogWarn(
- SDL_LOG_CATEGORY_GPU,
- "D3D12 WARNING: %s [%s %s #%d]",
- description,
- catStr,
- sevStr,
- id);
- }
- }
- static void D3D12_INTERNAL_TryInitializeD3D12DebugInfoLogger(D3D12Renderer *renderer)
- {
- ID3D12InfoQueue1 *infoQueue = NULL;
- HRESULT res;
- res = ID3D12Device_QueryInterface(
- renderer->device,
- D3D_GUID(D3D_IID_ID3D12InfoQueue1),
- (void **)&infoQueue);
- if (FAILED(res)) {
- return;
- }
- ID3D12InfoQueue1_RegisterMessageCallback(
- infoQueue,
- D3D12_INTERNAL_OnD3D12DebugInfoMsg,
- D3D12_MESSAGE_CALLBACK_FLAG_NONE,
- NULL,
- NULL);
- ID3D12InfoQueue1_Release(infoQueue);
- }
- #endif
- static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SDL_PropertiesID props)
- {
- SDL_GPUDevice *result;
- D3D12Renderer *renderer;
- HRESULT res;
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- PFN_D3D12_XBOX_CREATE_DEVICE D3D12XboxCreateDeviceFunc;
- D3D12XBOX_CREATE_DEVICE_PARAMETERS createDeviceParams;
- #else
- PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc;
- IDXGIFactory1 *factory1;
- IDXGIFactory5 *factory5;
- IDXGIFactory6 *factory6;
- DXGI_ADAPTER_DESC1 adapterDesc;
- LARGE_INTEGER umdVersion;
- PFN_D3D12_CREATE_DEVICE D3D12CreateDeviceFunc;
- #endif
- D3D12_FEATURE_DATA_ARCHITECTURE architecture;
- D3D12_COMMAND_QUEUE_DESC queueDesc;
- renderer = (D3D12Renderer *)SDL_calloc(1, sizeof(D3D12Renderer));
- #if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- // Load the DXGI library
- renderer->dxgi_dll = SDL_LoadObject(DXGI_DLL);
- if (renderer->dxgi_dll == NULL) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- SET_STRING_ERROR_AND_RETURN("Could not find " DXGI_DLL, NULL);
- }
- #ifdef HAVE_IDXGIINFOQUEUE
- // Initialize the DXGI debug layer, if applicable
- if (debugMode) {
- D3D12_INTERNAL_TryInitializeDXGIDebug(renderer);
- }
- #endif
- // Load the CreateDXGIFactory1 function
- CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction(
- renderer->dxgi_dll,
- CREATE_DXGI_FACTORY1_FUNC);
- if (CreateDXGIFactoryFunc == NULL) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- SET_STRING_ERROR_AND_RETURN("Could not load function: " CREATE_DXGI_FACTORY1_FUNC, NULL);
- }
- // Create the DXGI factory
- res = CreateDXGIFactoryFunc(
- &D3D_IID_IDXGIFactory1,
- (void **)&factory1);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not create DXGIFactory", NULL);
- }
- // Check for DXGI 1.4 support
- res = IDXGIFactory1_QueryInterface(
- factory1,
- D3D_GUID(D3D_IID_IDXGIFactory4),
- (void **)&renderer->factory);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("DXGI1.4 support not found, required for DX12", NULL);
- }
- IDXGIFactory1_Release(factory1);
- // Check for explicit tearing support
- res = IDXGIFactory4_QueryInterface(
- renderer->factory,
- D3D_GUID(D3D_IID_IDXGIFactory5),
- (void **)&factory5);
- if (SUCCEEDED(res)) {
- res = IDXGIFactory5_CheckFeatureSupport(
- factory5,
- DXGI_FEATURE_PRESENT_ALLOW_TEARING,
- &renderer->supportsTearing,
- sizeof(renderer->supportsTearing));
- if (FAILED(res)) {
- renderer->supportsTearing = false;
- }
- IDXGIFactory5_Release(factory5);
- }
- // Select the appropriate device for rendering
- res = IDXGIFactory4_QueryInterface(
- renderer->factory,
- D3D_GUID(D3D_IID_IDXGIFactory6),
- (void **)&factory6);
- if (SUCCEEDED(res)) {
- res = IDXGIFactory6_EnumAdapterByGpuPreference(
- factory6,
- 0,
- preferLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
- D3D_GUID(D3D_IID_IDXGIAdapter1),
- (void **)&renderer->adapter);
- IDXGIFactory6_Release(factory6);
- } else {
- res = IDXGIFactory4_EnumAdapters1(
- renderer->factory,
- 0,
- &renderer->adapter);
- }
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not find adapter for D3D12Device", NULL);
- }
- // Get information about the selected adapter. Used for logging info.
- res = IDXGIAdapter1_GetDesc1(renderer->adapter, &adapterDesc);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not get adapter description", NULL);
- }
- res = IDXGIAdapter1_CheckInterfaceSupport(renderer->adapter, D3D_GUID(D3D_IID_IDXGIDevice), &umdVersion);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not get adapter driver version", NULL);
- }
- SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: D3D12");
- SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "D3D12 Adapter: %S", adapterDesc.Description);
- SDL_LogInfo(
- SDL_LOG_CATEGORY_GPU,
- "D3D12 Driver: %d.%d.%d.%d",
- HIWORD(umdVersion.HighPart),
- LOWORD(umdVersion.HighPart),
- HIWORD(umdVersion.LowPart),
- LOWORD(umdVersion.LowPart));
- #endif
- // Load the D3D library
- renderer->d3d12_dll = SDL_LoadObject(D3D12_DLL);
- if (renderer->d3d12_dll == NULL) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- SET_STRING_ERROR_AND_RETURN("Could not find " D3D12_DLL, NULL);
- }
- // Load the CreateDevice function
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- D3D12XboxCreateDeviceFunc = (PFN_D3D12_XBOX_CREATE_DEVICE)SDL_LoadFunction(
- renderer->d3d12_dll,
- "D3D12XboxCreateDevice");
- if (D3D12XboxCreateDeviceFunc == NULL) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- SET_STRING_ERROR_AND_RETURN("Could not load function: D3D12XboxCreateDevice", NULL);
- }
- #else
- D3D12CreateDeviceFunc = (PFN_D3D12_CREATE_DEVICE)SDL_LoadFunction(
- renderer->d3d12_dll,
- D3D12_CREATE_DEVICE_FUNC);
- if (D3D12CreateDeviceFunc == NULL) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- SET_STRING_ERROR_AND_RETURN("Could not load function: " D3D12_CREATE_DEVICE_FUNC, NULL);
- }
- #endif
- renderer->D3D12SerializeRootSignature_func = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)SDL_LoadFunction(
- renderer->d3d12_dll,
- D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC);
- if (renderer->D3D12SerializeRootSignature_func == NULL) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- SET_STRING_ERROR_AND_RETURN("Could not load function: " D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC, NULL);
- }
- // Initialize the D3D12 debug layer, if applicable
- if (debugMode) {
- D3D12_INTERNAL_TryInitializeD3D12Debug(renderer);
- }
- // Create the D3D12Device
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- if (s_Device != NULL) {
- renderer->device = s_Device;
- } else {
- SDL_zero(createDeviceParams);
- createDeviceParams.Version = D3D12_SDK_VERSION;
- createDeviceParams.GraphicsCommandQueueRingSizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
- createDeviceParams.GraphicsScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
- createDeviceParams.ComputeScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
- createDeviceParams.DisableGeometryShaderAllocations = TRUE;
- createDeviceParams.DisableTessellationShaderAllocations = TRUE;
- #if defined(SDL_PLATFORM_XBOXSERIES)
- createDeviceParams.DisableDXR = TRUE;
- #endif
- if (debugMode) {
- createDeviceParams.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_DEBUG;
- }
- res = D3D12XboxCreateDeviceFunc(
- NULL,
- &createDeviceParams,
- IID_GRAPHICS_PPV_ARGS(&renderer->device));
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not create D3D12Device", NULL);
- }
- res = renderer->device->SetFrameIntervalX(
- NULL,
- D3D12XBOX_FRAME_INTERVAL_60_HZ,
- renderer->allowedFramesInFlight - 1,
- D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not get set frame interval", NULL);
- }
- res = renderer->device->ScheduleFrameEventX(
- D3D12XBOX_FRAME_EVENT_ORIGIN,
- 0,
- NULL,
- D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not schedule frame events", NULL);
- }
- s_Device = renderer->device;
- }
- #else
- res = D3D12CreateDeviceFunc(
- (IUnknown *)renderer->adapter,
- D3D_FEATURE_LEVEL_CHOICE,
- D3D_GUID(D3D_IID_ID3D12Device),
- (void **)&renderer->device);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not create D3D12Device", NULL);
- }
- // Initialize the D3D12 debug info queue, if applicable
- if (debugMode) {
- if (!D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(renderer)) {
- return NULL;
- }
- D3D12_INTERNAL_TryInitializeD3D12DebugInfoLogger(renderer);
- }
- #endif
- // Check UMA
- architecture.NodeIndex = 0;
- res = ID3D12Device_CheckFeatureSupport(
- renderer->device,
- D3D12_FEATURE_ARCHITECTURE,
- &architecture,
- sizeof(D3D12_FEATURE_DATA_ARCHITECTURE));
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not get device architecture", NULL);
- }
- renderer->UMA = (bool)architecture.UMA;
- renderer->UMACacheCoherent = (bool)architecture.CacheCoherentUMA;
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- renderer->GPUUploadHeapSupported = false;
- #else
- // Check "GPU Upload Heap" support (for fast uniform buffers)
- D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16; // 15 wasn't enough, huh?
- renderer->GPUUploadHeapSupported = false;
- res = ID3D12Device_CheckFeatureSupport(
- renderer->device,
- D3D12_FEATURE_D3D12_OPTIONS16,
- &options16,
- sizeof(options16));
- if (SUCCEEDED(res)) {
- renderer->GPUUploadHeapSupported = options16.GPUUploadHeapSupported;
- }
- #endif
- // Create command queue
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- if (s_CommandQueue != NULL) {
- renderer->commandQueue = s_CommandQueue;
- } else {
- #endif
- queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
- queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
- queueDesc.NodeMask = 0;
- queueDesc.Priority = 0;
- res = ID3D12Device_CreateCommandQueue(
- renderer->device,
- &queueDesc,
- D3D_GUID(D3D_IID_ID3D12CommandQueue),
- (void **)&renderer->commandQueue);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not create D3D12CommandQueue", NULL);
- }
- #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- s_CommandQueue = renderer->commandQueue;
- }
- #endif
- // Create indirect command signatures
- D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc;
- D3D12_INDIRECT_ARGUMENT_DESC indirectArgumentDesc;
- SDL_zero(indirectArgumentDesc);
- indirectArgumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
- commandSignatureDesc.NodeMask = 0;
- commandSignatureDesc.ByteStride = sizeof(SDL_GPUIndirectDrawCommand);
- commandSignatureDesc.NumArgumentDescs = 1;
- commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
- res = ID3D12Device_CreateCommandSignature(
- renderer->device,
- &commandSignatureDesc,
- NULL,
- D3D_GUID(D3D_IID_ID3D12CommandSignature),
- (void **)&renderer->indirectDrawCommandSignature);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not create indirect draw command signature", NULL);
- }
- indirectArgumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;
- commandSignatureDesc.ByteStride = sizeof(SDL_GPUIndexedIndirectDrawCommand);
- commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
- res = ID3D12Device_CreateCommandSignature(
- renderer->device,
- &commandSignatureDesc,
- NULL,
- D3D_GUID(D3D_IID_ID3D12CommandSignature),
- (void **)&renderer->indirectIndexedDrawCommandSignature);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not create indirect indexed draw command signature", NULL);
- }
- indirectArgumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH;
- commandSignatureDesc.ByteStride = sizeof(SDL_GPUIndirectDispatchCommand);
- commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
- res = ID3D12Device_CreateCommandSignature(
- renderer->device,
- &commandSignatureDesc,
- NULL,
- D3D_GUID(D3D_IID_ID3D12CommandSignature),
- (void **)&renderer->indirectDispatchCommandSignature);
- if (FAILED(res)) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- CHECK_D3D12_ERROR_AND_RETURN("Could not create indirect dispatch command signature", NULL);
- }
- // Initialize pools
- renderer->submittedCommandBufferCapacity = 4;
- renderer->submittedCommandBufferCount = 0;
- renderer->submittedCommandBuffers = (D3D12CommandBuffer **)SDL_calloc(
- renderer->submittedCommandBufferCapacity, sizeof(D3D12CommandBuffer *));
- if (!renderer->submittedCommandBuffers) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- renderer->uniformBufferPoolCapacity = 4;
- renderer->uniformBufferPoolCount = 0;
- renderer->uniformBufferPool = (D3D12UniformBuffer **)SDL_calloc(
- renderer->uniformBufferPoolCapacity, sizeof(D3D12UniformBuffer *));
- if (!renderer->uniformBufferPool) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- renderer->claimedWindowCapacity = 4;
- renderer->claimedWindowCount = 0;
- renderer->claimedWindows = (D3D12WindowData **)SDL_calloc(
- renderer->claimedWindowCapacity, sizeof(D3D12WindowData *));
- if (!renderer->claimedWindows) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- renderer->availableFenceCapacity = 4;
- renderer->availableFenceCount = 0;
- renderer->availableFences = (D3D12Fence **)SDL_calloc(
- renderer->availableFenceCapacity, sizeof(D3D12Fence *));
- if (!renderer->availableFences) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- // Initialize CPU descriptor heaps
- for (Uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1) {
- renderer->stagingDescriptorHeaps[i] = D3D12_INTERNAL_CreateDescriptorHeap(
- renderer,
- (D3D12_DESCRIPTOR_HEAP_TYPE)i,
- (i <= D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) ? VIEW_SAMPLER_STAGING_DESCRIPTOR_COUNT : TARGET_STAGING_DESCRIPTOR_COUNT,
- true);
- if (renderer->stagingDescriptorHeaps[i] == NULL) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- }
- // Initialize GPU descriptor heaps
- for (Uint32 i = 0; i < 2; i += 1) {
- renderer->descriptorHeapPools[i].lock = SDL_CreateMutex();
- renderer->descriptorHeapPools[i].capacity = 4;
- renderer->descriptorHeapPools[i].count = 4;
- renderer->descriptorHeapPools[i].heaps = (D3D12DescriptorHeap **)SDL_calloc(
- renderer->descriptorHeapPools[i].capacity, sizeof(D3D12DescriptorHeap *));
- for (Uint32 j = 0; j < renderer->descriptorHeapPools[i].capacity; j += 1) {
- renderer->descriptorHeapPools[i].heaps[j] = D3D12_INTERNAL_CreateDescriptorHeap(
- renderer,
- (D3D12_DESCRIPTOR_HEAP_TYPE)i,
- i == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ? VIEW_GPU_DESCRIPTOR_COUNT : SAMPLER_GPU_DESCRIPTOR_COUNT,
- false);
- if (renderer->descriptorHeapPools[i].heaps[j] == NULL) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- }
- }
- // Deferred resource releasing
- renderer->buffersToDestroyCapacity = 4;
- renderer->buffersToDestroyCount = 0;
- renderer->buffersToDestroy = (D3D12Buffer **)SDL_calloc(
- renderer->buffersToDestroyCapacity, sizeof(D3D12Buffer *));
- if (!renderer->buffersToDestroy) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- renderer->texturesToDestroyCapacity = 4;
- renderer->texturesToDestroyCount = 0;
- renderer->texturesToDestroy = (D3D12Texture **)SDL_calloc(
- renderer->texturesToDestroyCapacity, sizeof(D3D12Texture *));
- if (!renderer->texturesToDestroy) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- renderer->samplersToDestroyCapacity = 4;
- renderer->samplersToDestroyCount = 0;
- renderer->samplersToDestroy = (D3D12Sampler **)SDL_calloc(
- renderer->samplersToDestroyCapacity, sizeof(D3D12Sampler *));
- if (!renderer->samplersToDestroy) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- renderer->graphicsPipelinesToDestroyCapacity = 4;
- renderer->graphicsPipelinesToDestroyCount = 0;
- renderer->graphicsPipelinesToDestroy = (D3D12GraphicsPipeline **)SDL_calloc(
- renderer->graphicsPipelinesToDestroyCapacity, sizeof(D3D12GraphicsPipeline *));
- if (!renderer->graphicsPipelinesToDestroy) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- renderer->computePipelinesToDestroyCapacity = 4;
- renderer->computePipelinesToDestroyCount = 0;
- renderer->computePipelinesToDestroy = (D3D12ComputePipeline **)SDL_calloc(
- renderer->computePipelinesToDestroyCapacity, sizeof(D3D12ComputePipeline *));
- if (!renderer->computePipelinesToDestroy) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- // Locks
- renderer->stagingDescriptorHeapLock = SDL_CreateMutex();
- renderer->acquireCommandBufferLock = SDL_CreateMutex();
- renderer->acquireUniformBufferLock = SDL_CreateMutex();
- renderer->submitLock = SDL_CreateMutex();
- renderer->windowLock = SDL_CreateMutex();
- renderer->fenceLock = SDL_CreateMutex();
- renderer->disposeLock = SDL_CreateMutex();
- renderer->debug_mode = debugMode;
- renderer->allowedFramesInFlight = 2;
- renderer->semantic = SDL_GetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING, "TEXCOORD");
- // Blit resources
- D3D12_INTERNAL_InitBlitResources(renderer);
- // Create the SDL_GPU Device
- result = (SDL_GPUDevice *)SDL_calloc(1, sizeof(SDL_GPUDevice));
- if (!result) {
- D3D12_INTERNAL_DestroyRenderer(renderer);
- return NULL;
- }
- ASSIGN_DRIVER(D3D12)
- result->driverData = (SDL_GPURenderer *)renderer;
- result->debug_mode = debugMode;
- renderer->sdlGPUDevice = result;
- return result;
- }
- SDL_GPUBootstrap D3D12Driver = {
- "direct3d12",
- SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_DXBC,
- D3D12_PrepareDriver,
- D3D12_CreateDevice
- };
- #endif // SDL_GPU_D3D12
- // GDK-specific APIs
- #ifdef SDL_PLATFORM_GDK
- void SDL_GDKSuspendGPU(SDL_GPUDevice *device)
- {
- #if defined(SDL_GPU_D3D12) && (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- D3D12Renderer *renderer = (D3D12Renderer *)device->driverData;
- HRESULT res;
- if (device == NULL) {
- SET_STRING_ERROR_AND_RETURN("Invalid GPU device", );
- }
- SDL_LockMutex(renderer->submitLock);
- res = renderer->commandQueue->SuspendX(0);
- if (FAILED(res)) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "SuspendX failed: %X", res);
- }
- SDL_UnlockMutex(renderer->submitLock);
- #endif
- }
- void SDL_GDKResumeGPU(SDL_GPUDevice *device)
- {
- #if defined(SDL_GPU_D3D12) && (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
- D3D12Renderer *renderer = (D3D12Renderer *)device->driverData;
- HRESULT res;
- if (device == NULL) {
- SET_STRING_ERROR_AND_RETURN("Invalid GPU device", );
- }
- SDL_LockMutex(renderer->submitLock);
- res = renderer->commandQueue->ResumeX();
- if (FAILED(res)) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "ResumeX failed: %X", res);
- }
- SDL_UnlockMutex(renderer->submitLock);
- res = renderer->device->SetFrameIntervalX(
- NULL,
- D3D12XBOX_FRAME_INTERVAL_60_HZ,
- renderer->allowedFramesInFlight - 1,
- D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);
- if (FAILED(res)) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not set frame interval: %X", res);
- }
- res = renderer->device->ScheduleFrameEventX(
- D3D12XBOX_FRAME_EVENT_ORIGIN,
- 0,
- NULL,
- D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE);
- if (FAILED(res)) {
- SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not schedule frame events: %X", res);
- }
- #endif
- }
- #endif // SDL_PLATFORM_GDK
|