| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515 |
- /*
- 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"
- #include "SDL_hashtable.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) \
- if (renderer->debug_mode) { \
- SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
- } \
- SDL_SetError(fmt, msg);
- #define SET_ERROR_AND_RETURN(fmt, msg, ret) \
- if (renderer->debug_mode) { \
- SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
- } \
- SDL_SetError(fmt, msg); \
- return ret; \
- #define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
- #define CHECK_D3D12_ERROR_AND_RETURN(msg, ret) \
- if (FAILED(res)) { \
- D3D12_INTERNAL_SetError(renderer, msg, res); \
- return ret; \
- }
- // 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 } };
- #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 } };
- // 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);
- 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_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
- };
- SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TextureFormat, SDL_arraysize(SDLToD3D12_TextureFormat) == 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];
- SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
- 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;
- void *dxgi_dll;
- void *dxgidebug_dll;
- #endif
- ID3D12Debug *d3d12Debug;
- bool supportsTearing;
- void *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;
- // 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_TextureFormat[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;
- 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;
- 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);
- }
- 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 = SDLToD3D12_TextureFormat[createinfo->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 = SDLToD3D12_TextureFormat[createinfo->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_TextureFormat[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 outlen = wstrSize;
- 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,
- &outlen);
- *outSize = (Uint32)outlen;
- // 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;
- }
- 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);
- }
- 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);
- }
- 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);
- }
- 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 similar to D3D11 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 < MAX_FRAMES_IN_FLIGHT; 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;
- // 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 < MAX_FRAMES_IN_FLIGHT; 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 < MAX_FRAMES_IN_FLIGHT; 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 < MAX_FRAMES_IN_FLIGHT; 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);
- }
- int w, h;
- SDL_SyncWindow(windowData->window);
- SDL_GetWindowSizeInPixels(
- windowData->window,
- &w,
- &h);
- // Resize the swapchain
- HRESULT res = IDXGISwapChain_ResizeBuffers(
- windowData->swapchain,
- 0, // Keep buffer count the same
- w,
- h,
- 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 < MAX_FRAMES_IN_FLIGHT; i += 1) {
- if (!D3D12_INTERNAL_InitializeSwapchainTexture(
- renderer,
- windowData->swapchain,
- windowData->swapchainComposition,
- i,
- &windowData->textureContainers[i])) {
- return false;
- }
- }
- windowData->needsSwapchainRecreate = false;
- return true;
- }
- static void D3D12_INTERNAL_DestroySwapchain(
- D3D12Renderer *renderer,
- D3D12WindowData *windowData)
- {
- // Release views and clean up
- for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; 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];
- // Initialize the swapchain buffer descriptor
- swapchainDesc.Width = 0;
- swapchainDesc.Height = 0;
- swapchainDesc.Format = swapchainFormat;
- swapchainDesc.SampleDesc.Count = 1;
- swapchainDesc.SampleDesc.Quality = 0;
- swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapchainDesc.BufferCount = MAX_FRAMES_IN_FLIGHT;
- 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_APPLICATION,
- "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_APPLICATION,
- "MakeWindowAssociation failed! Error Code: " HRESULT_FMT,
- res);
- }
- // We're done with the parent now
- IDXGIFactory1_Release(pParent);
- }
- // Initialize the swapchain data
- windowData->swapchain = swapchain3;
- windowData->present_mode = presentMode;
- windowData->swapchainComposition = swapchainComposition;
- windowData->swapchainColorSpace = SwapchainCompositionToColorSpace[swapchainComposition];
- windowData->frameCounter = 0;
- // 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 < MAX_FRAMES_IN_FLIGHT; 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 {
- SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Window already claimed!");
- 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) {
- SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Window already unclaimed!");
- return;
- }
- 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 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 = CreateEventEx(NULL, 0, 0, EVENT_ALL_ACCESS);
- 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_AcquireSwapchainTexture(
- SDL_GPUCommandBuffer *commandBuffer,
- SDL_Window *window,
- SDL_GPUTexture **swapchainTexture)
- {
- D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
- D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
- D3D12WindowData *windowData;
- Uint32 swapchainIndex;
- HRESULT res;
- *swapchainTexture = NULL;
- 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 (windowData->inFlightFences[windowData->frameCounter] != NULL) {
- if (windowData->present_mode == SDL_GPU_PRESENTMODE_VSYNC) {
- // 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 (!D3D12_QueryFence(
- (SDL_GPURenderer *)renderer,
- windowData->inFlightFences[windowData->frameCounter])) {
- /*
- * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled,
- * return true to indicate that there is no error but rendering should be skipped
- */
- return true;
- }
- }
- 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 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)
- {
- Uint32 i;
- HRESULT res;
- bool result = true;
- // Perform deferred texture data copies
- for (i = 0; i < commandBuffer->textureDownloadCount; i += 1) {
- 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
- 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) % MAX_FRAMES_IN_FLIGHT;
- }
- // 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]);
- }
- }
- 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;
- D3D12_Submit(commandBuffer);
- return (SDL_GPUFence *)d3d12CommandBuffer->inFlightFence;
- }
- 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]);
- }
- 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]);
- }
- }
- 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;
- }
- 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_ALWAYS;
- 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
- void *d3d12Dll;
- void *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_APPLICATION, "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_APPLICATION, "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_APPLICATION, "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_APPLICATION, "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_APPLICATION, "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_APPLICATION, "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_APPLICATION, "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_APPLICATION, "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_APPLICATION, "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_APPLICATION, "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_APPLICATION, "Could not get IDXGIDebug interface");
- }
- res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, (void **)&renderer->dxgiInfoQueue);
- if (FAILED(res)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "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_APPLICATION, "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_ERROR,
- true);
- ID3D12InfoQueue_SetBreakOnSeverity(
- infoQueue,
- D3D12_MESSAGE_SEVERITY_CORRUPTION,
- true);
- ID3D12InfoQueue_Release(infoQueue);
- return true;
- }
- #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;
- 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);
- }
- SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: D3D12");
- SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "D3D12 Adapter: %S", adapterDesc.Description);
- #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,
- MAX_FRAMES_IN_FLIGHT - 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;
- }
- }
- #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->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,
- 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,
- MAX_FRAMES_IN_FLIGHT - 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
|