SDL_gpu_d3d11.c 226 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "SDL_internal.h"
  19. #ifdef SDL_GPU_D3D11
  20. #define D3D11_NO_HELPERS
  21. #define CINTERFACE
  22. #define COBJMACROS
  23. #include <d3d11.h>
  24. #include <d3d11_1.h>
  25. #include <dxgi.h>
  26. #include <dxgi1_6.h>
  27. #include <dxgidebug.h>
  28. #include "../SDL_sysgpu.h"
  29. #ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
  30. #define HAVE_IDXGIINFOQUEUE
  31. #endif
  32. // Function Pointer Signatures
  33. typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY1)(const GUID *riid, void **ppFactory);
  34. typedef HRESULT(WINAPI *PFN_DXGI_GET_DEBUG_INTERFACE)(const GUID *riid, void **ppDebug);
  35. // IIDs (from https://www.magnumdb.com/)
  36. static const IID D3D_IID_IDXGIFactory1 = { 0x770aae78, 0xf26f, 0x4dba, { 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87 } };
  37. static const IID D3D_IID_IDXGIFactory4 = { 0x1bc6ea02, 0xef36, 0x464f, { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a } };
  38. static const IID D3D_IID_IDXGIFactory5 = { 0x7632e1f5, 0xee65, 0x4dca, { 0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d } };
  39. static const IID D3D_IID_IDXGIFactory6 = { 0xc1b6694f, 0xff09, 0x44a9, { 0xb0, 0x3c, 0x77, 0x90, 0x0a, 0x0a, 0x1d, 0x17 } };
  40. static const IID D3D_IID_IDXGIAdapter1 = { 0x29038f61, 0x3839, 0x4626, { 0x91, 0xfd, 0x08, 0x68, 0x79, 0x01, 0x1a, 0x05 } };
  41. static const IID D3D_IID_IDXGISwapChain3 = { 0x94d99bdb, 0xf1f8, 0x4ab0, { 0xb2, 0x36, 0x7d, 0xa0, 0x17, 0x0e, 0xda, 0xb1 } };
  42. static const IID D3D_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
  43. static const IID D3D_IID_ID3DUserDefinedAnnotation = { 0xb2daad8b, 0x03d4, 0x4dbf, { 0x95, 0xeb, 0x32, 0xab, 0x4b, 0x63, 0xd0, 0xab } };
  44. static const IID D3D_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } };
  45. static const IID D3D_IID_IDXGIDebug = { 0x119e7452, 0xde9e, 0x40fe, { 0x88, 0x06, 0x88, 0xf9, 0x0c, 0x12, 0xb4, 0x41 } };
  46. #ifdef HAVE_IDXGIINFOQUEUE
  47. static const IID D3D_IID_IDXGIInfoQueue = { 0xd67441c7, 0x672a, 0x476f, { 0x9e, 0x82, 0xcd, 0x55, 0xb4, 0x49, 0x49, 0xce } };
  48. #endif
  49. static const GUID D3D_IID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, { 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 } };
  50. static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x08 } };
  51. // Defines
  52. #if defined(_WIN32)
  53. #define D3D11_DLL "d3d11.dll"
  54. #define DXGI_DLL "dxgi.dll"
  55. #define DXGIDEBUG_DLL "dxgidebug.dll"
  56. #elif defined(__APPLE__)
  57. #define D3D11_DLL "libdxvk_d3d11.0.dylib"
  58. #define DXGI_DLL "libdxvk_dxgi.0.dylib"
  59. #define DXGIDEBUG_DLL "libdxvk_dxgidebug.0.dylib"
  60. #else
  61. #define D3D11_DLL "libdxvk_d3d11.so.0"
  62. #define DXGI_DLL "libdxvk_dxgi.so.0"
  63. #define DXGIDEBUG_DLL "libdxvk_dxgidebug.so.0"
  64. #endif
  65. #define D3D11_CREATE_DEVICE_FUNC "D3D11CreateDevice"
  66. #define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1"
  67. #define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
  68. #define WINDOW_PROPERTY_DATA "SDL_GPUD3D11WindowPropertyData"
  69. #define SDL_GPU_SHADERSTAGE_COMPUTE 2
  70. #ifdef _WIN32
  71. #define HRESULT_FMT "(0x%08lX)"
  72. #else
  73. #define HRESULT_FMT "(0x%08X)"
  74. #endif
  75. // Built-in shaders, compiled with compile_shaders.bat
  76. #define g_FullscreenVert D3D11_FullscreenVert
  77. #define g_BlitFrom2D D3D11_BlitFrom2D
  78. #define g_BlitFrom2DArray D3D11_BlitFrom2DArray
  79. #define g_BlitFrom3D D3D11_BlitFrom3D
  80. #define g_BlitFromCube D3D11_BlitFromCube
  81. #define g_BlitFromCubeArray D3D11_BlitFromCubeArray
  82. #include "D3D11_Blit.h"
  83. #undef g_FullscreenVert
  84. #undef g_BlitFrom2D
  85. #undef g_BlitFrom2DArray
  86. #undef g_BlitFrom3D
  87. #undef g_BlitFromCube
  88. #undef g_BlitFromCubeArray
  89. // Macros
  90. #define SET_ERROR_AND_RETURN(fmt, msg, ret) \
  91. if (renderer->debugMode) { \
  92. SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
  93. } \
  94. SDL_SetError(fmt, msg); \
  95. return ret; \
  96. #define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
  97. #define CHECK_D3D11_ERROR_AND_RETURN(msg, ret) \
  98. if (FAILED(res)) { \
  99. D3D11_INTERNAL_SetError(renderer, msg, res); \
  100. return ret; \
  101. }
  102. #define TRACK_RESOURCE(resource, type, array, count, capacity) \
  103. Uint32 i; \
  104. \
  105. for (i = 0; i < commandBuffer->count; i += 1) { \
  106. if (commandBuffer->array[i] == resource) { \
  107. return; \
  108. } \
  109. } \
  110. \
  111. if (commandBuffer->count == commandBuffer->capacity) { \
  112. commandBuffer->capacity += 1; \
  113. commandBuffer->array = SDL_realloc( \
  114. commandBuffer->array, \
  115. commandBuffer->capacity * sizeof(type)); \
  116. } \
  117. commandBuffer->array[commandBuffer->count] = resource; \
  118. commandBuffer->count += 1; \
  119. SDL_AtomicIncRef(&resource->referenceCount);
  120. // Forward Declarations
  121. static bool D3D11_Wait(SDL_GPURenderer *driverData);
  122. static void D3D11_ReleaseWindow(
  123. SDL_GPURenderer *driverData,
  124. SDL_Window *window);
  125. static void D3D11_INTERNAL_DestroyBlitPipelines(SDL_GPURenderer *driverData);
  126. // Conversions
  127. static SDL_GPUTextureFormat SwapchainCompositionToSDLTextureFormat[] = {
  128. SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM, // SDR
  129. SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, // SDR_SRGB
  130. SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT, // HDR
  131. SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM, // HDR_ADVANCED
  132. };
  133. static DXGI_FORMAT SwapchainCompositionToTextureFormat[] = {
  134. DXGI_FORMAT_B8G8R8A8_UNORM, // SDR
  135. DXGI_FORMAT_B8G8R8A8_UNORM, /* SDR_SRGB */ // NOTE: The RTV uses the sRGB format
  136. DXGI_FORMAT_R16G16B16A16_FLOAT, // HDR
  137. DXGI_FORMAT_R10G10B10A2_UNORM, // HDR_ADVANCED
  138. };
  139. static DXGI_COLOR_SPACE_TYPE SwapchainCompositionToColorSpace[] = {
  140. DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, // SDR
  141. DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, // SDR_SRGB
  142. DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709, // HDR
  143. DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 // HDR_ADVANCED
  144. };
  145. static DXGI_FORMAT SDLToD3D11_TextureFormat[] = {
  146. DXGI_FORMAT_UNKNOWN, // INVALID
  147. DXGI_FORMAT_A8_UNORM, // A8_UNORM
  148. DXGI_FORMAT_R8_UNORM, // R8_UNORM
  149. DXGI_FORMAT_R8G8_UNORM, // R8G8_UNORM
  150. DXGI_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
  151. DXGI_FORMAT_R16_UNORM, // R16_UNORM
  152. DXGI_FORMAT_R16G16_UNORM, // R16G16_UNORM
  153. DXGI_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
  154. DXGI_FORMAT_R10G10B10A2_UNORM, // R10G10B10A2_UNORM
  155. DXGI_FORMAT_B5G6R5_UNORM, // B5G6R5_UNORM
  156. DXGI_FORMAT_B5G5R5A1_UNORM, // B5G5R5A1_UNORM
  157. DXGI_FORMAT_B4G4R4A4_UNORM, // B4G4R4A4_UNORM
  158. DXGI_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
  159. DXGI_FORMAT_BC1_UNORM, // BC1_UNORM
  160. DXGI_FORMAT_BC2_UNORM, // BC2_UNORM
  161. DXGI_FORMAT_BC3_UNORM, // BC3_UNORM
  162. DXGI_FORMAT_BC4_UNORM, // BC4_UNORM
  163. DXGI_FORMAT_BC5_UNORM, // BC5_UNORM
  164. DXGI_FORMAT_BC7_UNORM, // BC7_UNORM
  165. DXGI_FORMAT_BC6H_SF16, // BC6H_FLOAT
  166. DXGI_FORMAT_BC6H_UF16, // BC6H_UFLOAT
  167. DXGI_FORMAT_R8_SNORM, // R8_SNORM
  168. DXGI_FORMAT_R8G8_SNORM, // R8G8_SNORM
  169. DXGI_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
  170. DXGI_FORMAT_R16_SNORM, // R16_SNORM
  171. DXGI_FORMAT_R16G16_SNORM, // R16G16_SNORM
  172. DXGI_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
  173. DXGI_FORMAT_R16_FLOAT, // R16_FLOAT
  174. DXGI_FORMAT_R16G16_FLOAT, // R16G16_FLOAT
  175. DXGI_FORMAT_R16G16B16A16_FLOAT, // R16G16B16A16_FLOAT
  176. DXGI_FORMAT_R32_FLOAT, // R32_FLOAT
  177. DXGI_FORMAT_R32G32_FLOAT, // R32G32_FLOAT
  178. DXGI_FORMAT_R32G32B32A32_FLOAT, // R32G32B32A32_FLOAT
  179. DXGI_FORMAT_R11G11B10_FLOAT, // R11G11B10_UFLOAT
  180. DXGI_FORMAT_R8_UINT, // R8_UINT
  181. DXGI_FORMAT_R8G8_UINT, // R8G8_UINT
  182. DXGI_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
  183. DXGI_FORMAT_R16_UINT, // R16_UINT
  184. DXGI_FORMAT_R16G16_UINT, // R16G16_UINT
  185. DXGI_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
  186. DXGI_FORMAT_R32_UINT, // R32_UINT
  187. DXGI_FORMAT_R32G32_UINT, // R32G32_UINT
  188. DXGI_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
  189. DXGI_FORMAT_R8_SINT, // R8_INT
  190. DXGI_FORMAT_R8G8_SINT, // R8G8_INT
  191. DXGI_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
  192. DXGI_FORMAT_R16_SINT, // R16_INT
  193. DXGI_FORMAT_R16G16_SINT, // R16G16_INT
  194. DXGI_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
  195. DXGI_FORMAT_R32_SINT, // R32_INT
  196. DXGI_FORMAT_R32G32_SINT, // R32G32_INT
  197. DXGI_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
  198. DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, // R8G8B8A8_UNORM_SRGB
  199. DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, // B8G8R8A8_UNORM_SRGB
  200. DXGI_FORMAT_BC1_UNORM_SRGB, // BC1_UNORM_SRGB
  201. DXGI_FORMAT_BC2_UNORM_SRGB, // BC2_UNORM_SRGB
  202. DXGI_FORMAT_BC3_UNORM_SRGB, // BC3_UNORM_SRGB
  203. DXGI_FORMAT_BC7_UNORM_SRGB, // BC7_UNORM_SRGB
  204. DXGI_FORMAT_D16_UNORM, // D16_UNORM
  205. DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM
  206. DXGI_FORMAT_D32_FLOAT, // D32_FLOAT
  207. DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT
  208. DXGI_FORMAT_D32_FLOAT_S8X24_UINT, // D32_FLOAT_S8_UINT
  209. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM
  210. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM
  211. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM
  212. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM
  213. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM
  214. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM
  215. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM
  216. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM
  217. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM
  218. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM
  219. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM
  220. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM
  221. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM
  222. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM
  223. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB
  224. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB
  225. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB
  226. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB
  227. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB
  228. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB
  229. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB
  230. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB
  231. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB
  232. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB
  233. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB
  234. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB
  235. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB
  236. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB
  237. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT
  238. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT
  239. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT
  240. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT
  241. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT
  242. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT
  243. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT
  244. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT
  245. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT
  246. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT
  247. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT
  248. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT
  249. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT
  250. DXGI_FORMAT_UNKNOWN, // SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT
  251. };
  252. SDL_COMPILE_TIME_ASSERT(SDLToD3D11_TextureFormat, SDL_arraysize(SDLToD3D11_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
  253. static DXGI_FORMAT SDLToD3D11_VertexFormat[] = {
  254. DXGI_FORMAT_UNKNOWN, // INVALID
  255. DXGI_FORMAT_R32_SINT, // INT
  256. DXGI_FORMAT_R32G32_SINT, // INT2
  257. DXGI_FORMAT_R32G32B32_SINT, // INT3
  258. DXGI_FORMAT_R32G32B32A32_SINT, // INT4
  259. DXGI_FORMAT_R32_UINT, // UINT
  260. DXGI_FORMAT_R32G32_UINT, // UINT2
  261. DXGI_FORMAT_R32G32B32_UINT, // UINT3
  262. DXGI_FORMAT_R32G32B32A32_UINT, // UINT4
  263. DXGI_FORMAT_R32_FLOAT, // FLOAT
  264. DXGI_FORMAT_R32G32_FLOAT, // FLOAT2
  265. DXGI_FORMAT_R32G32B32_FLOAT, // FLOAT3
  266. DXGI_FORMAT_R32G32B32A32_FLOAT, // FLOAT4
  267. DXGI_FORMAT_R8G8_SINT, // BYTE2
  268. DXGI_FORMAT_R8G8B8A8_SINT, // BYTE4
  269. DXGI_FORMAT_R8G8_UINT, // UBYTE2
  270. DXGI_FORMAT_R8G8B8A8_UINT, // UBYTE4
  271. DXGI_FORMAT_R8G8_SNORM, // BYTE2_NORM
  272. DXGI_FORMAT_R8G8B8A8_SNORM, // BYTE4_NORM
  273. DXGI_FORMAT_R8G8_UNORM, // UBYTE2_NORM
  274. DXGI_FORMAT_R8G8B8A8_UNORM, // UBYTE4_NORM
  275. DXGI_FORMAT_R16G16_SINT, // SHORT2
  276. DXGI_FORMAT_R16G16B16A16_SINT, // SHORT4
  277. DXGI_FORMAT_R16G16_UINT, // USHORT2
  278. DXGI_FORMAT_R16G16B16A16_UINT, // USHORT4
  279. DXGI_FORMAT_R16G16_SNORM, // SHORT2_NORM
  280. DXGI_FORMAT_R16G16B16A16_SNORM, // SHORT4_NORM
  281. DXGI_FORMAT_R16G16_UNORM, // USHORT2_NORM
  282. DXGI_FORMAT_R16G16B16A16_UNORM, // USHORT4_NORM
  283. DXGI_FORMAT_R16G16_FLOAT, // HALF2
  284. DXGI_FORMAT_R16G16B16A16_FLOAT // HALF4
  285. };
  286. SDL_COMPILE_TIME_ASSERT(SDLToD3D11_VertexFormat, SDL_arraysize(SDLToD3D11_VertexFormat) == SDL_GPU_VERTEXELEMENTFORMAT_MAX_ENUM_VALUE);
  287. static Uint32 SDLToD3D11_SampleCount[] = {
  288. 1, // SDL_GPU_SAMPLECOUNT_1
  289. 2, // SDL_GPU_SAMPLECOUNT_2
  290. 4, // SDL_GPU_SAMPLECOUNT_4
  291. 8 // SDL_GPU_SAMPLECOUNT_8
  292. };
  293. static DXGI_FORMAT SDLToD3D11_IndexType[] = {
  294. DXGI_FORMAT_R16_UINT, // 16BIT
  295. DXGI_FORMAT_R32_UINT // 32BIT
  296. };
  297. static D3D11_PRIMITIVE_TOPOLOGY SDLToD3D11_PrimitiveType[] = {
  298. D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // TRIANGLELIST
  299. D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, // TRIANGLESTRIP
  300. D3D_PRIMITIVE_TOPOLOGY_LINELIST, // LINELIST
  301. D3D_PRIMITIVE_TOPOLOGY_LINESTRIP, // LINESTRIP
  302. D3D_PRIMITIVE_TOPOLOGY_POINTLIST // POINTLIST
  303. };
  304. static D3D11_CULL_MODE SDLToD3D11_CullMode[] = {
  305. D3D11_CULL_NONE, // NONE
  306. D3D11_CULL_FRONT, // FRONT
  307. D3D11_CULL_BACK // BACK
  308. };
  309. static D3D11_BLEND SDLToD3D11_BlendFactor[] = {
  310. D3D11_BLEND_ZERO, // INVALID
  311. D3D11_BLEND_ZERO, // ZERO
  312. D3D11_BLEND_ONE, // ONE
  313. D3D11_BLEND_SRC_COLOR, // SRC_COLOR
  314. D3D11_BLEND_INV_SRC_COLOR, // ONE_MINUS_SRC_COLOR
  315. D3D11_BLEND_DEST_COLOR, // DST_COLOR
  316. D3D11_BLEND_INV_DEST_COLOR, // ONE_MINUS_DST_COLOR
  317. D3D11_BLEND_SRC_ALPHA, // SRC_ALPHA
  318. D3D11_BLEND_INV_SRC_ALPHA, // ONE_MINUS_SRC_ALPHA
  319. D3D11_BLEND_DEST_ALPHA, // DST_ALPHA
  320. D3D11_BLEND_INV_DEST_ALPHA, // ONE_MINUS_DST_ALPHA
  321. D3D11_BLEND_BLEND_FACTOR, // CONSTANT_COLOR
  322. D3D11_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR
  323. D3D11_BLEND_SRC_ALPHA_SAT, // SRC_ALPHA_SATURATE
  324. };
  325. SDL_COMPILE_TIME_ASSERT(SDLToD3D11_BlendFactor, SDL_arraysize(SDLToD3D11_BlendFactor) == SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE);
  326. static D3D11_BLEND SDLToD3D11_BlendFactorAlpha[] = {
  327. D3D11_BLEND_ZERO, // ALPHA
  328. D3D11_BLEND_ZERO, // ZERO
  329. D3D11_BLEND_ONE, // ONE
  330. D3D11_BLEND_SRC_ALPHA, // SRC_COLOR
  331. D3D11_BLEND_INV_SRC_ALPHA, // ONE_MINUS_SRC_COLOR
  332. D3D11_BLEND_DEST_ALPHA, // DST_COLOR
  333. D3D11_BLEND_INV_DEST_ALPHA, // ONE_MINUS_DST_COLOR
  334. D3D11_BLEND_SRC_ALPHA, // SRC_ALPHA
  335. D3D11_BLEND_INV_SRC_ALPHA, // ONE_MINUS_SRC_ALPHA
  336. D3D11_BLEND_DEST_ALPHA, // DST_ALPHA
  337. D3D11_BLEND_INV_DEST_ALPHA, // ONE_MINUS_DST_ALPHA
  338. D3D11_BLEND_BLEND_FACTOR, // CONSTANT_COLOR
  339. D3D11_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR
  340. D3D11_BLEND_SRC_ALPHA_SAT, // SRC_ALPHA_SATURATE
  341. };
  342. SDL_COMPILE_TIME_ASSERT(SDLToD3D11_BlendFactorAlpha, SDL_arraysize(SDLToD3D11_BlendFactorAlpha) == SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE);
  343. static D3D11_BLEND_OP SDLToD3D11_BlendOp[] = {
  344. D3D11_BLEND_OP_ADD, // INVALID
  345. D3D11_BLEND_OP_ADD, // ADD
  346. D3D11_BLEND_OP_SUBTRACT, // SUBTRACT
  347. D3D11_BLEND_OP_REV_SUBTRACT, // REVERSE_SUBTRACT
  348. D3D11_BLEND_OP_MIN, // MIN
  349. D3D11_BLEND_OP_MAX // MAX
  350. };
  351. SDL_COMPILE_TIME_ASSERT(SDLToD3D11_BlendOp, SDL_arraysize(SDLToD3D11_BlendOp) == SDL_GPU_BLENDOP_MAX_ENUM_VALUE);
  352. static D3D11_COMPARISON_FUNC SDLToD3D11_CompareOp[] = {
  353. D3D11_COMPARISON_NEVER, // INVALID
  354. D3D11_COMPARISON_NEVER, // NEVER
  355. D3D11_COMPARISON_LESS, // LESS
  356. D3D11_COMPARISON_EQUAL, // EQUAL
  357. D3D11_COMPARISON_LESS_EQUAL, // LESS_OR_EQUAL
  358. D3D11_COMPARISON_GREATER, // GREATER
  359. D3D11_COMPARISON_NOT_EQUAL, // NOT_EQUAL
  360. D3D11_COMPARISON_GREATER_EQUAL, // GREATER_OR_EQUAL
  361. D3D11_COMPARISON_ALWAYS // ALWAYS
  362. };
  363. SDL_COMPILE_TIME_ASSERT(SDLToD3D11_CompareOp, SDL_arraysize(SDLToD3D11_CompareOp) == SDL_GPU_COMPAREOP_MAX_ENUM_VALUE);
  364. static D3D11_STENCIL_OP SDLToD3D11_StencilOp[] = {
  365. D3D11_STENCIL_OP_KEEP, // INVALID
  366. D3D11_STENCIL_OP_KEEP, // KEEP
  367. D3D11_STENCIL_OP_ZERO, // ZERO
  368. D3D11_STENCIL_OP_REPLACE, // REPLACE
  369. D3D11_STENCIL_OP_INCR_SAT, // INCREMENT_AND_CLAMP
  370. D3D11_STENCIL_OP_DECR_SAT, // DECREMENT_AND_CLAMP
  371. D3D11_STENCIL_OP_INVERT, // INVERT
  372. D3D11_STENCIL_OP_INCR, // INCREMENT_AND_WRAP
  373. D3D11_STENCIL_OP_DECR // DECREMENT_AND_WRAP
  374. };
  375. SDL_COMPILE_TIME_ASSERT(SDLToD3D11_StencilOp, SDL_arraysize(SDLToD3D11_StencilOp) == SDL_GPU_STENCILOP_MAX_ENUM_VALUE);
  376. static D3D11_INPUT_CLASSIFICATION SDLToD3D11_VertexInputRate[] = {
  377. D3D11_INPUT_PER_VERTEX_DATA, // VERTEX
  378. D3D11_INPUT_PER_INSTANCE_DATA // INSTANCE
  379. };
  380. static D3D11_TEXTURE_ADDRESS_MODE SDLToD3D11_SamplerAddressMode[] = {
  381. D3D11_TEXTURE_ADDRESS_WRAP, // REPEAT
  382. D3D11_TEXTURE_ADDRESS_MIRROR, // MIRRORED_REPEAT
  383. D3D11_TEXTURE_ADDRESS_CLAMP // CLAMP_TO_EDGE
  384. };
  385. static D3D11_FILTER SDLToD3D11_Filter(const SDL_GPUSamplerCreateInfo *createInfo)
  386. {
  387. if (createInfo->min_filter == SDL_GPU_FILTER_LINEAR) {
  388. if (createInfo->mag_filter == SDL_GPU_FILTER_LINEAR) {
  389. if (createInfo->mipmap_mode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) {
  390. return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  391. } else {
  392. return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
  393. }
  394. } else {
  395. if (createInfo->mipmap_mode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) {
  396. return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
  397. } else {
  398. return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
  399. }
  400. }
  401. } else {
  402. if (createInfo->mag_filter == SDL_GPU_FILTER_LINEAR) {
  403. if (createInfo->mipmap_mode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) {
  404. return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
  405. } else {
  406. return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
  407. }
  408. } else {
  409. if (createInfo->mipmap_mode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) {
  410. return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
  411. } else {
  412. return D3D11_FILTER_MIN_MAG_MIP_POINT;
  413. }
  414. }
  415. }
  416. }
  417. // Structs
  418. typedef struct D3D11Texture D3D11Texture;
  419. typedef struct D3D11TextureContainer
  420. {
  421. TextureCommonHeader header;
  422. D3D11Texture *activeTexture;
  423. Uint32 textureCapacity;
  424. Uint32 textureCount;
  425. D3D11Texture **textures;
  426. char *debugName;
  427. bool canBeCycled;
  428. } D3D11TextureContainer;
  429. typedef struct D3D11TextureSubresource
  430. {
  431. D3D11Texture *parent;
  432. Uint32 layer;
  433. Uint32 level;
  434. Uint32 depth; // total depth
  435. Uint32 index;
  436. // One RTV per depth slice
  437. ID3D11RenderTargetView **colorTargetViews; // NULL if not a color target
  438. ID3D11UnorderedAccessView *uav; // NULL if not a storage texture
  439. ID3D11DepthStencilView *depthStencilTargetView; // NULL if not a depth stencil target
  440. } D3D11TextureSubresource;
  441. struct D3D11Texture
  442. {
  443. D3D11TextureContainer *container;
  444. Uint32 containerIndex;
  445. ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */
  446. ID3D11ShaderResourceView *shaderView;
  447. D3D11TextureSubresource *subresources;
  448. Uint32 subresourceCount; /* layerCount * num_levels */
  449. SDL_AtomicInt referenceCount;
  450. };
  451. typedef struct D3D11Fence
  452. {
  453. ID3D11Query *handle;
  454. SDL_AtomicInt referenceCount;
  455. } D3D11Fence;
  456. typedef struct D3D11WindowData
  457. {
  458. SDL_Window *window;
  459. IDXGISwapChain *swapchain;
  460. D3D11Texture texture;
  461. D3D11TextureContainer textureContainer;
  462. SDL_GPUPresentMode presentMode;
  463. SDL_GPUSwapchainComposition swapchainComposition;
  464. DXGI_FORMAT swapchainFormat;
  465. DXGI_COLOR_SPACE_TYPE swapchainColorSpace;
  466. Uint32 width;
  467. Uint32 height;
  468. SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
  469. Uint32 frameCounter;
  470. bool needsSwapchainRecreate;
  471. } D3D11WindowData;
  472. typedef struct D3D11Shader
  473. {
  474. ID3D11DeviceChild *handle; // ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader
  475. void *bytecode;
  476. size_t bytecodeSize;
  477. Uint32 numSamplers;
  478. Uint32 numUniformBuffers;
  479. Uint32 numStorageBuffers;
  480. Uint32 numStorageTextures;
  481. } D3D11Shader;
  482. typedef struct D3D11GraphicsPipeline
  483. {
  484. Sint32 numColorTargets;
  485. DXGI_FORMAT colorTargetFormats[MAX_COLOR_TARGET_BINDINGS];
  486. ID3D11BlendState *colorTargetBlendState;
  487. Uint32 sampleMask;
  488. SDL_GPUMultisampleState multisampleState;
  489. Uint8 hasDepthStencilTarget;
  490. DXGI_FORMAT depthStencilTargetFormat;
  491. ID3D11DepthStencilState *depthStencilState;
  492. SDL_GPUPrimitiveType primitiveType;
  493. ID3D11RasterizerState *rasterizerState;
  494. ID3D11VertexShader *vertexShader;
  495. ID3D11PixelShader *fragmentShader;
  496. ID3D11InputLayout *inputLayout;
  497. Uint32 vertexStrides[MAX_VERTEX_BUFFERS];
  498. Uint32 vertexSamplerCount;
  499. Uint32 vertexUniformBufferCount;
  500. Uint32 vertexStorageBufferCount;
  501. Uint32 vertexStorageTextureCount;
  502. Uint32 fragmentSamplerCount;
  503. Uint32 fragmentUniformBufferCount;
  504. Uint32 fragmentStorageBufferCount;
  505. Uint32 fragmentStorageTextureCount;
  506. } D3D11GraphicsPipeline;
  507. typedef struct D3D11ComputePipeline
  508. {
  509. ID3D11ComputeShader *computeShader;
  510. Uint32 numSamplers;
  511. Uint32 numReadonlyStorageTextures;
  512. Uint32 numReadWriteStorageTextures;
  513. Uint32 numReadonlyStorageBuffers;
  514. Uint32 numReadWriteStorageBuffers;
  515. Uint32 numUniformBuffers;
  516. } D3D11ComputePipeline;
  517. typedef struct D3D11Buffer
  518. {
  519. ID3D11Buffer *handle;
  520. ID3D11UnorderedAccessView *uav;
  521. ID3D11ShaderResourceView *srv;
  522. Uint32 size;
  523. SDL_AtomicInt referenceCount;
  524. } D3D11Buffer;
  525. typedef struct D3D11BufferContainer
  526. {
  527. D3D11Buffer *activeBuffer;
  528. Uint32 bufferCapacity;
  529. Uint32 bufferCount;
  530. D3D11Buffer **buffers;
  531. D3D11_BUFFER_DESC bufferDesc;
  532. char *debugName;
  533. } D3D11BufferContainer;
  534. typedef struct D3D11BufferDownload
  535. {
  536. ID3D11Buffer *stagingBuffer;
  537. Uint32 dstOffset;
  538. Uint32 size;
  539. } D3D11BufferDownload;
  540. typedef struct D3D11TextureDownload
  541. {
  542. ID3D11Resource *stagingTexture;
  543. Uint32 width;
  544. Uint32 height;
  545. Uint32 depth;
  546. Uint32 bufferOffset;
  547. Uint32 bytesPerRow;
  548. Uint32 bytesPerDepthSlice;
  549. } D3D11TextureDownload;
  550. typedef struct D3D11TransferBuffer
  551. {
  552. Uint8 *data;
  553. Uint32 size;
  554. SDL_AtomicInt referenceCount;
  555. D3D11BufferDownload *bufferDownloads;
  556. Uint32 bufferDownloadCount;
  557. Uint32 bufferDownloadCapacity;
  558. D3D11TextureDownload *textureDownloads;
  559. Uint32 textureDownloadCount;
  560. Uint32 textureDownloadCapacity;
  561. } D3D11TransferBuffer;
  562. typedef struct D3D11TransferBufferContainer
  563. {
  564. D3D11TransferBuffer *activeBuffer;
  565. /* These are all the buffers that have been used by this container.
  566. * If the resource is bound and then updated with DISCARD, a new resource
  567. * will be added to this list.
  568. * These can be reused after they are submitted and command processing is complete.
  569. */
  570. Uint32 bufferCapacity;
  571. Uint32 bufferCount;
  572. D3D11TransferBuffer **buffers;
  573. } D3D11TransferBufferContainer;
  574. typedef struct D3D11UniformBuffer
  575. {
  576. ID3D11Buffer *buffer;
  577. void *mappedData;
  578. Uint32 drawOffset;
  579. Uint32 writeOffset;
  580. Uint32 currentBlockSize;
  581. } D3D11UniformBuffer;
  582. typedef struct D3D11Sampler
  583. {
  584. ID3D11SamplerState *handle;
  585. } D3D11Sampler;
  586. typedef struct D3D11Renderer D3D11Renderer;
  587. typedef struct D3D11CommandBuffer
  588. {
  589. CommandBufferCommonHeader common;
  590. D3D11Renderer *renderer;
  591. // Deferred Context
  592. ID3D11DeviceContext1 *context;
  593. // Presentation
  594. D3D11WindowData **windowDatas;
  595. Uint32 windowDataCount;
  596. Uint32 windowDataCapacity;
  597. // Render Pass
  598. D3D11GraphicsPipeline *graphicsPipeline;
  599. Uint8 stencilRef;
  600. SDL_FColor blendConstants;
  601. D3D11TextureSubresource *colorTargetSubresources[MAX_COLOR_TARGET_BINDINGS];
  602. D3D11TextureSubresource *colorResolveSubresources[MAX_COLOR_TARGET_BINDINGS];
  603. // Compute Pass
  604. D3D11ComputePipeline *computePipeline;
  605. // Debug Annotation
  606. ID3DUserDefinedAnnotation *annotation;
  607. // Resource slot state
  608. bool needVertexBufferBind;
  609. bool needVertexSamplerBind;
  610. bool needVertexStorageTextureBind;
  611. bool needVertexStorageBufferBind;
  612. bool needVertexUniformBufferBind;
  613. bool needFragmentSamplerBind;
  614. bool needFragmentStorageTextureBind;
  615. bool needFragmentStorageBufferBind;
  616. bool needFragmentUniformBufferBind;
  617. bool needComputeSamplerBind;
  618. bool needComputeReadOnlyTextureBind;
  619. bool needComputeReadOnlyBufferBind;
  620. bool needComputeUniformBufferBind;
  621. // defer OMSetBlendState because it combines three different states
  622. bool needBlendStateSet;
  623. ID3D11Buffer *vertexBuffers[MAX_VERTEX_BUFFERS];
  624. Uint32 vertexBufferOffsets[MAX_VERTEX_BUFFERS];
  625. Uint32 vertexBufferCount;
  626. D3D11Texture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  627. D3D11Sampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  628. D3D11Texture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
  629. D3D11Buffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
  630. D3D11Texture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  631. D3D11Sampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  632. D3D11Texture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
  633. D3D11Buffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
  634. D3D11Texture *computeSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  635. D3D11Sampler *computeSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  636. D3D11Texture *computeReadOnlyStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
  637. D3D11Buffer *computeReadOnlyStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
  638. D3D11TextureSubresource *computeReadWriteStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
  639. D3D11Buffer *computeReadWriteStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
  640. // Uniform buffers
  641. D3D11UniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
  642. D3D11UniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
  643. D3D11UniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
  644. // Fences
  645. D3D11Fence *fence;
  646. Uint8 autoReleaseFence;
  647. // Reference Counting
  648. D3D11Buffer **usedBuffers;
  649. Uint32 usedBufferCount;
  650. Uint32 usedBufferCapacity;
  651. D3D11TransferBuffer **usedTransferBuffers;
  652. Uint32 usedTransferBufferCount;
  653. Uint32 usedTransferBufferCapacity;
  654. D3D11Texture **usedTextures;
  655. Uint32 usedTextureCount;
  656. Uint32 usedTextureCapacity;
  657. D3D11UniformBuffer **usedUniformBuffers;
  658. Uint32 usedUniformBufferCount;
  659. Uint32 usedUniformBufferCapacity;
  660. } D3D11CommandBuffer;
  661. struct D3D11Renderer
  662. {
  663. ID3D11Device1 *device;
  664. ID3D11DeviceContext *immediateContext;
  665. IDXGIFactory1 *factory;
  666. IDXGIAdapter1 *adapter;
  667. IDXGIDebug *dxgiDebug;
  668. #ifdef HAVE_IDXGIINFOQUEUE
  669. IDXGIInfoQueue *dxgiInfoQueue;
  670. #endif
  671. SDL_SharedObject *d3d11_dll;
  672. SDL_SharedObject *dxgi_dll;
  673. SDL_SharedObject *dxgidebug_dll;
  674. Uint8 debugMode;
  675. BOOL supportsTearing;
  676. Uint8 supportsFlipDiscard;
  677. SDL_iconv_t iconv;
  678. // Blit
  679. BlitPipelineCacheEntry blitPipelines[5];
  680. SDL_GPUSampler *blitNearestSampler;
  681. SDL_GPUSampler *blitLinearSampler;
  682. // Resource Tracking
  683. D3D11WindowData **claimedWindows;
  684. Uint32 claimedWindowCount;
  685. Uint32 claimedWindowCapacity;
  686. D3D11CommandBuffer **availableCommandBuffers;
  687. Uint32 availableCommandBufferCount;
  688. Uint32 availableCommandBufferCapacity;
  689. D3D11CommandBuffer **submittedCommandBuffers;
  690. Uint32 submittedCommandBufferCount;
  691. Uint32 submittedCommandBufferCapacity;
  692. D3D11Fence **availableFences;
  693. Uint32 availableFenceCount;
  694. Uint32 availableFenceCapacity;
  695. D3D11UniformBuffer **uniformBufferPool;
  696. Uint32 uniformBufferPoolCount;
  697. Uint32 uniformBufferPoolCapacity;
  698. D3D11TransferBufferContainer **transferBufferContainersToDestroy;
  699. Uint32 transferBufferContainersToDestroyCount;
  700. Uint32 transferBufferContainersToDestroyCapacity;
  701. D3D11BufferContainer **bufferContainersToDestroy;
  702. Uint32 bufferContainersToDestroyCount;
  703. Uint32 bufferContainersToDestroyCapacity;
  704. D3D11TextureContainer **textureContainersToDestroy;
  705. Uint32 textureContainersToDestroyCount;
  706. Uint32 textureContainersToDestroyCapacity;
  707. SDL_Mutex *contextLock;
  708. SDL_Mutex *acquireCommandBufferLock;
  709. SDL_Mutex *acquireUniformBufferLock;
  710. SDL_Mutex *fenceLock;
  711. SDL_Mutex *windowLock;
  712. // Null arrays for resetting resource slots
  713. ID3D11RenderTargetView *nullRTVs[MAX_COLOR_TARGET_BINDINGS];
  714. ID3D11ShaderResourceView *nullSRVs[MAX_TEXTURE_SAMPLERS_PER_STAGE * 2 +
  715. MAX_STORAGE_TEXTURES_PER_STAGE +
  716. MAX_STORAGE_BUFFERS_PER_STAGE];
  717. ID3D11SamplerState *nullSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE * 2];
  718. ID3D11UnorderedAccessView *nullUAVs[MAX_COMPUTE_WRITE_TEXTURES +
  719. MAX_COMPUTE_WRITE_BUFFERS];
  720. };
  721. // Logging
  722. static void D3D11_INTERNAL_SetError(
  723. D3D11Renderer *renderer,
  724. const char *msg,
  725. HRESULT res)
  726. {
  727. #define MAX_ERROR_LEN 1024 // FIXME: Arbitrary!
  728. // Buffer for text, ensure space for \0 terminator after buffer
  729. char wszMsgBuff[MAX_ERROR_LEN + 1];
  730. DWORD dwChars; // Number of chars returned.
  731. if (res == DXGI_ERROR_DEVICE_REMOVED) {
  732. res = ID3D11Device_GetDeviceRemovedReason(renderer->device);
  733. }
  734. // Try to get the message from the system errors.
  735. #ifdef _WIN32
  736. dwChars = FormatMessageA(
  737. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  738. NULL,
  739. res,
  740. 0,
  741. wszMsgBuff,
  742. MAX_ERROR_LEN,
  743. NULL);
  744. #else
  745. // FIXME: Do we have error strings in dxvk-native? -flibit
  746. dwChars = 0;
  747. #endif
  748. // No message? Screw it, just post the code.
  749. if (dwChars == 0) {
  750. if (renderer->debugMode) {
  751. SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: " HRESULT_FMT, msg, res);
  752. }
  753. SDL_SetError("%s! Error Code: " HRESULT_FMT, msg, res);
  754. return;
  755. }
  756. // Ensure valid range
  757. dwChars = SDL_min(dwChars, MAX_ERROR_LEN);
  758. // Trim whitespace from tail of message
  759. while (dwChars > 0) {
  760. if (wszMsgBuff[dwChars - 1] <= ' ') {
  761. dwChars--;
  762. } else {
  763. break;
  764. }
  765. }
  766. // Ensure null-terminated string
  767. wszMsgBuff[dwChars] = '\0';
  768. if (renderer->debugMode) {
  769. SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
  770. }
  771. SDL_SetError("%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
  772. }
  773. // Helper Functions
  774. static inline Uint32 D3D11_INTERNAL_CalcSubresource(
  775. Uint32 mipLevel,
  776. Uint32 layer,
  777. Uint32 numLevels)
  778. {
  779. return mipLevel + (layer * numLevels);
  780. }
  781. static inline Uint32 D3D11_INTERNAL_NextHighestAlignment(
  782. Uint32 n,
  783. Uint32 align)
  784. {
  785. return align * ((n + align - 1) / align);
  786. }
  787. static DXGI_FORMAT D3D11_INTERNAL_GetTypelessFormat(
  788. DXGI_FORMAT typedFormat)
  789. {
  790. switch (typedFormat) {
  791. case DXGI_FORMAT_D16_UNORM:
  792. return DXGI_FORMAT_R16_TYPELESS;
  793. case DXGI_FORMAT_D32_FLOAT:
  794. return DXGI_FORMAT_R32_TYPELESS;
  795. case DXGI_FORMAT_D24_UNORM_S8_UINT:
  796. return DXGI_FORMAT_R24G8_TYPELESS;
  797. case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
  798. return DXGI_FORMAT_R32G8X24_TYPELESS;
  799. default:
  800. return DXGI_FORMAT_UNKNOWN;
  801. }
  802. }
  803. static DXGI_FORMAT D3D11_INTERNAL_GetSampleableFormat(
  804. DXGI_FORMAT format)
  805. {
  806. switch (format) {
  807. case DXGI_FORMAT_R16_TYPELESS:
  808. return DXGI_FORMAT_R16_UNORM;
  809. case DXGI_FORMAT_R32_TYPELESS:
  810. return DXGI_FORMAT_R32_FLOAT;
  811. case DXGI_FORMAT_R24G8_TYPELESS:
  812. return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
  813. case DXGI_FORMAT_R32G8X24_TYPELESS:
  814. return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
  815. default:
  816. return format;
  817. }
  818. }
  819. // Quit
  820. static void D3D11_INTERNAL_DestroyBufferContainer(
  821. D3D11BufferContainer *container)
  822. {
  823. for (Uint32 i = 0; i < container->bufferCount; i += 1) {
  824. D3D11Buffer *d3d11Buffer = container->buffers[i];
  825. if (d3d11Buffer->uav != NULL) {
  826. ID3D11UnorderedAccessView_Release(d3d11Buffer->uav);
  827. }
  828. if (d3d11Buffer->srv != NULL) {
  829. ID3D11ShaderResourceView_Release(d3d11Buffer->srv);
  830. }
  831. ID3D11Buffer_Release(d3d11Buffer->handle);
  832. SDL_free(d3d11Buffer);
  833. }
  834. SDL_free(container->buffers);
  835. SDL_free(container);
  836. }
  837. static void D3D11_DestroyDevice(
  838. SDL_GPUDevice *device)
  839. {
  840. D3D11Renderer *renderer = (D3D11Renderer *)device->driverData;
  841. // Flush any remaining GPU work...
  842. D3D11_Wait(device->driverData);
  843. // Release the window data
  844. for (Sint32 i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) {
  845. D3D11_ReleaseWindow(device->driverData, renderer->claimedWindows[i]->window);
  846. }
  847. SDL_free(renderer->claimedWindows);
  848. // Release the blit resources
  849. D3D11_INTERNAL_DestroyBlitPipelines(device->driverData);
  850. // Release UBOs
  851. for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
  852. ID3D11Buffer_Release(renderer->uniformBufferPool[i]->buffer);
  853. SDL_free(renderer->uniformBufferPool[i]);
  854. }
  855. SDL_free(renderer->uniformBufferPool);
  856. // Release command buffer infrastructure
  857. for (Uint32 i = 0; i < renderer->availableCommandBufferCount; i += 1) {
  858. D3D11CommandBuffer *commandBuffer = renderer->availableCommandBuffers[i];
  859. if (commandBuffer->annotation) {
  860. ID3DUserDefinedAnnotation_Release(commandBuffer->annotation);
  861. }
  862. ID3D11DeviceContext_Release(commandBuffer->context);
  863. SDL_free(commandBuffer->usedBuffers);
  864. SDL_free(commandBuffer->usedTransferBuffers);
  865. SDL_free(commandBuffer);
  866. }
  867. SDL_free(renderer->availableCommandBuffers);
  868. SDL_free(renderer->submittedCommandBuffers);
  869. // Release fence infrastructure
  870. for (Uint32 i = 0; i < renderer->availableFenceCount; i += 1) {
  871. D3D11Fence *fence = renderer->availableFences[i];
  872. ID3D11Query_Release(fence->handle);
  873. SDL_free(fence);
  874. }
  875. SDL_free(renderer->availableFences);
  876. // Release the iconv, if applicable
  877. if (renderer->iconv != NULL) {
  878. SDL_iconv_close(renderer->iconv);
  879. }
  880. // Release the mutexes
  881. SDL_DestroyMutex(renderer->acquireCommandBufferLock);
  882. SDL_DestroyMutex(renderer->acquireUniformBufferLock);
  883. SDL_DestroyMutex(renderer->contextLock);
  884. SDL_DestroyMutex(renderer->fenceLock);
  885. SDL_DestroyMutex(renderer->windowLock);
  886. // Release the device and associated objects
  887. ID3D11DeviceContext_Release(renderer->immediateContext);
  888. ID3D11Device_Release(renderer->device);
  889. IDXGIAdapter_Release(renderer->adapter);
  890. IDXGIFactory_Release(renderer->factory);
  891. // Report leaks and clean up debug objects
  892. if (renderer->dxgiDebug) {
  893. IDXGIDebug_ReportLiveObjects(
  894. renderer->dxgiDebug,
  895. D3D_IID_DXGI_DEBUG_ALL,
  896. DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL);
  897. IDXGIDebug_Release(renderer->dxgiDebug);
  898. }
  899. #ifdef HAVE_IDXGIINFOQUEUE
  900. if (renderer->dxgiInfoQueue) {
  901. IDXGIInfoQueue_Release(renderer->dxgiInfoQueue);
  902. }
  903. #endif
  904. // Release the DLLs
  905. SDL_UnloadObject(renderer->d3d11_dll);
  906. SDL_UnloadObject(renderer->dxgi_dll);
  907. if (renderer->dxgidebug_dll) {
  908. SDL_UnloadObject(renderer->dxgidebug_dll);
  909. }
  910. // Free the primary structures
  911. SDL_free(renderer);
  912. SDL_free(device);
  913. }
  914. // Resource tracking
  915. static void D3D11_INTERNAL_TrackBuffer(
  916. D3D11CommandBuffer *commandBuffer,
  917. D3D11Buffer *buffer)
  918. {
  919. TRACK_RESOURCE(
  920. buffer,
  921. D3D11Buffer *,
  922. usedBuffers,
  923. usedBufferCount,
  924. usedBufferCapacity);
  925. }
  926. static void D3D11_INTERNAL_TrackTransferBuffer(
  927. D3D11CommandBuffer *commandBuffer,
  928. D3D11TransferBuffer *buffer)
  929. {
  930. TRACK_RESOURCE(
  931. buffer,
  932. D3D11TransferBuffer *,
  933. usedTransferBuffers,
  934. usedTransferBufferCount,
  935. usedTransferBufferCapacity);
  936. }
  937. static void D3D11_INTERNAL_TrackTexture(
  938. D3D11CommandBuffer *commandBuffer,
  939. D3D11Texture *texture)
  940. {
  941. TRACK_RESOURCE(
  942. texture,
  943. D3D11Texture *,
  944. usedTextures,
  945. usedTextureCount,
  946. usedTextureCapacity);
  947. }
  948. static void D3D11_INTERNAL_TrackUniformBuffer(
  949. D3D11CommandBuffer *commandBuffer,
  950. D3D11UniformBuffer *uniformBuffer)
  951. {
  952. Uint32 i;
  953. for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
  954. if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) {
  955. return;
  956. }
  957. }
  958. if (commandBuffer->usedUniformBufferCount == commandBuffer->usedUniformBufferCapacity) {
  959. commandBuffer->usedUniformBufferCapacity += 1;
  960. commandBuffer->usedUniformBuffers = SDL_realloc(
  961. commandBuffer->usedUniformBuffers,
  962. commandBuffer->usedUniformBufferCapacity * sizeof(D3D11UniformBuffer *));
  963. }
  964. commandBuffer->usedUniformBuffers[commandBuffer->usedUniformBufferCount] = uniformBuffer;
  965. commandBuffer->usedUniformBufferCount += 1;
  966. }
  967. // Disposal
  968. static void D3D11_INTERNAL_DestroyTexture(D3D11Texture *d3d11Texture)
  969. {
  970. if (d3d11Texture->shaderView) {
  971. ID3D11ShaderResourceView_Release(d3d11Texture->shaderView);
  972. }
  973. for (Uint32 subresourceIndex = 0; subresourceIndex < d3d11Texture->subresourceCount; subresourceIndex += 1) {
  974. if (d3d11Texture->subresources[subresourceIndex].colorTargetViews != NULL) {
  975. for (Uint32 depthIndex = 0; depthIndex < d3d11Texture->subresources[subresourceIndex].depth; depthIndex += 1) {
  976. ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].colorTargetViews[depthIndex]);
  977. }
  978. SDL_free(d3d11Texture->subresources[subresourceIndex].colorTargetViews);
  979. }
  980. if (d3d11Texture->subresources[subresourceIndex].depthStencilTargetView != NULL) {
  981. ID3D11DepthStencilView_Release(d3d11Texture->subresources[subresourceIndex].depthStencilTargetView);
  982. }
  983. if (d3d11Texture->subresources[subresourceIndex].uav != NULL) {
  984. ID3D11UnorderedAccessView_Release(d3d11Texture->subresources[subresourceIndex].uav);
  985. }
  986. }
  987. SDL_free(d3d11Texture->subresources);
  988. ID3D11Resource_Release(d3d11Texture->handle);
  989. }
  990. static void D3D11_INTERNAL_DestroyTextureContainer(
  991. D3D11TextureContainer *container)
  992. {
  993. for (Uint32 i = 0; i < container->textureCount; i += 1) {
  994. D3D11_INTERNAL_DestroyTexture(container->textures[i]);
  995. }
  996. SDL_free(container->textures);
  997. SDL_free(container);
  998. }
  999. static void D3D11_ReleaseTexture(
  1000. SDL_GPURenderer *driverData,
  1001. SDL_GPUTexture *texture)
  1002. {
  1003. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1004. D3D11TextureContainer *container = (D3D11TextureContainer *)texture;
  1005. SDL_LockMutex(renderer->contextLock);
  1006. EXPAND_ARRAY_IF_NEEDED(
  1007. renderer->textureContainersToDestroy,
  1008. D3D11TextureContainer *,
  1009. renderer->textureContainersToDestroyCount + 1,
  1010. renderer->textureContainersToDestroyCapacity,
  1011. renderer->textureContainersToDestroyCapacity + 1);
  1012. renderer->textureContainersToDestroy[renderer->textureContainersToDestroyCount] = container;
  1013. renderer->textureContainersToDestroyCount += 1;
  1014. SDL_UnlockMutex(renderer->contextLock);
  1015. }
  1016. static void D3D11_ReleaseSampler(
  1017. SDL_GPURenderer *driverData,
  1018. SDL_GPUSampler *sampler)
  1019. {
  1020. (void)driverData; // used by other backends
  1021. D3D11Sampler *d3d11Sampler = (D3D11Sampler *)sampler;
  1022. ID3D11SamplerState_Release(d3d11Sampler->handle);
  1023. SDL_free(d3d11Sampler);
  1024. }
  1025. static void D3D11_ReleaseBuffer(
  1026. SDL_GPURenderer *driverData,
  1027. SDL_GPUBuffer *buffer)
  1028. {
  1029. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1030. D3D11BufferContainer *container = (D3D11BufferContainer *)buffer;
  1031. SDL_LockMutex(renderer->contextLock);
  1032. EXPAND_ARRAY_IF_NEEDED(
  1033. renderer->bufferContainersToDestroy,
  1034. D3D11BufferContainer *,
  1035. renderer->bufferContainersToDestroyCount + 1,
  1036. renderer->bufferContainersToDestroyCapacity,
  1037. renderer->bufferContainersToDestroyCapacity + 1);
  1038. renderer->bufferContainersToDestroy[renderer->bufferContainersToDestroyCount] = container;
  1039. renderer->bufferContainersToDestroyCount += 1;
  1040. SDL_UnlockMutex(renderer->contextLock);
  1041. }
  1042. static void D3D11_ReleaseTransferBuffer(
  1043. SDL_GPURenderer *driverData,
  1044. SDL_GPUTransferBuffer *transferBuffer)
  1045. {
  1046. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1047. SDL_LockMutex(renderer->contextLock);
  1048. EXPAND_ARRAY_IF_NEEDED(
  1049. renderer->transferBufferContainersToDestroy,
  1050. D3D11TransferBufferContainer *,
  1051. renderer->transferBufferContainersToDestroyCount + 1,
  1052. renderer->transferBufferContainersToDestroyCapacity,
  1053. renderer->transferBufferContainersToDestroyCapacity + 1);
  1054. renderer->transferBufferContainersToDestroy[renderer->transferBufferContainersToDestroyCount] = (D3D11TransferBufferContainer *)transferBuffer;
  1055. renderer->transferBufferContainersToDestroyCount += 1;
  1056. SDL_UnlockMutex(renderer->contextLock);
  1057. }
  1058. static void D3D11_INTERNAL_DestroyTransferBufferContainer(
  1059. D3D11TransferBufferContainer *transferBufferContainer)
  1060. {
  1061. for (Uint32 i = 0; i < transferBufferContainer->bufferCount; i += 1) {
  1062. if (transferBufferContainer->buffers[i]->bufferDownloadCount > 0) {
  1063. SDL_free(transferBufferContainer->buffers[i]->bufferDownloads);
  1064. }
  1065. if (transferBufferContainer->buffers[i]->textureDownloadCount > 0) {
  1066. SDL_free(transferBufferContainer->buffers[i]->textureDownloads);
  1067. }
  1068. SDL_free(transferBufferContainer->buffers[i]->data);
  1069. SDL_free(transferBufferContainer->buffers[i]);
  1070. }
  1071. SDL_free(transferBufferContainer->buffers);
  1072. }
  1073. static void D3D11_ReleaseShader(
  1074. SDL_GPURenderer *driverData,
  1075. SDL_GPUShader *shader)
  1076. {
  1077. (void)driverData; // used by other backends
  1078. D3D11Shader *d3dShader = (D3D11Shader *)shader;
  1079. ID3D11DeviceChild_Release(d3dShader->handle);
  1080. if (d3dShader->bytecode) {
  1081. SDL_free(d3dShader->bytecode);
  1082. }
  1083. SDL_free(d3dShader);
  1084. }
  1085. static void D3D11_ReleaseComputePipeline(
  1086. SDL_GPURenderer *driverData,
  1087. SDL_GPUComputePipeline *computePipeline)
  1088. {
  1089. D3D11ComputePipeline *d3d11ComputePipeline = (D3D11ComputePipeline *)computePipeline;
  1090. ID3D11ComputeShader_Release(d3d11ComputePipeline->computeShader);
  1091. SDL_free(d3d11ComputePipeline);
  1092. }
  1093. static void D3D11_ReleaseGraphicsPipeline(
  1094. SDL_GPURenderer *driverData,
  1095. SDL_GPUGraphicsPipeline *graphicsPipeline)
  1096. {
  1097. (void)driverData; // used by other backends
  1098. D3D11GraphicsPipeline *d3d11GraphicsPipeline = (D3D11GraphicsPipeline *)graphicsPipeline;
  1099. ID3D11BlendState_Release(d3d11GraphicsPipeline->colorTargetBlendState);
  1100. ID3D11DepthStencilState_Release(d3d11GraphicsPipeline->depthStencilState);
  1101. ID3D11RasterizerState_Release(d3d11GraphicsPipeline->rasterizerState);
  1102. if (d3d11GraphicsPipeline->inputLayout) {
  1103. ID3D11InputLayout_Release(d3d11GraphicsPipeline->inputLayout);
  1104. }
  1105. ID3D11VertexShader_Release(d3d11GraphicsPipeline->vertexShader);
  1106. ID3D11PixelShader_Release(d3d11GraphicsPipeline->fragmentShader);
  1107. SDL_free(d3d11GraphicsPipeline);
  1108. }
  1109. // State Creation
  1110. static ID3D11BlendState *D3D11_INTERNAL_FetchBlendState(
  1111. D3D11Renderer *renderer,
  1112. Uint32 numColorTargets,
  1113. const SDL_GPUColorTargetDescription *colorTargets)
  1114. {
  1115. ID3D11BlendState *result;
  1116. D3D11_BLEND_DESC blendDesc;
  1117. HRESULT res;
  1118. /* Create a new blend state.
  1119. * The spec says the driver will not create duplicate states, so there's no need to cache.
  1120. */
  1121. SDL_zero(blendDesc); // needed for any unused RT entries
  1122. blendDesc.AlphaToCoverageEnable = FALSE;
  1123. blendDesc.IndependentBlendEnable = TRUE;
  1124. for (Uint32 i = 0; i < numColorTargets; i += 1) {
  1125. SDL_GPUColorComponentFlags colorWriteMask = colorTargets[i].blend_state.enable_color_write_mask ?
  1126. colorTargets[i].blend_state.color_write_mask :
  1127. 0xF;
  1128. blendDesc.RenderTarget[i].BlendEnable = colorTargets[i].blend_state.enable_blend;
  1129. blendDesc.RenderTarget[i].BlendOp = SDLToD3D11_BlendOp[colorTargets[i].blend_state.color_blend_op];
  1130. blendDesc.RenderTarget[i].BlendOpAlpha = SDLToD3D11_BlendOp[colorTargets[i].blend_state.alpha_blend_op];
  1131. blendDesc.RenderTarget[i].DestBlend = SDLToD3D11_BlendFactor[colorTargets[i].blend_state.dst_color_blendfactor];
  1132. blendDesc.RenderTarget[i].DestBlendAlpha = SDLToD3D11_BlendFactorAlpha[colorTargets[i].blend_state.dst_alpha_blendfactor];
  1133. blendDesc.RenderTarget[i].RenderTargetWriteMask = colorWriteMask;
  1134. blendDesc.RenderTarget[i].SrcBlend = SDLToD3D11_BlendFactor[colorTargets[i].blend_state.src_color_blendfactor];
  1135. blendDesc.RenderTarget[i].SrcBlendAlpha = SDLToD3D11_BlendFactorAlpha[colorTargets[i].blend_state.src_alpha_blendfactor];
  1136. }
  1137. res = ID3D11Device_CreateBlendState(
  1138. renderer->device,
  1139. &blendDesc,
  1140. &result);
  1141. CHECK_D3D11_ERROR_AND_RETURN("Could not create blend state", NULL);
  1142. return result;
  1143. }
  1144. static ID3D11DepthStencilState *D3D11_INTERNAL_FetchDepthStencilState(
  1145. D3D11Renderer *renderer,
  1146. SDL_GPUDepthStencilState depthStencilState)
  1147. {
  1148. ID3D11DepthStencilState *result;
  1149. D3D11_DEPTH_STENCIL_DESC dsDesc;
  1150. HRESULT res;
  1151. /* Create a new depth-stencil state.
  1152. * The spec says the driver will not create duplicate states, so there's no need to cache.
  1153. */
  1154. dsDesc.DepthEnable = depthStencilState.enable_depth_test;
  1155. dsDesc.StencilEnable = depthStencilState.enable_stencil_test;
  1156. dsDesc.DepthFunc = SDLToD3D11_CompareOp[depthStencilState.compare_op];
  1157. dsDesc.DepthWriteMask = (depthStencilState.enable_depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO);
  1158. dsDesc.BackFace.StencilFunc = SDLToD3D11_CompareOp[depthStencilState.back_stencil_state.compare_op];
  1159. dsDesc.BackFace.StencilDepthFailOp = SDLToD3D11_StencilOp[depthStencilState.back_stencil_state.depth_fail_op];
  1160. dsDesc.BackFace.StencilFailOp = SDLToD3D11_StencilOp[depthStencilState.back_stencil_state.fail_op];
  1161. dsDesc.BackFace.StencilPassOp = SDLToD3D11_StencilOp[depthStencilState.back_stencil_state.pass_op];
  1162. dsDesc.FrontFace.StencilFunc = SDLToD3D11_CompareOp[depthStencilState.front_stencil_state.compare_op];
  1163. dsDesc.FrontFace.StencilDepthFailOp = SDLToD3D11_StencilOp[depthStencilState.front_stencil_state.depth_fail_op];
  1164. dsDesc.FrontFace.StencilFailOp = SDLToD3D11_StencilOp[depthStencilState.front_stencil_state.fail_op];
  1165. dsDesc.FrontFace.StencilPassOp = SDLToD3D11_StencilOp[depthStencilState.front_stencil_state.pass_op];
  1166. dsDesc.StencilReadMask = depthStencilState.compare_mask;
  1167. dsDesc.StencilWriteMask = depthStencilState.write_mask;
  1168. res = ID3D11Device_CreateDepthStencilState(
  1169. renderer->device,
  1170. &dsDesc,
  1171. &result);
  1172. CHECK_D3D11_ERROR_AND_RETURN("Could not create depth-stencil state", NULL);
  1173. return result;
  1174. }
  1175. static ID3D11RasterizerState *D3D11_INTERNAL_FetchRasterizerState(
  1176. D3D11Renderer *renderer,
  1177. SDL_GPURasterizerState rasterizerState)
  1178. {
  1179. ID3D11RasterizerState *result;
  1180. D3D11_RASTERIZER_DESC rasterizerDesc;
  1181. HRESULT res;
  1182. /* Create a new rasterizer state.
  1183. * The spec says the driver will not create duplicate states, so there's no need to cache.
  1184. */
  1185. rasterizerDesc.AntialiasedLineEnable = FALSE;
  1186. rasterizerDesc.CullMode = SDLToD3D11_CullMode[rasterizerState.cull_mode];
  1187. rasterizerDesc.DepthBias = SDL_lroundf(rasterizerState.depth_bias_constant_factor);
  1188. rasterizerDesc.DepthBiasClamp = rasterizerState.depth_bias_clamp;
  1189. rasterizerDesc.DepthClipEnable = rasterizerState.enable_depth_clip;
  1190. rasterizerDesc.FillMode = (rasterizerState.fill_mode == SDL_GPU_FILLMODE_FILL) ? D3D11_FILL_SOLID : D3D11_FILL_WIREFRAME;
  1191. rasterizerDesc.FrontCounterClockwise = (rasterizerState.front_face == SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE);
  1192. rasterizerDesc.MultisampleEnable = TRUE; // only applies to MSAA render targets
  1193. rasterizerDesc.ScissorEnable = TRUE;
  1194. rasterizerDesc.SlopeScaledDepthBias = rasterizerState.depth_bias_slope_factor;
  1195. res = ID3D11Device_CreateRasterizerState(
  1196. renderer->device,
  1197. &rasterizerDesc,
  1198. &result);
  1199. CHECK_D3D11_ERROR_AND_RETURN("Could not create rasterizer state", NULL);
  1200. return result;
  1201. }
  1202. static Uint32 D3D11_INTERNAL_FindIndexOfVertexSlot(
  1203. Uint32 targetSlot,
  1204. const SDL_GPUVertexBufferDescription *bufferDescriptions,
  1205. Uint32 numDescriptions)
  1206. {
  1207. for (Uint32 i = 0; i < numDescriptions; i += 1) {
  1208. if (bufferDescriptions[i].slot == targetSlot) {
  1209. return i;
  1210. }
  1211. }
  1212. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not find vertex buffer slot %u!", targetSlot);
  1213. return 0;
  1214. }
  1215. static ID3D11InputLayout *D3D11_INTERNAL_FetchInputLayout(
  1216. D3D11Renderer *renderer,
  1217. SDL_GPUVertexInputState inputState,
  1218. void *shaderBytes,
  1219. size_t shaderByteLength)
  1220. {
  1221. ID3D11InputLayout *result = NULL;
  1222. D3D11_INPUT_ELEMENT_DESC *elementDescs;
  1223. Uint32 bindingIndex;
  1224. HRESULT res;
  1225. // Don't bother creating/fetching an input layout if there are no attributes.
  1226. if (inputState.num_vertex_attributes == 0) {
  1227. return NULL;
  1228. }
  1229. // Allocate an array of vertex elements
  1230. elementDescs = SDL_stack_alloc(
  1231. D3D11_INPUT_ELEMENT_DESC,
  1232. inputState.num_vertex_attributes);
  1233. // Create the array of input elements
  1234. for (Uint32 i = 0; i < inputState.num_vertex_attributes; i += 1) {
  1235. elementDescs[i].AlignedByteOffset = inputState.vertex_attributes[i].offset;
  1236. elementDescs[i].Format = SDLToD3D11_VertexFormat[inputState.vertex_attributes[i].format];
  1237. elementDescs[i].InputSlot = inputState.vertex_attributes[i].buffer_slot;
  1238. bindingIndex = D3D11_INTERNAL_FindIndexOfVertexSlot(
  1239. elementDescs[i].InputSlot,
  1240. inputState.vertex_buffer_descriptions,
  1241. inputState.num_vertex_buffers);
  1242. elementDescs[i].InputSlotClass = SDLToD3D11_VertexInputRate[inputState.vertex_buffer_descriptions[bindingIndex].input_rate];
  1243. // The spec requires this to be 0 for per-vertex data
  1244. elementDescs[i].InstanceDataStepRate = (inputState.vertex_buffer_descriptions[bindingIndex].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE)
  1245. ? inputState.vertex_buffer_descriptions[bindingIndex].instance_step_rate
  1246. : 0;
  1247. elementDescs[i].SemanticIndex = inputState.vertex_attributes[i].location;
  1248. elementDescs[i].SemanticName = "TEXCOORD";
  1249. }
  1250. res = ID3D11Device_CreateInputLayout(
  1251. renderer->device,
  1252. elementDescs,
  1253. inputState.num_vertex_attributes,
  1254. shaderBytes,
  1255. shaderByteLength,
  1256. &result);
  1257. if (FAILED(res)) {
  1258. SDL_stack_free(elementDescs);
  1259. CHECK_D3D11_ERROR_AND_RETURN("Could not create input layout!", NULL)
  1260. return NULL;
  1261. }
  1262. /* FIXME:
  1263. * These are not cached by the driver! Should we cache them, or allow duplicates?
  1264. * If we have one input layout per graphics pipeline maybe that wouldn't be so bad...?
  1265. */
  1266. SDL_stack_free(elementDescs);
  1267. return result;
  1268. }
  1269. // Pipeline Creation
  1270. static ID3D11DeviceChild *D3D11_INTERNAL_CreateID3D11Shader(
  1271. D3D11Renderer *renderer,
  1272. Uint32 stage,
  1273. const Uint8 *code,
  1274. size_t codeSize,
  1275. const char *entrypointName,
  1276. void **pBytecode,
  1277. size_t *pBytecodeSize)
  1278. {
  1279. ID3D11DeviceChild *handle = NULL;
  1280. HRESULT res;
  1281. // Create the shader from the byte blob
  1282. if (stage == SDL_GPU_SHADERSTAGE_VERTEX) {
  1283. res = ID3D11Device_CreateVertexShader(
  1284. renderer->device,
  1285. code,
  1286. codeSize,
  1287. NULL,
  1288. (ID3D11VertexShader **)&handle);
  1289. CHECK_D3D11_ERROR_AND_RETURN("Could not create vertex shader", NULL)
  1290. } else if (stage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
  1291. res = ID3D11Device_CreatePixelShader(
  1292. renderer->device,
  1293. code,
  1294. codeSize,
  1295. NULL,
  1296. (ID3D11PixelShader **)&handle);
  1297. CHECK_D3D11_ERROR_AND_RETURN("Could not create pixel shader", NULL)
  1298. } else if (stage == SDL_GPU_SHADERSTAGE_COMPUTE) {
  1299. res = ID3D11Device_CreateComputeShader(
  1300. renderer->device,
  1301. code,
  1302. codeSize,
  1303. NULL,
  1304. (ID3D11ComputeShader **)&handle);
  1305. CHECK_D3D11_ERROR_AND_RETURN("Could not create compute shader", NULL)
  1306. }
  1307. if (pBytecode != NULL) {
  1308. *pBytecode = SDL_malloc(codeSize);
  1309. SDL_memcpy(*pBytecode, code, codeSize);
  1310. *pBytecodeSize = codeSize;
  1311. }
  1312. return handle;
  1313. }
  1314. static SDL_GPUComputePipeline *D3D11_CreateComputePipeline(
  1315. SDL_GPURenderer *driverData,
  1316. const SDL_GPUComputePipelineCreateInfo *createinfo)
  1317. {
  1318. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1319. ID3D11ComputeShader *shader;
  1320. D3D11ComputePipeline *pipeline;
  1321. shader = (ID3D11ComputeShader *)D3D11_INTERNAL_CreateID3D11Shader(
  1322. renderer,
  1323. SDL_GPU_SHADERSTAGE_COMPUTE,
  1324. createinfo->code,
  1325. createinfo->code_size,
  1326. createinfo->entrypoint,
  1327. NULL,
  1328. NULL);
  1329. if (shader == NULL) {
  1330. return NULL;
  1331. }
  1332. pipeline = SDL_malloc(sizeof(D3D11ComputePipeline));
  1333. pipeline->computeShader = shader;
  1334. pipeline->numSamplers = createinfo->num_samplers;
  1335. pipeline->numReadonlyStorageTextures = createinfo->num_readonly_storage_textures;
  1336. pipeline->numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
  1337. pipeline->numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers;
  1338. pipeline->numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
  1339. pipeline->numUniformBuffers = createinfo->num_uniform_buffers;
  1340. // thread counts are ignored in d3d11
  1341. return (SDL_GPUComputePipeline *)pipeline;
  1342. }
  1343. static SDL_GPUGraphicsPipeline *D3D11_CreateGraphicsPipeline(
  1344. SDL_GPURenderer *driverData,
  1345. const SDL_GPUGraphicsPipelineCreateInfo *createinfo)
  1346. {
  1347. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1348. D3D11Shader *vertShader = (D3D11Shader *)createinfo->vertex_shader;
  1349. D3D11Shader *fragShader = (D3D11Shader *)createinfo->fragment_shader;
  1350. D3D11GraphicsPipeline *pipeline = SDL_malloc(sizeof(D3D11GraphicsPipeline));
  1351. // Blend
  1352. pipeline->colorTargetBlendState = D3D11_INTERNAL_FetchBlendState(
  1353. renderer,
  1354. createinfo->target_info.num_color_targets,
  1355. createinfo->target_info.color_target_descriptions);
  1356. if (pipeline->colorTargetBlendState == NULL) {
  1357. return NULL;
  1358. }
  1359. pipeline->numColorTargets = createinfo->target_info.num_color_targets;
  1360. for (Sint32 i = 0; i < pipeline->numColorTargets; i += 1) {
  1361. pipeline->colorTargetFormats[i] = SDLToD3D11_TextureFormat[createinfo->target_info.color_target_descriptions[i].format];
  1362. }
  1363. // Multisample
  1364. pipeline->multisampleState = createinfo->multisample_state;
  1365. pipeline->sampleMask = createinfo->multisample_state.enable_mask ?
  1366. createinfo->multisample_state.sample_mask :
  1367. 0xFFFFFFFF;
  1368. // Depth-Stencil
  1369. pipeline->depthStencilState = D3D11_INTERNAL_FetchDepthStencilState(
  1370. renderer,
  1371. createinfo->depth_stencil_state);
  1372. if (pipeline->depthStencilState == NULL) {
  1373. return NULL;
  1374. }
  1375. pipeline->hasDepthStencilTarget = createinfo->target_info.has_depth_stencil_target;
  1376. pipeline->depthStencilTargetFormat = SDLToD3D11_TextureFormat[createinfo->target_info.depth_stencil_format];
  1377. // Rasterizer
  1378. pipeline->primitiveType = createinfo->primitive_type;
  1379. pipeline->rasterizerState = D3D11_INTERNAL_FetchRasterizerState(
  1380. renderer,
  1381. createinfo->rasterizer_state);
  1382. if (pipeline->rasterizerState == NULL) {
  1383. return NULL;
  1384. }
  1385. // Shaders
  1386. pipeline->vertexShader = (ID3D11VertexShader *)vertShader->handle;
  1387. ID3D11VertexShader_AddRef(pipeline->vertexShader);
  1388. pipeline->fragmentShader = (ID3D11PixelShader *)fragShader->handle;
  1389. ID3D11PixelShader_AddRef(pipeline->fragmentShader);
  1390. // Input Layout
  1391. pipeline->inputLayout = D3D11_INTERNAL_FetchInputLayout(
  1392. renderer,
  1393. createinfo->vertex_input_state,
  1394. vertShader->bytecode,
  1395. vertShader->bytecodeSize);
  1396. SDL_zeroa(pipeline->vertexStrides);
  1397. if (createinfo->vertex_input_state.num_vertex_buffers > 0) {
  1398. for (Uint32 i = 0; i < createinfo->vertex_input_state.num_vertex_buffers; i += 1) {
  1399. pipeline->vertexStrides[createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot] =
  1400. createinfo->vertex_input_state.vertex_buffer_descriptions[i].pitch;
  1401. }
  1402. }
  1403. // Resource layout
  1404. pipeline->vertexSamplerCount = vertShader->numSamplers;
  1405. pipeline->vertexStorageTextureCount = vertShader->numStorageTextures;
  1406. pipeline->vertexStorageBufferCount = vertShader->numStorageBuffers;
  1407. pipeline->vertexUniformBufferCount = vertShader->numUniformBuffers;
  1408. pipeline->fragmentSamplerCount = fragShader->numSamplers;
  1409. pipeline->fragmentStorageTextureCount = fragShader->numStorageTextures;
  1410. pipeline->fragmentStorageBufferCount = fragShader->numStorageBuffers;
  1411. pipeline->fragmentUniformBufferCount = fragShader->numUniformBuffers;
  1412. return (SDL_GPUGraphicsPipeline *)pipeline;
  1413. }
  1414. // Debug Naming
  1415. static void D3D11_INTERNAL_SetBufferName(
  1416. D3D11Renderer *renderer,
  1417. D3D11Buffer *buffer,
  1418. const char *text)
  1419. {
  1420. if (renderer->debugMode) {
  1421. ID3D11DeviceChild_SetPrivateData(
  1422. buffer->handle,
  1423. &D3D_IID_D3DDebugObjectName,
  1424. (UINT)SDL_strlen(text),
  1425. text);
  1426. }
  1427. }
  1428. static void D3D11_SetBufferName(
  1429. SDL_GPURenderer *driverData,
  1430. SDL_GPUBuffer *buffer,
  1431. const char *text)
  1432. {
  1433. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1434. D3D11BufferContainer *container = (D3D11BufferContainer *)buffer;
  1435. size_t textLength = SDL_strlen(text) + 1;
  1436. if (renderer->debugMode) {
  1437. container->debugName = SDL_realloc(
  1438. container->debugName,
  1439. textLength);
  1440. SDL_utf8strlcpy(
  1441. container->debugName,
  1442. text,
  1443. textLength);
  1444. for (Uint32 i = 0; i < container->bufferCount; i += 1) {
  1445. D3D11_INTERNAL_SetBufferName(
  1446. renderer,
  1447. container->buffers[i],
  1448. text);
  1449. }
  1450. }
  1451. }
  1452. static void D3D11_INTERNAL_SetTextureName(
  1453. D3D11Renderer *renderer,
  1454. D3D11Texture *texture,
  1455. const char *text)
  1456. {
  1457. if (renderer->debugMode) {
  1458. ID3D11DeviceChild_SetPrivateData(
  1459. texture->handle,
  1460. &D3D_IID_D3DDebugObjectName,
  1461. (UINT)SDL_strlen(text),
  1462. text);
  1463. }
  1464. }
  1465. static void D3D11_SetTextureName(
  1466. SDL_GPURenderer *driverData,
  1467. SDL_GPUTexture *texture,
  1468. const char *text)
  1469. {
  1470. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1471. D3D11TextureContainer *container = (D3D11TextureContainer *)texture;
  1472. size_t textLength = SDL_strlen(text) + 1;
  1473. if (renderer->debugMode) {
  1474. container->debugName = SDL_realloc(
  1475. container->debugName,
  1476. textLength);
  1477. SDL_utf8strlcpy(
  1478. container->debugName,
  1479. text,
  1480. textLength);
  1481. for (Uint32 i = 0; i < container->textureCount; i += 1) {
  1482. D3D11_INTERNAL_SetTextureName(
  1483. renderer,
  1484. container->textures[i],
  1485. text);
  1486. }
  1487. }
  1488. }
  1489. static bool D3D11_INTERNAL_StrToWStr(
  1490. D3D11Renderer *renderer,
  1491. const char *str,
  1492. wchar_t *wstr,
  1493. size_t wstrSize)
  1494. {
  1495. size_t inlen, result;
  1496. size_t outlen = wstrSize;
  1497. if (renderer->iconv == NULL) {
  1498. renderer->iconv = SDL_iconv_open("WCHAR_T", "UTF-8");
  1499. SDL_assert(renderer->iconv);
  1500. }
  1501. // Convert...
  1502. inlen = SDL_strlen(str) + 1;
  1503. result = SDL_iconv(
  1504. renderer->iconv,
  1505. &str,
  1506. &inlen,
  1507. (char **)&wstr,
  1508. &outlen);
  1509. // Check...
  1510. switch (result) {
  1511. case SDL_ICONV_ERROR:
  1512. case SDL_ICONV_E2BIG:
  1513. case SDL_ICONV_EILSEQ:
  1514. case SDL_ICONV_EINVAL:
  1515. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to convert string to wchar_t!");
  1516. return false;
  1517. default:
  1518. break;
  1519. }
  1520. return true;
  1521. }
  1522. static void D3D11_InsertDebugLabel(
  1523. SDL_GPUCommandBuffer *commandBuffer,
  1524. const char *text)
  1525. {
  1526. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  1527. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  1528. if (d3d11CommandBuffer->annotation == NULL) {
  1529. return;
  1530. }
  1531. wchar_t wstr[256];
  1532. if (!D3D11_INTERNAL_StrToWStr(renderer, text, wstr, sizeof(wstr))) {
  1533. return;
  1534. }
  1535. ID3DUserDefinedAnnotation_SetMarker(d3d11CommandBuffer->annotation, wstr);
  1536. }
  1537. static void D3D11_PushDebugGroup(
  1538. SDL_GPUCommandBuffer *commandBuffer,
  1539. const char *name)
  1540. {
  1541. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  1542. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  1543. if (d3d11CommandBuffer->annotation == NULL) {
  1544. return;
  1545. }
  1546. wchar_t wstr[256];
  1547. if (!D3D11_INTERNAL_StrToWStr(renderer, name, wstr, sizeof(wstr))) {
  1548. return;
  1549. }
  1550. ID3DUserDefinedAnnotation_BeginEvent(d3d11CommandBuffer->annotation, wstr);
  1551. }
  1552. static void D3D11_PopDebugGroup(
  1553. SDL_GPUCommandBuffer *commandBuffer)
  1554. {
  1555. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  1556. if (d3d11CommandBuffer->annotation == NULL) {
  1557. return;
  1558. }
  1559. ID3DUserDefinedAnnotation_EndEvent(d3d11CommandBuffer->annotation);
  1560. }
  1561. // Resource Creation
  1562. static SDL_GPUSampler *D3D11_CreateSampler(
  1563. SDL_GPURenderer *driverData,
  1564. const SDL_GPUSamplerCreateInfo *createinfo)
  1565. {
  1566. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1567. D3D11_SAMPLER_DESC samplerDesc;
  1568. ID3D11SamplerState *samplerStateHandle;
  1569. D3D11Sampler *d3d11Sampler;
  1570. HRESULT res;
  1571. samplerDesc.AddressU = SDLToD3D11_SamplerAddressMode[createinfo->address_mode_u];
  1572. samplerDesc.AddressV = SDLToD3D11_SamplerAddressMode[createinfo->address_mode_v];
  1573. samplerDesc.AddressW = SDLToD3D11_SamplerAddressMode[createinfo->address_mode_w];
  1574. samplerDesc.ComparisonFunc = (createinfo->enable_compare ? SDLToD3D11_CompareOp[createinfo->compare_op] : SDLToD3D11_CompareOp[SDL_GPU_COMPAREOP_ALWAYS]);
  1575. samplerDesc.MaxAnisotropy = (createinfo->enable_anisotropy ? (UINT)createinfo->max_anisotropy : 0);
  1576. samplerDesc.Filter = SDLToD3D11_Filter(createinfo);
  1577. samplerDesc.MaxLOD = createinfo->max_lod;
  1578. samplerDesc.MinLOD = createinfo->min_lod;
  1579. samplerDesc.MipLODBias = createinfo->mip_lod_bias;
  1580. SDL_zeroa(samplerDesc.BorderColor); // arbitrary, unused
  1581. res = ID3D11Device_CreateSamplerState(
  1582. renderer->device,
  1583. &samplerDesc,
  1584. &samplerStateHandle);
  1585. CHECK_D3D11_ERROR_AND_RETURN("Could not create sampler state", NULL);
  1586. d3d11Sampler = (D3D11Sampler *)SDL_malloc(sizeof(D3D11Sampler));
  1587. d3d11Sampler->handle = samplerStateHandle;
  1588. return (SDL_GPUSampler *)d3d11Sampler;
  1589. }
  1590. SDL_GPUShader *D3D11_CreateShader(
  1591. SDL_GPURenderer *driverData,
  1592. const SDL_GPUShaderCreateInfo *createinfo)
  1593. {
  1594. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1595. ID3D11DeviceChild *handle;
  1596. void *bytecode = NULL;
  1597. size_t bytecodeSize = 0;
  1598. D3D11Shader *shader;
  1599. handle = D3D11_INTERNAL_CreateID3D11Shader(
  1600. renderer,
  1601. createinfo->stage,
  1602. createinfo->code,
  1603. createinfo->code_size,
  1604. createinfo->entrypoint,
  1605. createinfo->stage == SDL_GPU_SHADERSTAGE_VERTEX ? &bytecode : NULL,
  1606. createinfo->stage == SDL_GPU_SHADERSTAGE_VERTEX ? &bytecodeSize : NULL);
  1607. if (handle == NULL) {
  1608. return NULL;
  1609. }
  1610. shader = (D3D11Shader *)SDL_calloc(1, sizeof(D3D11Shader));
  1611. shader->handle = handle;
  1612. shader->numSamplers = createinfo->num_samplers;
  1613. shader->numStorageBuffers = createinfo->num_storage_buffers;
  1614. shader->numStorageTextures = createinfo->num_storage_textures;
  1615. shader->numUniformBuffers = createinfo->num_uniform_buffers;
  1616. if (createinfo->stage == SDL_GPU_SHADERSTAGE_VERTEX) {
  1617. // Store the raw bytecode and its length for creating InputLayouts
  1618. shader->bytecode = bytecode;
  1619. shader->bytecodeSize = bytecodeSize;
  1620. }
  1621. return (SDL_GPUShader *)shader;
  1622. }
  1623. static D3D11Texture *D3D11_INTERNAL_CreateTexture(
  1624. D3D11Renderer *renderer,
  1625. const SDL_GPUTextureCreateInfo *createInfo,
  1626. D3D11_SUBRESOURCE_DATA *initialData)
  1627. {
  1628. Uint8 needsSRV, isColorTarget, isDepthStencil, isMultisample, isStaging, needSubresourceUAV, isMippable;
  1629. DXGI_FORMAT format;
  1630. ID3D11Resource *textureHandle;
  1631. ID3D11ShaderResourceView *srv = NULL;
  1632. D3D11Texture *d3d11Texture;
  1633. HRESULT res;
  1634. isColorTarget = createInfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
  1635. isDepthStencil = createInfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
  1636. needsSRV =
  1637. (createInfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) ||
  1638. (createInfo->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) ||
  1639. (createInfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ);
  1640. needSubresourceUAV =
  1641. (createInfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) ||
  1642. (createInfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE);
  1643. isMultisample = createInfo->sample_count > SDL_GPU_SAMPLECOUNT_1;
  1644. isStaging = createInfo->usage == 0;
  1645. isMippable =
  1646. createInfo->num_levels > 1 &&
  1647. (createInfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) &&
  1648. (createInfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET);
  1649. format = SDLToD3D11_TextureFormat[createInfo->format];
  1650. if (isDepthStencil) {
  1651. format = D3D11_INTERNAL_GetTypelessFormat(format);
  1652. }
  1653. Uint32 layerCount = createInfo->type == SDL_GPU_TEXTURETYPE_3D ? 1 : createInfo->layer_count_or_depth;
  1654. Uint32 depth = createInfo->type == SDL_GPU_TEXTURETYPE_3D ? createInfo->layer_count_or_depth : 1;
  1655. if (createInfo->type != SDL_GPU_TEXTURETYPE_3D) {
  1656. D3D11_TEXTURE2D_DESC desc2D;
  1657. desc2D.BindFlags = 0;
  1658. if (needsSRV) {
  1659. desc2D.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
  1660. }
  1661. if (needSubresourceUAV) {
  1662. desc2D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
  1663. }
  1664. if (isColorTarget) {
  1665. desc2D.BindFlags |= D3D11_BIND_RENDER_TARGET;
  1666. }
  1667. if (isDepthStencil) {
  1668. desc2D.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
  1669. }
  1670. desc2D.Width = createInfo->width;
  1671. desc2D.Height = createInfo->height;
  1672. desc2D.ArraySize = layerCount;
  1673. desc2D.CPUAccessFlags = isStaging ? D3D11_CPU_ACCESS_WRITE : 0;
  1674. desc2D.Format = format;
  1675. desc2D.MipLevels = createInfo->num_levels;
  1676. desc2D.MiscFlags = 0;
  1677. desc2D.SampleDesc.Count = SDLToD3D11_SampleCount[createInfo->sample_count];
  1678. desc2D.SampleDesc.Quality = isMultisample ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0;
  1679. desc2D.Usage = isStaging ? D3D11_USAGE_STAGING : D3D11_USAGE_DEFAULT;
  1680. if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
  1681. desc2D.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
  1682. }
  1683. if (isMippable) {
  1684. desc2D.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
  1685. }
  1686. res = ID3D11Device_CreateTexture2D(
  1687. renderer->device,
  1688. &desc2D,
  1689. initialData,
  1690. (ID3D11Texture2D **)&textureHandle);
  1691. CHECK_D3D11_ERROR_AND_RETURN("Could not create Texture2D", NULL);
  1692. // Create the SRV, if applicable
  1693. if (needsSRV) {
  1694. D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
  1695. srvDesc.Format = D3D11_INTERNAL_GetSampleableFormat(format);
  1696. if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
  1697. srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
  1698. srvDesc.TextureCube.MipLevels = desc2D.MipLevels;
  1699. srvDesc.TextureCube.MostDetailedMip = 0;
  1700. } else if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
  1701. srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
  1702. srvDesc.TextureCubeArray.MipLevels = desc2D.MipLevels;
  1703. srvDesc.TextureCubeArray.MostDetailedMip = 0;
  1704. srvDesc.TextureCubeArray.First2DArrayFace = 0;
  1705. srvDesc.TextureCubeArray.NumCubes = layerCount / 6;
  1706. } else if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
  1707. srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
  1708. srvDesc.Texture2DArray.MipLevels = desc2D.MipLevels;
  1709. srvDesc.Texture2DArray.MostDetailedMip = 0;
  1710. srvDesc.Texture2DArray.FirstArraySlice = 0;
  1711. srvDesc.Texture2DArray.ArraySize = layerCount;
  1712. } else {
  1713. srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
  1714. srvDesc.Texture2D.MipLevels = desc2D.MipLevels;
  1715. srvDesc.Texture2D.MostDetailedMip = 0;
  1716. }
  1717. res = ID3D11Device_CreateShaderResourceView(
  1718. renderer->device,
  1719. textureHandle,
  1720. &srvDesc,
  1721. &srv);
  1722. if (FAILED(res)) {
  1723. ID3D11Resource_Release(textureHandle);
  1724. D3D11_INTERNAL_SetError(renderer, "Could not create SRV for 2D texture", res);
  1725. return NULL;
  1726. }
  1727. }
  1728. } else {
  1729. D3D11_TEXTURE3D_DESC desc3D;
  1730. desc3D.BindFlags = 0;
  1731. if (needsSRV) {
  1732. desc3D.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
  1733. }
  1734. if (needSubresourceUAV) {
  1735. desc3D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
  1736. }
  1737. if (isColorTarget) {
  1738. desc3D.BindFlags |= D3D11_BIND_RENDER_TARGET;
  1739. }
  1740. desc3D.Width = createInfo->width;
  1741. desc3D.Height = createInfo->height;
  1742. desc3D.Depth = depth;
  1743. desc3D.CPUAccessFlags = isStaging ? D3D11_CPU_ACCESS_WRITE : 0;
  1744. desc3D.Format = format;
  1745. desc3D.MipLevels = createInfo->num_levels;
  1746. desc3D.MiscFlags = isMippable ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0;
  1747. desc3D.Usage = isStaging ? D3D11_USAGE_STAGING : D3D11_USAGE_DEFAULT;
  1748. res = ID3D11Device_CreateTexture3D(
  1749. renderer->device,
  1750. &desc3D,
  1751. initialData,
  1752. (ID3D11Texture3D **)&textureHandle);
  1753. CHECK_D3D11_ERROR_AND_RETURN("Could not create Texture3D", NULL);
  1754. // Create the SRV, if applicable
  1755. if (needsSRV) {
  1756. D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
  1757. srvDesc.Format = format;
  1758. srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
  1759. srvDesc.Texture3D.MipLevels = desc3D.MipLevels;
  1760. srvDesc.Texture3D.MostDetailedMip = 0;
  1761. res = ID3D11Device_CreateShaderResourceView(
  1762. renderer->device,
  1763. textureHandle,
  1764. &srvDesc,
  1765. &srv);
  1766. if (FAILED(res)) {
  1767. ID3D11Resource_Release(textureHandle);
  1768. D3D11_INTERNAL_SetError(renderer, "Could not create SRV for 3D texture", res);
  1769. return NULL;
  1770. }
  1771. }
  1772. }
  1773. d3d11Texture = (D3D11Texture *)SDL_malloc(sizeof(D3D11Texture));
  1774. d3d11Texture->handle = textureHandle;
  1775. d3d11Texture->shaderView = srv;
  1776. SDL_SetAtomicInt(&d3d11Texture->referenceCount, 0);
  1777. d3d11Texture->container = NULL;
  1778. d3d11Texture->containerIndex = 0;
  1779. d3d11Texture->subresourceCount = createInfo->num_levels * layerCount;
  1780. d3d11Texture->subresources = SDL_malloc(
  1781. d3d11Texture->subresourceCount * sizeof(D3D11TextureSubresource));
  1782. for (Uint32 layerIndex = 0; layerIndex < layerCount; layerIndex += 1) {
  1783. for (Uint32 levelIndex = 0; levelIndex < createInfo->num_levels; levelIndex += 1) {
  1784. Uint32 subresourceIndex = D3D11_INTERNAL_CalcSubresource(
  1785. levelIndex,
  1786. layerIndex,
  1787. createInfo->num_levels);
  1788. d3d11Texture->subresources[subresourceIndex].parent = d3d11Texture;
  1789. d3d11Texture->subresources[subresourceIndex].layer = layerIndex;
  1790. d3d11Texture->subresources[subresourceIndex].level = levelIndex;
  1791. d3d11Texture->subresources[subresourceIndex].depth = depth;
  1792. d3d11Texture->subresources[subresourceIndex].index = subresourceIndex;
  1793. d3d11Texture->subresources[subresourceIndex].colorTargetViews = NULL;
  1794. d3d11Texture->subresources[subresourceIndex].uav = NULL;
  1795. d3d11Texture->subresources[subresourceIndex].depthStencilTargetView = NULL;
  1796. if (isDepthStencil) {
  1797. D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
  1798. dsvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format];
  1799. dsvDesc.Flags = 0;
  1800. if (isMultisample) {
  1801. dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
  1802. } else {
  1803. dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
  1804. dsvDesc.Texture2D.MipSlice = levelIndex;
  1805. }
  1806. res = ID3D11Device_CreateDepthStencilView(
  1807. renderer->device,
  1808. d3d11Texture->handle,
  1809. &dsvDesc,
  1810. &d3d11Texture->subresources[subresourceIndex].depthStencilTargetView);
  1811. CHECK_D3D11_ERROR_AND_RETURN("Could not create DSV!", NULL);
  1812. } else if (isColorTarget) {
  1813. d3d11Texture->subresources[subresourceIndex].colorTargetViews = SDL_calloc(depth, sizeof(ID3D11RenderTargetView *));
  1814. for (Uint32 depthIndex = 0; depthIndex < depth; depthIndex += 1) {
  1815. D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
  1816. rtvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format];
  1817. if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
  1818. rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
  1819. rtvDesc.Texture2DArray.MipSlice = levelIndex;
  1820. rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
  1821. rtvDesc.Texture2DArray.ArraySize = 1;
  1822. } else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) {
  1823. rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
  1824. rtvDesc.Texture3D.MipSlice = levelIndex;
  1825. rtvDesc.Texture3D.FirstWSlice = depthIndex;
  1826. rtvDesc.Texture3D.WSize = 1;
  1827. } else if (isMultisample) {
  1828. rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
  1829. } else {
  1830. rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
  1831. rtvDesc.Texture2D.MipSlice = levelIndex;
  1832. }
  1833. res = ID3D11Device_CreateRenderTargetView(
  1834. renderer->device,
  1835. d3d11Texture->handle,
  1836. &rtvDesc,
  1837. &d3d11Texture->subresources[subresourceIndex].colorTargetViews[depthIndex]);
  1838. CHECK_D3D11_ERROR_AND_RETURN("Could not create RTV!", NULL);
  1839. }
  1840. }
  1841. if (needSubresourceUAV) {
  1842. D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
  1843. uavDesc.Format = format;
  1844. if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
  1845. uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
  1846. uavDesc.Texture2DArray.MipSlice = levelIndex;
  1847. uavDesc.Texture2DArray.FirstArraySlice = layerIndex;
  1848. uavDesc.Texture2DArray.ArraySize = 1;
  1849. } else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) {
  1850. uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
  1851. uavDesc.Texture3D.MipSlice = levelIndex;
  1852. uavDesc.Texture3D.FirstWSlice = 0;
  1853. uavDesc.Texture3D.WSize = depth;
  1854. } else {
  1855. uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
  1856. uavDesc.Texture2D.MipSlice = levelIndex;
  1857. }
  1858. res = ID3D11Device_CreateUnorderedAccessView(
  1859. renderer->device,
  1860. d3d11Texture->handle,
  1861. &uavDesc,
  1862. &d3d11Texture->subresources[subresourceIndex].uav);
  1863. CHECK_D3D11_ERROR_AND_RETURN("Could not create UAV!", NULL);
  1864. }
  1865. }
  1866. }
  1867. return d3d11Texture;
  1868. }
  1869. static bool D3D11_SupportsSampleCount(
  1870. SDL_GPURenderer *driverData,
  1871. SDL_GPUTextureFormat format,
  1872. SDL_GPUSampleCount sampleCount)
  1873. {
  1874. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1875. Uint32 levels;
  1876. HRESULT res = ID3D11Device_CheckMultisampleQualityLevels(
  1877. renderer->device,
  1878. SDLToD3D11_TextureFormat[format],
  1879. SDLToD3D11_SampleCount[sampleCount],
  1880. &levels);
  1881. return SUCCEEDED(res) && levels > 0;
  1882. }
  1883. static SDL_GPUTexture *D3D11_CreateTexture(
  1884. SDL_GPURenderer *driverData,
  1885. const SDL_GPUTextureCreateInfo *createinfo)
  1886. {
  1887. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  1888. D3D11TextureContainer *container;
  1889. D3D11Texture *texture;
  1890. texture = D3D11_INTERNAL_CreateTexture(
  1891. renderer,
  1892. createinfo,
  1893. NULL);
  1894. if (texture == NULL) {
  1895. return NULL;
  1896. }
  1897. container = SDL_malloc(sizeof(D3D11TextureContainer));
  1898. container->header.info = *createinfo;
  1899. container->canBeCycled = 1;
  1900. container->activeTexture = texture;
  1901. container->textureCapacity = 1;
  1902. container->textureCount = 1;
  1903. container->textures = SDL_malloc(
  1904. container->textureCapacity * sizeof(D3D11Texture *));
  1905. container->textures[0] = texture;
  1906. container->debugName = NULL;
  1907. texture->container = container;
  1908. texture->containerIndex = 0;
  1909. return (SDL_GPUTexture *)container;
  1910. }
  1911. static void D3D11_INTERNAL_CycleActiveTexture(
  1912. D3D11Renderer *renderer,
  1913. D3D11TextureContainer *container)
  1914. {
  1915. for (Uint32 i = 0; i < container->textureCount; i += 1) {
  1916. if (SDL_GetAtomicInt(&container->textures[i]->referenceCount) == 0) {
  1917. container->activeTexture = container->textures[i];
  1918. return;
  1919. }
  1920. }
  1921. D3D11Texture *texture = D3D11_INTERNAL_CreateTexture(
  1922. renderer,
  1923. &container->header.info,
  1924. NULL);
  1925. if (texture == NULL) {
  1926. return;
  1927. }
  1928. // No texture is available, generate a new one.
  1929. EXPAND_ARRAY_IF_NEEDED(
  1930. container->textures,
  1931. D3D11Texture *,
  1932. container->textureCount + 1,
  1933. container->textureCapacity,
  1934. container->textureCapacity + 1);
  1935. container->textures[container->textureCount] = texture;
  1936. texture->container = container;
  1937. texture->containerIndex = container->textureCount;
  1938. container->textureCount += 1;
  1939. container->activeTexture = container->textures[container->textureCount - 1];
  1940. if (renderer->debugMode && container->debugName != NULL) {
  1941. D3D11_INTERNAL_SetTextureName(
  1942. renderer,
  1943. container->activeTexture,
  1944. container->debugName);
  1945. }
  1946. }
  1947. static D3D11TextureSubresource *D3D11_INTERNAL_FetchTextureSubresource(
  1948. D3D11TextureContainer *container,
  1949. Uint32 layer,
  1950. Uint32 level)
  1951. {
  1952. Uint32 index = D3D11_INTERNAL_CalcSubresource(
  1953. level,
  1954. layer,
  1955. container->header.info.num_levels);
  1956. return &container->activeTexture->subresources[index];
  1957. }
  1958. static D3D11TextureSubresource *D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
  1959. D3D11Renderer *renderer,
  1960. D3D11TextureContainer *container,
  1961. Uint32 layer,
  1962. Uint32 level,
  1963. bool cycle)
  1964. {
  1965. D3D11TextureSubresource *subresource = D3D11_INTERNAL_FetchTextureSubresource(
  1966. container,
  1967. layer,
  1968. level);
  1969. if (
  1970. container->canBeCycled &&
  1971. cycle &&
  1972. SDL_GetAtomicInt(&subresource->parent->referenceCount) > 0) {
  1973. D3D11_INTERNAL_CycleActiveTexture(
  1974. renderer,
  1975. container);
  1976. subresource = D3D11_INTERNAL_FetchTextureSubresource(
  1977. container,
  1978. layer,
  1979. level);
  1980. }
  1981. return subresource;
  1982. }
  1983. static D3D11Buffer *D3D11_INTERNAL_CreateBuffer(
  1984. D3D11Renderer *renderer,
  1985. D3D11_BUFFER_DESC *bufferDesc,
  1986. Uint32 size)
  1987. {
  1988. ID3D11Buffer *bufferHandle;
  1989. ID3D11UnorderedAccessView *uav = NULL;
  1990. ID3D11ShaderResourceView *srv = NULL;
  1991. D3D11Buffer *d3d11Buffer;
  1992. HRESULT res;
  1993. // Storage buffers have to be 4-aligned, so might as well align them all
  1994. size = D3D11_INTERNAL_NextHighestAlignment(size, 4);
  1995. res = ID3D11Device_CreateBuffer(
  1996. renderer->device,
  1997. bufferDesc,
  1998. NULL,
  1999. &bufferHandle);
  2000. CHECK_D3D11_ERROR_AND_RETURN("Could not create buffer", NULL);
  2001. // Storage buffer
  2002. if (bufferDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) {
  2003. // Create a UAV for the buffer
  2004. D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
  2005. uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
  2006. uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
  2007. uavDesc.Buffer.FirstElement = 0;
  2008. uavDesc.Buffer.NumElements = size / sizeof(Uint32);
  2009. uavDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
  2010. res = ID3D11Device_CreateUnorderedAccessView(
  2011. renderer->device,
  2012. (ID3D11Resource *)bufferHandle,
  2013. &uavDesc,
  2014. &uav);
  2015. if (FAILED(res)) {
  2016. ID3D11Buffer_Release(bufferHandle);
  2017. CHECK_D3D11_ERROR_AND_RETURN("Could not create UAV for buffer!", NULL);
  2018. }
  2019. // Create a SRV for the buffer
  2020. D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
  2021. srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
  2022. srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
  2023. srvDesc.BufferEx.FirstElement = 0;
  2024. srvDesc.BufferEx.NumElements = size / sizeof(Uint32);
  2025. srvDesc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
  2026. res = ID3D11Device_CreateShaderResourceView(
  2027. renderer->device,
  2028. (ID3D11Resource *)bufferHandle,
  2029. &srvDesc,
  2030. &srv);
  2031. if (FAILED(res)) {
  2032. ID3D11Buffer_Release(bufferHandle);
  2033. CHECK_D3D11_ERROR_AND_RETURN("Could not create SRV for buffer!", NULL);
  2034. }
  2035. }
  2036. d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer));
  2037. d3d11Buffer->handle = bufferHandle;
  2038. d3d11Buffer->size = size;
  2039. d3d11Buffer->uav = uav;
  2040. d3d11Buffer->srv = srv;
  2041. SDL_SetAtomicInt(&d3d11Buffer->referenceCount, 0);
  2042. return d3d11Buffer;
  2043. }
  2044. static SDL_GPUBuffer *D3D11_CreateBuffer(
  2045. SDL_GPURenderer *driverData,
  2046. SDL_GPUBufferUsageFlags usageFlags,
  2047. Uint32 size)
  2048. {
  2049. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  2050. D3D11BufferContainer *container;
  2051. D3D11Buffer *buffer;
  2052. D3D11_BUFFER_DESC bufferDesc;
  2053. bufferDesc.BindFlags = 0;
  2054. if (usageFlags & SDL_GPU_BUFFERUSAGE_VERTEX) {
  2055. bufferDesc.BindFlags |= D3D11_BIND_VERTEX_BUFFER;
  2056. }
  2057. if (usageFlags & SDL_GPU_BUFFERUSAGE_INDEX) {
  2058. bufferDesc.BindFlags |= D3D11_BIND_INDEX_BUFFER;
  2059. }
  2060. if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT) {
  2061. bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
  2062. }
  2063. if (usageFlags & (SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ |
  2064. SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ |
  2065. SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE)) {
  2066. bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
  2067. }
  2068. bufferDesc.ByteWidth = size;
  2069. bufferDesc.Usage = D3D11_USAGE_DEFAULT;
  2070. bufferDesc.CPUAccessFlags = 0;
  2071. bufferDesc.StructureByteStride = 0;
  2072. bufferDesc.MiscFlags = 0;
  2073. if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT) {
  2074. bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
  2075. }
  2076. if (usageFlags & (SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ |
  2077. SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ |
  2078. SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE)) {
  2079. bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
  2080. }
  2081. buffer = D3D11_INTERNAL_CreateBuffer(
  2082. renderer,
  2083. &bufferDesc,
  2084. size);
  2085. if (buffer == NULL) {
  2086. return NULL;
  2087. }
  2088. container = SDL_malloc(sizeof(D3D11BufferContainer));
  2089. container->activeBuffer = buffer;
  2090. container->bufferCapacity = 1;
  2091. container->bufferCount = 1;
  2092. container->buffers = SDL_malloc(
  2093. container->bufferCapacity * sizeof(D3D11Buffer *));
  2094. container->buffers[0] = container->activeBuffer;
  2095. container->bufferDesc = bufferDesc;
  2096. container->debugName = NULL;
  2097. return (SDL_GPUBuffer *)container;
  2098. }
  2099. static D3D11UniformBuffer *D3D11_INTERNAL_CreateUniformBuffer(
  2100. D3D11Renderer *renderer,
  2101. Uint32 size)
  2102. {
  2103. D3D11UniformBuffer *uniformBuffer;
  2104. ID3D11Buffer *buffer;
  2105. D3D11_BUFFER_DESC bufferDesc;
  2106. HRESULT res;
  2107. bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
  2108. bufferDesc.ByteWidth = size;
  2109. bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  2110. bufferDesc.MiscFlags = 0;
  2111. bufferDesc.StructureByteStride = 0;
  2112. bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
  2113. res = ID3D11Device_CreateBuffer(
  2114. renderer->device,
  2115. &bufferDesc,
  2116. NULL,
  2117. &buffer);
  2118. CHECK_D3D11_ERROR_AND_RETURN("Could not create uniform buffer", NULL)
  2119. uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer));
  2120. uniformBuffer->buffer = buffer;
  2121. uniformBuffer->writeOffset = 0;
  2122. uniformBuffer->drawOffset = 0;
  2123. uniformBuffer->currentBlockSize = 0;
  2124. return uniformBuffer;
  2125. }
  2126. static void D3D11_INTERNAL_CycleActiveBuffer(
  2127. D3D11Renderer *renderer,
  2128. D3D11BufferContainer *container)
  2129. {
  2130. Uint32 size = container->activeBuffer->size;
  2131. for (Uint32 i = 0; i < container->bufferCount; i += 1) {
  2132. if (SDL_GetAtomicInt(&container->buffers[i]->referenceCount) == 0) {
  2133. container->activeBuffer = container->buffers[i];
  2134. return;
  2135. }
  2136. }
  2137. EXPAND_ARRAY_IF_NEEDED(
  2138. container->buffers,
  2139. D3D11Buffer *,
  2140. container->bufferCount + 1,
  2141. container->bufferCapacity,
  2142. container->bufferCapacity + 1);
  2143. container->buffers[container->bufferCount] = D3D11_INTERNAL_CreateBuffer(
  2144. renderer,
  2145. &container->bufferDesc,
  2146. size);
  2147. container->bufferCount += 1;
  2148. container->activeBuffer = container->buffers[container->bufferCount - 1];
  2149. if (renderer->debugMode && container->debugName != NULL) {
  2150. D3D11_INTERNAL_SetBufferName(
  2151. renderer,
  2152. container->activeBuffer,
  2153. container->debugName);
  2154. }
  2155. }
  2156. static D3D11Buffer *D3D11_INTERNAL_PrepareBufferForWrite(
  2157. D3D11Renderer *renderer,
  2158. D3D11BufferContainer *container,
  2159. bool cycle)
  2160. {
  2161. if (
  2162. cycle &&
  2163. SDL_GetAtomicInt(&container->activeBuffer->referenceCount) > 0) {
  2164. D3D11_INTERNAL_CycleActiveBuffer(
  2165. renderer,
  2166. container);
  2167. }
  2168. return container->activeBuffer;
  2169. }
  2170. static D3D11TransferBuffer *D3D11_INTERNAL_CreateTransferBuffer(
  2171. D3D11Renderer *renderer,
  2172. Uint32 size)
  2173. {
  2174. D3D11TransferBuffer *transferBuffer = SDL_malloc(sizeof(D3D11TransferBuffer));
  2175. transferBuffer->data = (Uint8 *)SDL_malloc(size);
  2176. transferBuffer->size = size;
  2177. SDL_SetAtomicInt(&transferBuffer->referenceCount, 0);
  2178. transferBuffer->bufferDownloads = NULL;
  2179. transferBuffer->bufferDownloadCount = 0;
  2180. transferBuffer->bufferDownloadCapacity = 0;
  2181. transferBuffer->textureDownloads = NULL;
  2182. transferBuffer->textureDownloadCount = 0;
  2183. transferBuffer->textureDownloadCapacity = 0;
  2184. return transferBuffer;
  2185. }
  2186. // This actually returns a container handle so we can rotate buffers on Cycle.
  2187. static SDL_GPUTransferBuffer *D3D11_CreateTransferBuffer(
  2188. SDL_GPURenderer *driverData,
  2189. SDL_GPUTransferBufferUsage usage, // ignored on D3D11
  2190. Uint32 size)
  2191. {
  2192. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  2193. D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer *)SDL_malloc(sizeof(D3D11TransferBufferContainer));
  2194. container->bufferCapacity = 1;
  2195. container->bufferCount = 1;
  2196. container->buffers = SDL_malloc(
  2197. container->bufferCapacity * sizeof(D3D11TransferBuffer *));
  2198. container->buffers[0] = D3D11_INTERNAL_CreateTransferBuffer(
  2199. renderer,
  2200. size);
  2201. container->activeBuffer = container->buffers[0];
  2202. return (SDL_GPUTransferBuffer *)container;
  2203. }
  2204. // TransferBuffer Data
  2205. static void D3D11_INTERNAL_CycleActiveTransferBuffer(
  2206. D3D11Renderer *renderer,
  2207. D3D11TransferBufferContainer *container)
  2208. {
  2209. Uint32 size = container->activeBuffer->size;
  2210. for (Uint32 i = 0; i < container->bufferCount; i += 1) {
  2211. if (SDL_GetAtomicInt(&container->buffers[i]->referenceCount) == 0) {
  2212. container->activeBuffer = container->buffers[i];
  2213. return;
  2214. }
  2215. }
  2216. EXPAND_ARRAY_IF_NEEDED(
  2217. container->buffers,
  2218. D3D11TransferBuffer *,
  2219. container->bufferCount + 1,
  2220. container->bufferCapacity,
  2221. container->bufferCapacity + 1);
  2222. container->buffers[container->bufferCount] = D3D11_INTERNAL_CreateTransferBuffer(
  2223. renderer,
  2224. size);
  2225. container->bufferCount += 1;
  2226. container->activeBuffer = container->buffers[container->bufferCount - 1];
  2227. }
  2228. static void *D3D11_MapTransferBuffer(
  2229. SDL_GPURenderer *driverData,
  2230. SDL_GPUTransferBuffer *transferBuffer,
  2231. bool cycle)
  2232. {
  2233. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  2234. D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer *)transferBuffer;
  2235. D3D11TransferBuffer *buffer = container->activeBuffer;
  2236. // Rotate the transfer buffer if necessary
  2237. if (
  2238. cycle &&
  2239. SDL_GetAtomicInt(&container->activeBuffer->referenceCount) > 0) {
  2240. D3D11_INTERNAL_CycleActiveTransferBuffer(
  2241. renderer,
  2242. container);
  2243. buffer = container->activeBuffer;
  2244. }
  2245. return buffer->data;
  2246. }
  2247. static void D3D11_UnmapTransferBuffer(
  2248. SDL_GPURenderer *driverData,
  2249. SDL_GPUTransferBuffer *transferBuffer)
  2250. {
  2251. // no-op
  2252. (void)driverData;
  2253. (void)transferBuffer;
  2254. }
  2255. // Copy Pass
  2256. static void D3D11_BeginCopyPass(
  2257. SDL_GPUCommandBuffer *commandBuffer)
  2258. {
  2259. // no-op
  2260. }
  2261. static void D3D11_UploadToTexture(
  2262. SDL_GPUCommandBuffer *commandBuffer,
  2263. const SDL_GPUTextureTransferInfo *source,
  2264. const SDL_GPUTextureRegion *destination,
  2265. bool cycle)
  2266. {
  2267. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2268. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  2269. D3D11TransferBufferContainer *srcTransferContainer = (D3D11TransferBufferContainer *)source->transfer_buffer;
  2270. D3D11TransferBuffer *srcTransferBuffer = srcTransferContainer->activeBuffer;
  2271. D3D11TextureContainer *dstTextureContainer = (D3D11TextureContainer *)destination->texture;
  2272. SDL_GPUTextureFormat dstFormat = dstTextureContainer->header.info.format;
  2273. Uint32 bufferStride = source->pixels_per_row;
  2274. Uint32 bufferImageHeight = source->rows_per_layer;
  2275. Sint32 w = destination->w;
  2276. Sint32 h = destination->h;
  2277. D3D11Texture *stagingTexture;
  2278. SDL_GPUTextureCreateInfo stagingTextureCreateInfo;
  2279. D3D11_SUBRESOURCE_DATA initialData;
  2280. D3D11TextureSubresource *textureSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
  2281. renderer,
  2282. dstTextureContainer,
  2283. destination->layer,
  2284. destination->mip_level,
  2285. cycle);
  2286. Sint32 blockSize = Texture_GetBlockSize(dstFormat);
  2287. if (blockSize > 1) {
  2288. w = (w + blockSize - 1) & ~(blockSize - 1);
  2289. h = (h + blockSize - 1) & ~(blockSize - 1);
  2290. }
  2291. if (bufferStride == 0) {
  2292. bufferStride = w;
  2293. }
  2294. if (bufferImageHeight == 0) {
  2295. bufferImageHeight = h;
  2296. }
  2297. Uint32 bytesPerRow = BytesPerRow(bufferStride, dstFormat);
  2298. Uint32 bytesPerDepthSlice = bytesPerRow * bufferImageHeight;
  2299. /* UpdateSubresource1 is completely busted on AMD, it truncates after X bytes.
  2300. * So we get to do this Fun (Tm) workaround where we create a staging texture
  2301. * with initial data before issuing a copy command.
  2302. */
  2303. stagingTextureCreateInfo.width = w;
  2304. stagingTextureCreateInfo.height = h;
  2305. stagingTextureCreateInfo.layer_count_or_depth = 1;
  2306. stagingTextureCreateInfo.num_levels = 1;
  2307. stagingTextureCreateInfo.type = SDL_GPU_TEXTURETYPE_2D;
  2308. stagingTextureCreateInfo.usage = 0;
  2309. stagingTextureCreateInfo.sample_count = SDL_GPU_SAMPLECOUNT_1;
  2310. stagingTextureCreateInfo.format = dstFormat;
  2311. initialData.pSysMem = srcTransferBuffer->data + source->offset;
  2312. initialData.SysMemPitch = bytesPerRow;
  2313. initialData.SysMemSlicePitch = bytesPerDepthSlice;
  2314. stagingTexture = D3D11_INTERNAL_CreateTexture(
  2315. renderer,
  2316. &stagingTextureCreateInfo,
  2317. &initialData);
  2318. if (stagingTexture == NULL) {
  2319. return;
  2320. }
  2321. ID3D11DeviceContext_CopySubresourceRegion(
  2322. d3d11CommandBuffer->context,
  2323. textureSubresource->parent->handle,
  2324. textureSubresource->index,
  2325. destination->x,
  2326. destination->y,
  2327. destination->z,
  2328. stagingTexture->handle,
  2329. 0,
  2330. NULL);
  2331. // Clean up the staging texture
  2332. D3D11_INTERNAL_DestroyTexture(stagingTexture);
  2333. D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, textureSubresource->parent);
  2334. D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, srcTransferBuffer);
  2335. }
  2336. static void D3D11_UploadToBuffer(
  2337. SDL_GPUCommandBuffer *commandBuffer,
  2338. const SDL_GPUTransferBufferLocation *source,
  2339. const SDL_GPUBufferRegion *destination,
  2340. bool cycle)
  2341. {
  2342. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2343. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  2344. D3D11TransferBufferContainer *transferContainer = (D3D11TransferBufferContainer *)source->transfer_buffer;
  2345. D3D11TransferBuffer *d3d11TransferBuffer = transferContainer->activeBuffer;
  2346. D3D11BufferContainer *bufferContainer = (D3D11BufferContainer *)destination->buffer;
  2347. D3D11Buffer *d3d11Buffer = D3D11_INTERNAL_PrepareBufferForWrite(
  2348. renderer,
  2349. bufferContainer,
  2350. cycle);
  2351. ID3D11Buffer *stagingBuffer;
  2352. D3D11_BUFFER_DESC stagingBufferDesc;
  2353. D3D11_SUBRESOURCE_DATA stagingBufferData;
  2354. HRESULT res;
  2355. // Upload to staging buffer immediately
  2356. stagingBufferDesc.ByteWidth = destination->size;
  2357. stagingBufferDesc.Usage = D3D11_USAGE_STAGING;
  2358. stagingBufferDesc.BindFlags = 0;
  2359. stagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  2360. stagingBufferDesc.MiscFlags = 0;
  2361. stagingBufferDesc.StructureByteStride = 0;
  2362. stagingBufferData.pSysMem = d3d11TransferBuffer->data + source->offset;
  2363. stagingBufferData.SysMemPitch = 0;
  2364. stagingBufferData.SysMemSlicePitch = 0;
  2365. res = ID3D11Device_CreateBuffer(
  2366. renderer->device,
  2367. &stagingBufferDesc,
  2368. &stagingBufferData,
  2369. &stagingBuffer);
  2370. CHECK_D3D11_ERROR_AND_RETURN("Could not create staging buffer", )
  2371. // Copy from staging buffer to buffer
  2372. ID3D11DeviceContext1_CopySubresourceRegion(
  2373. d3d11CommandBuffer->context,
  2374. (ID3D11Resource *)d3d11Buffer->handle,
  2375. 0,
  2376. destination->offset,
  2377. 0,
  2378. 0,
  2379. (ID3D11Resource *)stagingBuffer,
  2380. 0,
  2381. NULL);
  2382. ID3D11Buffer_Release(stagingBuffer);
  2383. D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
  2384. D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer);
  2385. }
  2386. static void D3D11_DownloadFromTexture(
  2387. SDL_GPUCommandBuffer *commandBuffer,
  2388. const SDL_GPUTextureRegion *source,
  2389. const SDL_GPUTextureTransferInfo *destination)
  2390. {
  2391. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2392. D3D11Renderer *renderer = d3d11CommandBuffer->renderer;
  2393. D3D11TransferBufferContainer *dstTransferContainer = (D3D11TransferBufferContainer *)destination->transfer_buffer;
  2394. D3D11TransferBuffer *d3d11TransferBuffer = dstTransferContainer->activeBuffer;
  2395. D3D11TextureContainer *srcTextureContainer = (D3D11TextureContainer *)source->texture;
  2396. SDL_GPUTextureFormat srcFormat = srcTextureContainer->header.info.format;
  2397. D3D11_TEXTURE2D_DESC stagingDesc2D;
  2398. D3D11_TEXTURE3D_DESC stagingDesc3D;
  2399. D3D11TextureSubresource *textureSubresource = D3D11_INTERNAL_FetchTextureSubresource(
  2400. srcTextureContainer,
  2401. source->layer,
  2402. source->mip_level);
  2403. D3D11TextureDownload *textureDownload;
  2404. Uint32 bufferStride = destination->pixels_per_row;
  2405. Uint32 bufferImageHeight = destination->rows_per_layer;
  2406. Uint32 bytesPerRow, bytesPerDepthSlice;
  2407. D3D11_BOX srcBox = { source->x, source->y, source->z, source->x + source->w, source->y + source->h, source->z + source->d };
  2408. HRESULT res;
  2409. if (d3d11TransferBuffer->textureDownloadCount >= d3d11TransferBuffer->textureDownloadCapacity) {
  2410. d3d11TransferBuffer->textureDownloadCapacity += 1;
  2411. d3d11TransferBuffer->textureDownloads = SDL_realloc(
  2412. d3d11TransferBuffer->textureDownloads,
  2413. d3d11TransferBuffer->textureDownloadCapacity * sizeof(D3D11TextureDownload));
  2414. }
  2415. textureDownload = &d3d11TransferBuffer->textureDownloads[d3d11TransferBuffer->textureDownloadCount];
  2416. d3d11TransferBuffer->textureDownloadCount += 1;
  2417. if (bufferStride == 0) {
  2418. bufferStride = source->w;
  2419. }
  2420. if (bufferImageHeight == 0) {
  2421. bufferImageHeight = source->h;
  2422. }
  2423. bytesPerRow = BytesPerRow(bufferStride, srcFormat);
  2424. bytesPerDepthSlice = bytesPerRow * bufferImageHeight;
  2425. if (source->d == 1) {
  2426. stagingDesc2D.Width = source->w;
  2427. stagingDesc2D.Height = source->h;
  2428. stagingDesc2D.MipLevels = 1;
  2429. stagingDesc2D.ArraySize = 1;
  2430. stagingDesc2D.Format = SDLToD3D11_TextureFormat[srcFormat];
  2431. stagingDesc2D.SampleDesc.Count = 1;
  2432. stagingDesc2D.SampleDesc.Quality = 0;
  2433. stagingDesc2D.Usage = D3D11_USAGE_STAGING;
  2434. stagingDesc2D.BindFlags = 0;
  2435. stagingDesc2D.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  2436. stagingDesc2D.MiscFlags = 0;
  2437. res = ID3D11Device_CreateTexture2D(
  2438. renderer->device,
  2439. &stagingDesc2D,
  2440. NULL,
  2441. (ID3D11Texture2D **)&textureDownload->stagingTexture);
  2442. CHECK_D3D11_ERROR_AND_RETURN("Staging texture creation failed", )
  2443. } else {
  2444. stagingDesc3D.Width = source->w;
  2445. stagingDesc3D.Height = source->h;
  2446. stagingDesc3D.Depth = source->d;
  2447. stagingDesc3D.MipLevels = 1;
  2448. stagingDesc3D.Format = SDLToD3D11_TextureFormat[srcFormat];
  2449. stagingDesc3D.Usage = D3D11_USAGE_STAGING;
  2450. stagingDesc3D.BindFlags = 0;
  2451. stagingDesc3D.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  2452. stagingDesc3D.MiscFlags = 0;
  2453. res = ID3D11Device_CreateTexture3D(
  2454. renderer->device,
  2455. &stagingDesc3D,
  2456. NULL,
  2457. (ID3D11Texture3D **)&textureDownload->stagingTexture);
  2458. }
  2459. textureDownload->width = source->w;
  2460. textureDownload->height = source->h;
  2461. textureDownload->depth = source->d;
  2462. textureDownload->bufferOffset = destination->offset;
  2463. textureDownload->bytesPerRow = bytesPerRow;
  2464. textureDownload->bytesPerDepthSlice = bytesPerDepthSlice;
  2465. ID3D11DeviceContext1_CopySubresourceRegion1(
  2466. d3d11CommandBuffer->context,
  2467. textureDownload->stagingTexture,
  2468. 0,
  2469. 0,
  2470. 0,
  2471. 0,
  2472. textureSubresource->parent->handle,
  2473. textureSubresource->index,
  2474. &srcBox,
  2475. D3D11_COPY_NO_OVERWRITE);
  2476. D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, textureSubresource->parent);
  2477. D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer);
  2478. }
  2479. static void D3D11_DownloadFromBuffer(
  2480. SDL_GPUCommandBuffer *commandBuffer,
  2481. const SDL_GPUBufferRegion *source,
  2482. const SDL_GPUTransferBufferLocation *destination)
  2483. {
  2484. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2485. D3D11Renderer *renderer = d3d11CommandBuffer->renderer;
  2486. D3D11TransferBufferContainer *dstTransferContainer = (D3D11TransferBufferContainer *)destination->transfer_buffer;
  2487. D3D11TransferBuffer *d3d11TransferBuffer = dstTransferContainer->activeBuffer;
  2488. D3D11BufferContainer *srcBufferContainer = (D3D11BufferContainer *)source->buffer;
  2489. D3D11BufferDownload *bufferDownload;
  2490. D3D11_BOX srcBox = { source->offset, 0, 0, source->size, 1, 1 };
  2491. D3D11_BUFFER_DESC stagingBufferDesc;
  2492. HRESULT res;
  2493. if (d3d11TransferBuffer->bufferDownloadCount >= d3d11TransferBuffer->bufferDownloadCapacity) {
  2494. d3d11TransferBuffer->bufferDownloadCapacity += 1;
  2495. d3d11TransferBuffer->bufferDownloads = SDL_realloc(
  2496. d3d11TransferBuffer->bufferDownloads,
  2497. d3d11TransferBuffer->bufferDownloadCapacity * sizeof(D3D11BufferDownload));
  2498. }
  2499. bufferDownload = &d3d11TransferBuffer->bufferDownloads[d3d11TransferBuffer->bufferDownloadCount];
  2500. d3d11TransferBuffer->bufferDownloadCount += 1;
  2501. stagingBufferDesc.ByteWidth = source->size;
  2502. stagingBufferDesc.Usage = D3D11_USAGE_STAGING;
  2503. stagingBufferDesc.BindFlags = 0;
  2504. stagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  2505. stagingBufferDesc.MiscFlags = 0;
  2506. stagingBufferDesc.StructureByteStride = 0;
  2507. res = ID3D11Device_CreateBuffer(
  2508. renderer->device,
  2509. &stagingBufferDesc,
  2510. NULL,
  2511. &bufferDownload->stagingBuffer);
  2512. CHECK_D3D11_ERROR_AND_RETURN("Could not create staging buffer", )
  2513. ID3D11DeviceContext1_CopySubresourceRegion1(
  2514. d3d11CommandBuffer->context,
  2515. (ID3D11Resource *)bufferDownload->stagingBuffer,
  2516. 0,
  2517. 0,
  2518. 0,
  2519. 0,
  2520. (ID3D11Resource *)srcBufferContainer->activeBuffer->handle,
  2521. 0,
  2522. &srcBox,
  2523. D3D11_COPY_NO_OVERWRITE);
  2524. bufferDownload->dstOffset = destination->offset;
  2525. bufferDownload->size = source->size;
  2526. D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, srcBufferContainer->activeBuffer);
  2527. D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer);
  2528. }
  2529. static void D3D11_CopyTextureToTexture(
  2530. SDL_GPUCommandBuffer *commandBuffer,
  2531. const SDL_GPUTextureLocation *source,
  2532. const SDL_GPUTextureLocation *destination,
  2533. Uint32 w,
  2534. Uint32 h,
  2535. Uint32 d,
  2536. bool cycle)
  2537. {
  2538. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2539. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  2540. D3D11TextureContainer *srcContainer = (D3D11TextureContainer *)source->texture;
  2541. D3D11TextureContainer *dstContainer = (D3D11TextureContainer *)destination->texture;
  2542. D3D11_BOX srcBox = { source->x, source->y, source->z, source->x + w, source->y + h, source->z + d };
  2543. D3D11TextureSubresource *srcSubresource = D3D11_INTERNAL_FetchTextureSubresource(
  2544. srcContainer,
  2545. source->layer,
  2546. source->mip_level);
  2547. D3D11TextureSubresource *dstSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
  2548. renderer,
  2549. dstContainer,
  2550. destination->layer,
  2551. destination->mip_level,
  2552. cycle);
  2553. ID3D11DeviceContext1_CopySubresourceRegion(
  2554. d3d11CommandBuffer->context,
  2555. dstSubresource->parent->handle,
  2556. dstSubresource->index,
  2557. destination->x,
  2558. destination->y,
  2559. destination->z,
  2560. srcSubresource->parent->handle,
  2561. srcSubresource->index,
  2562. &srcBox);
  2563. D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, srcSubresource->parent);
  2564. D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, dstSubresource->parent);
  2565. }
  2566. static void D3D11_CopyBufferToBuffer(
  2567. SDL_GPUCommandBuffer *commandBuffer,
  2568. const SDL_GPUBufferLocation *source,
  2569. const SDL_GPUBufferLocation *destination,
  2570. Uint32 size,
  2571. bool cycle)
  2572. {
  2573. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2574. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  2575. D3D11BufferContainer *srcBufferContainer = (D3D11BufferContainer *)source->buffer;
  2576. D3D11BufferContainer *dstBufferContainer = (D3D11BufferContainer *)destination->buffer;
  2577. D3D11_BOX srcBox = { source->offset, 0, 0, source->offset + size, 1, 1 };
  2578. D3D11Buffer *srcBuffer = srcBufferContainer->activeBuffer;
  2579. D3D11Buffer *dstBuffer = D3D11_INTERNAL_PrepareBufferForWrite(
  2580. renderer,
  2581. dstBufferContainer,
  2582. cycle);
  2583. ID3D11DeviceContext1_CopySubresourceRegion(
  2584. d3d11CommandBuffer->context,
  2585. (ID3D11Resource *)dstBuffer->handle,
  2586. 0,
  2587. destination->offset,
  2588. 0,
  2589. 0,
  2590. (ID3D11Resource *)srcBuffer->handle,
  2591. 0,
  2592. &srcBox);
  2593. D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, srcBuffer);
  2594. D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, dstBuffer);
  2595. }
  2596. static void D3D11_GenerateMipmaps(
  2597. SDL_GPUCommandBuffer *commandBuffer,
  2598. SDL_GPUTexture *texture)
  2599. {
  2600. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2601. D3D11TextureContainer *d3d11TextureContainer = (D3D11TextureContainer *)texture;
  2602. ID3D11DeviceContext1_GenerateMips(
  2603. d3d11CommandBuffer->context,
  2604. d3d11TextureContainer->activeTexture->shaderView);
  2605. D3D11_INTERNAL_TrackTexture(
  2606. d3d11CommandBuffer,
  2607. d3d11TextureContainer->activeTexture);
  2608. }
  2609. static void D3D11_EndCopyPass(
  2610. SDL_GPUCommandBuffer *commandBuffer)
  2611. {
  2612. // no-op
  2613. }
  2614. // Graphics State
  2615. static void D3D11_INTERNAL_AllocateCommandBuffers(
  2616. D3D11Renderer *renderer,
  2617. Uint32 allocateCount)
  2618. {
  2619. D3D11CommandBuffer *commandBuffer;
  2620. HRESULT res;
  2621. renderer->availableCommandBufferCapacity += allocateCount;
  2622. renderer->availableCommandBuffers = SDL_realloc(
  2623. renderer->availableCommandBuffers,
  2624. sizeof(D3D11CommandBuffer *) * renderer->availableCommandBufferCapacity);
  2625. for (Uint32 i = 0; i < allocateCount; i += 1) {
  2626. commandBuffer = SDL_calloc(1, sizeof(D3D11CommandBuffer));
  2627. commandBuffer->renderer = renderer;
  2628. // Deferred Device Context
  2629. res = ID3D11Device1_CreateDeferredContext1(
  2630. renderer->device,
  2631. 0,
  2632. &commandBuffer->context);
  2633. CHECK_D3D11_ERROR_AND_RETURN("Could not create deferred context", );
  2634. // Initialize debug annotation support, if available
  2635. ID3D11DeviceContext_QueryInterface(
  2636. commandBuffer->context,
  2637. &D3D_IID_ID3DUserDefinedAnnotation,
  2638. (void **)&commandBuffer->annotation);
  2639. // Window handling
  2640. commandBuffer->windowDataCapacity = 1;
  2641. commandBuffer->windowDataCount = 0;
  2642. commandBuffer->windowDatas = SDL_malloc(
  2643. commandBuffer->windowDataCapacity * sizeof(D3D11WindowData *));
  2644. // Reference Counting
  2645. commandBuffer->usedBufferCapacity = 4;
  2646. commandBuffer->usedBufferCount = 0;
  2647. commandBuffer->usedBuffers = SDL_malloc(
  2648. commandBuffer->usedBufferCapacity * sizeof(D3D11Buffer *));
  2649. commandBuffer->usedTransferBufferCapacity = 4;
  2650. commandBuffer->usedTransferBufferCount = 0;
  2651. commandBuffer->usedTransferBuffers = SDL_malloc(
  2652. commandBuffer->usedTransferBufferCapacity * sizeof(D3D11TransferBuffer *));
  2653. commandBuffer->usedTextureCapacity = 4;
  2654. commandBuffer->usedTextureCount = 0;
  2655. commandBuffer->usedTextures = SDL_malloc(
  2656. commandBuffer->usedTextureCapacity * sizeof(D3D11Texture *));
  2657. commandBuffer->usedUniformBufferCapacity = 4;
  2658. commandBuffer->usedUniformBufferCount = 0;
  2659. commandBuffer->usedUniformBuffers = SDL_malloc(
  2660. commandBuffer->usedUniformBufferCapacity * sizeof(D3D11UniformBuffer *));
  2661. renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
  2662. renderer->availableCommandBufferCount += 1;
  2663. }
  2664. }
  2665. static D3D11CommandBuffer *D3D11_INTERNAL_GetInactiveCommandBufferFromPool(
  2666. D3D11Renderer *renderer)
  2667. {
  2668. D3D11CommandBuffer *commandBuffer;
  2669. if (renderer->availableCommandBufferCount == 0) {
  2670. D3D11_INTERNAL_AllocateCommandBuffers(
  2671. renderer,
  2672. renderer->availableCommandBufferCapacity);
  2673. }
  2674. commandBuffer = renderer->availableCommandBuffers[renderer->availableCommandBufferCount - 1];
  2675. renderer->availableCommandBufferCount -= 1;
  2676. return commandBuffer;
  2677. }
  2678. static bool D3D11_INTERNAL_CreateFence(
  2679. D3D11Renderer *renderer)
  2680. {
  2681. D3D11_QUERY_DESC queryDesc;
  2682. ID3D11Query *queryHandle;
  2683. D3D11Fence *fence;
  2684. HRESULT res;
  2685. queryDesc.Query = D3D11_QUERY_EVENT;
  2686. queryDesc.MiscFlags = 0;
  2687. res = ID3D11Device_CreateQuery(
  2688. renderer->device,
  2689. &queryDesc,
  2690. &queryHandle);
  2691. CHECK_D3D11_ERROR_AND_RETURN("Could not create query", false);
  2692. fence = SDL_malloc(sizeof(D3D11Fence));
  2693. fence->handle = queryHandle;
  2694. SDL_SetAtomicInt(&fence->referenceCount, 0);
  2695. // Add it to the available pool
  2696. if (renderer->availableFenceCount >= renderer->availableFenceCapacity) {
  2697. renderer->availableFenceCapacity *= 2;
  2698. renderer->availableFences = SDL_realloc(
  2699. renderer->availableFences,
  2700. sizeof(D3D11Fence *) * renderer->availableFenceCapacity);
  2701. }
  2702. renderer->availableFences[renderer->availableFenceCount] = fence;
  2703. renderer->availableFenceCount += 1;
  2704. return true;
  2705. }
  2706. static bool D3D11_INTERNAL_AcquireFence(
  2707. D3D11CommandBuffer *commandBuffer)
  2708. {
  2709. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2710. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  2711. D3D11Fence *fence;
  2712. // Acquire a fence from the pool
  2713. SDL_LockMutex(renderer->fenceLock);
  2714. if (renderer->availableFenceCount == 0) {
  2715. if (!D3D11_INTERNAL_CreateFence(renderer)) {
  2716. SDL_UnlockMutex(renderer->fenceLock);
  2717. return false;
  2718. }
  2719. }
  2720. fence = renderer->availableFences[renderer->availableFenceCount - 1];
  2721. renderer->availableFenceCount -= 1;
  2722. SDL_UnlockMutex(renderer->fenceLock);
  2723. // Associate the fence with the command buffer
  2724. commandBuffer->fence = fence;
  2725. (void)SDL_AtomicIncRef(&commandBuffer->fence->referenceCount);
  2726. return true;
  2727. }
  2728. static SDL_GPUCommandBuffer *D3D11_AcquireCommandBuffer(
  2729. SDL_GPURenderer *driverData)
  2730. {
  2731. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  2732. D3D11CommandBuffer *commandBuffer;
  2733. Uint32 i;
  2734. SDL_LockMutex(renderer->acquireCommandBufferLock);
  2735. commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer);
  2736. commandBuffer->graphicsPipeline = NULL;
  2737. commandBuffer->stencilRef = 0;
  2738. commandBuffer->blendConstants.r = 1.0f;
  2739. commandBuffer->blendConstants.g = 1.0f;
  2740. commandBuffer->blendConstants.b = 1.0f;
  2741. commandBuffer->blendConstants.a = 1.0f;
  2742. commandBuffer->computePipeline = NULL;
  2743. for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
  2744. commandBuffer->colorTargetSubresources[i] = NULL;
  2745. commandBuffer->colorResolveSubresources[i] = NULL;
  2746. }
  2747. for (i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
  2748. commandBuffer->vertexUniformBuffers[i] = NULL;
  2749. commandBuffer->fragmentUniformBuffers[i] = NULL;
  2750. commandBuffer->computeUniformBuffers[i] = NULL;
  2751. }
  2752. commandBuffer->needVertexSamplerBind = true;
  2753. commandBuffer->needVertexStorageTextureBind = true;
  2754. commandBuffer->needVertexStorageBufferBind = true;
  2755. commandBuffer->needVertexUniformBufferBind = true;
  2756. commandBuffer->needFragmentSamplerBind = true;
  2757. commandBuffer->needFragmentStorageTextureBind = true;
  2758. commandBuffer->needFragmentStorageBufferBind = true;
  2759. commandBuffer->needFragmentUniformBufferBind = true;
  2760. commandBuffer->needComputeUniformBufferBind = true;
  2761. commandBuffer->needBlendStateSet = true;
  2762. SDL_zeroa(commandBuffer->vertexSamplers);
  2763. SDL_zeroa(commandBuffer->vertexSamplerTextures);
  2764. SDL_zeroa(commandBuffer->vertexStorageTextures);
  2765. SDL_zeroa(commandBuffer->vertexStorageBuffers);
  2766. SDL_zeroa(commandBuffer->fragmentSamplers);
  2767. SDL_zeroa(commandBuffer->fragmentSamplerTextures);
  2768. SDL_zeroa(commandBuffer->fragmentStorageTextures);
  2769. SDL_zeroa(commandBuffer->fragmentStorageBuffers);
  2770. SDL_zeroa(commandBuffer->computeSamplers);
  2771. SDL_zeroa(commandBuffer->computeSamplerTextures);
  2772. SDL_zeroa(commandBuffer->computeReadOnlyStorageTextures);
  2773. SDL_zeroa(commandBuffer->computeReadOnlyStorageBuffers);
  2774. SDL_zeroa(commandBuffer->computeReadWriteStorageTextureSubresources);
  2775. SDL_zeroa(commandBuffer->computeReadWriteStorageBuffers);
  2776. bool acquireFenceResult = D3D11_INTERNAL_AcquireFence(commandBuffer);
  2777. commandBuffer->autoReleaseFence = 1;
  2778. SDL_UnlockMutex(renderer->acquireCommandBufferLock);
  2779. if (!acquireFenceResult) {
  2780. return NULL;
  2781. }
  2782. return (SDL_GPUCommandBuffer *)commandBuffer;
  2783. }
  2784. static D3D11UniformBuffer *D3D11_INTERNAL_AcquireUniformBufferFromPool(
  2785. D3D11CommandBuffer *commandBuffer)
  2786. {
  2787. D3D11Renderer *renderer = commandBuffer->renderer;
  2788. D3D11UniformBuffer *uniformBuffer;
  2789. SDL_LockMutex(renderer->acquireUniformBufferLock);
  2790. if (renderer->uniformBufferPoolCount > 0) {
  2791. uniformBuffer = renderer->uniformBufferPool[renderer->uniformBufferPoolCount - 1];
  2792. renderer->uniformBufferPoolCount -= 1;
  2793. } else {
  2794. uniformBuffer = D3D11_INTERNAL_CreateUniformBuffer(
  2795. renderer,
  2796. UNIFORM_BUFFER_SIZE);
  2797. }
  2798. SDL_UnlockMutex(renderer->acquireUniformBufferLock);
  2799. D3D11_INTERNAL_TrackUniformBuffer(commandBuffer, uniformBuffer);
  2800. return uniformBuffer;
  2801. }
  2802. static void D3D11_INTERNAL_ReturnUniformBufferToPool(
  2803. D3D11Renderer *renderer,
  2804. D3D11UniformBuffer *uniformBuffer)
  2805. {
  2806. if (renderer->uniformBufferPoolCount >= renderer->uniformBufferPoolCapacity) {
  2807. renderer->uniformBufferPoolCapacity *= 2;
  2808. renderer->uniformBufferPool = SDL_realloc(
  2809. renderer->uniformBufferPool,
  2810. renderer->uniformBufferPoolCapacity * sizeof(D3D11UniformBuffer *));
  2811. }
  2812. renderer->uniformBufferPool[renderer->uniformBufferPoolCount] = uniformBuffer;
  2813. renderer->uniformBufferPoolCount += 1;
  2814. uniformBuffer->writeOffset = 0;
  2815. uniformBuffer->drawOffset = 0;
  2816. uniformBuffer->mappedData = NULL;
  2817. }
  2818. static void D3D11_INTERNAL_PushUniformData(
  2819. D3D11CommandBuffer *d3d11CommandBuffer,
  2820. SDL_GPUShaderStage shaderStage,
  2821. Uint32 slotIndex,
  2822. const void *data,
  2823. Uint32 length)
  2824. {
  2825. D3D11Renderer *renderer = d3d11CommandBuffer->renderer;
  2826. D3D11UniformBuffer *d3d11UniformBuffer;
  2827. D3D11_MAPPED_SUBRESOURCE subres;
  2828. HRESULT res;
  2829. if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
  2830. if (d3d11CommandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
  2831. d3d11CommandBuffer->vertexUniformBuffers[slotIndex] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
  2832. d3d11CommandBuffer);
  2833. }
  2834. d3d11UniformBuffer = d3d11CommandBuffer->vertexUniformBuffers[slotIndex];
  2835. } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
  2836. if (d3d11CommandBuffer->fragmentUniformBuffers[slotIndex] == NULL) {
  2837. d3d11CommandBuffer->fragmentUniformBuffers[slotIndex] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
  2838. d3d11CommandBuffer);
  2839. }
  2840. d3d11UniformBuffer = d3d11CommandBuffer->fragmentUniformBuffers[slotIndex];
  2841. } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
  2842. if (d3d11CommandBuffer->computeUniformBuffers[slotIndex] == NULL) {
  2843. d3d11CommandBuffer->computeUniformBuffers[slotIndex] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
  2844. d3d11CommandBuffer);
  2845. }
  2846. d3d11UniformBuffer = d3d11CommandBuffer->computeUniformBuffers[slotIndex];
  2847. } else {
  2848. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
  2849. return;
  2850. }
  2851. d3d11UniformBuffer->currentBlockSize =
  2852. D3D11_INTERNAL_NextHighestAlignment(
  2853. length,
  2854. 256);
  2855. // If there is no more room, acquire a new uniform buffer
  2856. if (d3d11UniformBuffer->writeOffset + d3d11UniformBuffer->currentBlockSize >= UNIFORM_BUFFER_SIZE) {
  2857. ID3D11DeviceContext_Unmap(
  2858. d3d11CommandBuffer->context,
  2859. (ID3D11Resource *)d3d11UniformBuffer->buffer,
  2860. 0);
  2861. d3d11UniformBuffer->mappedData = NULL;
  2862. d3d11UniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool(d3d11CommandBuffer);
  2863. d3d11UniformBuffer->drawOffset = 0;
  2864. d3d11UniformBuffer->writeOffset = 0;
  2865. if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
  2866. d3d11CommandBuffer->vertexUniformBuffers[slotIndex] = d3d11UniformBuffer;
  2867. } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
  2868. d3d11CommandBuffer->fragmentUniformBuffers[slotIndex] = d3d11UniformBuffer;
  2869. } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
  2870. d3d11CommandBuffer->computeUniformBuffers[slotIndex] = d3d11UniformBuffer;
  2871. } else {
  2872. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
  2873. }
  2874. }
  2875. // Map the uniform data on first push
  2876. if (d3d11UniformBuffer->writeOffset == 0) {
  2877. res = ID3D11DeviceContext_Map(
  2878. d3d11CommandBuffer->context,
  2879. (ID3D11Resource *)d3d11UniformBuffer->buffer,
  2880. 0,
  2881. D3D11_MAP_WRITE_DISCARD,
  2882. 0,
  2883. &subres);
  2884. CHECK_D3D11_ERROR_AND_RETURN("Failed to map uniform buffer", )
  2885. d3d11UniformBuffer->mappedData = subres.pData;
  2886. }
  2887. d3d11UniformBuffer->drawOffset = d3d11UniformBuffer->writeOffset;
  2888. SDL_memcpy(
  2889. (Uint8 *)d3d11UniformBuffer->mappedData + d3d11UniformBuffer->writeOffset,
  2890. data,
  2891. length);
  2892. d3d11UniformBuffer->writeOffset += d3d11UniformBuffer->currentBlockSize;
  2893. if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
  2894. d3d11CommandBuffer->needVertexUniformBufferBind = true;
  2895. } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
  2896. d3d11CommandBuffer->needFragmentUniformBufferBind = true;
  2897. } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
  2898. d3d11CommandBuffer->needComputeUniformBufferBind = true;
  2899. } else {
  2900. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
  2901. }
  2902. }
  2903. static void D3D11_SetViewport(
  2904. SDL_GPUCommandBuffer *commandBuffer,
  2905. const SDL_GPUViewport *viewport)
  2906. {
  2907. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2908. D3D11_VIEWPORT vp = {
  2909. viewport->x,
  2910. viewport->y,
  2911. viewport->w,
  2912. viewport->h,
  2913. viewport->min_depth,
  2914. viewport->max_depth
  2915. };
  2916. ID3D11DeviceContext_RSSetViewports(
  2917. d3d11CommandBuffer->context,
  2918. 1,
  2919. &vp);
  2920. }
  2921. static void D3D11_SetScissor(
  2922. SDL_GPUCommandBuffer *commandBuffer,
  2923. const SDL_Rect *scissor)
  2924. {
  2925. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2926. D3D11_RECT rect = {
  2927. scissor->x,
  2928. scissor->y,
  2929. scissor->x + scissor->w,
  2930. scissor->y + scissor->h
  2931. };
  2932. ID3D11DeviceContext_RSSetScissorRects(
  2933. d3d11CommandBuffer->context,
  2934. 1,
  2935. &rect);
  2936. }
  2937. static void D3D11_SetBlendConstants(
  2938. SDL_GPUCommandBuffer *commandBuffer,
  2939. SDL_FColor blendConstants)
  2940. {
  2941. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2942. d3d11CommandBuffer->blendConstants = blendConstants;
  2943. d3d11CommandBuffer->needBlendStateSet = true;
  2944. }
  2945. static void D3D11_SetStencilReference(
  2946. SDL_GPUCommandBuffer *commandBuffer,
  2947. Uint8 reference)
  2948. {
  2949. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2950. d3d11CommandBuffer->stencilRef = reference;
  2951. if (d3d11CommandBuffer->graphicsPipeline != NULL) {
  2952. ID3D11DeviceContext_OMSetDepthStencilState(
  2953. d3d11CommandBuffer->context,
  2954. d3d11CommandBuffer->graphicsPipeline->depthStencilState,
  2955. reference);
  2956. }
  2957. }
  2958. static void D3D11_BeginRenderPass(
  2959. SDL_GPUCommandBuffer *commandBuffer,
  2960. const SDL_GPUColorTargetInfo *colorTargetInfos,
  2961. Uint32 numColorTargets,
  2962. const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo)
  2963. {
  2964. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  2965. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  2966. ID3D11RenderTargetView *rtvs[MAX_COLOR_TARGET_BINDINGS];
  2967. ID3D11DepthStencilView *dsv = NULL;
  2968. Uint32 vpWidth = SDL_MAX_UINT32;
  2969. Uint32 vpHeight = SDL_MAX_UINT32;
  2970. SDL_GPUViewport viewport;
  2971. SDL_Rect scissorRect;
  2972. // Clear the bound targets for the current command buffer
  2973. for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
  2974. d3d11CommandBuffer->colorTargetSubresources[i] = NULL;
  2975. d3d11CommandBuffer->colorResolveSubresources[i] = NULL;
  2976. }
  2977. // Set up the new color target bindings
  2978. for (Uint32 i = 0; i < numColorTargets; i += 1) {
  2979. D3D11TextureContainer *container = (D3D11TextureContainer *)colorTargetInfos[i].texture;
  2980. D3D11TextureSubresource *subresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
  2981. renderer,
  2982. container,
  2983. container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorTargetInfos[i].layer_or_depth_plane,
  2984. colorTargetInfos[i].mip_level,
  2985. colorTargetInfos[i].cycle);
  2986. Uint32 rtvIndex = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0;
  2987. rtvs[i] = subresource->colorTargetViews[rtvIndex];
  2988. d3d11CommandBuffer->colorTargetSubresources[i] = subresource;
  2989. if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) {
  2990. D3D11TextureContainer *resolveContainer = (D3D11TextureContainer *)colorTargetInfos[i].resolve_texture;
  2991. D3D11TextureSubresource *resolveSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
  2992. renderer,
  2993. resolveContainer,
  2994. colorTargetInfos[i].resolve_layer,
  2995. colorTargetInfos[i].resolve_mip_level,
  2996. colorTargetInfos[i].cycle_resolve_texture);
  2997. d3d11CommandBuffer->colorResolveSubresources[i] = resolveSubresource;
  2998. }
  2999. if (colorTargetInfos[i].load_op == SDL_GPU_LOADOP_CLEAR) {
  3000. float clearColor[] = {
  3001. colorTargetInfos[i].clear_color.r,
  3002. colorTargetInfos[i].clear_color.g,
  3003. colorTargetInfos[i].clear_color.b,
  3004. colorTargetInfos[i].clear_color.a
  3005. };
  3006. ID3D11DeviceContext_ClearRenderTargetView(
  3007. d3d11CommandBuffer->context,
  3008. rtvs[i],
  3009. clearColor);
  3010. }
  3011. D3D11_INTERNAL_TrackTexture(
  3012. d3d11CommandBuffer,
  3013. subresource->parent);
  3014. }
  3015. // Get the DSV for the depth stencil target, if applicable
  3016. if (depthStencilTargetInfo != NULL) {
  3017. D3D11TextureContainer *container = (D3D11TextureContainer *)depthStencilTargetInfo->texture;
  3018. D3D11TextureSubresource *subresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
  3019. renderer,
  3020. container,
  3021. 0,
  3022. 0,
  3023. depthStencilTargetInfo->cycle);
  3024. dsv = subresource->depthStencilTargetView;
  3025. D3D11_INTERNAL_TrackTexture(
  3026. d3d11CommandBuffer,
  3027. subresource->parent);
  3028. }
  3029. // Actually set the RTs
  3030. ID3D11DeviceContext_OMSetRenderTargets(
  3031. d3d11CommandBuffer->context,
  3032. numColorTargets,
  3033. numColorTargets > 0 ? rtvs : NULL,
  3034. dsv);
  3035. if (depthStencilTargetInfo != NULL) {
  3036. D3D11_CLEAR_FLAG dsClearFlags = 0;
  3037. if (depthStencilTargetInfo->load_op == SDL_GPU_LOADOP_CLEAR) {
  3038. dsClearFlags |= D3D11_CLEAR_DEPTH;
  3039. }
  3040. if (depthStencilTargetInfo->stencil_load_op == SDL_GPU_LOADOP_CLEAR) {
  3041. dsClearFlags |= D3D11_CLEAR_STENCIL;
  3042. }
  3043. if (dsClearFlags != 0) {
  3044. ID3D11DeviceContext_ClearDepthStencilView(
  3045. d3d11CommandBuffer->context,
  3046. dsv,
  3047. dsClearFlags,
  3048. depthStencilTargetInfo->clear_depth,
  3049. depthStencilTargetInfo->clear_stencil);
  3050. }
  3051. }
  3052. // The viewport cannot be larger than the smallest target.
  3053. for (Uint32 i = 0; i < numColorTargets; i += 1) {
  3054. D3D11TextureContainer *container = (D3D11TextureContainer *)colorTargetInfos[i].texture;
  3055. Uint32 w = container->header.info.width >> colorTargetInfos[i].mip_level;
  3056. Uint32 h = container->header.info.height >> colorTargetInfos[i].mip_level;
  3057. if (w < vpWidth) {
  3058. vpWidth = w;
  3059. }
  3060. if (h < vpHeight) {
  3061. vpHeight = h;
  3062. }
  3063. }
  3064. if (depthStencilTargetInfo != NULL) {
  3065. D3D11TextureContainer *container = (D3D11TextureContainer *)depthStencilTargetInfo->texture;
  3066. Uint32 w = container->header.info.width;
  3067. Uint32 h = container->header.info.height;
  3068. if (w < vpWidth) {
  3069. vpWidth = w;
  3070. }
  3071. if (h < vpHeight) {
  3072. vpHeight = h;
  3073. }
  3074. }
  3075. // Set sensible default states
  3076. viewport.x = 0;
  3077. viewport.y = 0;
  3078. viewport.w = (float)vpWidth;
  3079. viewport.h = (float)vpHeight;
  3080. viewport.min_depth = 0;
  3081. viewport.max_depth = 1;
  3082. D3D11_SetViewport(
  3083. commandBuffer,
  3084. &viewport);
  3085. scissorRect.x = 0;
  3086. scissorRect.y = 0;
  3087. scissorRect.w = (int)vpWidth;
  3088. scissorRect.h = (int)vpHeight;
  3089. D3D11_SetScissor(
  3090. commandBuffer,
  3091. &scissorRect);
  3092. D3D11_SetStencilReference(
  3093. commandBuffer,
  3094. 0);
  3095. SDL_FColor blendConstants;
  3096. blendConstants.r = 1.0f;
  3097. blendConstants.g = 1.0f;
  3098. blendConstants.b = 1.0f;
  3099. blendConstants.a = 1.0f;
  3100. D3D11_SetBlendConstants(
  3101. commandBuffer,
  3102. blendConstants);
  3103. }
  3104. static void D3D11_BindGraphicsPipeline(
  3105. SDL_GPUCommandBuffer *commandBuffer,
  3106. SDL_GPUGraphicsPipeline *graphicsPipeline)
  3107. {
  3108. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3109. D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline *)graphicsPipeline;
  3110. d3d11CommandBuffer->graphicsPipeline = pipeline;
  3111. ID3D11DeviceContext_OMSetDepthStencilState(
  3112. d3d11CommandBuffer->context,
  3113. pipeline->depthStencilState,
  3114. d3d11CommandBuffer->stencilRef);
  3115. ID3D11DeviceContext_IASetPrimitiveTopology(
  3116. d3d11CommandBuffer->context,
  3117. SDLToD3D11_PrimitiveType[pipeline->primitiveType]);
  3118. ID3D11DeviceContext_IASetInputLayout(
  3119. d3d11CommandBuffer->context,
  3120. pipeline->inputLayout);
  3121. ID3D11DeviceContext_RSSetState(
  3122. d3d11CommandBuffer->context,
  3123. pipeline->rasterizerState);
  3124. ID3D11DeviceContext_VSSetShader(
  3125. d3d11CommandBuffer->context,
  3126. pipeline->vertexShader,
  3127. NULL,
  3128. 0);
  3129. ID3D11DeviceContext_PSSetShader(
  3130. d3d11CommandBuffer->context,
  3131. pipeline->fragmentShader,
  3132. NULL,
  3133. 0);
  3134. // Acquire uniform buffers if necessary
  3135. for (Uint32 i = 0; i < pipeline->vertexUniformBufferCount; i += 1) {
  3136. if (d3d11CommandBuffer->vertexUniformBuffers[i] == NULL) {
  3137. d3d11CommandBuffer->vertexUniformBuffers[i] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
  3138. d3d11CommandBuffer);
  3139. }
  3140. }
  3141. for (Uint32 i = 0; i < pipeline->fragmentUniformBufferCount; i += 1) {
  3142. if (d3d11CommandBuffer->fragmentUniformBuffers[i] == NULL) {
  3143. d3d11CommandBuffer->fragmentUniformBuffers[i] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
  3144. d3d11CommandBuffer);
  3145. }
  3146. }
  3147. // Mark that bindings are needed
  3148. d3d11CommandBuffer->needVertexSamplerBind = true;
  3149. d3d11CommandBuffer->needVertexStorageTextureBind = true;
  3150. d3d11CommandBuffer->needVertexStorageBufferBind = true;
  3151. d3d11CommandBuffer->needVertexUniformBufferBind = true;
  3152. d3d11CommandBuffer->needFragmentSamplerBind = true;
  3153. d3d11CommandBuffer->needFragmentStorageTextureBind = true;
  3154. d3d11CommandBuffer->needFragmentStorageBufferBind = true;
  3155. d3d11CommandBuffer->needFragmentUniformBufferBind = true;
  3156. d3d11CommandBuffer->needBlendStateSet = true;
  3157. }
  3158. static void D3D11_BindVertexBuffers(
  3159. SDL_GPUCommandBuffer *commandBuffer,
  3160. Uint32 firstSlot,
  3161. const SDL_GPUBufferBinding *bindings,
  3162. Uint32 numBindings)
  3163. {
  3164. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3165. for (Uint32 i = 0; i < numBindings; i += 1) {
  3166. D3D11Buffer *currentBuffer = ((D3D11BufferContainer *)bindings[i].buffer)->activeBuffer;
  3167. d3d11CommandBuffer->vertexBuffers[firstSlot + i] = currentBuffer->handle;
  3168. d3d11CommandBuffer->vertexBufferOffsets[firstSlot + i] = bindings[i].offset;
  3169. D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, currentBuffer);
  3170. }
  3171. d3d11CommandBuffer->vertexBufferCount =
  3172. SDL_max(d3d11CommandBuffer->vertexBufferCount, firstSlot + numBindings);
  3173. d3d11CommandBuffer->needVertexBufferBind = true;
  3174. }
  3175. static void D3D11_BindIndexBuffer(
  3176. SDL_GPUCommandBuffer *commandBuffer,
  3177. const SDL_GPUBufferBinding *binding,
  3178. SDL_GPUIndexElementSize indexElementSize)
  3179. {
  3180. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3181. D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)binding->buffer)->activeBuffer;
  3182. D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
  3183. ID3D11DeviceContext_IASetIndexBuffer(
  3184. d3d11CommandBuffer->context,
  3185. d3d11Buffer->handle,
  3186. SDLToD3D11_IndexType[indexElementSize],
  3187. (UINT)binding->offset);
  3188. }
  3189. static void D3D11_BindVertexSamplers(
  3190. SDL_GPUCommandBuffer *commandBuffer,
  3191. Uint32 firstSlot,
  3192. const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
  3193. Uint32 numBindings)
  3194. {
  3195. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3196. for (Uint32 i = 0; i < numBindings; i += 1) {
  3197. D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)textureSamplerBindings[i].texture;
  3198. D3D11_INTERNAL_TrackTexture(
  3199. d3d11CommandBuffer,
  3200. textureContainer->activeTexture);
  3201. d3d11CommandBuffer->vertexSamplers[firstSlot + i] =
  3202. (D3D11Sampler *)textureSamplerBindings[i].sampler;
  3203. d3d11CommandBuffer->vertexSamplerTextures[firstSlot + i] =
  3204. textureContainer->activeTexture;
  3205. }
  3206. d3d11CommandBuffer->needVertexSamplerBind = true;
  3207. }
  3208. static void D3D11_BindVertexStorageTextures(
  3209. SDL_GPUCommandBuffer *commandBuffer,
  3210. Uint32 firstSlot,
  3211. SDL_GPUTexture *const *storageTextures,
  3212. Uint32 numBindings)
  3213. {
  3214. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3215. for (Uint32 i = 0; i < numBindings; i += 1) {
  3216. D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)storageTextures[i];
  3217. D3D11_INTERNAL_TrackTexture(
  3218. d3d11CommandBuffer,
  3219. textureContainer->activeTexture);
  3220. d3d11CommandBuffer->vertexStorageTextures[firstSlot + i] =
  3221. textureContainer->activeTexture;
  3222. }
  3223. d3d11CommandBuffer->needVertexStorageTextureBind = true;
  3224. }
  3225. static void D3D11_BindVertexStorageBuffers(
  3226. SDL_GPUCommandBuffer *commandBuffer,
  3227. Uint32 firstSlot,
  3228. SDL_GPUBuffer *const *storageBuffers,
  3229. Uint32 numBindings)
  3230. {
  3231. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3232. D3D11BufferContainer *bufferContainer;
  3233. Uint32 i;
  3234. for (i = 0; i < numBindings; i += 1) {
  3235. bufferContainer = (D3D11BufferContainer *)storageBuffers[i];
  3236. D3D11_INTERNAL_TrackBuffer(
  3237. d3d11CommandBuffer,
  3238. bufferContainer->activeBuffer);
  3239. d3d11CommandBuffer->vertexStorageBuffers[firstSlot + i] =
  3240. bufferContainer->activeBuffer;
  3241. }
  3242. d3d11CommandBuffer->needVertexStorageBufferBind = true;
  3243. }
  3244. static void D3D11_BindFragmentSamplers(
  3245. SDL_GPUCommandBuffer *commandBuffer,
  3246. Uint32 firstSlot,
  3247. const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
  3248. Uint32 numBindings)
  3249. {
  3250. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3251. for (Uint32 i = 0; i < numBindings; i += 1) {
  3252. D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)textureSamplerBindings[i].texture;
  3253. D3D11_INTERNAL_TrackTexture(
  3254. d3d11CommandBuffer,
  3255. textureContainer->activeTexture);
  3256. d3d11CommandBuffer->fragmentSamplers[firstSlot + i] =
  3257. (D3D11Sampler *)textureSamplerBindings[i].sampler;
  3258. d3d11CommandBuffer->fragmentSamplerTextures[firstSlot + i] =
  3259. (D3D11Texture *)textureContainer->activeTexture;
  3260. }
  3261. d3d11CommandBuffer->needFragmentSamplerBind = true;
  3262. }
  3263. static void D3D11_BindFragmentStorageTextures(
  3264. SDL_GPUCommandBuffer *commandBuffer,
  3265. Uint32 firstSlot,
  3266. SDL_GPUTexture *const *storageTextures,
  3267. Uint32 numBindings)
  3268. {
  3269. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3270. for (Uint32 i = 0; i < numBindings; i += 1) {
  3271. D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)storageTextures[i];
  3272. D3D11_INTERNAL_TrackTexture(
  3273. d3d11CommandBuffer,
  3274. textureContainer->activeTexture);
  3275. d3d11CommandBuffer->fragmentStorageTextures[firstSlot + i] =
  3276. textureContainer->activeTexture;
  3277. }
  3278. d3d11CommandBuffer->needFragmentStorageTextureBind = true;
  3279. }
  3280. static void D3D11_BindFragmentStorageBuffers(
  3281. SDL_GPUCommandBuffer *commandBuffer,
  3282. Uint32 firstSlot,
  3283. SDL_GPUBuffer *const *storageBuffers,
  3284. Uint32 numBindings)
  3285. {
  3286. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3287. D3D11BufferContainer *bufferContainer;
  3288. Uint32 i;
  3289. for (i = 0; i < numBindings; i += 1) {
  3290. bufferContainer = (D3D11BufferContainer *)storageBuffers[i];
  3291. D3D11_INTERNAL_TrackBuffer(
  3292. d3d11CommandBuffer,
  3293. bufferContainer->activeBuffer);
  3294. d3d11CommandBuffer->fragmentStorageBuffers[firstSlot + i] =
  3295. bufferContainer->activeBuffer;
  3296. }
  3297. d3d11CommandBuffer->needFragmentStorageBufferBind = true;
  3298. }
  3299. static void D3D11_INTERNAL_BindGraphicsResources(
  3300. D3D11CommandBuffer *commandBuffer)
  3301. {
  3302. D3D11GraphicsPipeline *graphicsPipeline = commandBuffer->graphicsPipeline;
  3303. ID3D11Buffer *nullBuf = NULL;
  3304. Uint32 offsetInConstants, blockSizeInConstants;
  3305. if (commandBuffer->needVertexBufferBind) {
  3306. ID3D11DeviceContext_IASetVertexBuffers(
  3307. commandBuffer->context,
  3308. 0,
  3309. commandBuffer->vertexBufferCount,
  3310. commandBuffer->vertexBuffers,
  3311. graphicsPipeline->vertexStrides,
  3312. commandBuffer->vertexBufferOffsets);
  3313. }
  3314. if (commandBuffer->needVertexSamplerBind) {
  3315. if (graphicsPipeline->vertexSamplerCount > 0) {
  3316. ID3D11SamplerState *samplerStates[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  3317. ID3D11ShaderResourceView *srvs[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  3318. for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) {
  3319. samplerStates[i] = commandBuffer->vertexSamplers[i]->handle;
  3320. srvs[i] = commandBuffer->vertexSamplerTextures[i]->shaderView;
  3321. }
  3322. ID3D11DeviceContext_VSSetSamplers(
  3323. commandBuffer->context,
  3324. 0,
  3325. graphicsPipeline->vertexSamplerCount,
  3326. samplerStates);
  3327. ID3D11DeviceContext_VSSetShaderResources(
  3328. commandBuffer->context,
  3329. 0,
  3330. graphicsPipeline->vertexSamplerCount,
  3331. srvs);
  3332. }
  3333. commandBuffer->needVertexSamplerBind = false;
  3334. }
  3335. if (commandBuffer->needVertexStorageTextureBind) {
  3336. if (graphicsPipeline->vertexStorageTextureCount > 0) {
  3337. ID3D11ShaderResourceView *srvs[MAX_STORAGE_TEXTURES_PER_STAGE];
  3338. for (Uint32 i = 0; i < graphicsPipeline->vertexStorageTextureCount; i += 1) {
  3339. srvs[i] = commandBuffer->vertexStorageTextures[i]->shaderView;
  3340. }
  3341. ID3D11DeviceContext_VSSetShaderResources(
  3342. commandBuffer->context,
  3343. graphicsPipeline->vertexSamplerCount,
  3344. graphicsPipeline->vertexStorageTextureCount,
  3345. srvs);
  3346. }
  3347. commandBuffer->needVertexStorageTextureBind = false;
  3348. }
  3349. if (commandBuffer->needVertexStorageBufferBind) {
  3350. if (graphicsPipeline->vertexStorageBufferCount > 0) {
  3351. ID3D11ShaderResourceView *srvs[MAX_STORAGE_BUFFERS_PER_STAGE];
  3352. for (Uint32 i = 0; i < graphicsPipeline->vertexStorageBufferCount; i += 1) {
  3353. srvs[i] = commandBuffer->vertexStorageBuffers[i]->srv;
  3354. }
  3355. ID3D11DeviceContext_VSSetShaderResources(
  3356. commandBuffer->context,
  3357. graphicsPipeline->vertexSamplerCount + graphicsPipeline->vertexStorageTextureCount,
  3358. graphicsPipeline->vertexStorageBufferCount,
  3359. srvs);
  3360. }
  3361. commandBuffer->needVertexStorageBufferBind = false;
  3362. }
  3363. if (commandBuffer->needVertexUniformBufferBind) {
  3364. for (Uint32 i = 0; i < graphicsPipeline->vertexUniformBufferCount; i += 1) {
  3365. /* stupid workaround for god awful D3D11 drivers
  3366. * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1#calling-vssetconstantbuffers1-with-command-list-emulation
  3367. */
  3368. ID3D11DeviceContext1_VSSetConstantBuffers(
  3369. commandBuffer->context,
  3370. i,
  3371. 1,
  3372. &nullBuf);
  3373. offsetInConstants = commandBuffer->vertexUniformBuffers[i]->drawOffset / 16;
  3374. blockSizeInConstants = commandBuffer->vertexUniformBuffers[i]->currentBlockSize / 16;
  3375. ID3D11DeviceContext1_VSSetConstantBuffers1(
  3376. commandBuffer->context,
  3377. i,
  3378. 1,
  3379. &commandBuffer->vertexUniformBuffers[i]->buffer,
  3380. &offsetInConstants,
  3381. &blockSizeInConstants);
  3382. }
  3383. commandBuffer->needVertexUniformBufferBind = false;
  3384. }
  3385. if (commandBuffer->needFragmentSamplerBind) {
  3386. if (graphicsPipeline->fragmentSamplerCount > 0) {
  3387. ID3D11SamplerState *samplerStates[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  3388. ID3D11ShaderResourceView *srvs[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  3389. for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) {
  3390. samplerStates[i] = commandBuffer->fragmentSamplers[i]->handle;
  3391. srvs[i] = commandBuffer->fragmentSamplerTextures[i]->shaderView;
  3392. }
  3393. ID3D11DeviceContext_PSSetSamplers(
  3394. commandBuffer->context,
  3395. 0,
  3396. graphicsPipeline->fragmentSamplerCount,
  3397. samplerStates);
  3398. ID3D11DeviceContext_PSSetShaderResources(
  3399. commandBuffer->context,
  3400. 0,
  3401. graphicsPipeline->fragmentSamplerCount,
  3402. srvs);
  3403. }
  3404. commandBuffer->needFragmentSamplerBind = false;
  3405. }
  3406. if (commandBuffer->needFragmentStorageTextureBind) {
  3407. if (graphicsPipeline->fragmentStorageTextureCount > 0) {
  3408. ID3D11ShaderResourceView *srvs[MAX_STORAGE_TEXTURES_PER_STAGE];
  3409. for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageTextureCount; i += 1) {
  3410. srvs[i] = commandBuffer->fragmentStorageTextures[i]->shaderView;
  3411. }
  3412. ID3D11DeviceContext_PSSetShaderResources(
  3413. commandBuffer->context,
  3414. graphicsPipeline->fragmentSamplerCount,
  3415. graphicsPipeline->fragmentStorageTextureCount,
  3416. srvs);
  3417. }
  3418. commandBuffer->needFragmentStorageTextureBind = false;
  3419. }
  3420. if (commandBuffer->needFragmentStorageBufferBind) {
  3421. if (graphicsPipeline->fragmentStorageBufferCount > 0) {
  3422. ID3D11ShaderResourceView *srvs[MAX_STORAGE_BUFFERS_PER_STAGE];
  3423. for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageBufferCount; i += 1) {
  3424. srvs[i] = commandBuffer->fragmentStorageBuffers[i]->srv;
  3425. }
  3426. ID3D11DeviceContext_PSSetShaderResources(
  3427. commandBuffer->context,
  3428. graphicsPipeline->fragmentSamplerCount + graphicsPipeline->fragmentStorageTextureCount,
  3429. graphicsPipeline->fragmentStorageBufferCount,
  3430. srvs);
  3431. }
  3432. commandBuffer->needFragmentStorageBufferBind = false;
  3433. }
  3434. if (commandBuffer->needFragmentUniformBufferBind) {
  3435. for (Uint32 i = 0; i < graphicsPipeline->fragmentUniformBufferCount; i += 1) {
  3436. /* stupid workaround for god awful D3D11 drivers
  3437. * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-pssetconstantbuffers1#calling-pssetconstantbuffers1-with-command-list-emulation
  3438. */
  3439. ID3D11DeviceContext1_PSSetConstantBuffers(
  3440. commandBuffer->context,
  3441. i,
  3442. 1,
  3443. &nullBuf);
  3444. offsetInConstants = commandBuffer->fragmentUniformBuffers[i]->drawOffset / 16;
  3445. blockSizeInConstants = commandBuffer->fragmentUniformBuffers[i]->currentBlockSize / 16;
  3446. ID3D11DeviceContext1_PSSetConstantBuffers1(
  3447. commandBuffer->context,
  3448. i,
  3449. 1,
  3450. &commandBuffer->fragmentUniformBuffers[i]->buffer,
  3451. &offsetInConstants,
  3452. &blockSizeInConstants);
  3453. }
  3454. commandBuffer->needFragmentUniformBufferBind = false;
  3455. }
  3456. if (commandBuffer->needBlendStateSet) {
  3457. FLOAT blendFactor[4] = {
  3458. commandBuffer->blendConstants.r,
  3459. commandBuffer->blendConstants.g,
  3460. commandBuffer->blendConstants.b,
  3461. commandBuffer->blendConstants.a
  3462. };
  3463. ID3D11DeviceContext_OMSetBlendState(
  3464. commandBuffer->context,
  3465. graphicsPipeline->colorTargetBlendState,
  3466. blendFactor,
  3467. graphicsPipeline->sampleMask);
  3468. commandBuffer->needBlendStateSet = false;
  3469. }
  3470. }
  3471. static void D3D11_DrawIndexedPrimitives(
  3472. SDL_GPUCommandBuffer *commandBuffer,
  3473. Uint32 numIndices,
  3474. Uint32 numInstances,
  3475. Uint32 firstIndex,
  3476. Sint32 vertexOffset,
  3477. Uint32 firstInstance)
  3478. {
  3479. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3480. D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer);
  3481. ID3D11DeviceContext_DrawIndexedInstanced(
  3482. d3d11CommandBuffer->context,
  3483. numIndices,
  3484. numInstances,
  3485. firstIndex,
  3486. vertexOffset,
  3487. firstInstance);
  3488. }
  3489. static void D3D11_DrawPrimitives(
  3490. SDL_GPUCommandBuffer *commandBuffer,
  3491. Uint32 numVertices,
  3492. Uint32 numInstances,
  3493. Uint32 firstVertex,
  3494. Uint32 firstInstance)
  3495. {
  3496. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3497. D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer);
  3498. ID3D11DeviceContext_DrawInstanced(
  3499. d3d11CommandBuffer->context,
  3500. numVertices,
  3501. numInstances,
  3502. firstVertex,
  3503. firstInstance);
  3504. }
  3505. static void D3D11_DrawPrimitivesIndirect(
  3506. SDL_GPUCommandBuffer *commandBuffer,
  3507. SDL_GPUBuffer *buffer,
  3508. Uint32 offset,
  3509. Uint32 drawCount)
  3510. {
  3511. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3512. D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer);
  3513. D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)buffer)->activeBuffer;
  3514. /* D3D11: "We have multi-draw at home!"
  3515. * Multi-draw at home:
  3516. */
  3517. for (Uint32 i = 0; i < drawCount; i += 1) {
  3518. ID3D11DeviceContext_DrawInstancedIndirect(
  3519. d3d11CommandBuffer->context,
  3520. d3d11Buffer->handle,
  3521. offset + (sizeof(SDL_GPUIndirectDrawCommand) * i));
  3522. }
  3523. D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
  3524. }
  3525. static void D3D11_DrawIndexedPrimitivesIndirect(
  3526. SDL_GPUCommandBuffer *commandBuffer,
  3527. SDL_GPUBuffer *buffer,
  3528. Uint32 offset,
  3529. Uint32 drawCount)
  3530. {
  3531. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3532. D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer);
  3533. D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)buffer)->activeBuffer;
  3534. /* D3D11: "We have multi-draw at home!"
  3535. * Multi-draw at home:
  3536. */
  3537. for (Uint32 i = 0; i < drawCount; i += 1) {
  3538. ID3D11DeviceContext_DrawIndexedInstancedIndirect(
  3539. d3d11CommandBuffer->context,
  3540. d3d11Buffer->handle,
  3541. offset + (sizeof(SDL_GPUIndexedIndirectDrawCommand) * i));
  3542. }
  3543. D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
  3544. }
  3545. static void D3D11_EndRenderPass(
  3546. SDL_GPUCommandBuffer *commandBuffer)
  3547. {
  3548. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3549. D3D11Renderer *renderer = d3d11CommandBuffer->renderer;
  3550. Uint32 i;
  3551. // Set render target slots to NULL to avoid NULL set behavior
  3552. // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-pssetshaderresources
  3553. ID3D11DeviceContext_OMSetRenderTargets(
  3554. d3d11CommandBuffer->context,
  3555. MAX_COLOR_TARGET_BINDINGS,
  3556. renderer->nullRTVs,
  3557. NULL);
  3558. // Resolve MSAA color render targets
  3559. for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
  3560. if (d3d11CommandBuffer->colorResolveSubresources[i] != NULL) {
  3561. ID3D11DeviceContext_ResolveSubresource(
  3562. d3d11CommandBuffer->context,
  3563. d3d11CommandBuffer->colorResolveSubresources[i]->parent->handle,
  3564. d3d11CommandBuffer->colorResolveSubresources[i]->index,
  3565. d3d11CommandBuffer->colorTargetSubresources[i]->parent->handle,
  3566. d3d11CommandBuffer->colorTargetSubresources[i]->index,
  3567. SDLToD3D11_TextureFormat[d3d11CommandBuffer->colorTargetSubresources[i]->parent->container->header.info.format]);
  3568. }
  3569. }
  3570. ID3D11DeviceContext_VSSetSamplers(
  3571. d3d11CommandBuffer->context,
  3572. 0,
  3573. MAX_TEXTURE_SAMPLERS_PER_STAGE,
  3574. renderer->nullSamplers);
  3575. ID3D11DeviceContext_VSSetShaderResources(
  3576. d3d11CommandBuffer->context,
  3577. 0,
  3578. MAX_TEXTURE_SAMPLERS_PER_STAGE * 2 + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_STORAGE_BUFFERS_PER_STAGE,
  3579. renderer->nullSRVs);
  3580. ID3D11DeviceContext_PSSetSamplers(
  3581. d3d11CommandBuffer->context,
  3582. 0,
  3583. MAX_TEXTURE_SAMPLERS_PER_STAGE,
  3584. renderer->nullSamplers);
  3585. ID3D11DeviceContext_PSSetShaderResources(
  3586. d3d11CommandBuffer->context,
  3587. 0,
  3588. MAX_TEXTURE_SAMPLERS_PER_STAGE * 2 + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_STORAGE_BUFFERS_PER_STAGE,
  3589. renderer->nullSRVs);
  3590. // Reset bind state
  3591. SDL_zeroa(d3d11CommandBuffer->vertexBuffers);
  3592. SDL_zeroa(d3d11CommandBuffer->vertexBufferOffsets);
  3593. d3d11CommandBuffer->vertexBufferCount = 0;
  3594. SDL_zeroa(d3d11CommandBuffer->vertexSamplers);
  3595. SDL_zeroa(d3d11CommandBuffer->vertexSamplerTextures);
  3596. SDL_zeroa(d3d11CommandBuffer->vertexStorageTextures);
  3597. SDL_zeroa(d3d11CommandBuffer->vertexStorageBuffers);
  3598. SDL_zeroa(d3d11CommandBuffer->fragmentSamplers);
  3599. SDL_zeroa(d3d11CommandBuffer->fragmentSamplerTextures);
  3600. SDL_zeroa(d3d11CommandBuffer->fragmentStorageTextures);
  3601. SDL_zeroa(d3d11CommandBuffer->fragmentStorageBuffers);
  3602. }
  3603. static void D3D11_PushVertexUniformData(
  3604. SDL_GPUCommandBuffer *commandBuffer,
  3605. Uint32 slotIndex,
  3606. const void *data,
  3607. Uint32 length)
  3608. {
  3609. D3D11_INTERNAL_PushUniformData(
  3610. (D3D11CommandBuffer *)commandBuffer,
  3611. SDL_GPU_SHADERSTAGE_VERTEX,
  3612. slotIndex,
  3613. data,
  3614. length);
  3615. }
  3616. static void D3D11_PushFragmentUniformData(
  3617. SDL_GPUCommandBuffer *commandBuffer,
  3618. Uint32 slotIndex,
  3619. const void *data,
  3620. Uint32 length)
  3621. {
  3622. D3D11_INTERNAL_PushUniformData(
  3623. (D3D11CommandBuffer *)commandBuffer,
  3624. SDL_GPU_SHADERSTAGE_FRAGMENT,
  3625. slotIndex,
  3626. data,
  3627. length);
  3628. }
  3629. // Blit
  3630. static void D3D11_Blit(
  3631. SDL_GPUCommandBuffer *commandBuffer,
  3632. const SDL_GPUBlitInfo *info)
  3633. {
  3634. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3635. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  3636. BlitPipelineCacheEntry *blitPipelines = &renderer->blitPipelines[0];
  3637. SDL_GPU_BlitCommon(
  3638. commandBuffer,
  3639. info,
  3640. renderer->blitLinearSampler,
  3641. renderer->blitNearestSampler,
  3642. NULL,
  3643. NULL,
  3644. NULL,
  3645. NULL,
  3646. NULL,
  3647. NULL,
  3648. &blitPipelines,
  3649. NULL,
  3650. NULL);
  3651. }
  3652. // Compute State
  3653. static void D3D11_BeginComputePass(
  3654. SDL_GPUCommandBuffer *commandBuffer,
  3655. const SDL_GPUStorageTextureReadWriteBinding *storageTextureBindings,
  3656. Uint32 numStorageTextureBindings,
  3657. const SDL_GPUStorageBufferReadWriteBinding *storageBufferBindings,
  3658. Uint32 numStorageBufferBindings)
  3659. {
  3660. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3661. D3D11TextureContainer *textureContainer;
  3662. D3D11TextureSubresource *textureSubresource;
  3663. D3D11BufferContainer *bufferContainer;
  3664. D3D11Buffer *buffer;
  3665. ID3D11UnorderedAccessView *uavs[MAX_COMPUTE_WRITE_TEXTURES + MAX_COMPUTE_WRITE_BUFFERS];
  3666. for (Uint32 i = 0; i < numStorageTextureBindings; i += 1) {
  3667. textureContainer = (D3D11TextureContainer *)storageTextureBindings[i].texture;
  3668. textureSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
  3669. d3d11CommandBuffer->renderer,
  3670. textureContainer,
  3671. storageTextureBindings[i].layer,
  3672. storageTextureBindings[i].mip_level,
  3673. storageTextureBindings[i].cycle);
  3674. D3D11_INTERNAL_TrackTexture(
  3675. d3d11CommandBuffer,
  3676. textureSubresource->parent);
  3677. d3d11CommandBuffer->computeReadWriteStorageTextureSubresources[i] = textureSubresource;
  3678. }
  3679. for (Uint32 i = 0; i < numStorageBufferBindings; i += 1) {
  3680. bufferContainer = (D3D11BufferContainer *)storageBufferBindings[i].buffer;
  3681. buffer = D3D11_INTERNAL_PrepareBufferForWrite(
  3682. d3d11CommandBuffer->renderer,
  3683. bufferContainer,
  3684. storageBufferBindings[i].cycle);
  3685. D3D11_INTERNAL_TrackBuffer(
  3686. d3d11CommandBuffer,
  3687. buffer);
  3688. d3d11CommandBuffer->computeReadWriteStorageBuffers[i] = buffer;
  3689. }
  3690. for (Uint32 i = 0; i < numStorageTextureBindings; i += 1) {
  3691. uavs[i] = d3d11CommandBuffer->computeReadWriteStorageTextureSubresources[i]->uav;
  3692. }
  3693. for (Uint32 i = 0; i < numStorageBufferBindings; i += 1) {
  3694. uavs[numStorageTextureBindings + i] = d3d11CommandBuffer->computeReadWriteStorageBuffers[i]->uav;
  3695. }
  3696. ID3D11DeviceContext_CSSetUnorderedAccessViews(
  3697. d3d11CommandBuffer->context,
  3698. 0,
  3699. numStorageTextureBindings + numStorageBufferBindings,
  3700. uavs,
  3701. NULL);
  3702. }
  3703. static void D3D11_BindComputePipeline(
  3704. SDL_GPUCommandBuffer *commandBuffer,
  3705. SDL_GPUComputePipeline *computePipeline)
  3706. {
  3707. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3708. D3D11ComputePipeline *pipeline = (D3D11ComputePipeline *)computePipeline;
  3709. d3d11CommandBuffer->computePipeline = pipeline;
  3710. ID3D11DeviceContext_CSSetShader(
  3711. d3d11CommandBuffer->context,
  3712. pipeline->computeShader,
  3713. NULL,
  3714. 0);
  3715. // Acquire uniform buffers if necessary
  3716. for (Uint32 i = 0; i < pipeline->numUniformBuffers; i += 1) {
  3717. if (d3d11CommandBuffer->computeUniformBuffers[i] == NULL) {
  3718. d3d11CommandBuffer->computeUniformBuffers[i] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
  3719. d3d11CommandBuffer);
  3720. }
  3721. }
  3722. d3d11CommandBuffer->needComputeSamplerBind = true;
  3723. d3d11CommandBuffer->needComputeReadOnlyTextureBind = true;
  3724. d3d11CommandBuffer->needComputeReadOnlyBufferBind = true;
  3725. d3d11CommandBuffer->needComputeUniformBufferBind = true;
  3726. }
  3727. static void D3D11_BindComputeSamplers(
  3728. SDL_GPUCommandBuffer *commandBuffer,
  3729. Uint32 firstSlot,
  3730. const SDL_GPUTextureSamplerBinding *textureSamplerBindings,
  3731. Uint32 numBindings)
  3732. {
  3733. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3734. for (Uint32 i = 0; i < numBindings; i += 1) {
  3735. D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)textureSamplerBindings[i].texture;
  3736. D3D11_INTERNAL_TrackTexture(
  3737. d3d11CommandBuffer,
  3738. textureContainer->activeTexture);
  3739. d3d11CommandBuffer->computeSamplers[firstSlot + i] =
  3740. (D3D11Sampler *)textureSamplerBindings[i].sampler;
  3741. d3d11CommandBuffer->computeSamplerTextures[firstSlot + i] =
  3742. textureContainer->activeTexture;
  3743. }
  3744. d3d11CommandBuffer->needComputeSamplerBind = true;
  3745. }
  3746. static void D3D11_BindComputeStorageTextures(
  3747. SDL_GPUCommandBuffer *commandBuffer,
  3748. Uint32 firstSlot,
  3749. SDL_GPUTexture *const *storageTextures,
  3750. Uint32 numBindings)
  3751. {
  3752. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3753. for (Uint32 i = 0; i < numBindings; i += 1) {
  3754. D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)storageTextures[i];
  3755. D3D11_INTERNAL_TrackTexture(
  3756. d3d11CommandBuffer,
  3757. textureContainer->activeTexture);
  3758. d3d11CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i] =
  3759. textureContainer->activeTexture;
  3760. }
  3761. d3d11CommandBuffer->needComputeReadOnlyTextureBind = true;
  3762. }
  3763. static void D3D11_BindComputeStorageBuffers(
  3764. SDL_GPUCommandBuffer *commandBuffer,
  3765. Uint32 firstSlot,
  3766. SDL_GPUBuffer *const *storageBuffers,
  3767. Uint32 numBindings)
  3768. {
  3769. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3770. D3D11BufferContainer *bufferContainer;
  3771. Uint32 i;
  3772. for (i = 0; i < numBindings; i += 1) {
  3773. bufferContainer = (D3D11BufferContainer *)storageBuffers[i];
  3774. D3D11_INTERNAL_TrackBuffer(
  3775. d3d11CommandBuffer,
  3776. bufferContainer->activeBuffer);
  3777. d3d11CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] =
  3778. bufferContainer->activeBuffer;
  3779. }
  3780. d3d11CommandBuffer->needComputeReadOnlyBufferBind = true;
  3781. }
  3782. static void D3D11_PushComputeUniformData(
  3783. SDL_GPUCommandBuffer *commandBuffer,
  3784. Uint32 slotIndex,
  3785. const void *data,
  3786. Uint32 length)
  3787. {
  3788. D3D11_INTERNAL_PushUniformData(
  3789. (D3D11CommandBuffer *)commandBuffer,
  3790. SDL_GPU_SHADERSTAGE_COMPUTE,
  3791. slotIndex,
  3792. data,
  3793. length);
  3794. }
  3795. static void D3D11_INTERNAL_BindComputeResources(
  3796. D3D11CommandBuffer *commandBuffer)
  3797. {
  3798. D3D11ComputePipeline *computePipeline = commandBuffer->computePipeline;
  3799. ID3D11Buffer *nullBuf = NULL;
  3800. Uint32 offsetInConstants, blockSizeInConstants;
  3801. if (commandBuffer->needComputeSamplerBind) {
  3802. if (computePipeline->numSamplers > 0) {
  3803. ID3D11SamplerState *samplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  3804. ID3D11ShaderResourceView *srvs[MAX_TEXTURE_SAMPLERS_PER_STAGE];
  3805. for (Uint32 i = 0; i < computePipeline->numSamplers; i += 1) {
  3806. samplers[i] = commandBuffer->computeSamplers[i]->handle;
  3807. srvs[i] = commandBuffer->computeSamplerTextures[i]->shaderView;
  3808. }
  3809. ID3D11DeviceContext_CSSetSamplers(
  3810. commandBuffer->context,
  3811. 0,
  3812. computePipeline->numSamplers,
  3813. samplers);
  3814. ID3D11DeviceContext_CSSetShaderResources(
  3815. commandBuffer->context,
  3816. 0,
  3817. computePipeline->numSamplers,
  3818. srvs);
  3819. }
  3820. commandBuffer->needComputeSamplerBind = false;
  3821. }
  3822. if (commandBuffer->needComputeReadOnlyTextureBind) {
  3823. if (computePipeline->numReadonlyStorageTextures > 0) {
  3824. ID3D11ShaderResourceView *srvs[MAX_STORAGE_TEXTURES_PER_STAGE];
  3825. for (Uint32 i = 0; i < computePipeline->numReadonlyStorageTextures; i += 1) {
  3826. srvs[i] = commandBuffer->computeReadOnlyStorageTextures[i]->shaderView;
  3827. }
  3828. ID3D11DeviceContext_CSSetShaderResources(
  3829. commandBuffer->context,
  3830. computePipeline->numSamplers,
  3831. computePipeline->numReadonlyStorageTextures,
  3832. srvs);
  3833. }
  3834. commandBuffer->needComputeReadOnlyTextureBind = false;
  3835. }
  3836. if (commandBuffer->needComputeReadOnlyBufferBind) {
  3837. if (computePipeline->numReadonlyStorageBuffers > 0) {
  3838. ID3D11ShaderResourceView *srvs[MAX_STORAGE_TEXTURES_PER_STAGE];
  3839. for (Uint32 i = 0; i < computePipeline->numReadonlyStorageBuffers; i += 1) {
  3840. srvs[i] = commandBuffer->computeReadOnlyStorageBuffers[i]->srv;
  3841. }
  3842. ID3D11DeviceContext_CSSetShaderResources(
  3843. commandBuffer->context,
  3844. computePipeline->numSamplers + computePipeline->numReadonlyStorageTextures,
  3845. computePipeline->numReadonlyStorageBuffers,
  3846. srvs);
  3847. }
  3848. commandBuffer->needComputeReadOnlyBufferBind = false;
  3849. }
  3850. if (commandBuffer->needComputeUniformBufferBind) {
  3851. for (Uint32 i = 0; i < computePipeline->numUniformBuffers; i += 1) {
  3852. /* stupid workaround for god awful D3D11 drivers
  3853. * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1#calling-vssetconstantbuffers1-with-command-list-emulation
  3854. */
  3855. ID3D11DeviceContext1_CSSetConstantBuffers(
  3856. commandBuffer->context,
  3857. i,
  3858. 1,
  3859. &nullBuf);
  3860. offsetInConstants = commandBuffer->computeUniformBuffers[i]->drawOffset / 16;
  3861. blockSizeInConstants = commandBuffer->computeUniformBuffers[i]->currentBlockSize / 16;
  3862. ID3D11DeviceContext1_CSSetConstantBuffers1(
  3863. commandBuffer->context,
  3864. i,
  3865. 1,
  3866. &commandBuffer->computeUniformBuffers[i]->buffer,
  3867. &offsetInConstants,
  3868. &blockSizeInConstants);
  3869. }
  3870. commandBuffer->needComputeUniformBufferBind = false;
  3871. }
  3872. }
  3873. static void D3D11_DispatchCompute(
  3874. SDL_GPUCommandBuffer *commandBuffer,
  3875. Uint32 groupcountX,
  3876. Uint32 groupcountY,
  3877. Uint32 groupcountZ)
  3878. {
  3879. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3880. D3D11_INTERNAL_BindComputeResources(d3d11CommandBuffer);
  3881. ID3D11DeviceContext_Dispatch(
  3882. d3d11CommandBuffer->context,
  3883. groupcountX,
  3884. groupcountY,
  3885. groupcountZ);
  3886. }
  3887. static void D3D11_DispatchComputeIndirect(
  3888. SDL_GPUCommandBuffer *commandBuffer,
  3889. SDL_GPUBuffer *buffer,
  3890. Uint32 offset)
  3891. {
  3892. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3893. D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)buffer)->activeBuffer;
  3894. D3D11_INTERNAL_BindComputeResources(d3d11CommandBuffer);
  3895. ID3D11DeviceContext_DispatchIndirect(
  3896. d3d11CommandBuffer->context,
  3897. d3d11Buffer->handle,
  3898. offset);
  3899. D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
  3900. }
  3901. static void D3D11_EndComputePass(
  3902. SDL_GPUCommandBuffer *commandBuffer)
  3903. {
  3904. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  3905. D3D11Renderer *renderer = d3d11CommandBuffer->renderer;
  3906. // reset UAV slots to avoid NULL set behavior
  3907. // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-cssetshaderresources
  3908. ID3D11DeviceContext_CSSetUnorderedAccessViews(
  3909. d3d11CommandBuffer->context,
  3910. 0,
  3911. MAX_COMPUTE_WRITE_TEXTURES + MAX_COMPUTE_WRITE_BUFFERS,
  3912. renderer->nullUAVs,
  3913. NULL);
  3914. ID3D11DeviceContext_CSSetSamplers(
  3915. d3d11CommandBuffer->context,
  3916. 0,
  3917. MAX_TEXTURE_SAMPLERS_PER_STAGE,
  3918. renderer->nullSamplers);
  3919. ID3D11DeviceContext_CSSetShaderResources(
  3920. d3d11CommandBuffer->context,
  3921. 0,
  3922. MAX_TEXTURE_SAMPLERS_PER_STAGE + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_STORAGE_BUFFERS_PER_STAGE,
  3923. renderer->nullSRVs);
  3924. d3d11CommandBuffer->computePipeline = NULL;
  3925. // Reset bind state
  3926. SDL_zeroa(d3d11CommandBuffer->computeSamplers);
  3927. SDL_zeroa(d3d11CommandBuffer->computeSamplerTextures);
  3928. SDL_zeroa(d3d11CommandBuffer->computeReadOnlyStorageTextures);
  3929. SDL_zeroa(d3d11CommandBuffer->computeReadOnlyStorageBuffers);
  3930. SDL_zeroa(d3d11CommandBuffer->computeReadWriteStorageTextureSubresources);
  3931. SDL_zeroa(d3d11CommandBuffer->computeReadWriteStorageBuffers);
  3932. }
  3933. // Fence Cleanup
  3934. static void D3D11_INTERNAL_ReleaseFenceToPool(
  3935. D3D11Renderer *renderer,
  3936. D3D11Fence *fence)
  3937. {
  3938. SDL_LockMutex(renderer->fenceLock);
  3939. if (renderer->availableFenceCount == renderer->availableFenceCapacity) {
  3940. renderer->availableFenceCapacity *= 2;
  3941. renderer->availableFences = SDL_realloc(
  3942. renderer->availableFences,
  3943. renderer->availableFenceCapacity * sizeof(D3D11Fence *));
  3944. }
  3945. renderer->availableFences[renderer->availableFenceCount] = fence;
  3946. renderer->availableFenceCount += 1;
  3947. SDL_UnlockMutex(renderer->fenceLock);
  3948. }
  3949. static void D3D11_ReleaseFence(
  3950. SDL_GPURenderer *driverData,
  3951. SDL_GPUFence *fence)
  3952. {
  3953. D3D11Fence *d3d11Fence = (D3D11Fence *)fence;
  3954. if (SDL_AtomicDecRef(&d3d11Fence->referenceCount)) {
  3955. D3D11_INTERNAL_ReleaseFenceToPool(
  3956. (D3D11Renderer *)driverData,
  3957. d3d11Fence);
  3958. }
  3959. }
  3960. // Cleanup
  3961. /* D3D11 does not provide a deferred texture-to-buffer copy operation,
  3962. * so instead of the transfer buffer containing an actual D3D11 buffer,
  3963. * the transfer buffer data is just a malloc'd pointer.
  3964. * In the download operation we copy data to a staging resource, and
  3965. * wait until the command buffer has finished executing to map the staging resource.
  3966. */
  3967. static bool D3D11_INTERNAL_MapAndCopyBufferDownload(
  3968. D3D11Renderer *renderer,
  3969. D3D11TransferBuffer *transferBuffer,
  3970. D3D11BufferDownload *bufferDownload)
  3971. {
  3972. D3D11_MAPPED_SUBRESOURCE subres;
  3973. HRESULT res;
  3974. SDL_LockMutex(renderer->contextLock);
  3975. res = ID3D11DeviceContext_Map(
  3976. renderer->immediateContext,
  3977. (ID3D11Resource *)bufferDownload->stagingBuffer,
  3978. 0,
  3979. D3D11_MAP_READ,
  3980. 0,
  3981. &subres);
  3982. SDL_UnlockMutex(renderer->contextLock);
  3983. CHECK_D3D11_ERROR_AND_RETURN("Failed to map staging buffer", false)
  3984. SDL_memcpy(
  3985. ((Uint8 *)transferBuffer->data) + bufferDownload->dstOffset,
  3986. ((Uint8 *)subres.pData),
  3987. bufferDownload->size);
  3988. SDL_LockMutex(renderer->contextLock);
  3989. ID3D11DeviceContext_Unmap(
  3990. renderer->immediateContext,
  3991. (ID3D11Resource *)bufferDownload->stagingBuffer,
  3992. 0);
  3993. SDL_UnlockMutex(renderer->contextLock);
  3994. ID3D11Buffer_Release(bufferDownload->stagingBuffer);
  3995. return true;
  3996. }
  3997. static bool D3D11_INTERNAL_MapAndCopyTextureDownload(
  3998. D3D11Renderer *renderer,
  3999. D3D11TransferBuffer *transferBuffer,
  4000. D3D11TextureDownload *textureDownload)
  4001. {
  4002. D3D11_MAPPED_SUBRESOURCE subres;
  4003. HRESULT res;
  4004. Uint32 dataPtrOffset;
  4005. Uint32 depth, row;
  4006. SDL_LockMutex(renderer->contextLock);
  4007. res = ID3D11DeviceContext_Map(
  4008. renderer->immediateContext,
  4009. (ID3D11Resource *)textureDownload->stagingTexture,
  4010. 0,
  4011. D3D11_MAP_READ,
  4012. 0,
  4013. &subres);
  4014. SDL_UnlockMutex(renderer->contextLock);
  4015. CHECK_D3D11_ERROR_AND_RETURN("Could not map staging texture", false)
  4016. for (depth = 0; depth < textureDownload->depth; depth += 1) {
  4017. dataPtrOffset = textureDownload->bufferOffset + (depth * textureDownload->bytesPerDepthSlice);
  4018. for (row = 0; row < textureDownload->height; row += 1) {
  4019. SDL_memcpy(
  4020. transferBuffer->data + dataPtrOffset,
  4021. (Uint8 *)subres.pData + (depth * subres.DepthPitch) + (row * subres.RowPitch),
  4022. textureDownload->bytesPerRow);
  4023. dataPtrOffset += textureDownload->bytesPerRow;
  4024. }
  4025. }
  4026. SDL_LockMutex(renderer->contextLock);
  4027. ID3D11DeviceContext_Unmap(
  4028. renderer->immediateContext,
  4029. textureDownload->stagingTexture,
  4030. 0);
  4031. SDL_UnlockMutex(renderer->contextLock);
  4032. ID3D11Resource_Release(textureDownload->stagingTexture);
  4033. return true;
  4034. }
  4035. static bool D3D11_INTERNAL_CleanCommandBuffer(
  4036. D3D11Renderer *renderer,
  4037. D3D11CommandBuffer *commandBuffer)
  4038. {
  4039. Uint32 i, j;
  4040. bool result = true;
  4041. // Perform deferred download map and copy
  4042. for (i = 0; i < commandBuffer->usedTransferBufferCount; i += 1) {
  4043. D3D11TransferBuffer *transferBuffer = commandBuffer->usedTransferBuffers[i];
  4044. for (j = 0; j < transferBuffer->bufferDownloadCount; j += 1) {
  4045. result &= D3D11_INTERNAL_MapAndCopyBufferDownload(
  4046. renderer,
  4047. transferBuffer,
  4048. &transferBuffer->bufferDownloads[j]);
  4049. }
  4050. for (j = 0; j < transferBuffer->textureDownloadCount; j += 1) {
  4051. result &= D3D11_INTERNAL_MapAndCopyTextureDownload(
  4052. renderer,
  4053. transferBuffer,
  4054. &transferBuffer->textureDownloads[j]);
  4055. }
  4056. transferBuffer->bufferDownloadCount = 0;
  4057. transferBuffer->textureDownloadCount = 0;
  4058. }
  4059. // Uniform buffers are now available
  4060. SDL_LockMutex(renderer->acquireUniformBufferLock);
  4061. for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
  4062. D3D11_INTERNAL_ReturnUniformBufferToPool(
  4063. renderer,
  4064. commandBuffer->usedUniformBuffers[i]);
  4065. }
  4066. commandBuffer->usedUniformBufferCount = 0;
  4067. SDL_UnlockMutex(renderer->acquireUniformBufferLock);
  4068. // Reference Counting
  4069. for (i = 0; i < commandBuffer->usedBufferCount; i += 1) {
  4070. (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
  4071. }
  4072. commandBuffer->usedBufferCount = 0;
  4073. for (i = 0; i < commandBuffer->usedTransferBufferCount; i += 1) {
  4074. (void)SDL_AtomicDecRef(&commandBuffer->usedTransferBuffers[i]->referenceCount);
  4075. }
  4076. commandBuffer->usedTransferBufferCount = 0;
  4077. for (i = 0; i < commandBuffer->usedTextureCount; i += 1) {
  4078. (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
  4079. }
  4080. commandBuffer->usedTextureCount = 0;
  4081. // Reset presentation
  4082. commandBuffer->windowDataCount = 0;
  4083. // The fence is now available (unless SubmitAndAcquireFence was called)
  4084. if (commandBuffer->autoReleaseFence) {
  4085. D3D11_ReleaseFence(
  4086. (SDL_GPURenderer *)renderer,
  4087. (SDL_GPUFence *)commandBuffer->fence);
  4088. }
  4089. // Return command buffer to pool
  4090. SDL_LockMutex(renderer->acquireCommandBufferLock);
  4091. if (renderer->availableCommandBufferCount == renderer->availableCommandBufferCapacity) {
  4092. renderer->availableCommandBufferCapacity += 1;
  4093. renderer->availableCommandBuffers = SDL_realloc(
  4094. renderer->availableCommandBuffers,
  4095. renderer->availableCommandBufferCapacity * sizeof(D3D11CommandBuffer *));
  4096. }
  4097. renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
  4098. renderer->availableCommandBufferCount += 1;
  4099. SDL_UnlockMutex(renderer->acquireCommandBufferLock);
  4100. // Remove this command buffer from the submitted list
  4101. for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
  4102. if (renderer->submittedCommandBuffers[i] == commandBuffer) {
  4103. renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
  4104. renderer->submittedCommandBufferCount -= 1;
  4105. }
  4106. }
  4107. return result;
  4108. }
  4109. static void D3D11_INTERNAL_PerformPendingDestroys(
  4110. D3D11Renderer *renderer)
  4111. {
  4112. Sint32 referenceCount = 0;
  4113. Sint32 i;
  4114. Uint32 j;
  4115. for (i = renderer->transferBufferContainersToDestroyCount - 1; i >= 0; i -= 1) {
  4116. referenceCount = 0;
  4117. for (j = 0; j < renderer->transferBufferContainersToDestroy[i]->bufferCount; j += 1) {
  4118. referenceCount += SDL_GetAtomicInt(&renderer->transferBufferContainersToDestroy[i]->buffers[j]->referenceCount);
  4119. }
  4120. if (referenceCount == 0) {
  4121. D3D11_INTERNAL_DestroyTransferBufferContainer(
  4122. renderer->transferBufferContainersToDestroy[i]);
  4123. renderer->transferBufferContainersToDestroy[i] = renderer->transferBufferContainersToDestroy[renderer->transferBufferContainersToDestroyCount - 1];
  4124. renderer->transferBufferContainersToDestroyCount -= 1;
  4125. }
  4126. }
  4127. for (i = renderer->bufferContainersToDestroyCount - 1; i >= 0; i -= 1) {
  4128. referenceCount = 0;
  4129. for (j = 0; j < renderer->bufferContainersToDestroy[i]->bufferCount; j += 1) {
  4130. referenceCount += SDL_GetAtomicInt(&renderer->bufferContainersToDestroy[i]->buffers[j]->referenceCount);
  4131. }
  4132. if (referenceCount == 0) {
  4133. D3D11_INTERNAL_DestroyBufferContainer(
  4134. renderer->bufferContainersToDestroy[i]);
  4135. renderer->bufferContainersToDestroy[i] = renderer->bufferContainersToDestroy[renderer->bufferContainersToDestroyCount - 1];
  4136. renderer->bufferContainersToDestroyCount -= 1;
  4137. }
  4138. }
  4139. for (i = renderer->textureContainersToDestroyCount - 1; i >= 0; i -= 1) {
  4140. referenceCount = 0;
  4141. for (j = 0; j < renderer->textureContainersToDestroy[i]->textureCount; j += 1) {
  4142. referenceCount += SDL_GetAtomicInt(&renderer->textureContainersToDestroy[i]->textures[j]->referenceCount);
  4143. }
  4144. if (referenceCount == 0) {
  4145. D3D11_INTERNAL_DestroyTextureContainer(
  4146. renderer->textureContainersToDestroy[i]);
  4147. renderer->textureContainersToDestroy[i] = renderer->textureContainersToDestroy[renderer->textureContainersToDestroyCount - 1];
  4148. renderer->textureContainersToDestroyCount -= 1;
  4149. }
  4150. }
  4151. }
  4152. // Fences
  4153. static void D3D11_INTERNAL_WaitForFence(
  4154. D3D11Renderer *renderer,
  4155. D3D11Fence *fence)
  4156. {
  4157. BOOL queryData;
  4158. HRESULT res;
  4159. SDL_LockMutex(renderer->contextLock);
  4160. do {
  4161. res = ID3D11DeviceContext_GetData(
  4162. renderer->immediateContext,
  4163. (ID3D11Asynchronous *)fence->handle,
  4164. &queryData,
  4165. sizeof(queryData),
  4166. 0);
  4167. } while (res != S_OK); // Spin until we get a result back...
  4168. SDL_UnlockMutex(renderer->contextLock);
  4169. }
  4170. static bool D3D11_WaitForFences(
  4171. SDL_GPURenderer *driverData,
  4172. bool waitAll,
  4173. SDL_GPUFence *const *fences,
  4174. Uint32 numFences)
  4175. {
  4176. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4177. D3D11Fence *fence;
  4178. BOOL queryData;
  4179. HRESULT res = S_FALSE;
  4180. if (waitAll) {
  4181. for (Uint32 i = 0; i < numFences; i += 1) {
  4182. fence = (D3D11Fence *)fences[i];
  4183. D3D11_INTERNAL_WaitForFence(renderer, fence);
  4184. }
  4185. } else {
  4186. SDL_LockMutex(renderer->contextLock);
  4187. while (res != S_OK) {
  4188. for (Uint32 i = 0; i < numFences; i += 1) {
  4189. fence = (D3D11Fence *)fences[i];
  4190. res = ID3D11DeviceContext_GetData(
  4191. renderer->immediateContext,
  4192. (ID3D11Asynchronous *)fence->handle,
  4193. &queryData,
  4194. sizeof(queryData),
  4195. 0);
  4196. if (res == S_OK) {
  4197. break;
  4198. }
  4199. }
  4200. }
  4201. SDL_UnlockMutex(renderer->contextLock);
  4202. }
  4203. SDL_LockMutex(renderer->contextLock);
  4204. bool result = true;
  4205. // Check if we can perform any cleanups
  4206. for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
  4207. res = ID3D11DeviceContext_GetData(
  4208. renderer->immediateContext,
  4209. (ID3D11Asynchronous *)renderer->submittedCommandBuffers[i]->fence->handle,
  4210. &queryData,
  4211. sizeof(queryData),
  4212. 0);
  4213. if (res == S_OK) {
  4214. result &= D3D11_INTERNAL_CleanCommandBuffer(
  4215. renderer,
  4216. renderer->submittedCommandBuffers[i]);
  4217. }
  4218. }
  4219. D3D11_INTERNAL_PerformPendingDestroys(renderer);
  4220. SDL_UnlockMutex(renderer->contextLock);
  4221. return result;
  4222. }
  4223. static bool D3D11_QueryFence(
  4224. SDL_GPURenderer *driverData,
  4225. SDL_GPUFence *fence)
  4226. {
  4227. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4228. D3D11Fence *d3d11Fence = (D3D11Fence *)fence;
  4229. BOOL queryData;
  4230. HRESULT res;
  4231. SDL_LockMutex(renderer->contextLock);
  4232. res = ID3D11DeviceContext_GetData(
  4233. renderer->immediateContext,
  4234. (ID3D11Asynchronous *)d3d11Fence->handle,
  4235. &queryData,
  4236. sizeof(queryData),
  4237. 0);
  4238. SDL_UnlockMutex(renderer->contextLock);
  4239. return res == S_OK;
  4240. }
  4241. // Window and Swapchain Management
  4242. static D3D11WindowData *D3D11_INTERNAL_FetchWindowData(
  4243. SDL_Window *window)
  4244. {
  4245. SDL_PropertiesID properties = SDL_GetWindowProperties(window);
  4246. return (D3D11WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
  4247. }
  4248. static bool D3D11_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
  4249. {
  4250. SDL_Window *w = (SDL_Window *)userdata;
  4251. D3D11WindowData *data;
  4252. if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
  4253. data = D3D11_INTERNAL_FetchWindowData(w);
  4254. data->needsSwapchainRecreate = true;
  4255. }
  4256. return true;
  4257. }
  4258. static bool D3D11_INTERNAL_InitializeSwapchainTexture(
  4259. D3D11Renderer *renderer,
  4260. IDXGISwapChain *swapchain,
  4261. DXGI_FORMAT swapchainFormat,
  4262. DXGI_FORMAT rtvFormat,
  4263. D3D11Texture *pTexture)
  4264. {
  4265. ID3D11Texture2D *swapchainTexture;
  4266. D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
  4267. ID3D11RenderTargetView *rtv;
  4268. HRESULT res;
  4269. // Clear all the texture data
  4270. SDL_zerop(pTexture);
  4271. // Grab the buffer from the swapchain
  4272. res = IDXGISwapChain_GetBuffer(
  4273. swapchain,
  4274. 0,
  4275. &D3D_IID_ID3D11Texture2D,
  4276. (void **)&swapchainTexture);
  4277. CHECK_D3D11_ERROR_AND_RETURN("Could not get buffer from swapchain!", false);
  4278. // Create the RTV for the swapchain
  4279. rtvDesc.Format = rtvFormat;
  4280. rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
  4281. rtvDesc.Texture2D.MipSlice = 0;
  4282. res = ID3D11Device_CreateRenderTargetView(
  4283. renderer->device,
  4284. (ID3D11Resource *)swapchainTexture,
  4285. &rtvDesc,
  4286. &rtv);
  4287. if (FAILED(res)) {
  4288. ID3D11Texture2D_Release(swapchainTexture);
  4289. D3D11_INTERNAL_SetError(renderer, "Swapchain RTV creation failed", res);
  4290. return false;
  4291. }
  4292. // Fill out the texture struct
  4293. pTexture->handle = NULL; // This will be set in AcquireSwapchainTexture.
  4294. pTexture->shaderView = NULL; // We don't allow swapchain texture to be sampled
  4295. SDL_SetAtomicInt(&pTexture->referenceCount, 0);
  4296. pTexture->subresourceCount = 1;
  4297. pTexture->subresources = SDL_malloc(sizeof(D3D11TextureSubresource));
  4298. pTexture->subresources[0].colorTargetViews = SDL_calloc(1, sizeof(ID3D11RenderTargetView *));
  4299. pTexture->subresources[0].colorTargetViews[0] = rtv;
  4300. pTexture->subresources[0].uav = NULL;
  4301. pTexture->subresources[0].depthStencilTargetView = NULL;
  4302. pTexture->subresources[0].layer = 0;
  4303. pTexture->subresources[0].level = 0;
  4304. pTexture->subresources[0].depth = 1;
  4305. pTexture->subresources[0].index = 0;
  4306. pTexture->subresources[0].parent = pTexture;
  4307. // Cleanup
  4308. ID3D11Texture2D_Release(swapchainTexture);
  4309. return true;
  4310. }
  4311. static bool D3D11_INTERNAL_CreateSwapchain(
  4312. D3D11Renderer *renderer,
  4313. D3D11WindowData *windowData,
  4314. SDL_GPUSwapchainComposition swapchainComposition,
  4315. SDL_GPUPresentMode presentMode)
  4316. {
  4317. HWND dxgiHandle;
  4318. Uint32 i;
  4319. DXGI_SWAP_CHAIN_DESC swapchainDesc;
  4320. DXGI_FORMAT swapchainFormat;
  4321. IDXGIFactory1 *pParent;
  4322. IDXGISwapChain *swapchain;
  4323. IDXGISwapChain3 *swapchain3;
  4324. HRESULT res;
  4325. // Get the DXGI handle
  4326. #ifdef _WIN32
  4327. dxgiHandle = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(windowData->window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
  4328. #else
  4329. dxgiHandle = (HWND)windowData->window;
  4330. #endif
  4331. swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
  4332. // Initialize the swapchain buffer descriptor
  4333. swapchainDesc.BufferDesc.Width = 0;
  4334. swapchainDesc.BufferDesc.Height = 0;
  4335. swapchainDesc.BufferDesc.RefreshRate.Numerator = 0;
  4336. swapchainDesc.BufferDesc.RefreshRate.Denominator = 0;
  4337. swapchainDesc.BufferDesc.Format = swapchainFormat;
  4338. swapchainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
  4339. swapchainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
  4340. // Initialize the rest of the swapchain descriptor
  4341. swapchainDesc.SampleDesc.Count = 1;
  4342. swapchainDesc.SampleDesc.Quality = 0;
  4343. swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  4344. swapchainDesc.BufferCount = 2;
  4345. swapchainDesc.OutputWindow = dxgiHandle;
  4346. swapchainDesc.Windowed = 1;
  4347. if (renderer->supportsTearing) {
  4348. swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
  4349. // We know this is supported because tearing support implies DXGI 1.5+
  4350. swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
  4351. } else {
  4352. swapchainDesc.Flags = 0;
  4353. swapchainDesc.SwapEffect = (renderer->supportsFlipDiscard ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD);
  4354. }
  4355. // Create the swapchain!
  4356. res = IDXGIFactory1_CreateSwapChain(
  4357. (IDXGIFactory1 *)renderer->factory,
  4358. (IUnknown *)renderer->device,
  4359. &swapchainDesc,
  4360. &swapchain);
  4361. CHECK_D3D11_ERROR_AND_RETURN("Could not create swapchain", false);
  4362. /*
  4363. * The swapchain's parent is a separate factory from the factory that
  4364. * we used to create the swapchain, and only that parent can be used to
  4365. * set the window association. Trying to set an association on our factory
  4366. * will silently fail and doesn't even verify arguments or return errors.
  4367. * See https://gamedev.net/forums/topic/634235-dxgidisabling-altenter/4999955/
  4368. */
  4369. res = IDXGISwapChain_GetParent(
  4370. swapchain,
  4371. &D3D_IID_IDXGIFactory1,
  4372. (void **)&pParent);
  4373. if (FAILED(res)) {
  4374. SDL_LogWarn(
  4375. SDL_LOG_CATEGORY_GPU,
  4376. "Could not get swapchain parent! Error Code: " HRESULT_FMT,
  4377. res);
  4378. } else {
  4379. // Disable DXGI window crap
  4380. res = IDXGIFactory1_MakeWindowAssociation(
  4381. pParent,
  4382. dxgiHandle,
  4383. DXGI_MWA_NO_WINDOW_CHANGES);
  4384. if (FAILED(res)) {
  4385. SDL_LogWarn(
  4386. SDL_LOG_CATEGORY_GPU,
  4387. "MakeWindowAssociation failed! Error Code: " HRESULT_FMT,
  4388. res);
  4389. }
  4390. // We're done with the parent now
  4391. IDXGIFactory1_Release(pParent);
  4392. }
  4393. if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) {
  4394. // Set the color space, support already verified if we hit this block
  4395. IDXGISwapChain3_QueryInterface(
  4396. swapchain,
  4397. &D3D_IID_IDXGISwapChain3,
  4398. (void **)&swapchain3);
  4399. IDXGISwapChain3_SetColorSpace1(
  4400. swapchain3,
  4401. SwapchainCompositionToColorSpace[swapchainComposition]);
  4402. IDXGISwapChain3_Release(swapchain3);
  4403. }
  4404. // Initialize the swapchain data
  4405. windowData->swapchain = swapchain;
  4406. windowData->presentMode = presentMode;
  4407. windowData->swapchainComposition = swapchainComposition;
  4408. windowData->swapchainFormat = swapchainFormat;
  4409. windowData->swapchainColorSpace = SwapchainCompositionToColorSpace[swapchainComposition];
  4410. windowData->frameCounter = 0;
  4411. for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
  4412. windowData->inFlightFences[i] = NULL;
  4413. }
  4414. /* If a you are using a FLIP model format you can't create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM_SRGB.
  4415. * 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
  4416. */
  4417. if (!D3D11_INTERNAL_InitializeSwapchainTexture(
  4418. renderer,
  4419. swapchain,
  4420. swapchainFormat,
  4421. (swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat,
  4422. &windowData->texture)) {
  4423. IDXGISwapChain_Release(swapchain);
  4424. return false;
  4425. }
  4426. int w, h;
  4427. SDL_SyncWindow(windowData->window);
  4428. SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
  4429. // Initialize dummy container, width/height will be filled out in AcquireSwapchainTexture
  4430. SDL_zerop(&windowData->textureContainer);
  4431. windowData->textureContainer.textures = SDL_calloc(1, sizeof(D3D11Texture *));
  4432. windowData->textureContainer.activeTexture = &windowData->texture;
  4433. windowData->textureContainer.textures[0] = &windowData->texture;
  4434. windowData->textureContainer.canBeCycled = false;
  4435. windowData->textureContainer.textureCount = 1;
  4436. windowData->textureContainer.textureCapacity = 1;
  4437. windowData->textureContainer.header.info.layer_count_or_depth = 1;
  4438. windowData->textureContainer.header.info.format = SwapchainCompositionToSDLTextureFormat[windowData->swapchainComposition];
  4439. windowData->textureContainer.header.info.type = SDL_GPU_TEXTURETYPE_2D;
  4440. windowData->textureContainer.header.info.num_levels = 1;
  4441. windowData->textureContainer.header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
  4442. windowData->textureContainer.header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
  4443. windowData->textureContainer.header.info.width = w;
  4444. windowData->textureContainer.header.info.height = h;
  4445. windowData->texture.container = &windowData->textureContainer;
  4446. windowData->texture.containerIndex = 0;
  4447. windowData->width = w;
  4448. windowData->height = h;
  4449. return true;
  4450. }
  4451. static bool D3D11_INTERNAL_ResizeSwapchain(
  4452. D3D11Renderer *renderer,
  4453. D3D11WindowData *windowData)
  4454. {
  4455. D3D11_Wait((SDL_GPURenderer *)renderer);
  4456. // Release the old RTV
  4457. ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetViews[0]);
  4458. SDL_free(windowData->texture.subresources[0].colorTargetViews);
  4459. SDL_free(windowData->texture.subresources);
  4460. int w, h;
  4461. SDL_SyncWindow(windowData->window);
  4462. SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
  4463. // Resize the swapchain
  4464. HRESULT res = IDXGISwapChain_ResizeBuffers(
  4465. windowData->swapchain,
  4466. 0, // Keep buffer count the same
  4467. w,
  4468. h,
  4469. DXGI_FORMAT_UNKNOWN, // Keep the old format
  4470. renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
  4471. CHECK_D3D11_ERROR_AND_RETURN("Could not resize swapchain buffers", false);
  4472. // Create the texture object for the swapchain
  4473. bool result = D3D11_INTERNAL_InitializeSwapchainTexture(
  4474. renderer,
  4475. windowData->swapchain,
  4476. windowData->swapchainFormat,
  4477. (windowData->swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat,
  4478. &windowData->texture);
  4479. windowData->textureContainer.header.info.width = w;
  4480. windowData->textureContainer.header.info.height = h;
  4481. windowData->width = w;
  4482. windowData->height = h;
  4483. windowData->needsSwapchainRecreate = !result;
  4484. return result;
  4485. }
  4486. static bool D3D11_SupportsSwapchainComposition(
  4487. SDL_GPURenderer *driverData,
  4488. SDL_Window *window,
  4489. SDL_GPUSwapchainComposition swapchainComposition)
  4490. {
  4491. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4492. DXGI_FORMAT format;
  4493. Uint32 formatSupport = 0;
  4494. IDXGISwapChain3 *swapchain3;
  4495. Uint32 colorSpaceSupport;
  4496. HRESULT res;
  4497. format = SwapchainCompositionToTextureFormat[swapchainComposition];
  4498. res = ID3D11Device_CheckFormatSupport(
  4499. renderer->device,
  4500. format,
  4501. &formatSupport);
  4502. if (FAILED(res)) {
  4503. // Format is apparently unknown
  4504. return false;
  4505. }
  4506. if (!(formatSupport & D3D11_FORMAT_SUPPORT_DISPLAY)) {
  4507. return false;
  4508. }
  4509. D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
  4510. if (windowData == NULL) {
  4511. SET_STRING_ERROR_AND_RETURN("Must claim window before querying swapchain composition support!", false)
  4512. }
  4513. // Check the color space support if necessary
  4514. if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) {
  4515. if (SUCCEEDED(IDXGISwapChain3_QueryInterface(
  4516. windowData->swapchain,
  4517. &D3D_IID_IDXGISwapChain3,
  4518. (void **)&swapchain3))) {
  4519. IDXGISwapChain3_CheckColorSpaceSupport(
  4520. swapchain3,
  4521. SwapchainCompositionToColorSpace[swapchainComposition],
  4522. &colorSpaceSupport);
  4523. IDXGISwapChain3_Release(swapchain3);
  4524. if (!(colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) {
  4525. return false;
  4526. }
  4527. } else {
  4528. SET_STRING_ERROR_AND_RETURN("DXGI 1.4 not supported, cannot use composition other than SDL_GPU_SWAPCHAINCOMPOSITION_SDR!", false)
  4529. }
  4530. }
  4531. return true;
  4532. }
  4533. static bool D3D11_SupportsPresentMode(
  4534. SDL_GPURenderer *driverData,
  4535. SDL_Window *window,
  4536. SDL_GPUPresentMode presentMode)
  4537. {
  4538. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4539. (void)window; // used by other backends
  4540. switch (presentMode) {
  4541. case SDL_GPU_PRESENTMODE_IMMEDIATE:
  4542. case SDL_GPU_PRESENTMODE_VSYNC:
  4543. return true;
  4544. case SDL_GPU_PRESENTMODE_MAILBOX:
  4545. return renderer->supportsFlipDiscard;
  4546. }
  4547. SDL_assert(!"Unrecognized present mode");
  4548. return false;
  4549. }
  4550. static bool D3D11_ClaimWindow(
  4551. SDL_GPURenderer *driverData,
  4552. SDL_Window *window)
  4553. {
  4554. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4555. D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
  4556. if (windowData == NULL) {
  4557. windowData = (D3D11WindowData *)SDL_calloc(1, sizeof(D3D11WindowData));
  4558. windowData->window = window;
  4559. if (D3D11_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
  4560. SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
  4561. SDL_LockMutex(renderer->windowLock);
  4562. if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
  4563. renderer->claimedWindowCapacity *= 2;
  4564. renderer->claimedWindows = SDL_realloc(
  4565. renderer->claimedWindows,
  4566. renderer->claimedWindowCapacity * sizeof(D3D11WindowData *));
  4567. }
  4568. renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
  4569. renderer->claimedWindowCount += 1;
  4570. SDL_UnlockMutex(renderer->windowLock);
  4571. SDL_AddEventWatch(D3D11_INTERNAL_OnWindowResize, window);
  4572. return true;
  4573. } else {
  4574. SDL_free(windowData);
  4575. SET_STRING_ERROR_AND_RETURN("Could not create swapchain, failed to claim window!", false)
  4576. }
  4577. } else {
  4578. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Window already claimed!");
  4579. return false;
  4580. }
  4581. }
  4582. static void D3D11_INTERNAL_DestroySwapchain(
  4583. D3D11Renderer *renderer,
  4584. D3D11WindowData *windowData)
  4585. {
  4586. Uint32 i;
  4587. D3D11_Wait((SDL_GPURenderer *)renderer);
  4588. ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetViews[0]);
  4589. SDL_free(windowData->texture.subresources[0].colorTargetViews);
  4590. SDL_free(windowData->texture.subresources);
  4591. SDL_free(windowData->textureContainer.textures);
  4592. IDXGISwapChain_Release(windowData->swapchain);
  4593. // DXGI will crash if we don't flush deferred swapchain destruction
  4594. SDL_LockMutex(renderer->contextLock);
  4595. ID3D11DeviceContext_ClearState(renderer->immediateContext);
  4596. ID3D11DeviceContext_Flush(renderer->immediateContext);
  4597. SDL_UnlockMutex(renderer->contextLock);
  4598. windowData->swapchain = NULL;
  4599. for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
  4600. if (windowData->inFlightFences[i] != NULL) {
  4601. D3D11_ReleaseFence(
  4602. (SDL_GPURenderer *)renderer,
  4603. windowData->inFlightFences[i]);
  4604. }
  4605. }
  4606. }
  4607. static void D3D11_ReleaseWindow(
  4608. SDL_GPURenderer *driverData,
  4609. SDL_Window *window)
  4610. {
  4611. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4612. D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
  4613. if (windowData == NULL) {
  4614. return;
  4615. }
  4616. D3D11_INTERNAL_DestroySwapchain(
  4617. renderer,
  4618. windowData);
  4619. SDL_LockMutex(renderer->windowLock);
  4620. for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
  4621. if (renderer->claimedWindows[i]->window == window) {
  4622. renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
  4623. renderer->claimedWindowCount -= 1;
  4624. break;
  4625. }
  4626. }
  4627. SDL_UnlockMutex(renderer->windowLock);
  4628. SDL_free(windowData);
  4629. SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
  4630. SDL_RemoveEventWatch(D3D11_INTERNAL_OnWindowResize, window);
  4631. }
  4632. static bool D3D11_AcquireSwapchainTexture(
  4633. SDL_GPUCommandBuffer *commandBuffer,
  4634. SDL_Window *window,
  4635. SDL_GPUTexture **swapchainTexture,
  4636. Uint32 *swapchainTextureWidth,
  4637. Uint32 *swapchainTextureHeight)
  4638. {
  4639. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  4640. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  4641. D3D11WindowData *windowData;
  4642. HRESULT res;
  4643. *swapchainTexture = NULL;
  4644. if (swapchainTextureWidth) {
  4645. *swapchainTextureWidth = 0;
  4646. }
  4647. if (swapchainTextureHeight) {
  4648. *swapchainTextureHeight = 0;
  4649. }
  4650. windowData = D3D11_INTERNAL_FetchWindowData(window);
  4651. if (windowData == NULL) {
  4652. SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false)
  4653. }
  4654. if (windowData->needsSwapchainRecreate) {
  4655. if (!D3D11_INTERNAL_ResizeSwapchain(renderer, windowData)) {
  4656. return false;
  4657. }
  4658. }
  4659. if (swapchainTextureWidth) {
  4660. *swapchainTextureWidth = windowData->width;
  4661. }
  4662. if (swapchainTextureHeight) {
  4663. *swapchainTextureHeight = windowData->height;
  4664. }
  4665. if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
  4666. if (windowData->presentMode == SDL_GPU_PRESENTMODE_VSYNC) {
  4667. // In VSYNC mode, block until the least recent presented frame is done
  4668. if (!D3D11_WaitForFences(
  4669. (SDL_GPURenderer *)renderer,
  4670. true,
  4671. &windowData->inFlightFences[windowData->frameCounter],
  4672. 1)) {
  4673. return false;
  4674. }
  4675. } else {
  4676. if (!D3D11_QueryFence(
  4677. (SDL_GPURenderer *)d3d11CommandBuffer->renderer,
  4678. windowData->inFlightFences[windowData->frameCounter])) {
  4679. /*
  4680. * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled,
  4681. * return true to indicate that there is no error but rendering should be skipped
  4682. */
  4683. return true;
  4684. }
  4685. }
  4686. D3D11_ReleaseFence(
  4687. (SDL_GPURenderer *)d3d11CommandBuffer->renderer,
  4688. windowData->inFlightFences[windowData->frameCounter]);
  4689. windowData->inFlightFences[windowData->frameCounter] = NULL;
  4690. }
  4691. // Set the handle on the windowData texture data.
  4692. res = IDXGISwapChain_GetBuffer(
  4693. windowData->swapchain,
  4694. 0,
  4695. &D3D_IID_ID3D11Texture2D,
  4696. (void **)&windowData->texture.handle);
  4697. CHECK_D3D11_ERROR_AND_RETURN("Could not acquire swapchain!", false);
  4698. // Set up presentation
  4699. if (d3d11CommandBuffer->windowDataCount == d3d11CommandBuffer->windowDataCapacity) {
  4700. d3d11CommandBuffer->windowDataCapacity += 1;
  4701. d3d11CommandBuffer->windowDatas = SDL_realloc(
  4702. d3d11CommandBuffer->windowDatas,
  4703. d3d11CommandBuffer->windowDataCapacity * sizeof(D3D11WindowData *));
  4704. }
  4705. d3d11CommandBuffer->windowDatas[d3d11CommandBuffer->windowDataCount] = windowData;
  4706. d3d11CommandBuffer->windowDataCount += 1;
  4707. // Return the swapchain texture
  4708. *swapchainTexture = (SDL_GPUTexture*) &windowData->textureContainer;
  4709. return true;
  4710. }
  4711. static SDL_GPUTextureFormat D3D11_GetSwapchainTextureFormat(
  4712. SDL_GPURenderer *driverData,
  4713. SDL_Window *window)
  4714. {
  4715. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4716. D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
  4717. if (windowData == NULL) {
  4718. SET_STRING_ERROR_AND_RETURN("Cannot get swapchain format, window has not been claimed!", SDL_GPU_TEXTUREFORMAT_INVALID)
  4719. }
  4720. return windowData->textureContainer.header.info.format;
  4721. }
  4722. static bool D3D11_SetSwapchainParameters(
  4723. SDL_GPURenderer *driverData,
  4724. SDL_Window *window,
  4725. SDL_GPUSwapchainComposition swapchainComposition,
  4726. SDL_GPUPresentMode presentMode)
  4727. {
  4728. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4729. D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
  4730. if (windowData == NULL) {
  4731. SET_STRING_ERROR_AND_RETURN("Cannot set swapchain parameters on unclaimed window!", false)
  4732. }
  4733. if (!D3D11_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
  4734. SET_STRING_ERROR_AND_RETURN("Swapchain composition not supported!", false)
  4735. }
  4736. if (!D3D11_SupportsPresentMode(driverData, window, presentMode)) {
  4737. SET_STRING_ERROR_AND_RETURN("Present mode not supported!", false)
  4738. }
  4739. if (
  4740. swapchainComposition != windowData->swapchainComposition ||
  4741. presentMode != windowData->presentMode) {
  4742. D3D11_Wait(driverData);
  4743. // Recreate the swapchain
  4744. D3D11_INTERNAL_DestroySwapchain(
  4745. renderer,
  4746. windowData);
  4747. return D3D11_INTERNAL_CreateSwapchain(
  4748. renderer,
  4749. windowData,
  4750. swapchainComposition,
  4751. presentMode);
  4752. }
  4753. return true;
  4754. }
  4755. // Submission
  4756. static bool D3D11_Submit(
  4757. SDL_GPUCommandBuffer *commandBuffer)
  4758. {
  4759. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  4760. D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
  4761. ID3D11CommandList *commandList;
  4762. HRESULT res;
  4763. // Unmap uniform buffers
  4764. for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
  4765. if (d3d11CommandBuffer->vertexUniformBuffers[i] != NULL) {
  4766. ID3D11DeviceContext_Unmap(
  4767. d3d11CommandBuffer->context,
  4768. (ID3D11Resource *)d3d11CommandBuffer->vertexUniformBuffers[i]->buffer,
  4769. 0);
  4770. }
  4771. if (d3d11CommandBuffer->fragmentUniformBuffers[i] != NULL) {
  4772. ID3D11DeviceContext_Unmap(
  4773. d3d11CommandBuffer->context,
  4774. (ID3D11Resource *)d3d11CommandBuffer->fragmentUniformBuffers[i]->buffer,
  4775. 0);
  4776. }
  4777. if (d3d11CommandBuffer->computeUniformBuffers[i] != NULL) {
  4778. ID3D11DeviceContext_Unmap(
  4779. d3d11CommandBuffer->context,
  4780. (ID3D11Resource *)d3d11CommandBuffer->computeUniformBuffers[i]->buffer,
  4781. 0);
  4782. }
  4783. }
  4784. SDL_LockMutex(renderer->contextLock);
  4785. // Notify the command buffer completion query that we have completed recording
  4786. ID3D11DeviceContext_End(
  4787. renderer->immediateContext,
  4788. (ID3D11Asynchronous *)d3d11CommandBuffer->fence->handle);
  4789. // Serialize the commands into the command list
  4790. res = ID3D11DeviceContext_FinishCommandList(
  4791. d3d11CommandBuffer->context,
  4792. 0,
  4793. &commandList);
  4794. if (FAILED(res)) {
  4795. SDL_UnlockMutex(renderer->contextLock);
  4796. CHECK_D3D11_ERROR_AND_RETURN("Could not finish command list recording!", false)
  4797. }
  4798. // Submit the command list to the immediate context
  4799. ID3D11DeviceContext_ExecuteCommandList(
  4800. renderer->immediateContext,
  4801. commandList,
  4802. 0);
  4803. ID3D11CommandList_Release(commandList);
  4804. // Mark the command buffer as submitted
  4805. if (renderer->submittedCommandBufferCount >= renderer->submittedCommandBufferCapacity) {
  4806. renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
  4807. renderer->submittedCommandBuffers = SDL_realloc(
  4808. renderer->submittedCommandBuffers,
  4809. sizeof(D3D11CommandBuffer *) * renderer->submittedCommandBufferCapacity);
  4810. }
  4811. renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = d3d11CommandBuffer;
  4812. renderer->submittedCommandBufferCount += 1;
  4813. bool result = true;
  4814. // Present, if applicable
  4815. for (Uint32 i = 0; i < d3d11CommandBuffer->windowDataCount; i += 1) {
  4816. D3D11WindowData *windowData = d3d11CommandBuffer->windowDatas[i];
  4817. Uint32 syncInterval = 1;
  4818. if (windowData->presentMode == SDL_GPU_PRESENTMODE_IMMEDIATE ||
  4819. (renderer->supportsFlipDiscard && windowData->presentMode == SDL_GPU_PRESENTMODE_MAILBOX)) {
  4820. syncInterval = 0;
  4821. }
  4822. Uint32 presentFlags = 0;
  4823. if (renderer->supportsTearing &&
  4824. windowData->presentMode == SDL_GPU_PRESENTMODE_IMMEDIATE) {
  4825. presentFlags = DXGI_PRESENT_ALLOW_TEARING;
  4826. }
  4827. res = IDXGISwapChain_Present(
  4828. windowData->swapchain,
  4829. syncInterval,
  4830. presentFlags);
  4831. if (FAILED(res)) {
  4832. result = false;
  4833. }
  4834. ID3D11Texture2D_Release(windowData->texture.handle);
  4835. windowData->inFlightFences[windowData->frameCounter] = (SDL_GPUFence*)d3d11CommandBuffer->fence;
  4836. (void)SDL_AtomicIncRef(&d3d11CommandBuffer->fence->referenceCount);
  4837. windowData->frameCounter = (windowData->frameCounter + 1) % MAX_FRAMES_IN_FLIGHT;
  4838. }
  4839. // Check if we can perform any cleanups
  4840. for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
  4841. BOOL queryData;
  4842. res = ID3D11DeviceContext_GetData(
  4843. renderer->immediateContext,
  4844. (ID3D11Asynchronous *)renderer->submittedCommandBuffers[i]->fence->handle,
  4845. &queryData,
  4846. sizeof(queryData),
  4847. 0);
  4848. if (res == S_OK) {
  4849. result &= D3D11_INTERNAL_CleanCommandBuffer(
  4850. renderer,
  4851. renderer->submittedCommandBuffers[i]);
  4852. }
  4853. }
  4854. D3D11_INTERNAL_PerformPendingDestroys(renderer);
  4855. SDL_UnlockMutex(renderer->contextLock);
  4856. return result;
  4857. }
  4858. static SDL_GPUFence *D3D11_SubmitAndAcquireFence(
  4859. SDL_GPUCommandBuffer *commandBuffer)
  4860. {
  4861. D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
  4862. D3D11Fence *fence = d3d11CommandBuffer->fence;
  4863. d3d11CommandBuffer->autoReleaseFence = 0;
  4864. D3D11_Submit(commandBuffer);
  4865. return (SDL_GPUFence *)fence;
  4866. }
  4867. static bool D3D11_Wait(
  4868. SDL_GPURenderer *driverData)
  4869. {
  4870. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4871. D3D11CommandBuffer *commandBuffer;
  4872. bool result = true;
  4873. /*
  4874. * Wait for all submitted command buffers to complete.
  4875. * Sort of equivalent to vkDeviceWaitIdle.
  4876. */
  4877. for (Uint32 i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
  4878. D3D11_INTERNAL_WaitForFence(
  4879. renderer,
  4880. renderer->submittedCommandBuffers[i]->fence);
  4881. }
  4882. SDL_LockMutex(renderer->contextLock); // This effectively acts as a lock around submittedCommandBuffers
  4883. for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
  4884. commandBuffer = renderer->submittedCommandBuffers[i];
  4885. result &= D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
  4886. }
  4887. D3D11_INTERNAL_PerformPendingDestroys(renderer);
  4888. SDL_UnlockMutex(renderer->contextLock);
  4889. return result;
  4890. }
  4891. // Format Info
  4892. static bool D3D11_SupportsTextureFormat(
  4893. SDL_GPURenderer *driverData,
  4894. SDL_GPUTextureFormat format,
  4895. SDL_GPUTextureType type,
  4896. SDL_GPUTextureUsageFlags usage)
  4897. {
  4898. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  4899. DXGI_FORMAT dxgiFormat = SDLToD3D11_TextureFormat[format];
  4900. DXGI_FORMAT typelessFormat = D3D11_INTERNAL_GetTypelessFormat(dxgiFormat);
  4901. UINT formatSupport, sampleableFormatSupport;
  4902. D3D11_FEATURE_DATA_FORMAT_SUPPORT2 formatSupport2 = { dxgiFormat, 0 };
  4903. HRESULT res;
  4904. res = ID3D11Device_CheckFormatSupport(
  4905. renderer->device,
  4906. dxgiFormat,
  4907. &formatSupport);
  4908. if (FAILED(res)) {
  4909. // Format is apparently unknown
  4910. return false;
  4911. }
  4912. /* Depth textures are stored as typeless textures, but interpreted as color textures for sampling.
  4913. * In order to get supported usages for both interpretations, we have to do this.
  4914. */
  4915. if (typelessFormat != DXGI_FORMAT_UNKNOWN) {
  4916. res = ID3D11Device_CheckFormatSupport(
  4917. renderer->device,
  4918. D3D11_INTERNAL_GetSampleableFormat(typelessFormat),
  4919. &sampleableFormatSupport);
  4920. if (SUCCEEDED(res)) {
  4921. formatSupport |= sampleableFormatSupport;
  4922. }
  4923. }
  4924. // Checks for SIMULTANEOUS_READ_WRITE support
  4925. if (usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE) {
  4926. res = ID3D11Device_CheckFeatureSupport(
  4927. renderer->device,
  4928. D3D11_FEATURE_FORMAT_SUPPORT2,
  4929. &formatSupport2,
  4930. sizeof(formatSupport2));
  4931. if (FAILED(res)) {
  4932. // Format is apparently unknown
  4933. return false;
  4934. }
  4935. }
  4936. // Is the texture type supported?
  4937. if (type == SDL_GPU_TEXTURETYPE_2D && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) {
  4938. return false;
  4939. }
  4940. if (type == SDL_GPU_TEXTURETYPE_2D_ARRAY && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) {
  4941. return false;
  4942. }
  4943. if (type == SDL_GPU_TEXTURETYPE_3D && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D)) {
  4944. return false;
  4945. }
  4946. if (type == SDL_GPU_TEXTURETYPE_CUBE && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE)) {
  4947. return false;
  4948. }
  4949. if (type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE)) {
  4950. return false;
  4951. }
  4952. // Are the usage flags supported?
  4953. if ((usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) && !(formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) {
  4954. return false;
  4955. }
  4956. if ((usage & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)) && !(formatSupport & D3D11_FORMAT_SUPPORT_SHADER_LOAD)) {
  4957. return false;
  4958. }
  4959. if ((usage & (SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) && !(formatSupport & D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW))) {
  4960. // TYPED_UNORDERED_ACCESS_VIEW implies support for typed UAV stores
  4961. return false;
  4962. }
  4963. #define D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD 0x40 /* for old toolchains */
  4964. if ((usage & (SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE) && !(formatSupport2.OutFormatSupport2 & D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD))) {
  4965. return false;
  4966. }
  4967. if ((usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) && !(formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) {
  4968. return false;
  4969. }
  4970. if ((usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) && !(formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)) {
  4971. return false;
  4972. }
  4973. return true;
  4974. }
  4975. // Device Creation
  4976. static bool D3D11_PrepareDriver(SDL_VideoDevice *this)
  4977. {
  4978. SDL_SharedObject *d3d11_dll;
  4979. SDL_SharedObject *dxgi_dll;
  4980. PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc;
  4981. D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 };
  4982. PFN_CREATE_DXGI_FACTORY1 CreateDxgiFactoryFunc;
  4983. HRESULT res;
  4984. // Can we load D3D11?
  4985. d3d11_dll = SDL_LoadObject(D3D11_DLL);
  4986. if (d3d11_dll == NULL) {
  4987. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find " D3D11_DLL);
  4988. return false;
  4989. }
  4990. D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE)SDL_LoadFunction(
  4991. d3d11_dll,
  4992. D3D11_CREATE_DEVICE_FUNC);
  4993. if (D3D11CreateDeviceFunc == NULL) {
  4994. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find function " D3D11_CREATE_DEVICE_FUNC " in " D3D11_DLL);
  4995. SDL_UnloadObject(d3d11_dll);
  4996. return false;
  4997. }
  4998. // Can we create a device?
  4999. res = D3D11CreateDeviceFunc(
  5000. NULL,
  5001. D3D_DRIVER_TYPE_HARDWARE,
  5002. NULL,
  5003. D3D11_CREATE_DEVICE_BGRA_SUPPORT,
  5004. levels,
  5005. SDL_arraysize(levels),
  5006. D3D11_SDK_VERSION,
  5007. NULL,
  5008. NULL,
  5009. NULL);
  5010. SDL_UnloadObject(d3d11_dll);
  5011. if (FAILED(res)) {
  5012. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not create D3D11Device with feature level 11_1");
  5013. return false;
  5014. }
  5015. // Can we load DXGI?
  5016. dxgi_dll = SDL_LoadObject(DXGI_DLL);
  5017. if (dxgi_dll == NULL) {
  5018. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find " DXGI_DLL);
  5019. return false;
  5020. }
  5021. CreateDxgiFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction(
  5022. dxgi_dll,
  5023. CREATE_DXGI_FACTORY1_FUNC);
  5024. SDL_UnloadObject(dxgi_dll); // We're not going to call this function, so we can just unload now.
  5025. if (CreateDxgiFactoryFunc == NULL) {
  5026. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find function " CREATE_DXGI_FACTORY1_FUNC " in " DXGI_DLL);
  5027. return false;
  5028. }
  5029. return true;
  5030. }
  5031. static void D3D11_INTERNAL_TryInitializeDXGIDebug(D3D11Renderer *renderer)
  5032. {
  5033. PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc;
  5034. HRESULT res;
  5035. renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL);
  5036. if (renderer->dxgidebug_dll == NULL) {
  5037. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not find " DXGIDEBUG_DLL);
  5038. return;
  5039. }
  5040. DXGIGetDebugInterfaceFunc = (PFN_DXGI_GET_DEBUG_INTERFACE)SDL_LoadFunction(
  5041. renderer->dxgidebug_dll,
  5042. DXGI_GET_DEBUG_INTERFACE_FUNC);
  5043. if (DXGIGetDebugInterfaceFunc == NULL) {
  5044. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " DXGI_GET_DEBUG_INTERFACE_FUNC);
  5045. return;
  5046. }
  5047. res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, (void **)&renderer->dxgiDebug);
  5048. if (FAILED(res)) {
  5049. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIDebug interface");
  5050. }
  5051. #ifdef HAVE_IDXGIINFOQUEUE
  5052. res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, (void **)&renderer->dxgiInfoQueue);
  5053. if (FAILED(res)) {
  5054. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIInfoQueue interface");
  5055. }
  5056. #endif
  5057. }
  5058. static void D3D11_INTERNAL_InitBlitPipelines(
  5059. D3D11Renderer *renderer)
  5060. {
  5061. SDL_GPUShaderCreateInfo shaderCreateInfo;
  5062. SDL_GPUShader *fullscreenVertexShader;
  5063. SDL_GPUShader *blitFrom2DPixelShader;
  5064. SDL_GPUShader *blitFrom2DArrayPixelShader;
  5065. SDL_GPUShader *blitFrom3DPixelShader;
  5066. SDL_GPUShader *blitFromCubePixelShader;
  5067. SDL_GPUShader *blitFromCubeArrayPixelShader;
  5068. SDL_GPUGraphicsPipelineCreateInfo blitPipelineCreateInfo;
  5069. SDL_GPUGraphicsPipeline *blitPipeline;
  5070. SDL_GPUSamplerCreateInfo samplerCreateInfo;
  5071. SDL_GPUColorTargetDescription colorTargetDesc;
  5072. // Fullscreen vertex shader
  5073. SDL_zero(shaderCreateInfo);
  5074. shaderCreateInfo.code = (Uint8 *)D3D11_FullscreenVert;
  5075. shaderCreateInfo.code_size = sizeof(D3D11_FullscreenVert);
  5076. shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX;
  5077. shaderCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
  5078. shaderCreateInfo.entrypoint = "main";
  5079. fullscreenVertexShader = D3D11_CreateShader(
  5080. (SDL_GPURenderer *)renderer,
  5081. &shaderCreateInfo);
  5082. if (fullscreenVertexShader == NULL) {
  5083. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile vertex shader for blit!");
  5084. }
  5085. // BlitFrom2D pixel shader
  5086. shaderCreateInfo.code = (Uint8 *)D3D11_BlitFrom2D;
  5087. shaderCreateInfo.code_size = sizeof(D3D11_BlitFrom2D);
  5088. shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
  5089. shaderCreateInfo.num_samplers = 1;
  5090. shaderCreateInfo.num_uniform_buffers = 1;
  5091. blitFrom2DPixelShader = D3D11_CreateShader(
  5092. (SDL_GPURenderer *)renderer,
  5093. &shaderCreateInfo);
  5094. if (blitFrom2DPixelShader == NULL) {
  5095. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2D pixel shader!");
  5096. }
  5097. // BlitFrom2DArray pixel shader
  5098. shaderCreateInfo.code = (Uint8 *)D3D11_BlitFrom2DArray;
  5099. shaderCreateInfo.code_size = sizeof(D3D11_BlitFrom2DArray);
  5100. blitFrom2DArrayPixelShader = D3D11_CreateShader(
  5101. (SDL_GPURenderer *)renderer,
  5102. &shaderCreateInfo);
  5103. if (blitFrom2DArrayPixelShader == NULL) {
  5104. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2DArray pixel shader!");
  5105. }
  5106. // BlitFrom3D pixel shader
  5107. shaderCreateInfo.code = (Uint8 *)D3D11_BlitFrom3D;
  5108. shaderCreateInfo.code_size = sizeof(D3D11_BlitFrom3D);
  5109. blitFrom3DPixelShader = D3D11_CreateShader(
  5110. (SDL_GPURenderer *)renderer,
  5111. &shaderCreateInfo);
  5112. if (blitFrom3DPixelShader == NULL) {
  5113. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom3D pixel shader!");
  5114. }
  5115. // BlitFromCube pixel shader
  5116. shaderCreateInfo.code = (Uint8 *)D3D11_BlitFromCube;
  5117. shaderCreateInfo.code_size = sizeof(D3D11_BlitFromCube);
  5118. blitFromCubePixelShader = D3D11_CreateShader(
  5119. (SDL_GPURenderer *)renderer,
  5120. &shaderCreateInfo);
  5121. if (blitFromCubePixelShader == NULL) {
  5122. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCube pixel shader!");
  5123. }
  5124. // BlitFromCubeArray pixel shader
  5125. shaderCreateInfo.code = (Uint8 *)D3D11_BlitFromCubeArray;
  5126. shaderCreateInfo.code_size = sizeof(D3D11_BlitFromCubeArray);
  5127. blitFromCubeArrayPixelShader = D3D11_CreateShader(
  5128. (SDL_GPURenderer *)renderer,
  5129. &shaderCreateInfo);
  5130. if (blitFromCubeArrayPixelShader == NULL) {
  5131. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCubeArray pixel shader!");
  5132. }
  5133. // BlitFrom2D pipeline
  5134. SDL_zero(blitPipelineCreateInfo);
  5135. SDL_zero(colorTargetDesc);
  5136. colorTargetDesc.blend_state.color_write_mask = 0xF;
  5137. colorTargetDesc.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; // format doesn't matter in d3d11
  5138. blitPipelineCreateInfo.target_info.color_target_descriptions = &colorTargetDesc;
  5139. blitPipelineCreateInfo.target_info.num_color_targets = 1;
  5140. blitPipelineCreateInfo.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D16_UNORM; // arbitrary
  5141. blitPipelineCreateInfo.target_info.has_depth_stencil_target = false;
  5142. blitPipelineCreateInfo.vertex_shader = fullscreenVertexShader;
  5143. blitPipelineCreateInfo.fragment_shader = blitFrom2DPixelShader;
  5144. blitPipelineCreateInfo.multisample_state.sample_count = SDL_GPU_SAMPLECOUNT_1;
  5145. blitPipelineCreateInfo.multisample_state.enable_mask = false;
  5146. blitPipelineCreateInfo.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
  5147. blitPipeline = D3D11_CreateGraphicsPipeline(
  5148. (SDL_GPURenderer *)renderer,
  5149. &blitPipelineCreateInfo);
  5150. if (blitPipeline == NULL) {
  5151. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFrom2D pipeline!");
  5152. }
  5153. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D].pipeline = blitPipeline;
  5154. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D].type = SDL_GPU_TEXTURETYPE_2D;
  5155. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D].format = SDL_GPU_TEXTUREFORMAT_INVALID;
  5156. // BlitFrom2DArrayPipeline
  5157. blitPipelineCreateInfo.fragment_shader = blitFrom2DArrayPixelShader;
  5158. blitPipeline = D3D11_CreateGraphicsPipeline(
  5159. (SDL_GPURenderer *)renderer,
  5160. &blitPipelineCreateInfo);
  5161. if (blitPipeline == NULL) {
  5162. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFrom2DArray pipeline!");
  5163. }
  5164. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D_ARRAY].pipeline = blitPipeline;
  5165. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D_ARRAY].type = SDL_GPU_TEXTURETYPE_2D_ARRAY;
  5166. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D_ARRAY].format = SDL_GPU_TEXTUREFORMAT_INVALID;
  5167. // BlitFrom3DPipeline
  5168. blitPipelineCreateInfo.fragment_shader = blitFrom3DPixelShader;
  5169. blitPipeline = D3D11_CreateGraphicsPipeline(
  5170. (SDL_GPURenderer *)renderer,
  5171. &blitPipelineCreateInfo);
  5172. if (blitPipeline == NULL) {
  5173. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFrom3D pipeline!");
  5174. }
  5175. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_3D].pipeline = blitPipeline;
  5176. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_3D].type = SDL_GPU_TEXTURETYPE_3D;
  5177. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_3D].format = SDL_GPU_TEXTUREFORMAT_INVALID;
  5178. // BlitFromCubePipeline
  5179. blitPipelineCreateInfo.fragment_shader = blitFromCubePixelShader;
  5180. blitPipeline = D3D11_CreateGraphicsPipeline(
  5181. (SDL_GPURenderer *)renderer,
  5182. &blitPipelineCreateInfo);
  5183. if (blitPipeline == NULL) {
  5184. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFromCube pipeline!");
  5185. }
  5186. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].pipeline = blitPipeline;
  5187. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].type = SDL_GPU_TEXTURETYPE_CUBE;
  5188. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].format = SDL_GPU_TEXTUREFORMAT_INVALID;
  5189. // BlitFromCubeArrayPipeline
  5190. blitPipelineCreateInfo.fragment_shader = blitFromCubeArrayPixelShader;
  5191. blitPipeline = D3D11_CreateGraphicsPipeline(
  5192. (SDL_GPURenderer *)renderer,
  5193. &blitPipelineCreateInfo);
  5194. if (blitPipeline == NULL) {
  5195. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFromCubeArray pipeline!");
  5196. }
  5197. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE_ARRAY].pipeline = blitPipeline;
  5198. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE_ARRAY].type = SDL_GPU_TEXTURETYPE_CUBE_ARRAY;
  5199. renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE_ARRAY].format = SDL_GPU_TEXTUREFORMAT_INVALID;
  5200. // Create samplers
  5201. samplerCreateInfo.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
  5202. samplerCreateInfo.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
  5203. samplerCreateInfo.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
  5204. samplerCreateInfo.enable_anisotropy = 0;
  5205. samplerCreateInfo.enable_compare = 0;
  5206. samplerCreateInfo.mag_filter = SDL_GPU_FILTER_NEAREST;
  5207. samplerCreateInfo.min_filter = SDL_GPU_FILTER_NEAREST;
  5208. samplerCreateInfo.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
  5209. samplerCreateInfo.mip_lod_bias = 0.0f;
  5210. samplerCreateInfo.min_lod = 0;
  5211. samplerCreateInfo.max_lod = 1000;
  5212. renderer->blitNearestSampler = D3D11_CreateSampler(
  5213. (SDL_GPURenderer *)renderer,
  5214. &samplerCreateInfo);
  5215. if (renderer->blitNearestSampler == NULL) {
  5216. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit nearest sampler!");
  5217. }
  5218. samplerCreateInfo.mag_filter = SDL_GPU_FILTER_LINEAR;
  5219. samplerCreateInfo.min_filter = SDL_GPU_FILTER_LINEAR;
  5220. samplerCreateInfo.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
  5221. renderer->blitLinearSampler = D3D11_CreateSampler(
  5222. (SDL_GPURenderer *)renderer,
  5223. &samplerCreateInfo);
  5224. if (renderer->blitLinearSampler == NULL) {
  5225. SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit linear sampler!");
  5226. }
  5227. // Clean up
  5228. D3D11_ReleaseShader((SDL_GPURenderer *)renderer, fullscreenVertexShader);
  5229. D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFrom2DPixelShader);
  5230. D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFrom2DArrayPixelShader);
  5231. D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFrom3DPixelShader);
  5232. D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFromCubePixelShader);
  5233. D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFromCubeArrayPixelShader);
  5234. }
  5235. static void D3D11_INTERNAL_DestroyBlitPipelines(
  5236. SDL_GPURenderer *driverData)
  5237. {
  5238. D3D11Renderer *renderer = (D3D11Renderer *)driverData;
  5239. D3D11_ReleaseSampler(driverData, renderer->blitLinearSampler);
  5240. D3D11_ReleaseSampler(driverData, renderer->blitNearestSampler);
  5241. for (int i = 0; i < SDL_arraysize(renderer->blitPipelines); i += 1) {
  5242. D3D11_ReleaseGraphicsPipeline(driverData, renderer->blitPipelines[i].pipeline);
  5243. }
  5244. }
  5245. static SDL_GPUDevice *D3D11_CreateDevice(bool debugMode, bool preferLowPower, SDL_PropertiesID props)
  5246. {
  5247. D3D11Renderer *renderer;
  5248. PFN_CREATE_DXGI_FACTORY1 CreateDxgiFactoryFunc;
  5249. PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc;
  5250. D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 };
  5251. IDXGIFactory4 *factory4;
  5252. IDXGIFactory5 *factory5;
  5253. IDXGIFactory6 *factory6;
  5254. Uint32 flags;
  5255. DXGI_ADAPTER_DESC1 adapterDesc;
  5256. HRESULT res;
  5257. SDL_GPUDevice *result;
  5258. // Allocate and zero out the renderer
  5259. renderer = (D3D11Renderer *)SDL_calloc(1, sizeof(D3D11Renderer));
  5260. // Load the DXGI library
  5261. renderer->dxgi_dll = SDL_LoadObject(DXGI_DLL);
  5262. if (renderer->dxgi_dll == NULL) {
  5263. SET_STRING_ERROR_AND_RETURN("Could not find " DXGI_DLL, NULL)
  5264. }
  5265. // Load the CreateDXGIFactory1 function
  5266. CreateDxgiFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction(
  5267. renderer->dxgi_dll,
  5268. CREATE_DXGI_FACTORY1_FUNC);
  5269. if (CreateDxgiFactoryFunc == NULL) {
  5270. SET_STRING_ERROR_AND_RETURN("Could not load function: " CREATE_DXGI_FACTORY1_FUNC, NULL)
  5271. }
  5272. // Create the DXGI factory
  5273. res = CreateDxgiFactoryFunc(
  5274. &D3D_IID_IDXGIFactory1,
  5275. (void **)&renderer->factory);
  5276. CHECK_D3D11_ERROR_AND_RETURN("Could not create DXGIFactory", NULL);
  5277. // Check for flip-model discard support (supported on Windows 10+)
  5278. res = IDXGIFactory1_QueryInterface(
  5279. renderer->factory,
  5280. &D3D_IID_IDXGIFactory4,
  5281. (void **)&factory4);
  5282. if (SUCCEEDED(res)) {
  5283. renderer->supportsFlipDiscard = 1;
  5284. IDXGIFactory4_Release(factory4);
  5285. }
  5286. // Check for explicit tearing support
  5287. res = IDXGIFactory1_QueryInterface(
  5288. renderer->factory,
  5289. &D3D_IID_IDXGIFactory5,
  5290. (void **)&factory5);
  5291. if (SUCCEEDED(res)) {
  5292. res = IDXGIFactory5_CheckFeatureSupport(
  5293. factory5,
  5294. DXGI_FEATURE_PRESENT_ALLOW_TEARING,
  5295. &renderer->supportsTearing,
  5296. sizeof(renderer->supportsTearing));
  5297. if (FAILED(res)) {
  5298. renderer->supportsTearing = FALSE;
  5299. }
  5300. IDXGIFactory5_Release(factory5);
  5301. }
  5302. // Select the appropriate device for rendering
  5303. res = IDXGIAdapter1_QueryInterface(
  5304. renderer->factory,
  5305. &D3D_IID_IDXGIFactory6,
  5306. (void **)&factory6);
  5307. if (SUCCEEDED(res)) {
  5308. IDXGIFactory6_EnumAdapterByGpuPreference(
  5309. factory6,
  5310. 0,
  5311. preferLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
  5312. &D3D_IID_IDXGIAdapter1,
  5313. (void **)&renderer->adapter);
  5314. IDXGIFactory6_Release(factory6);
  5315. } else {
  5316. IDXGIFactory1_EnumAdapters1(
  5317. renderer->factory,
  5318. 0,
  5319. &renderer->adapter);
  5320. }
  5321. // Get information about the selected adapter. Used for logging info.
  5322. IDXGIAdapter1_GetDesc1(renderer->adapter, &adapterDesc);
  5323. // Initialize the DXGI debug layer, if applicable
  5324. if (debugMode) {
  5325. D3D11_INTERNAL_TryInitializeDXGIDebug(renderer);
  5326. }
  5327. // Load the D3D library
  5328. renderer->d3d11_dll = SDL_LoadObject(D3D11_DLL);
  5329. if (renderer->d3d11_dll == NULL) {
  5330. SET_STRING_ERROR_AND_RETURN("Could not find " D3D11_DLL, NULL)
  5331. }
  5332. // Load the CreateDevice function
  5333. D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE)SDL_LoadFunction(
  5334. renderer->d3d11_dll,
  5335. D3D11_CREATE_DEVICE_FUNC);
  5336. if (D3D11CreateDeviceFunc == NULL) {
  5337. SET_STRING_ERROR_AND_RETURN("Could not load function: " D3D11_CREATE_DEVICE_FUNC, NULL)
  5338. }
  5339. // Set up device flags
  5340. flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
  5341. if (debugMode) {
  5342. flags |= D3D11_CREATE_DEVICE_DEBUG;
  5343. }
  5344. // Create the device
  5345. ID3D11Device *d3d11Device;
  5346. tryCreateDevice:
  5347. res = D3D11CreateDeviceFunc(
  5348. (IDXGIAdapter *)renderer->adapter,
  5349. D3D_DRIVER_TYPE_UNKNOWN, // Must be UNKNOWN if adapter is non-null according to spec
  5350. NULL,
  5351. flags,
  5352. levels,
  5353. SDL_arraysize(levels),
  5354. D3D11_SDK_VERSION,
  5355. &d3d11Device,
  5356. NULL,
  5357. &renderer->immediateContext);
  5358. if (FAILED(res) && debugMode) {
  5359. // If device creation failed, and we're in debug mode, remove the debug flag and try again.
  5360. SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Creating device in debug mode failed with error " HRESULT_FMT ". Trying non-debug.", res);
  5361. flags &= ~D3D11_CREATE_DEVICE_DEBUG;
  5362. debugMode = 0;
  5363. goto tryCreateDevice;
  5364. }
  5365. CHECK_D3D11_ERROR_AND_RETURN("Could not create D3D11 device", NULL);
  5366. // The actual device we want is the ID3D11Device1 interface...
  5367. res = ID3D11Device_QueryInterface(
  5368. d3d11Device,
  5369. &D3D_IID_ID3D11Device1,
  5370. (void **)&renderer->device);
  5371. CHECK_D3D11_ERROR_AND_RETURN("Could not get ID3D11Device1 interface", NULL);
  5372. // Release the old device interface, we don't need it anymore
  5373. ID3D11Device_Release(d3d11Device);
  5374. #ifdef HAVE_IDXGIINFOQUEUE
  5375. // Set up the info queue
  5376. if (renderer->dxgiInfoQueue) {
  5377. DXGI_INFO_QUEUE_MESSAGE_SEVERITY sevList[] = {
  5378. DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION,
  5379. DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR,
  5380. DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING,
  5381. // DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO, // This can be a bit much, so toggle as needed for debugging.
  5382. DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE
  5383. };
  5384. DXGI_INFO_QUEUE_FILTER filter = { 0 };
  5385. filter.AllowList.NumSeverities = SDL_arraysize(sevList);
  5386. filter.AllowList.pSeverityList = sevList;
  5387. IDXGIInfoQueue_PushStorageFilter(
  5388. renderer->dxgiInfoQueue,
  5389. D3D_IID_DXGI_DEBUG_ALL,
  5390. &filter);
  5391. }
  5392. #endif
  5393. // Print driver info
  5394. SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL GPU Driver: D3D11");
  5395. SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "D3D11 Adapter: %S", adapterDesc.Description);
  5396. // Create mutexes
  5397. renderer->contextLock = SDL_CreateMutex();
  5398. renderer->acquireCommandBufferLock = SDL_CreateMutex();
  5399. renderer->acquireUniformBufferLock = SDL_CreateMutex();
  5400. renderer->fenceLock = SDL_CreateMutex();
  5401. renderer->windowLock = SDL_CreateMutex();
  5402. // Initialize miscellaneous renderer members
  5403. renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG);
  5404. // Create command buffer pool
  5405. D3D11_INTERNAL_AllocateCommandBuffers(renderer, 2);
  5406. // Create fence pool
  5407. renderer->availableFenceCapacity = 2;
  5408. renderer->availableFences = SDL_malloc(
  5409. sizeof(D3D11Fence *) * renderer->availableFenceCapacity);
  5410. // Create uniform buffer pool
  5411. renderer->uniformBufferPoolCapacity = 32;
  5412. renderer->uniformBufferPoolCount = 32;
  5413. renderer->uniformBufferPool = SDL_malloc(
  5414. renderer->uniformBufferPoolCapacity * sizeof(D3D11UniformBuffer *));
  5415. for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
  5416. renderer->uniformBufferPool[i] = D3D11_INTERNAL_CreateUniformBuffer(
  5417. renderer,
  5418. UNIFORM_BUFFER_SIZE);
  5419. }
  5420. // Create deferred destroy arrays
  5421. renderer->transferBufferContainersToDestroyCapacity = 2;
  5422. renderer->transferBufferContainersToDestroyCount = 0;
  5423. renderer->transferBufferContainersToDestroy = SDL_malloc(
  5424. renderer->transferBufferContainersToDestroyCapacity * sizeof(D3D11TransferBufferContainer *));
  5425. renderer->bufferContainersToDestroyCapacity = 2;
  5426. renderer->bufferContainersToDestroyCount = 0;
  5427. renderer->bufferContainersToDestroy = SDL_malloc(
  5428. renderer->bufferContainersToDestroyCapacity * sizeof(D3D11BufferContainer *));
  5429. renderer->textureContainersToDestroyCapacity = 2;
  5430. renderer->textureContainersToDestroyCount = 0;
  5431. renderer->textureContainersToDestroy = SDL_malloc(
  5432. renderer->textureContainersToDestroyCapacity * sizeof(D3D11TextureContainer *));
  5433. // Create claimed window list
  5434. renderer->claimedWindowCapacity = 1;
  5435. renderer->claimedWindows = SDL_malloc(
  5436. sizeof(D3D11WindowData *) * renderer->claimedWindowCapacity);
  5437. // Initialize null states
  5438. SDL_zeroa(renderer->nullRTVs);
  5439. SDL_zeroa(renderer->nullSRVs);
  5440. SDL_zeroa(renderer->nullSamplers);
  5441. SDL_zeroa(renderer->nullUAVs);
  5442. // Initialize built-in pipelines
  5443. D3D11_INTERNAL_InitBlitPipelines(renderer);
  5444. // Create the SDL_GPU Device
  5445. result = (SDL_GPUDevice *)SDL_malloc(sizeof(SDL_GPUDevice));
  5446. ASSIGN_DRIVER(D3D11)
  5447. result->driverData = (SDL_GPURenderer *)renderer;
  5448. return result;
  5449. }
  5450. SDL_GPUBootstrap D3D11Driver = {
  5451. "direct3d11",
  5452. SDL_GPU_SHADERFORMAT_DXBC,
  5453. D3D11_PrepareDriver,
  5454. D3D11_CreateDevice
  5455. };
  5456. #endif // SDL_GPU_D3D11