sokol_gfx.h 479 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943
  1. #ifndef SOKOL_GFX_INCLUDED
  2. /*
  3. sokol_gfx.h -- simple 3D API wrapper
  4. Project URL: https://github.com/floooh/sokol
  5. Do this:
  6. #define SOKOL_IMPL
  7. before you include this file in *one* C or C++ file to create the
  8. implementation.
  9. In the same place define one of the following to select the rendering
  10. backend:
  11. #define SOKOL_GLCORE33
  12. #define SOKOL_GLES2
  13. #define SOKOL_GLES3
  14. #define SOKOL_D3D11
  15. #define SOKOL_METAL
  16. #define SOKOL_DUMMY_BACKEND
  17. I.e. for the GL 3.3 Core Profile it should look like this:
  18. #include ...
  19. #include ...
  20. #define SOKOL_IMPL
  21. #define SOKOL_GLCORE33
  22. #include "sokol_gfx.h"
  23. The dummy backend replaces the platform-specific backend code with empty
  24. stub functions. This is useful for writing tests that need to run on the
  25. command line.
  26. Optionally provide the following defines with your own implementations:
  27. SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
  28. SOKOL_MALLOC(s) - your own malloc function (default: malloc(s))
  29. SOKOL_FREE(p) - your own free function (default: free(p))
  30. SOKOL_LOG(msg) - your own logging function (default: puts(msg))
  31. SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
  32. SOKOL_API_DECL - public function declaration prefix (default: extern)
  33. SOKOL_API_IMPL - public function implementation prefix (default: -)
  34. SOKOL_TRACE_HOOKS - enable trace hook callbacks (search below for TRACE HOOKS)
  35. If sokol_gfx.h is compiled as a DLL, define the following before
  36. including the declaration or implementation:
  37. SOKOL_DLL
  38. On Windows, SOKOL_DLL will define SOKOL_API_DECL as __declspec(dllexport)
  39. or __declspec(dllimport) as needed.
  40. If you want to compile without deprecated structs and functions,
  41. define:
  42. SOKOL_NO_DEPRECATED
  43. API usage validation macros:
  44. SOKOL_VALIDATE_BEGIN() - begin a validation block (default:_sg_validate_begin())
  45. SOKOL_VALIDATE(cond, err) - like assert but for API validation (default: _sg_validate(cond, err))
  46. SOKOL_VALIDATE_END() - end a validation block, return true if all checks in block passed (default: bool _sg_validate())
  47. If you don't want validation errors to be fatal, define SOKOL_VALIDATE_NON_FATAL,
  48. be aware though that this may spam SOKOL_LOG messages.
  49. Optionally define the following to force debug checks and validations
  50. even in release mode:
  51. SOKOL_DEBUG - by default this is defined if _DEBUG is defined
  52. sokol_gfx DOES NOT:
  53. ===================
  54. - create a window or the 3D-API context/device, you must do this
  55. before sokol_gfx is initialized, and pass any required information
  56. (like 3D device pointers) to the sokol_gfx initialization call
  57. - present the rendered frame, how this is done exactly usually depends
  58. on how the window and 3D-API context/device was created
  59. - provide a unified shader language, instead 3D-API-specific shader
  60. source-code or shader-bytecode must be provided
  61. For complete code examples using the various backend 3D-APIs, see:
  62. https://github.com/floooh/sokol-samples
  63. For an optional shader-cross-compile solution, see:
  64. https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md
  65. STEP BY STEP
  66. ============
  67. --- to initialize sokol_gfx, after creating a window and a 3D-API
  68. context/device, call:
  69. sg_setup(const sg_desc*)
  70. --- create resource objects (at least buffers, shaders and pipelines,
  71. and optionally images and passes):
  72. sg_buffer sg_make_buffer(const sg_buffer_desc*)
  73. sg_image sg_make_image(const sg_image_desc*)
  74. sg_shader sg_make_shader(const sg_shader_desc*)
  75. sg_pipeline sg_make_pipeline(const sg_pipeline_desc*)
  76. sg_pass sg_make_pass(const sg_pass_desc*)
  77. --- start rendering to the default frame buffer with:
  78. sg_begin_default_pass(const sg_pass_action* actions, int width, int height)
  79. --- or start rendering to an offscreen framebuffer with:
  80. sg_begin_pass(sg_pass pass, const sg_pass_action* actions)
  81. --- set the pipeline state for the next draw call with:
  82. sg_apply_pipeline(sg_pipeline pip)
  83. --- fill an sg_bindings struct with the resource bindings for the next
  84. draw call (1..N vertex buffers, 0 or 1 index buffer, 0..N image objects
  85. to use as textures each on the vertex-shader- and fragment-shader-stage
  86. and then call
  87. sg_apply_bindings(const sg_bindings* bindings)
  88. to update the resource bindings
  89. --- optionally update shader uniform data with:
  90. sg_apply_uniforms(sg_shader_stage stage, int ub_index, const void* data, int num_bytes)
  91. --- kick off a draw call with:
  92. sg_draw(int base_element, int num_elements, int num_instances)
  93. --- finish the current rendering pass with:
  94. sg_end_pass()
  95. --- when done with the current frame, call
  96. sg_commit()
  97. --- at the end of your program, shutdown sokol_gfx with:
  98. sg_shutdown()
  99. --- if you need to destroy resources before sg_shutdown(), call:
  100. sg_destroy_buffer(sg_buffer buf)
  101. sg_destroy_image(sg_image img)
  102. sg_destroy_shader(sg_shader shd)
  103. sg_destroy_pipeline(sg_pipeline pip)
  104. sg_destroy_pass(sg_pass pass)
  105. --- to set a new viewport rectangle, call
  106. sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left)
  107. --- to set a new scissor rect, call:
  108. sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left)
  109. both sg_apply_viewport() and sg_apply_scissor_rect() must be called
  110. inside a rendering pass
  111. beginning a pass will reset the viewport to the size of the framebuffer used
  112. in the new pass,
  113. --- to update (overwrite) the content of buffer and image resources, call:
  114. sg_update_buffer(sg_buffer buf, const void* ptr, int num_bytes)
  115. sg_update_image(sg_image img, const sg_image_content* content)
  116. Buffers and images to be updated must have been created with
  117. SG_USAGE_DYNAMIC or SG_USAGE_STREAM
  118. Only one update per frame is allowed for buffer and image resources.
  119. The rationale is to have a simple countermeasure to avoid the CPU
  120. scribbling over data the GPU is currently using, or the CPU having to
  121. wait for the GPU
  122. Buffer and image updates can be partial, as long as a rendering
  123. operation only references the valid (updated) data in the
  124. buffer or image.
  125. --- to append a chunk of data to a buffer resource, call:
  126. int sg_append_buffer(sg_buffer buf, const void* ptr, int num_bytes)
  127. The difference to sg_update_buffer() is that sg_append_buffer()
  128. can be called multiple times per frame to append new data to the
  129. buffer piece by piece, optionally interleaved with draw calls referencing
  130. the previously written data.
  131. sg_append_buffer() returns a byte offset to the start of the
  132. written data, this offset can be assigned to
  133. sg_bindings.vertex_buffer_offsets[n] or
  134. sg_bindings.index_buffer_offset
  135. Code example:
  136. for (...) {
  137. const void* data = ...;
  138. const int num_bytes = ...;
  139. int offset = sg_append_buffer(buf, data, num_bytes);
  140. bindings.vertex_buffer_offsets[0] = offset;
  141. sg_apply_pipeline(pip);
  142. sg_apply_bindings(&bindings);
  143. sg_apply_uniforms(...);
  144. sg_draw(...);
  145. }
  146. A buffer to be used with sg_append_buffer() must have been created
  147. with SG_USAGE_DYNAMIC or SG_USAGE_STREAM.
  148. If the application appends more data to the buffer then fits into
  149. the buffer, the buffer will go into the "overflow" state for the
  150. rest of the frame.
  151. Any draw calls attempting to render an overflown buffer will be
  152. silently dropped (in debug mode this will also result in a
  153. validation error).
  154. You can also check manually if a buffer is in overflow-state by calling
  155. bool sg_query_buffer_overflow(sg_buffer buf)
  156. --- to check at runtime for optional features, limits and pixelformat support,
  157. call:
  158. sg_features sg_query_features()
  159. sg_limits sg_query_limits()
  160. sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt)
  161. --- if you need to call into the underlying 3D-API directly, you must call:
  162. sg_reset_state_cache()
  163. ...before calling sokol_gfx functions again
  164. --- you can inspect the original sg_desc structure handed to sg_setup()
  165. by calling sg_query_desc(). This will return an sg_desc struct with
  166. the default values patched in instead of any zero-initialized values
  167. --- you can inspect various internal resource attributes via:
  168. sg_buffer_info sg_query_buffer_info(sg_buffer buf)
  169. sg_image_info sg_query_image_info(sg_image img)
  170. sg_shader_info sg_query_shader_info(sg_shader shd)
  171. sg_pipeline_info sg_query_pipeline_info(sg_pipeline pip)
  172. sg_pass_info sg_query_pass_info(sg_pass pass)
  173. ...please note that the returned info-structs are tied quite closely
  174. to sokol_gfx.h internals, and may change more often than other
  175. public API functions and structs.
  176. --- you can ask at runtime what backend sokol_gfx.h has been compiled
  177. for, or whether the GLES3 backend had to fall back to GLES2 with:
  178. sg_backend sg_query_backend(void)
  179. --- you can query the default resource creation parameters through the functions
  180. sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc* desc)
  181. sg_image_desc sg_query_image_defaults(const sg_image_desc* desc)
  182. sg_shader_desc sg_query_shader_defaults(const sg_shader_desc* desc)
  183. sg_pipeline_desc sg_query_pipeline_defaults(const sg_pipeline_desc* desc)
  184. sg_pass_desc sg_query_pass_defaults(const sg_pass_desc* desc)
  185. These functions take a pointer to a desc structure which may contain
  186. zero-initialized items for default values. These zero-init values
  187. will be replaced with their concrete values in the returned desc
  188. struct.
  189. BACKEND-SPECIFIC TOPICS:
  190. ========================
  191. --- the GL backends need to know about the internal structure of uniform
  192. blocks, and the texture sampler-name and -type:
  193. typedef struct {
  194. float mvp[16]; // model-view-projection matrix
  195. float offset0[2]; // some 2D vectors
  196. float offset1[2];
  197. float offset2[2];
  198. } params_t;
  199. // uniform block structure and texture image definition in sg_shader_desc:
  200. sg_shader_desc desc = {
  201. // uniform block description (size and internal structure)
  202. .vs.uniform_blocks[0] = {
  203. .size = sizeof(params_t),
  204. .uniforms = {
  205. [0] = { .name="mvp", .type=SG_UNIFORMTYPE_MAT4 },
  206. [1] = { .name="offset0", .type=SG_UNIFORMTYPE_VEC2 },
  207. ...
  208. }
  209. },
  210. // one texture on the fragment-shader-stage, GLES2/WebGL needs name and image type
  211. .fs.images[0] = { .name="tex", .type=SG_IMAGETYPE_ARRAY }
  212. ...
  213. };
  214. --- the Metal and D3D11 backends only need to know the size of uniform blocks,
  215. not their internal member structure, and they only need to know
  216. the type of a texture sampler, not its name:
  217. sg_shader_desc desc = {
  218. .vs.uniform_blocks[0].size = sizeof(params_t),
  219. .fs.images[0].type = SG_IMAGETYPE_ARRAY,
  220. ...
  221. };
  222. --- when creating a shader object, GLES2/WebGL need to know the vertex
  223. attribute names as used in the vertex shader:
  224. sg_shader_desc desc = {
  225. .attrs = {
  226. [0] = { .name="position" },
  227. [1] = { .name="color1" }
  228. }
  229. };
  230. The vertex attribute names provided when creating a shader will be
  231. used later in sg_create_pipeline() for matching the vertex layout
  232. to vertex shader inputs.
  233. --- on D3D11 you need to provide a semantic name and semantic index in the
  234. shader description struct instead (see the D3D11 documentation on
  235. D3D11_INPUT_ELEMENT_DESC for details):
  236. sg_shader_desc desc = {
  237. .attrs = {
  238. [0] = { .sem_name="POSITION", .sem_index=0 }
  239. [1] = { .sem_name="COLOR", .sem_index=1 }
  240. }
  241. };
  242. The provided semantic information will be used later in sg_create_pipeline()
  243. to match the vertex layout to vertex shader inputs.
  244. --- on Metal, GL 3.3 or GLES3/WebGL2, you don't need to provide an attribute
  245. name or semantic name, since vertex attributes can be bound by their slot index
  246. (this is mandatory in Metal, and optional in GL):
  247. sg_pipeline_desc desc = {
  248. .layout = {
  249. .attrs = {
  250. [0] = { .format=SG_VERTEXFORMAT_FLOAT3 },
  251. [1] = { .format=SG_VERTEXFORMAT_FLOAT4 }
  252. }
  253. }
  254. };
  255. WORKING WITH CONTEXTS
  256. =====================
  257. sokol-gfx allows to switch between different rendering contexts and
  258. associate resource objects with contexts. This is useful to
  259. create GL applications that render into multiple windows.
  260. A rendering context keeps track of all resources created while
  261. the context is active. When the context is destroyed, all resources
  262. "belonging to the context" are destroyed as well.
  263. A default context will be created and activated implicitly in
  264. sg_setup(), and destroyed in sg_shutdown(). So for a typical application
  265. which *doesn't* use multiple contexts, nothing changes, and calling
  266. the context functions isn't necessary.
  267. Three functions have been added to work with contexts:
  268. --- sg_context sg_setup_context():
  269. This must be called once after a GL context has been created and
  270. made active.
  271. --- void sg_activate_context(sg_context ctx)
  272. This must be called after making a different GL context active.
  273. Apart from 3D-API-specific actions, the call to sg_activate_context()
  274. will internally call sg_reset_state_cache().
  275. --- void sg_discard_context(sg_context ctx)
  276. This must be called right before a GL context is destroyed and
  277. will destroy all resources associated with the context (that
  278. have been created while the context was active) The GL context must be
  279. active at the time sg_discard_context(sg_context ctx) is called.
  280. Also note that resources (buffers, images, shaders and pipelines) must
  281. only be used or destroyed while the same GL context is active that
  282. was also active while the resource was created (an exception is
  283. resource sharing on GL, such resources can be used while
  284. another context is active, but must still be destroyed under
  285. the same context that was active during creation).
  286. For more information, check out the multiwindow-glfw sample:
  287. https://github.com/floooh/sokol-samples/blob/master/glfw/multiwindow-glfw.c
  288. TRACE HOOKS:
  289. ============
  290. sokol_gfx.h optionally allows to install "trace hook" callbacks for
  291. each public API functions. When a public API function is called, and
  292. a trace hook callback has been installed for this function, the
  293. callback will be invoked with the parameters and result of the function.
  294. This is useful for things like debugging- and profiling-tools, or
  295. keeping track of resource creation and destruction.
  296. To use the trace hook feature:
  297. --- Define SOKOL_TRACE_HOOKS before including the implementation.
  298. --- Setup an sg_trace_hooks structure with your callback function
  299. pointers (keep all function pointers you're not interested
  300. in zero-initialized), optionally set the user_data member
  301. in the sg_trace_hooks struct.
  302. --- Install the trace hooks by calling sg_install_trace_hooks(),
  303. the return value of this function is another sg_trace_hooks
  304. struct which contains the previously set of trace hooks.
  305. You should keep this struct around, and call those previous
  306. functions pointers from your own trace callbacks for proper
  307. chaining.
  308. As an example of how trace hooks are used, have a look at the
  309. imgui/sokol_gfx_imgui.h header which implements a realtime
  310. debugging UI for sokol_gfx.h on top of Dear ImGui.
  311. A NOTE ON PORTABLE PACKED VERTEX FORMATS:
  312. =========================================
  313. There are two things to consider when using packed
  314. vertex formats like UBYTE4, SHORT2, etc which need to work
  315. across all backends:
  316. - D3D11 can only convert *normalized* vertex formats to
  317. floating point during vertex fetch, normalized formats
  318. have a trailing 'N', and are "normalized" to a range
  319. -1.0..+1.0 (for the signed formats) or 0.0..1.0 (for the
  320. unsigned formats):
  321. - SG_VERTEXFORMAT_BYTE4N
  322. - SG_VERTEXFORMAT_UBYTE4N
  323. - SG_VERTEXFORMAT_SHORT2N
  324. - SG_VERTEXFORMAT_USHORT2N
  325. - SG_VERTEXFORMAT_SHORT4N
  326. - SG_VERTEXFORMAT_USHORT4N
  327. D3D11 will not convert *non-normalized* vertex formats to floating point
  328. vertex shader inputs, those can only be uses with the *ivecn* vertex shader
  329. input types when D3D11 is used as backend (GL and Metal can use both formats)
  330. - SG_VERTEXFORMAT_BYTE4,
  331. - SG_VERTEXFORMAT_UBYTE4
  332. - SG_VERTEXFORMAT_SHORT2
  333. - SG_VERTEXFORMAT_SHORT4
  334. - WebGL/GLES2 cannot use integer vertex shader inputs (int or ivecn)
  335. - SG_VERTEXFORMAT_UINT10_N2 is not supported on WebGL/GLES2
  336. So for a vertex input layout which works on all platforms, only use the following
  337. vertex formats, and if needed "expand" the normalized vertex shader
  338. inputs in the vertex shader by multiplying with 127.0, 255.0, 32767.0 or
  339. 65535.0:
  340. - SG_VERTEXFORMAT_FLOAT,
  341. - SG_VERTEXFORMAT_FLOAT2,
  342. - SG_VERTEXFORMAT_FLOAT3,
  343. - SG_VERTEXFORMAT_FLOAT4,
  344. - SG_VERTEXFORMAT_BYTE4N,
  345. - SG_VERTEXFORMAT_UBYTE4N,
  346. - SG_VERTEXFORMAT_SHORT2N,
  347. - SG_VERTEXFORMAT_USHORT2N
  348. - SG_VERTEXFORMAT_SHORT4N,
  349. - SG_VERTEXFORMAT_USHORT4N
  350. TODO:
  351. ====
  352. - talk about asynchronous resource creation
  353. zlib/libpng license
  354. Copyright (c) 2018 Andre Weissflog
  355. This software is provided 'as-is', without any express or implied warranty.
  356. In no event will the authors be held liable for any damages arising from the
  357. use of this software.
  358. Permission is granted to anyone to use this software for any purpose,
  359. including commercial applications, and to alter it and redistribute it
  360. freely, subject to the following restrictions:
  361. 1. The origin of this software must not be misrepresented; you must not
  362. claim that you wrote the original software. If you use this software in a
  363. product, an acknowledgment in the product documentation would be
  364. appreciated but is not required.
  365. 2. Altered source versions must be plainly marked as such, and must not
  366. be misrepresented as being the original software.
  367. 3. This notice may not be removed or altered from any source
  368. distribution.
  369. */
  370. #define SOKOL_GFX_INCLUDED (1)
  371. #include <stdint.h>
  372. #include <stdbool.h>
  373. #ifndef SOKOL_API_DECL
  374. #if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_IMPL)
  375. #define SOKOL_API_DECL __declspec(dllexport)
  376. #elif defined(_WIN32) && defined(SOKOL_DLL)
  377. #define SOKOL_API_DECL __declspec(dllimport)
  378. #else
  379. #define SOKOL_API_DECL extern
  380. #endif
  381. #endif
  382. #ifdef __cplusplus
  383. extern "C" {
  384. #endif
  385. #ifdef _MSC_VER
  386. #pragma warning(push)
  387. #pragma warning(disable:4201) /* nonstandard extension used: nameless struct/union */
  388. #endif
  389. /*
  390. Resource id typedefs:
  391. sg_buffer: vertex- and index-buffers
  392. sg_image: textures and render targets
  393. sg_shader: vertex- and fragment-shaders, uniform blocks
  394. sg_pipeline: associated shader and vertex-layouts, and render states
  395. sg_pass: a bundle of render targets and actions on them
  396. sg_context: a 'context handle' for switching between 3D-API contexts
  397. Instead of pointers, resource creation functions return a 32-bit
  398. number which uniquely identifies the resource object.
  399. The 32-bit resource id is split into a 16-bit pool index in the lower bits,
  400. and a 16-bit 'unique counter' in the upper bits. The index allows fast
  401. pool lookups, and combined with the unique-mask it allows to detect
  402. 'dangling accesses' (trying to use an object which no longer exists, and
  403. its pool slot has been reused for a new object)
  404. The resource ids are wrapped into a struct so that the compiler
  405. can complain when the wrong resource type is used.
  406. */
  407. typedef struct sg_buffer { uint32_t id; } sg_buffer;
  408. typedef struct sg_image { uint32_t id; } sg_image;
  409. typedef struct sg_shader { uint32_t id; } sg_shader;
  410. typedef struct sg_pipeline { uint32_t id; } sg_pipeline;
  411. typedef struct sg_pass { uint32_t id; } sg_pass;
  412. typedef struct sg_context { uint32_t id; } sg_context;
  413. /*
  414. various compile-time constants
  415. FIXME: it may make sense to convert some of those into defines so
  416. that the user code can override them.
  417. */
  418. enum {
  419. SG_INVALID_ID = 0,
  420. SG_NUM_SHADER_STAGES = 2,
  421. SG_NUM_INFLIGHT_FRAMES = 2,
  422. SG_MAX_COLOR_ATTACHMENTS = 4,
  423. SG_MAX_SHADERSTAGE_BUFFERS = 8,
  424. SG_MAX_SHADERSTAGE_IMAGES = 12,
  425. SG_MAX_SHADERSTAGE_UBS = 4,
  426. SG_MAX_UB_MEMBERS = 16,
  427. SG_MAX_VERTEX_ATTRIBUTES = 16, /* NOTE: actual max vertex attrs can be less on GLES2, see sg_limits! */
  428. SG_MAX_MIPMAPS = 16,
  429. SG_MAX_TEXTUREARRAY_LAYERS = 128
  430. };
  431. /*
  432. sg_backend
  433. The active 3D-API backend, use the function sg_query_backend()
  434. to get the currently active backend.
  435. For returned value corresponds with the compile-time define to select
  436. a backend, with the only exception of SOKOL_GLES3: this may
  437. return SG_BACKEND_GLES2 if the backend has to fallback to GLES2 mode
  438. because GLES3 isn't supported.
  439. */
  440. typedef enum sg_backend {
  441. SG_BACKEND_GLCORE33,
  442. SG_BACKEND_GLES2,
  443. SG_BACKEND_GLES3,
  444. SG_BACKEND_D3D11,
  445. SG_BACKEND_METAL_IOS,
  446. SG_BACKEND_METAL_MACOS,
  447. SG_BACKEND_METAL_SIMULATOR,
  448. SG_BACKEND_DUMMY,
  449. } sg_backend;
  450. /*
  451. sg_pixel_format
  452. sokol_gfx.h basically uses the same pixel formats as WebGPU, since these
  453. are supported on most newer GPUs. GLES2 and WebGL has a much smaller
  454. subset of available pixel formats. Call sg_query_pixelformat() to check
  455. at runtime if a pixel format supports the desired features.
  456. A pixelformat name consist of three parts:
  457. - components (R, RG, RGB or RGBA)
  458. - bit width per component (8, 16 or 32)
  459. - component data type:
  460. - unsigned normalized (no postfix)
  461. - signed normalized (SN postfix)
  462. - unsigned integer (UI postfix)
  463. - signed integer (SI postfix)
  464. - float (F postfix)
  465. Not all pixel formats can be used for everything, call sg_query_pixelformat()
  466. to inspect the capabilities of a given pixelformat. The function returns
  467. an sg_pixelformat_info struct with the following bool members:
  468. - sample: the pixelformat can be sampled as texture at least with
  469. nearest filtering
  470. - filter: the pixelformat can be samples as texture with linear
  471. filtering
  472. - render: the pixelformat can be used for render targets
  473. - blend: blending is supported when using the pixelformat for
  474. render targets
  475. - msaa: multisample-antialiasing is supported when using the
  476. pixelformat for render targets
  477. - depth: the pixelformat can be used for depth-stencil attachments
  478. When targeting GLES2/WebGL, the only safe formats to use
  479. as texture are SG_PIXELFORMAT_R8 and SG_PIXELFORMAT_RGBA8. For rendering
  480. in GLES2/WebGL, only SG_PIXELFORMAT_RGBA8 is safe. All other formats
  481. must be checked via sg_query_pixelformats().
  482. The default pixel format for texture images is SG_PIXELFORMAT_RGBA8.
  483. The default pixel format for render target images is platform-dependent:
  484. - for Metal and D3D11 it is SG_PIXELFORMAT_BGRA8
  485. - for GL backends it is SG_PIXELFORMAT_RGBA8
  486. This is mainly because of the default framebuffer which is setup outside
  487. of sokol_gfx.h. On some backends, using BGRA for the default frame buffer
  488. allows more efficient frame flips. For your own offscreen-render-targets,
  489. use whatever renderable pixel format is convenient for you.
  490. */
  491. typedef enum sg_pixel_format {
  492. _SG_PIXELFORMAT_DEFAULT, /* value 0 reserved for default-init */
  493. SG_PIXELFORMAT_NONE,
  494. SG_PIXELFORMAT_R8,
  495. SG_PIXELFORMAT_R8SN,
  496. SG_PIXELFORMAT_R8UI,
  497. SG_PIXELFORMAT_R8SI,
  498. SG_PIXELFORMAT_R16,
  499. SG_PIXELFORMAT_R16SN,
  500. SG_PIXELFORMAT_R16UI,
  501. SG_PIXELFORMAT_R16SI,
  502. SG_PIXELFORMAT_R16F,
  503. SG_PIXELFORMAT_RG8,
  504. SG_PIXELFORMAT_RG8SN,
  505. SG_PIXELFORMAT_RG8UI,
  506. SG_PIXELFORMAT_RG8SI,
  507. SG_PIXELFORMAT_R32UI,
  508. SG_PIXELFORMAT_R32SI,
  509. SG_PIXELFORMAT_R32F,
  510. SG_PIXELFORMAT_RG16,
  511. SG_PIXELFORMAT_RG16SN,
  512. SG_PIXELFORMAT_RG16UI,
  513. SG_PIXELFORMAT_RG16SI,
  514. SG_PIXELFORMAT_RG16F,
  515. SG_PIXELFORMAT_RGBA8,
  516. SG_PIXELFORMAT_RGBA8SN,
  517. SG_PIXELFORMAT_RGBA8UI,
  518. SG_PIXELFORMAT_RGBA8SI,
  519. SG_PIXELFORMAT_BGRA8,
  520. SG_PIXELFORMAT_RGB10A2,
  521. SG_PIXELFORMAT_RG11B10F,
  522. SG_PIXELFORMAT_RG32UI,
  523. SG_PIXELFORMAT_RG32SI,
  524. SG_PIXELFORMAT_RG32F,
  525. SG_PIXELFORMAT_RGBA16,
  526. SG_PIXELFORMAT_RGBA16SN,
  527. SG_PIXELFORMAT_RGBA16UI,
  528. SG_PIXELFORMAT_RGBA16SI,
  529. SG_PIXELFORMAT_RGBA16F,
  530. SG_PIXELFORMAT_RGBA32UI,
  531. SG_PIXELFORMAT_RGBA32SI,
  532. SG_PIXELFORMAT_RGBA32F,
  533. SG_PIXELFORMAT_DEPTH,
  534. SG_PIXELFORMAT_DEPTH_STENCIL,
  535. SG_PIXELFORMAT_BC1_RGBA,
  536. SG_PIXELFORMAT_BC2_RGBA,
  537. SG_PIXELFORMAT_BC3_RGBA,
  538. SG_PIXELFORMAT_BC4_R,
  539. SG_PIXELFORMAT_BC4_RSN,
  540. SG_PIXELFORMAT_BC5_RG,
  541. SG_PIXELFORMAT_BC5_RGSN,
  542. SG_PIXELFORMAT_BC6H_RGBF,
  543. SG_PIXELFORMAT_BC6H_RGBUF,
  544. SG_PIXELFORMAT_BC7_RGBA,
  545. SG_PIXELFORMAT_PVRTC_RGB_2BPP,
  546. SG_PIXELFORMAT_PVRTC_RGB_4BPP,
  547. SG_PIXELFORMAT_PVRTC_RGBA_2BPP,
  548. SG_PIXELFORMAT_PVRTC_RGBA_4BPP,
  549. SG_PIXELFORMAT_ETC2_RGB8,
  550. SG_PIXELFORMAT_ETC2_RGB8A1,
  551. SG_PIXELFORMAT_ETC2_RGBA8,
  552. SG_PIXELFORMAT_ETC2_RG11,
  553. SG_PIXELFORMAT_ETC2_RG11SN,
  554. _SG_PIXELFORMAT_NUM,
  555. _SG_PIXELFORMAT_FORCE_U32 = 0x7FFFFFFF
  556. } sg_pixel_format;
  557. /*
  558. Runtime information about a pixel format, returned
  559. by sg_query_pixelformat().
  560. */
  561. typedef struct sg_pixelformat_info {
  562. bool sample; /* pixel format can be sampled in shaders */
  563. bool filter; /* pixel format can be sampled with filtering */
  564. bool render; /* pixel format can be used as render target */
  565. bool blend; /* alpha-blending is supported */
  566. bool msaa; /* pixel format can be used as MSAA render target */
  567. bool depth; /* pixel format is a depth format */
  568. } sg_pixelformat_info;
  569. /*
  570. Runtime information about available optional features,
  571. returned by sg_query_features()
  572. */
  573. typedef struct sg_features {
  574. bool instancing; /* hardware instancing supported */
  575. bool origin_top_left; /* framebuffer and texture origin is in top left corner */
  576. bool multiple_render_targets; /* offscreen render passes can have multiple render targets attached */
  577. bool msaa_render_targets; /* offscreen render passes support MSAA antialiasing */
  578. bool imagetype_3d; /* creation of SG_IMAGETYPE_3D images is supported */
  579. bool imagetype_array; /* creation of SG_IMAGETYPE_ARRAY images is supported */
  580. bool image_clamp_to_border; /* border color and clamp-to-border UV-wrap mode is supported */
  581. } sg_features;
  582. /*
  583. Runtime information about resource limits, returned by sg_query_limit()
  584. */
  585. typedef struct sg_limits {
  586. uint32_t max_image_size_2d; /* max width/height of SG_IMAGETYPE_2D images */
  587. uint32_t max_image_size_cube; /* max width/height of SG_IMAGETYPE_CUBE images */
  588. uint32_t max_image_size_3d; /* max width/height/depth of SG_IMAGETYPE_3D images */
  589. uint32_t max_image_size_array; /* max width/height pf SG_IMAGETYPE_ARRAY images */
  590. uint32_t max_image_array_layers; /* max number of layers in SG_IMAGETYPE_ARRAY images */
  591. uint32_t max_vertex_attrs; /* <= SG_MAX_VERTEX_ATTRIBUTES (only on some GLES2 impls) */
  592. } sg_limits;
  593. /*
  594. sg_resource_state
  595. The current state of a resource in its resource pool.
  596. Resources start in the INITIAL state, which means the
  597. pool slot is unoccupied and can be allocated. When a resource is
  598. created, first an id is allocated, and the resource pool slot
  599. is set to state ALLOC. After allocation, the resource is
  600. initialized, which may result in the VALID or FAILED state. The
  601. reason why allocation and initialization are separate is because
  602. some resource types (e.g. buffers and images) might be asynchronously
  603. initialized by the user application. If a resource which is not
  604. in the VALID state is attempted to be used for rendering, rendering
  605. operations will silently be dropped.
  606. The special INVALID state is returned in sg_query_xxx_state() if no
  607. resource object exists for the provided resource id.
  608. */
  609. typedef enum sg_resource_state {
  610. SG_RESOURCESTATE_INITIAL,
  611. SG_RESOURCESTATE_ALLOC,
  612. SG_RESOURCESTATE_VALID,
  613. SG_RESOURCESTATE_FAILED,
  614. SG_RESOURCESTATE_INVALID,
  615. _SG_RESOURCESTATE_FORCE_U32 = 0x7FFFFFFF
  616. } sg_resource_state;
  617. /*
  618. sg_usage
  619. A resource usage hint describing the update strategy of
  620. buffers and images. This is used in the sg_buffer_desc.usage
  621. and sg_image_desc.usage members when creating buffers
  622. and images:
  623. SG_USAGE_IMMUTABLE: the resource will never be updated with
  624. new data, instead the content of the
  625. resource must be provided on creation
  626. SG_USAGE_DYNAMIC: the resource will be updated infrequently
  627. with new data (this could range from "once
  628. after creation", to "quite often but not
  629. every frame")
  630. SG_USAGE_STREAM: the resource will be updated each frame
  631. with new content
  632. The rendering backends use this hint to prevent that the
  633. CPU needs to wait for the GPU when attempting to update
  634. a resource that might be currently accessed by the GPU.
  635. Resource content is updated with the function sg_update_buffer() for
  636. buffer objects, and sg_update_image() for image objects. Only
  637. one update is allowed per frame and resource object. The
  638. application must update all data required for rendering (this
  639. means that the update data can be smaller than the resource size,
  640. if only a part of the overall resource size is used for rendering,
  641. you only need to make sure that the data that *is* used is valid).
  642. The default usage is SG_USAGE_IMMUTABLE.
  643. */
  644. typedef enum sg_usage {
  645. _SG_USAGE_DEFAULT, /* value 0 reserved for default-init */
  646. SG_USAGE_IMMUTABLE,
  647. SG_USAGE_DYNAMIC,
  648. SG_USAGE_STREAM,
  649. _SG_USAGE_NUM,
  650. _SG_USAGE_FORCE_U32 = 0x7FFFFFFF
  651. } sg_usage;
  652. /*
  653. sg_buffer_type
  654. This indicates whether a buffer contains vertex- or index-data,
  655. used in the sg_buffer_desc.type member when creating a buffer.
  656. The default value is SG_BUFFERTYPE_VERTEXBUFFER.
  657. */
  658. typedef enum sg_buffer_type {
  659. _SG_BUFFERTYPE_DEFAULT, /* value 0 reserved for default-init */
  660. SG_BUFFERTYPE_VERTEXBUFFER,
  661. SG_BUFFERTYPE_INDEXBUFFER,
  662. _SG_BUFFERTYPE_NUM,
  663. _SG_BUFFERTYPE_FORCE_U32 = 0x7FFFFFFF
  664. } sg_buffer_type;
  665. /*
  666. sg_index_type
  667. Indicates whether indexed rendering (fetching vertex-indices from an
  668. index buffer) is used, and if yes, the index data type (16- or 32-bits).
  669. This is used in the sg_pipeline_desc.index_type member when creating a
  670. pipeline object.
  671. The default index type is SG_INDEXTYPE_NONE.
  672. */
  673. typedef enum sg_index_type {
  674. _SG_INDEXTYPE_DEFAULT, /* value 0 reserved for default-init */
  675. SG_INDEXTYPE_NONE,
  676. SG_INDEXTYPE_UINT16,
  677. SG_INDEXTYPE_UINT32,
  678. _SG_INDEXTYPE_NUM,
  679. _SG_INDEXTYPE_FORCE_U32 = 0x7FFFFFFF
  680. } sg_index_type;
  681. /*
  682. sg_image_type
  683. Indicates the basic type of an image object (2D-texture, cubemap,
  684. 3D-texture or 2D-array-texture). 3D- and array-textures are not supported
  685. on the GLES2/WebGL backend (use sg_query_features().imagetype_3d and
  686. sg_query_features().imagetype_array to check for support). The image type
  687. is used in the sg_image_desc.type member when creating an image.
  688. The default image type when creating an image is SG_IMAGETYPE_2D.
  689. */
  690. typedef enum sg_image_type {
  691. _SG_IMAGETYPE_DEFAULT, /* value 0 reserved for default-init */
  692. SG_IMAGETYPE_2D,
  693. SG_IMAGETYPE_CUBE,
  694. SG_IMAGETYPE_3D,
  695. SG_IMAGETYPE_ARRAY,
  696. _SG_IMAGETYPE_NUM,
  697. _SG_IMAGETYPE_FORCE_U32 = 0x7FFFFFFF
  698. } sg_image_type;
  699. /*
  700. sg_cube_face
  701. The cubemap faces. Use these as indices in the sg_image_desc.content
  702. array.
  703. */
  704. typedef enum sg_cube_face {
  705. SG_CUBEFACE_POS_X,
  706. SG_CUBEFACE_NEG_X,
  707. SG_CUBEFACE_POS_Y,
  708. SG_CUBEFACE_NEG_Y,
  709. SG_CUBEFACE_POS_Z,
  710. SG_CUBEFACE_NEG_Z,
  711. SG_CUBEFACE_NUM,
  712. _SG_CUBEFACE_FORCE_U32 = 0x7FFFFFFF
  713. } sg_cube_face;
  714. /*
  715. sg_shader_stage
  716. There are 2 shader stages: vertex- and fragment-shader-stage.
  717. Each shader stage consists of:
  718. - one slot for a shader function (provided as source- or byte-code)
  719. - SG_MAX_SHADERSTAGE_UBS slots for uniform blocks
  720. - SG_MAX_SHADERSTAGE_IMAGES slots for images used as textures by
  721. the shader function
  722. */
  723. typedef enum sg_shader_stage {
  724. SG_SHADERSTAGE_VS,
  725. SG_SHADERSTAGE_FS,
  726. _SG_SHADERSTAGE_FORCE_U32 = 0x7FFFFFFF
  727. } sg_shader_stage;
  728. /*
  729. sg_primitive_type
  730. This is the common subset of 3D primitive types supported across all 3D
  731. APIs. This is used in the sg_pipeline_desc.primitive_type member when
  732. creating a pipeline object.
  733. The default primitive type is SG_PRIMITIVETYPE_TRIANGLES.
  734. */
  735. typedef enum sg_primitive_type {
  736. _SG_PRIMITIVETYPE_DEFAULT, /* value 0 reserved for default-init */
  737. SG_PRIMITIVETYPE_POINTS,
  738. SG_PRIMITIVETYPE_LINES,
  739. SG_PRIMITIVETYPE_LINE_STRIP,
  740. SG_PRIMITIVETYPE_TRIANGLES,
  741. SG_PRIMITIVETYPE_TRIANGLE_STRIP,
  742. _SG_PRIMITIVETYPE_NUM,
  743. _SG_PRIMITIVETYPE_FORCE_U32 = 0x7FFFFFFF
  744. } sg_primitive_type;
  745. /*
  746. sg_filter
  747. The filtering mode when sampling a texture image. This is
  748. used in the sg_image_desc.min_filter and sg_image_desc.mag_filter
  749. members when creating an image object.
  750. The default filter mode is SG_FILTER_NEAREST.
  751. */
  752. typedef enum sg_filter {
  753. _SG_FILTER_DEFAULT, /* value 0 reserved for default-init */
  754. SG_FILTER_NEAREST,
  755. SG_FILTER_LINEAR,
  756. SG_FILTER_NEAREST_MIPMAP_NEAREST,
  757. SG_FILTER_NEAREST_MIPMAP_LINEAR,
  758. SG_FILTER_LINEAR_MIPMAP_NEAREST,
  759. SG_FILTER_LINEAR_MIPMAP_LINEAR,
  760. _SG_FILTER_NUM,
  761. _SG_FILTER_FORCE_U32 = 0x7FFFFFFF
  762. } sg_filter;
  763. /*
  764. sg_wrap
  765. The texture coordinates wrapping mode when sampling a texture
  766. image. This is used in the sg_image_desc.wrap_u, .wrap_v
  767. and .wrap_w members when creating an image.
  768. The default wrap mode is SG_WRAP_REPEAT.
  769. NOTE: SG_WRAP_CLAMP_TO_BORDER is not supported on all backends
  770. and platforms. To check for support, call sg_query_features()
  771. and check the "clamp_to_border" boolean in the returned
  772. sg_features struct.
  773. Platforms which don't support SG_WRAP_CLAMP_TO_BORDER will silently fall back
  774. to SG_WRAP_CLAMP_TO_EDGE without a validation error.
  775. Platforms which support clamp-to-border are:
  776. - all desktop GL platforms
  777. - Metal on macOS
  778. - D3D11
  779. Platforms which do not support clamp-to-border:
  780. - GLES2/3 and WebGL/WebGL2
  781. - Metal on iOS
  782. */
  783. typedef enum sg_wrap {
  784. _SG_WRAP_DEFAULT, /* value 0 reserved for default-init */
  785. SG_WRAP_REPEAT,
  786. SG_WRAP_CLAMP_TO_EDGE,
  787. SG_WRAP_CLAMP_TO_BORDER,
  788. SG_WRAP_MIRRORED_REPEAT,
  789. _SG_WRAP_NUM,
  790. _SG_WRAP_FORCE_U32 = 0x7FFFFFFF
  791. } sg_wrap;
  792. /*
  793. sg_border_color
  794. The border color to use when sampling a texture, and the UV wrap
  795. mode is SG_WRAP_CLAMP_TO_BORDER.
  796. The default border color is SG_BORDERCOLOR_OPAQUE_BLACK
  797. */
  798. typedef enum sg_border_color {
  799. _SG_BORDERCOLOR_DEFAULT, /* value 0 reserved for default-init */
  800. SG_BORDERCOLOR_TRANSPARENT_BLACK,
  801. SG_BORDERCOLOR_OPAQUE_BLACK,
  802. SG_BORDERCOLOR_OPAQUE_WHITE,
  803. _SG_BORDERCOLOR_NUM,
  804. _SG_BORDERCOLOR_FORCE_U32 = 0x7FFFFFFF
  805. } sg_border_color;
  806. /*
  807. sg_vertex_format
  808. The data type of a vertex component. This is used to describe
  809. the layout of vertex data when creating a pipeline object.
  810. */
  811. typedef enum sg_vertex_format {
  812. SG_VERTEXFORMAT_INVALID,
  813. SG_VERTEXFORMAT_FLOAT,
  814. SG_VERTEXFORMAT_FLOAT2,
  815. SG_VERTEXFORMAT_FLOAT3,
  816. SG_VERTEXFORMAT_FLOAT4,
  817. SG_VERTEXFORMAT_BYTE4,
  818. SG_VERTEXFORMAT_BYTE4N,
  819. SG_VERTEXFORMAT_UBYTE4,
  820. SG_VERTEXFORMAT_UBYTE4N,
  821. SG_VERTEXFORMAT_SHORT2,
  822. SG_VERTEXFORMAT_SHORT2N,
  823. SG_VERTEXFORMAT_USHORT2N,
  824. SG_VERTEXFORMAT_SHORT4,
  825. SG_VERTEXFORMAT_SHORT4N,
  826. SG_VERTEXFORMAT_USHORT4N,
  827. SG_VERTEXFORMAT_UINT10_N2,
  828. _SG_VERTEXFORMAT_NUM,
  829. _SG_VERTEXFORMAT_FORCE_U32 = 0x7FFFFFFF
  830. } sg_vertex_format;
  831. /*
  832. sg_vertex_step
  833. Defines whether the input pointer of a vertex input stream is advanced
  834. 'per vertex' or 'per instance'. The default step-func is
  835. SG_VERTEXSTEP_PER_VERTEX. SG_VERTEXSTEP_PER_INSTANCE is used with
  836. instanced-rendering.
  837. The vertex-step is part of the vertex-layout definition
  838. when creating pipeline objects.
  839. */
  840. typedef enum sg_vertex_step {
  841. _SG_VERTEXSTEP_DEFAULT, /* value 0 reserved for default-init */
  842. SG_VERTEXSTEP_PER_VERTEX,
  843. SG_VERTEXSTEP_PER_INSTANCE,
  844. _SG_VERTEXSTEP_NUM,
  845. _SG_VERTEXSTEP_FORCE_U32 = 0x7FFFFFFF
  846. } sg_vertex_step;
  847. /*
  848. sg_uniform_type
  849. The data type of a uniform block member. This is used to
  850. describe the internal layout of uniform blocks when creating
  851. a shader object.
  852. */
  853. typedef enum sg_uniform_type {
  854. SG_UNIFORMTYPE_INVALID,
  855. SG_UNIFORMTYPE_FLOAT,
  856. SG_UNIFORMTYPE_FLOAT2,
  857. SG_UNIFORMTYPE_FLOAT3,
  858. SG_UNIFORMTYPE_FLOAT4,
  859. SG_UNIFORMTYPE_MAT4,
  860. _SG_UNIFORMTYPE_NUM,
  861. _SG_UNIFORMTYPE_FORCE_U32 = 0x7FFFFFFF
  862. } sg_uniform_type;
  863. /*
  864. sg_cull_mode
  865. The face-culling mode, this is used in the
  866. sg_pipeline_desc.rasterizer.cull_mode member when creating a
  867. pipeline object.
  868. The default cull mode is SG_CULLMODE_NONE
  869. */
  870. typedef enum sg_cull_mode {
  871. _SG_CULLMODE_DEFAULT, /* value 0 reserved for default-init */
  872. SG_CULLMODE_NONE,
  873. SG_CULLMODE_FRONT,
  874. SG_CULLMODE_BACK,
  875. _SG_CULLMODE_NUM,
  876. _SG_CULLMODE_FORCE_U32 = 0x7FFFFFFF
  877. } sg_cull_mode;
  878. /*
  879. sg_face_winding
  880. The vertex-winding rule that determines a front-facing primitive. This
  881. is used in the member sg_pipeline_desc.rasterizer.face_winding
  882. when creating a pipeline object.
  883. The default winding is SG_FACEWINDING_CW (clockwise)
  884. */
  885. typedef enum sg_face_winding {
  886. _SG_FACEWINDING_DEFAULT, /* value 0 reserved for default-init */
  887. SG_FACEWINDING_CCW,
  888. SG_FACEWINDING_CW,
  889. _SG_FACEWINDING_NUM,
  890. _SG_FACEWINDING_FORCE_U32 = 0x7FFFFFFF
  891. } sg_face_winding;
  892. /*
  893. sg_compare_func
  894. The compare-function for depth- and stencil-ref tests.
  895. This is used when creating pipeline objects in the members:
  896. sg_pipeline_desc
  897. .depth_stencil
  898. .depth_compare_func
  899. .stencil_front.compare_func
  900. .stencil_back.compare_func
  901. The default compare func for depth- and stencil-tests is
  902. SG_COMPAREFUNC_ALWAYS.
  903. */
  904. typedef enum sg_compare_func {
  905. _SG_COMPAREFUNC_DEFAULT, /* value 0 reserved for default-init */
  906. SG_COMPAREFUNC_NEVER,
  907. SG_COMPAREFUNC_LESS,
  908. SG_COMPAREFUNC_EQUAL,
  909. SG_COMPAREFUNC_LESS_EQUAL,
  910. SG_COMPAREFUNC_GREATER,
  911. SG_COMPAREFUNC_NOT_EQUAL,
  912. SG_COMPAREFUNC_GREATER_EQUAL,
  913. SG_COMPAREFUNC_ALWAYS,
  914. _SG_COMPAREFUNC_NUM,
  915. _SG_COMPAREFUNC_FORCE_U32 = 0x7FFFFFFF
  916. } sg_compare_func;
  917. /*
  918. sg_stencil_op
  919. The operation performed on a currently stored stencil-value when a
  920. comparison test passes or fails. This is used when creating a pipeline
  921. object in the members:
  922. sg_pipeline_desc
  923. .depth_stencil
  924. .stencil_front
  925. .fail_op
  926. .depth_fail_op
  927. .pass_op
  928. .stencil_back
  929. .fail_op
  930. .depth_fail_op
  931. .pass_op
  932. The default value is SG_STENCILOP_KEEP.
  933. */
  934. typedef enum sg_stencil_op {
  935. _SG_STENCILOP_DEFAULT, /* value 0 reserved for default-init */
  936. SG_STENCILOP_KEEP,
  937. SG_STENCILOP_ZERO,
  938. SG_STENCILOP_REPLACE,
  939. SG_STENCILOP_INCR_CLAMP,
  940. SG_STENCILOP_DECR_CLAMP,
  941. SG_STENCILOP_INVERT,
  942. SG_STENCILOP_INCR_WRAP,
  943. SG_STENCILOP_DECR_WRAP,
  944. _SG_STENCILOP_NUM,
  945. _SG_STENCILOP_FORCE_U32 = 0x7FFFFFFF
  946. } sg_stencil_op;
  947. /*
  948. sg_blend_factor
  949. The source and destination factors in blending operations.
  950. This is used in the following members when creating a pipeline object:
  951. sg_pipeline_desc
  952. .blend
  953. .src_factor_rgb
  954. .dst_factor_rgb
  955. .src_factor_alpha
  956. .dst_factor_alpha
  957. The default value is SG_BLENDFACTOR_ONE for source
  958. factors, and SG_BLENDFACTOR_ZERO for destination factors.
  959. */
  960. typedef enum sg_blend_factor {
  961. _SG_BLENDFACTOR_DEFAULT, /* value 0 reserved for default-init */
  962. SG_BLENDFACTOR_ZERO,
  963. SG_BLENDFACTOR_ONE,
  964. SG_BLENDFACTOR_SRC_COLOR,
  965. SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR,
  966. SG_BLENDFACTOR_SRC_ALPHA,
  967. SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
  968. SG_BLENDFACTOR_DST_COLOR,
  969. SG_BLENDFACTOR_ONE_MINUS_DST_COLOR,
  970. SG_BLENDFACTOR_DST_ALPHA,
  971. SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA,
  972. SG_BLENDFACTOR_SRC_ALPHA_SATURATED,
  973. SG_BLENDFACTOR_BLEND_COLOR,
  974. SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR,
  975. SG_BLENDFACTOR_BLEND_ALPHA,
  976. SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA,
  977. _SG_BLENDFACTOR_NUM,
  978. _SG_BLENDFACTOR_FORCE_U32 = 0x7FFFFFFF
  979. } sg_blend_factor;
  980. /*
  981. sg_blend_op
  982. Describes how the source and destination values are combined in the
  983. fragment blending operation. It is used in the following members when
  984. creating a pipeline object:
  985. sg_pipeline_desc
  986. .blend
  987. .op_rgb
  988. .op_alpha
  989. The default value is SG_BLENDOP_ADD.
  990. */
  991. typedef enum sg_blend_op {
  992. _SG_BLENDOP_DEFAULT, /* value 0 reserved for default-init */
  993. SG_BLENDOP_ADD,
  994. SG_BLENDOP_SUBTRACT,
  995. SG_BLENDOP_REVERSE_SUBTRACT,
  996. _SG_BLENDOP_NUM,
  997. _SG_BLENDOP_FORCE_U32 = 0x7FFFFFFF
  998. } sg_blend_op;
  999. /*
  1000. sg_color_mask
  1001. Selects the color channels when writing a fragment color to the
  1002. framebuffer. This is used in the members
  1003. sg_pipeline_desc.blend.color_write_mask when creating a pipeline object.
  1004. The default colormask is SG_COLORMASK_RGBA (write all colors channels)
  1005. NOTE: since the color mask value 0 is reserved for the default value
  1006. (SG_COLORMASK_RGBA), use SG_COLORMASK_NONE if all color channels
  1007. should be disabled.
  1008. */
  1009. typedef enum sg_color_mask {
  1010. _SG_COLORMASK_DEFAULT = 0, /* value 0 reserved for default-init */
  1011. SG_COLORMASK_NONE = (0x10), /* special value for 'all channels disabled */
  1012. SG_COLORMASK_R = (1<<0),
  1013. SG_COLORMASK_G = (1<<1),
  1014. SG_COLORMASK_B = (1<<2),
  1015. SG_COLORMASK_A = (1<<3),
  1016. SG_COLORMASK_RGB = 0x7,
  1017. SG_COLORMASK_RGBA = 0xF,
  1018. _SG_COLORMASK_FORCE_U32 = 0x7FFFFFFF
  1019. } sg_color_mask;
  1020. /*
  1021. sg_action
  1022. Defines what action should be performed at the start of a render pass:
  1023. SG_ACTION_CLEAR: clear the render target image
  1024. SG_ACTION_LOAD: load the previous content of the render target image
  1025. SG_ACTION_DONTCARE: leave the render target image content undefined
  1026. This is used in the sg_pass_action structure.
  1027. The default action for all pass attachments is SG_ACTION_CLEAR, with the
  1028. clear color rgba = {0.5f, 0.5f, 0.5f, 1.0f], depth=1.0 and stencil=0.
  1029. If you want to override the default behaviour, it is important to not
  1030. only set the clear color, but the 'action' field as well (as long as this
  1031. is in its _SG_ACTION_DEFAULT, the value fields will be ignored).
  1032. */
  1033. typedef enum sg_action {
  1034. _SG_ACTION_DEFAULT,
  1035. SG_ACTION_CLEAR,
  1036. SG_ACTION_LOAD,
  1037. SG_ACTION_DONTCARE,
  1038. _SG_ACTION_NUM,
  1039. _SG_ACTION_FORCE_U32 = 0x7FFFFFFF
  1040. } sg_action;
  1041. /*
  1042. sg_pass_action
  1043. The sg_pass_action struct defines the actions to be performed
  1044. at the start of a rendering pass in the functions sg_begin_pass()
  1045. and sg_begin_default_pass().
  1046. A separate action and clear values can be defined for each
  1047. color attachment, and for the depth-stencil attachment.
  1048. The default clear values are defined by the macros:
  1049. - SG_DEFAULT_CLEAR_RED: 0.5f
  1050. - SG_DEFAULT_CLEAR_GREEN: 0.5f
  1051. - SG_DEFAULT_CLEAR_BLUE: 0.5f
  1052. - SG_DEFAULT_CLEAR_ALPHA: 1.0f
  1053. - SG_DEFAULT_CLEAR_DEPTH: 1.0f
  1054. - SG_DEFAULT_CLEAR_STENCIL: 0
  1055. */
  1056. typedef struct sg_color_attachment_action {
  1057. sg_action action;
  1058. float val[4];
  1059. } sg_color_attachment_action;
  1060. typedef struct sg_depth_attachment_action {
  1061. sg_action action;
  1062. float val;
  1063. } sg_depth_attachment_action;
  1064. typedef struct sg_stencil_attachment_action {
  1065. sg_action action;
  1066. uint8_t val;
  1067. } sg_stencil_attachment_action;
  1068. typedef struct sg_pass_action {
  1069. uint32_t _start_canary;
  1070. sg_color_attachment_action colors[SG_MAX_COLOR_ATTACHMENTS];
  1071. sg_depth_attachment_action depth;
  1072. sg_stencil_attachment_action stencil;
  1073. uint32_t _end_canary;
  1074. } sg_pass_action;
  1075. /*
  1076. sg_bindings
  1077. The sg_bindings structure defines the resource binding slots
  1078. of the sokol_gfx render pipeline, used as argument to the
  1079. sg_apply_bindings() function.
  1080. A resource binding struct contains:
  1081. - 1..N vertex buffers
  1082. - 0..N vertex buffer offsets
  1083. - 0..1 index buffers
  1084. - 0..1 index buffer offsets
  1085. - 0..N vertex shader stage images
  1086. - 0..N fragment shader stage images
  1087. The max number of vertex buffer and shader stage images
  1088. are defined by the SG_MAX_SHADERSTAGE_BUFFERS and
  1089. SG_MAX_SHADERSTAGE_IMAGES configuration constants.
  1090. The optional buffer offsets can be used to put different unrelated
  1091. chunks of vertex- and/or index-data into the same buffer objects.
  1092. */
  1093. typedef struct sg_bindings {
  1094. uint32_t _start_canary;
  1095. sg_buffer vertex_buffers[SG_MAX_SHADERSTAGE_BUFFERS];
  1096. int vertex_buffer_offsets[SG_MAX_SHADERSTAGE_BUFFERS];
  1097. sg_buffer index_buffer;
  1098. int index_buffer_offset;
  1099. sg_image vs_images[SG_MAX_SHADERSTAGE_IMAGES];
  1100. sg_image fs_images[SG_MAX_SHADERSTAGE_IMAGES];
  1101. uint32_t _end_canary;
  1102. } sg_bindings;
  1103. /*
  1104. sg_buffer_desc
  1105. Creation parameters for sg_buffer objects, used in the
  1106. sg_make_buffer() call.
  1107. The default configuration is:
  1108. .size: 0 (this *must* be set to a valid size in bytes)
  1109. .type: SG_BUFFERTYPE_VERTEXBUFFER
  1110. .usage: SG_USAGE_IMMUTABLE
  1111. .content 0
  1112. .label 0 (optional string label for trace hooks)
  1113. The label will be ignored by sokol_gfx.h, it is only useful
  1114. when hooking into sg_make_buffer() or sg_init_buffer() via
  1115. the sg_install_trace_hooks() function.
  1116. ADVANCED TOPIC: Injecting native 3D-API buffers:
  1117. The following struct members allow to inject your own GL, Metal
  1118. or D3D11 buffers into sokol_gfx:
  1119. .gl_buffers[SG_NUM_INFLIGHT_FRAMES]
  1120. .mtl_buffers[SG_NUM_INFLIGHT_FRAMES]
  1121. .d3d11_buffer
  1122. You must still provide all other members except the .content member, and
  1123. these must match the creation parameters of the native buffers you
  1124. provide. For SG_USAGE_IMMUTABLE, only provide a single native 3D-API
  1125. buffer, otherwise you need to provide SG_NUM_INFLIGHT_FRAMES buffers
  1126. (only for GL and Metal, not D3D11). Providing multiple buffers for GL and
  1127. Metal is necessary because sokol_gfx will rotate through them when
  1128. calling sg_update_buffer() to prevent lock-stalls.
  1129. Note that it is expected that immutable injected buffer have already been
  1130. initialized with content, and the .content member must be 0!
  1131. Also you need to call sg_reset_state_cache() after calling native 3D-API
  1132. functions, and before calling any sokol_gfx function.
  1133. */
  1134. typedef struct sg_buffer_desc {
  1135. uint32_t _start_canary;
  1136. int size;
  1137. sg_buffer_type type;
  1138. sg_usage usage;
  1139. const void* content;
  1140. const char* label;
  1141. /* GL specific */
  1142. uint32_t gl_buffers[SG_NUM_INFLIGHT_FRAMES];
  1143. /* Metal specific */
  1144. const void* mtl_buffers[SG_NUM_INFLIGHT_FRAMES];
  1145. /* D3D11 specific */
  1146. const void* d3d11_buffer;
  1147. uint32_t _end_canary;
  1148. } sg_buffer_desc;
  1149. /*
  1150. sg_subimage_content
  1151. Pointer to and size of a subimage-surface data, this is
  1152. used to describe the initial content of immutable-usage images,
  1153. or for updating a dynamic- or stream-usage images.
  1154. For 3D- or array-textures, one sg_subimage_content item
  1155. describes an entire mipmap level consisting of all array- or
  1156. 3D-slices of the mipmap level. It is only possible to update
  1157. an entire mipmap level, not parts of it.
  1158. */
  1159. typedef struct sg_subimage_content {
  1160. const void* ptr; /* pointer to subimage data */
  1161. int size; /* size in bytes of pointed-to subimage data */
  1162. } sg_subimage_content;
  1163. /*
  1164. sg_image_content
  1165. Defines the content of an image through a 2D array
  1166. of sg_subimage_content structs. The first array dimension
  1167. is the cubemap face, and the second array dimension the
  1168. mipmap level.
  1169. */
  1170. typedef struct sg_image_content {
  1171. sg_subimage_content subimage[SG_CUBEFACE_NUM][SG_MAX_MIPMAPS];
  1172. } sg_image_content;
  1173. /*
  1174. sg_image_desc
  1175. Creation parameters for sg_image objects, used in the
  1176. sg_make_image() call.
  1177. The default configuration is:
  1178. .type: SG_IMAGETYPE_2D
  1179. .render_target: false
  1180. .width 0 (must be set to >0)
  1181. .height 0 (must be set to >0)
  1182. .depth/.layers: 1
  1183. .num_mipmaps: 1
  1184. .usage: SG_USAGE_IMMUTABLE
  1185. .pixel_format: SG_PIXELFORMAT_RGBA8 for textures, backend-dependent
  1186. for render targets (RGBA8 or BGRA8)
  1187. .sample_count: 1 (only used in render_targets)
  1188. .min_filter: SG_FILTER_NEAREST
  1189. .mag_filter: SG_FILTER_NEAREST
  1190. .wrap_u: SG_WRAP_REPEAT
  1191. .wrap_v: SG_WRAP_REPEAT
  1192. .wrap_w: SG_WRAP_REPEAT (only SG_IMAGETYPE_3D)
  1193. .border_color SG_BORDERCOLOR_OPAQUE_BLACK
  1194. .max_anisotropy 1 (must be 1..16)
  1195. .min_lod 0.0f
  1196. .max_lod FLT_MAX
  1197. .content an sg_image_content struct to define the initial content
  1198. .label 0 (optional string label for trace hooks)
  1199. SG_IMAGETYPE_ARRAY and SG_IMAGETYPE_3D are not supported on
  1200. WebGL/GLES2, use sg_query_features().imagetype_array and
  1201. sg_query_features().imagetype_3d at runtime to check
  1202. if array- and 3D-textures are supported.
  1203. Images with usage SG_USAGE_IMMUTABLE must be fully initialized by
  1204. providing a valid .content member which points to
  1205. initialization data.
  1206. ADVANCED TOPIC: Injecting native 3D-API textures:
  1207. The following struct members allow to inject your own GL, Metal
  1208. or D3D11 textures into sokol_gfx:
  1209. .gl_textures[SG_NUM_INFLIGHT_FRAMES]
  1210. .mtl_textures[SG_NUM_INFLIGHT_FRAMES]
  1211. .d3d11_texture
  1212. The same rules apply as for injecting native buffers
  1213. (see sg_buffer_desc documentation for more details).
  1214. */
  1215. typedef struct sg_image_desc {
  1216. uint32_t _start_canary;
  1217. sg_image_type type;
  1218. bool render_target;
  1219. int width;
  1220. int height;
  1221. union {
  1222. int depth;
  1223. int layers;
  1224. };
  1225. int num_mipmaps;
  1226. sg_usage usage;
  1227. sg_pixel_format pixel_format;
  1228. int sample_count;
  1229. sg_filter min_filter;
  1230. sg_filter mag_filter;
  1231. sg_wrap wrap_u;
  1232. sg_wrap wrap_v;
  1233. sg_wrap wrap_w;
  1234. sg_border_color border_color;
  1235. uint32_t max_anisotropy;
  1236. float min_lod;
  1237. float max_lod;
  1238. sg_image_content content;
  1239. const char* label;
  1240. /* GL specific */
  1241. uint32_t gl_textures[SG_NUM_INFLIGHT_FRAMES];
  1242. /* Metal specific */
  1243. const void* mtl_textures[SG_NUM_INFLIGHT_FRAMES];
  1244. /* D3D11 specific */
  1245. const void* d3d11_texture;
  1246. uint32_t _end_canary;
  1247. } sg_image_desc;
  1248. /*
  1249. sg_shader_desc
  1250. The structure sg_shader_desc defines all creation parameters
  1251. for shader programs, used as input to the sg_make_shader() function:
  1252. - reflection information for vertex attributes (vertex shader inputs):
  1253. - vertex attribute name (required for GLES2, optional for GLES3 and GL)
  1254. - a semantic name and index (required for D3D11)
  1255. - for each vertex- and fragment-shader-stage:
  1256. - the shader source or bytecode
  1257. - an optional entry function name
  1258. - reflection info for each uniform block used by the shader stage:
  1259. - the size of the uniform block in bytes
  1260. - reflection info for each uniform block member (only required for GL backends):
  1261. - member name
  1262. - member type (SG_UNIFORMTYPE_xxx)
  1263. - if the member is an array, the number of array items
  1264. - reflection info for the texture images used by the shader stage:
  1265. - the image type (SG_IMAGETYPE_xxx)
  1266. - the name of the texture sampler (required for GLES2, optional everywhere else)
  1267. For all GL backends, shader source-code must be provided. For D3D11 and Metal,
  1268. either shader source-code or byte-code can be provided.
  1269. For D3D11, if source code is provided, the d3dcompiler_47.dll will be loaded
  1270. on demand. If this fails, shader creation will fail.
  1271. */
  1272. typedef struct sg_shader_attr_desc {
  1273. const char* name; /* GLSL vertex attribute name (only required for GLES2) */
  1274. const char* sem_name; /* HLSL semantic name */
  1275. int sem_index; /* HLSL semantic index */
  1276. } sg_shader_attr_desc;
  1277. typedef struct sg_shader_uniform_desc {
  1278. const char* name;
  1279. sg_uniform_type type;
  1280. int array_count;
  1281. } sg_shader_uniform_desc;
  1282. typedef struct sg_shader_uniform_block_desc {
  1283. int size;
  1284. sg_shader_uniform_desc uniforms[SG_MAX_UB_MEMBERS];
  1285. } sg_shader_uniform_block_desc;
  1286. typedef struct sg_shader_image_desc {
  1287. const char* name;
  1288. sg_image_type type;
  1289. } sg_shader_image_desc;
  1290. typedef struct sg_shader_stage_desc {
  1291. const char* source;
  1292. const uint8_t* byte_code;
  1293. int byte_code_size;
  1294. const char* entry;
  1295. sg_shader_uniform_block_desc uniform_blocks[SG_MAX_SHADERSTAGE_UBS];
  1296. sg_shader_image_desc images[SG_MAX_SHADERSTAGE_IMAGES];
  1297. } sg_shader_stage_desc;
  1298. typedef struct sg_shader_desc {
  1299. uint32_t _start_canary;
  1300. sg_shader_attr_desc attrs[SG_MAX_VERTEX_ATTRIBUTES];
  1301. sg_shader_stage_desc vs;
  1302. sg_shader_stage_desc fs;
  1303. const char* label;
  1304. uint32_t _end_canary;
  1305. } sg_shader_desc;
  1306. /*
  1307. sg_pipeline_desc
  1308. The sg_pipeline_desc struct defines all creation parameters
  1309. for an sg_pipeline object, used as argument to the
  1310. sg_make_pipeline() function:
  1311. - the vertex layout for all input vertex buffers
  1312. - a shader object
  1313. - the 3D primitive type (points, lines, triangles, ...)
  1314. - the index type (none, 16- or 32-bit)
  1315. - depth-stencil state
  1316. - alpha-blending state
  1317. - rasterizer state
  1318. If the vertex data has no gaps between vertex components, you can omit
  1319. the .layout.buffers[].stride and layout.attrs[].offset items (leave them
  1320. default-initialized to 0), sokol-gfx will then compute the offsets and strides
  1321. from the vertex component formats (.layout.attrs[].format). Please note
  1322. that ALL vertex attribute offsets must be 0 in order for the
  1323. automatic offset computation to kick in.
  1324. The default configuration is as follows:
  1325. .layout:
  1326. .buffers[]: vertex buffer layouts
  1327. .stride: 0 (if no stride is given it will be computed)
  1328. .step_func SG_VERTEXSTEP_PER_VERTEX
  1329. .step_rate 1
  1330. .attrs[]: vertex attribute declarations
  1331. .buffer_index 0 the vertex buffer bind slot
  1332. .offset 0 (offsets can be omitted if the vertex layout has no gaps)
  1333. .format SG_VERTEXFORMAT_INVALID (must be initialized!)
  1334. .shader: 0 (must be initialized with a valid sg_shader id!)
  1335. .primitive_type: SG_PRIMITIVETYPE_TRIANGLES
  1336. .index_type: SG_INDEXTYPE_NONE
  1337. .depth_stencil:
  1338. .stencil_front, .stencil_back:
  1339. .fail_op: SG_STENCILOP_KEEP
  1340. .depth_fail_op: SG_STENCILOP_KEEP
  1341. .pass_op: SG_STENCILOP_KEEP
  1342. .compare_func SG_COMPAREFUNC_ALWAYS
  1343. .depth_compare_func: SG_COMPAREFUNC_ALWAYS
  1344. .depth_write_enabled: false
  1345. .stencil_enabled: false
  1346. .stencil_read_mask: 0
  1347. .stencil_write_mask: 0
  1348. .stencil_ref: 0
  1349. .blend:
  1350. .enabled: false
  1351. .src_factor_rgb: SG_BLENDFACTOR_ONE
  1352. .dst_factor_rgb: SG_BLENDFACTOR_ZERO
  1353. .op_rgb: SG_BLENDOP_ADD
  1354. .src_factor_alpha: SG_BLENDFACTOR_ONE
  1355. .dst_factor_alpha: SG_BLENDFACTOR_ZERO
  1356. .op_alpha: SG_BLENDOP_ADD
  1357. .color_write_mask: SG_COLORMASK_RGBA
  1358. .color_attachment_count 1
  1359. .color_format SG_PIXELFORMAT_RGBA8
  1360. .depth_format SG_PIXELFORMAT_DEPTHSTENCIL
  1361. .blend_color: { 0.0f, 0.0f, 0.0f, 0.0f }
  1362. .rasterizer:
  1363. .alpha_to_coverage_enabled: false
  1364. .cull_mode: SG_CULLMODE_NONE
  1365. .face_winding: SG_FACEWINDING_CW
  1366. .sample_count: 1
  1367. .depth_bias: 0.0f
  1368. .depth_bias_slope_scale: 0.0f
  1369. .depth_bias_clamp: 0.0f
  1370. .label 0 (optional string label for trace hooks)
  1371. */
  1372. typedef struct sg_buffer_layout_desc {
  1373. int stride;
  1374. sg_vertex_step step_func;
  1375. int step_rate;
  1376. } sg_buffer_layout_desc;
  1377. typedef struct sg_vertex_attr_desc {
  1378. int buffer_index;
  1379. int offset;
  1380. sg_vertex_format format;
  1381. } sg_vertex_attr_desc;
  1382. typedef struct sg_layout_desc {
  1383. sg_buffer_layout_desc buffers[SG_MAX_SHADERSTAGE_BUFFERS];
  1384. sg_vertex_attr_desc attrs[SG_MAX_VERTEX_ATTRIBUTES];
  1385. } sg_layout_desc;
  1386. typedef struct sg_stencil_state {
  1387. sg_stencil_op fail_op;
  1388. sg_stencil_op depth_fail_op;
  1389. sg_stencil_op pass_op;
  1390. sg_compare_func compare_func;
  1391. } sg_stencil_state;
  1392. typedef struct sg_depth_stencil_state {
  1393. sg_stencil_state stencil_front;
  1394. sg_stencil_state stencil_back;
  1395. sg_compare_func depth_compare_func;
  1396. bool depth_write_enabled;
  1397. bool stencil_enabled;
  1398. uint8_t stencil_read_mask;
  1399. uint8_t stencil_write_mask;
  1400. uint8_t stencil_ref;
  1401. } sg_depth_stencil_state;
  1402. typedef struct sg_blend_state {
  1403. bool enabled;
  1404. sg_blend_factor src_factor_rgb;
  1405. sg_blend_factor dst_factor_rgb;
  1406. sg_blend_op op_rgb;
  1407. sg_blend_factor src_factor_alpha;
  1408. sg_blend_factor dst_factor_alpha;
  1409. sg_blend_op op_alpha;
  1410. uint8_t color_write_mask;
  1411. int color_attachment_count;
  1412. sg_pixel_format color_format;
  1413. sg_pixel_format depth_format;
  1414. float blend_color[4];
  1415. } sg_blend_state;
  1416. typedef struct sg_rasterizer_state {
  1417. bool alpha_to_coverage_enabled;
  1418. sg_cull_mode cull_mode;
  1419. sg_face_winding face_winding;
  1420. int sample_count;
  1421. float depth_bias;
  1422. float depth_bias_slope_scale;
  1423. float depth_bias_clamp;
  1424. } sg_rasterizer_state;
  1425. typedef struct sg_pipeline_desc {
  1426. uint32_t _start_canary;
  1427. sg_layout_desc layout;
  1428. sg_shader shader;
  1429. sg_primitive_type primitive_type;
  1430. sg_index_type index_type;
  1431. sg_depth_stencil_state depth_stencil;
  1432. sg_blend_state blend;
  1433. sg_rasterizer_state rasterizer;
  1434. const char* label;
  1435. uint32_t _end_canary;
  1436. } sg_pipeline_desc;
  1437. /*
  1438. sg_pass_desc
  1439. Creation parameters for an sg_pass object, used as argument
  1440. to the sg_make_pass() function.
  1441. A pass object contains 1..4 color-attachments and none, or one,
  1442. depth-stencil-attachment. Each attachment consists of
  1443. an image, and two additional indices describing
  1444. which subimage the pass will render to: one mipmap index, and
  1445. if the image is a cubemap, array-texture or 3D-texture, the
  1446. face-index, array-layer or depth-slice.
  1447. Pass images must fulfill the following requirements:
  1448. All images must have:
  1449. - been created as render target (sg_image_desc.render_target = true)
  1450. - the same size
  1451. - the same sample count
  1452. In addition, all color-attachment images must have the same pixel format.
  1453. */
  1454. typedef struct sg_attachment_desc {
  1455. sg_image image;
  1456. int mip_level;
  1457. union {
  1458. int face;
  1459. int layer;
  1460. int slice;
  1461. };
  1462. } sg_attachment_desc;
  1463. typedef struct sg_pass_desc {
  1464. uint32_t _start_canary;
  1465. sg_attachment_desc color_attachments[SG_MAX_COLOR_ATTACHMENTS];
  1466. sg_attachment_desc depth_stencil_attachment;
  1467. const char* label;
  1468. uint32_t _end_canary;
  1469. } sg_pass_desc;
  1470. /*
  1471. sg_trace_hooks
  1472. Installable callback functions to keep track of the sokol-gfx calls,
  1473. this is useful for debugging, or keeping track of resource creation
  1474. and destruction.
  1475. Trace hooks are installed with sg_install_trace_hooks(), this returns
  1476. another sg_trace_hooks struct with the previous set of
  1477. trace hook function pointers. These should be invoked by the
  1478. new trace hooks to form a proper call chain.
  1479. */
  1480. typedef struct sg_trace_hooks {
  1481. void* user_data;
  1482. void (*reset_state_cache)(void* user_data);
  1483. void (*make_buffer)(const sg_buffer_desc* desc, sg_buffer result, void* user_data);
  1484. void (*make_image)(const sg_image_desc* desc, sg_image result, void* user_data);
  1485. void (*make_shader)(const sg_shader_desc* desc, sg_shader result, void* user_data);
  1486. void (*make_pipeline)(const sg_pipeline_desc* desc, sg_pipeline result, void* user_data);
  1487. void (*make_pass)(const sg_pass_desc* desc, sg_pass result, void* user_data);
  1488. void (*destroy_buffer)(sg_buffer buf, void* user_data);
  1489. void (*destroy_image)(sg_image img, void* user_data);
  1490. void (*destroy_shader)(sg_shader shd, void* user_data);
  1491. void (*destroy_pipeline)(sg_pipeline pip, void* user_data);
  1492. void (*destroy_pass)(sg_pass pass, void* user_data);
  1493. void (*update_buffer)(sg_buffer buf, const void* data_ptr, int data_size, void* user_data);
  1494. void (*update_image)(sg_image img, const sg_image_content* data, void* user_data);
  1495. void (*append_buffer)(sg_buffer buf, const void* data_ptr, int data_size, int result, void* user_data);
  1496. void (*begin_default_pass)(const sg_pass_action* pass_action, int width, int height, void* user_data);
  1497. void (*begin_pass)(sg_pass pass, const sg_pass_action* pass_action, void* user_data);
  1498. void (*apply_viewport)(int x, int y, int width, int height, bool origin_top_left, void* user_data);
  1499. void (*apply_scissor_rect)(int x, int y, int width, int height, bool origin_top_left, void* user_data);
  1500. void (*apply_pipeline)(sg_pipeline pip, void* user_data);
  1501. void (*apply_bindings)(const sg_bindings* bindings, void* user_data);
  1502. void (*apply_uniforms)(sg_shader_stage stage, int ub_index, const void* data, int num_bytes, void* user_data);
  1503. void (*draw)(int base_element, int num_elements, int num_instances, void* user_data);
  1504. void (*end_pass)(void* user_data);
  1505. void (*commit)(void* user_data);
  1506. void (*alloc_buffer)(sg_buffer result, void* user_data);
  1507. void (*alloc_image)(sg_image result, void* user_data);
  1508. void (*alloc_shader)(sg_shader result, void* user_data);
  1509. void (*alloc_pipeline)(sg_pipeline result, void* user_data);
  1510. void (*alloc_pass)(sg_pass result, void* user_data);
  1511. void (*init_buffer)(sg_buffer buf_id, const sg_buffer_desc* desc, void* user_data);
  1512. void (*init_image)(sg_image img_id, const sg_image_desc* desc, void* user_data);
  1513. void (*init_shader)(sg_shader shd_id, const sg_shader_desc* desc, void* user_data);
  1514. void (*init_pipeline)(sg_pipeline pip_id, const sg_pipeline_desc* desc, void* user_data);
  1515. void (*init_pass)(sg_pass pass_id, const sg_pass_desc* desc, void* user_data);
  1516. void (*fail_buffer)(sg_buffer buf_id, void* user_data);
  1517. void (*fail_image)(sg_image img_id, void* user_data);
  1518. void (*fail_shader)(sg_shader shd_id, void* user_data);
  1519. void (*fail_pipeline)(sg_pipeline pip_id, void* user_data);
  1520. void (*fail_pass)(sg_pass pass_id, void* user_data);
  1521. void (*push_debug_group)(const char* name, void* user_data);
  1522. void (*pop_debug_group)(void* user_data);
  1523. void (*err_buffer_pool_exhausted)(void* user_data);
  1524. void (*err_image_pool_exhausted)(void* user_data);
  1525. void (*err_shader_pool_exhausted)(void* user_data);
  1526. void (*err_pipeline_pool_exhausted)(void* user_data);
  1527. void (*err_pass_pool_exhausted)(void* user_data);
  1528. void (*err_context_mismatch)(void* user_data);
  1529. void (*err_pass_invalid)(void* user_data);
  1530. void (*err_draw_invalid)(void* user_data);
  1531. void (*err_bindings_invalid)(void* user_data);
  1532. } sg_trace_hooks;
  1533. /*
  1534. sg_buffer_info
  1535. sg_image_info
  1536. sg_shader_info
  1537. sg_pipeline_info
  1538. sg_pass_info
  1539. These structs contain various internal resource attributes which
  1540. might be useful for debug-inspection. Please don't rely on the
  1541. actual content of those structs too much, as they are quite closely
  1542. tied to sokol_gfx.h internals and may change more frequently than
  1543. the other public API elements.
  1544. The *_info structs are used as the return values of the following functions:
  1545. sg_query_buffer_info()
  1546. sg_query_image_info()
  1547. sg_query_shader_info()
  1548. sg_query_pipeline_info()
  1549. sg_query_pass_info()
  1550. */
  1551. typedef struct sg_slot_info {
  1552. sg_resource_state state; /* the current state of this resource slot */
  1553. uint32_t res_id; /* type-neutral resource if (e.g. sg_buffer.id) */
  1554. uint32_t ctx_id; /* the context this resource belongs to */
  1555. } sg_slot_info;
  1556. typedef struct sg_buffer_info {
  1557. sg_slot_info slot; /* resource pool slot info */
  1558. uint32_t update_frame_index; /* frame index of last sg_update_buffer() */
  1559. uint32_t append_frame_index; /* frame index of last sg_append_buffer() */
  1560. int append_pos; /* current position in buffer for sg_append_buffer() */
  1561. bool append_overflow; /* is buffer in overflow state (due to sg_append_buffer) */
  1562. int num_slots; /* number of renaming-slots for dynamically updated buffers */
  1563. int active_slot; /* currently active write-slot for dynamically updated buffers */
  1564. } sg_buffer_info;
  1565. typedef struct sg_image_info {
  1566. sg_slot_info slot; /* resource pool slot info */
  1567. uint32_t upd_frame_index; /* frame index of last sg_update_image() */
  1568. int num_slots; /* number of renaming-slots for dynamically updated images */
  1569. int active_slot; /* currently active write-slot for dynamically updated images */
  1570. } sg_image_info;
  1571. typedef struct sg_shader_info {
  1572. sg_slot_info slot; /* resoure pool slot info */
  1573. } sg_shader_info;
  1574. typedef struct sg_pipeline_info {
  1575. sg_slot_info slot; /* resource pool slot info */
  1576. } sg_pipeline_info;
  1577. typedef struct sg_pass_info {
  1578. sg_slot_info slot; /* resource pool slot info */
  1579. } sg_pass_info;
  1580. /*
  1581. sg_desc
  1582. The sg_desc struct contains configuration values for sokol_gfx,
  1583. it is used as parameter to the sg_setup() call.
  1584. The default configuration is:
  1585. .buffer_pool_size: 128
  1586. .image_pool_size: 128
  1587. .shader_pool_size: 32
  1588. .pipeline_pool_size: 64
  1589. .pass_pool_size: 16
  1590. .context_pool_size: 16
  1591. GL specific:
  1592. .gl_force_gles2
  1593. if this is true the GL backend will act in "GLES2 fallback mode" even
  1594. when compiled with SOKOL_GLES3, this is useful to fall back
  1595. to traditional WebGL if a browser doesn't support a WebGL2 context
  1596. Metal specific:
  1597. (NOTE: All Objective-C object references are transferred through
  1598. a bridged (const void*) to sokol_gfx, which will use a unretained
  1599. bridged cast (__bridged id<xxx>) to retrieve the Objective-C
  1600. references back. Since the bridge cast is unretained, the caller
  1601. must hold a strong reference to the Objective-C object for the
  1602. duration of the sokol_gfx call!
  1603. .mtl_device
  1604. a pointer to the MTLDevice object
  1605. .mtl_renderpass_descriptor_cb
  1606. a C callback function to obtain the MTLRenderPassDescriptor for the
  1607. current frame when rendering to the default framebuffer, will be called
  1608. in sg_begin_default_pass()
  1609. .mtl_drawable_cb
  1610. a C callback function to obtain a MTLDrawable for the current
  1611. frame when rendering to the default framebuffer, will be called in
  1612. sg_end_pass() of the default pass
  1613. .mtl_global_uniform_buffer_size
  1614. the size of the global uniform buffer in bytes, this must be big
  1615. enough to hold all uniform block updates for a single frame,
  1616. the default value is 4 MByte (4 * 1024 * 1024)
  1617. .mtl_sampler_cache_size
  1618. the number of slots in the sampler cache, the Metal backend
  1619. will share texture samplers with the same state in this
  1620. cache, the default value is 64
  1621. D3D11 specific:
  1622. .d3d11_device
  1623. a pointer to the ID3D11Device object, this must have been created
  1624. before sg_setup() is called
  1625. .d3d11_device_context
  1626. a pointer to the ID3D11DeviceContext object
  1627. .d3d11_render_target_view_cb
  1628. a C callback function to obtain a pointer to the current
  1629. ID3D11RenderTargetView object of the default framebuffer,
  1630. this function will be called in sg_begin_pass() when rendering
  1631. to the default framebuffer
  1632. .d3d11_depth_stencil_view_cb
  1633. a C callback function to obtain a pointer to the current
  1634. ID3D11DepthStencilView object of the default framebuffer,
  1635. this function will be called in sg_begin_pass() when rendering
  1636. to the default framebuffer
  1637. */
  1638. typedef struct sg_desc {
  1639. uint32_t _start_canary;
  1640. int buffer_pool_size;
  1641. int image_pool_size;
  1642. int shader_pool_size;
  1643. int pipeline_pool_size;
  1644. int pass_pool_size;
  1645. int context_pool_size;
  1646. /* GL specific */
  1647. bool gl_force_gles2;
  1648. /* Metal-specific */
  1649. const void* mtl_device;
  1650. const void* (*mtl_renderpass_descriptor_cb)(void);
  1651. const void* (*mtl_drawable_cb)(void);
  1652. int mtl_global_uniform_buffer_size;
  1653. int mtl_sampler_cache_size;
  1654. /* D3D11-specific */
  1655. const void* d3d11_device;
  1656. const void* d3d11_device_context;
  1657. const void* (*d3d11_render_target_view_cb)(void);
  1658. const void* (*d3d11_depth_stencil_view_cb)(void);
  1659. uint32_t _end_canary;
  1660. } sg_desc;
  1661. /* setup and misc functions */
  1662. SOKOL_API_DECL void sg_setup(const sg_desc* desc);
  1663. SOKOL_API_DECL void sg_shutdown(void);
  1664. SOKOL_API_DECL bool sg_isvalid(void);
  1665. SOKOL_API_DECL void sg_reset_state_cache(void);
  1666. SOKOL_API_DECL sg_trace_hooks sg_install_trace_hooks(const sg_trace_hooks* trace_hooks);
  1667. SOKOL_API_DECL void sg_push_debug_group(const char* name);
  1668. SOKOL_API_DECL void sg_pop_debug_group(void);
  1669. /* resource creation, destruction and updating */
  1670. SOKOL_API_DECL sg_buffer sg_make_buffer(const sg_buffer_desc* desc);
  1671. SOKOL_API_DECL sg_image sg_make_image(const sg_image_desc* desc);
  1672. SOKOL_API_DECL sg_shader sg_make_shader(const sg_shader_desc* desc);
  1673. SOKOL_API_DECL sg_pipeline sg_make_pipeline(const sg_pipeline_desc* desc);
  1674. SOKOL_API_DECL sg_pass sg_make_pass(const sg_pass_desc* desc);
  1675. SOKOL_API_DECL void sg_destroy_buffer(sg_buffer buf);
  1676. SOKOL_API_DECL void sg_destroy_image(sg_image img);
  1677. SOKOL_API_DECL void sg_destroy_shader(sg_shader shd);
  1678. SOKOL_API_DECL void sg_destroy_pipeline(sg_pipeline pip);
  1679. SOKOL_API_DECL void sg_destroy_pass(sg_pass pass);
  1680. SOKOL_API_DECL void sg_update_buffer(sg_buffer buf, const void* data_ptr, int data_size);
  1681. SOKOL_API_DECL void sg_update_image(sg_image img, const sg_image_content* data);
  1682. SOKOL_API_DECL int sg_append_buffer(sg_buffer buf, const void* data_ptr, int data_size);
  1683. SOKOL_API_DECL bool sg_query_buffer_overflow(sg_buffer buf);
  1684. /* rendering functions */
  1685. SOKOL_API_DECL void sg_begin_default_pass(const sg_pass_action* pass_action, int width, int height);
  1686. SOKOL_API_DECL void sg_begin_pass(sg_pass pass, const sg_pass_action* pass_action);
  1687. SOKOL_API_DECL void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left);
  1688. SOKOL_API_DECL void sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left);
  1689. SOKOL_API_DECL void sg_apply_pipeline(sg_pipeline pip);
  1690. SOKOL_API_DECL void sg_apply_bindings(const sg_bindings* bindings);
  1691. SOKOL_API_DECL void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const void* data, int num_bytes);
  1692. SOKOL_API_DECL void sg_draw(int base_element, int num_elements, int num_instances);
  1693. SOKOL_API_DECL void sg_end_pass(void);
  1694. SOKOL_API_DECL void sg_commit(void);
  1695. /* getting information */
  1696. SOKOL_API_DECL sg_desc sg_query_desc(void);
  1697. SOKOL_API_DECL sg_backend sg_query_backend(void);
  1698. SOKOL_API_DECL sg_features sg_query_features(void);
  1699. SOKOL_API_DECL sg_limits sg_query_limits(void);
  1700. SOKOL_API_DECL sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt);
  1701. /* get current state of a resource (INITIAL, ALLOC, VALID, FAILED, INVALID) */
  1702. SOKOL_API_DECL sg_resource_state sg_query_buffer_state(sg_buffer buf);
  1703. SOKOL_API_DECL sg_resource_state sg_query_image_state(sg_image img);
  1704. SOKOL_API_DECL sg_resource_state sg_query_shader_state(sg_shader shd);
  1705. SOKOL_API_DECL sg_resource_state sg_query_pipeline_state(sg_pipeline pip);
  1706. SOKOL_API_DECL sg_resource_state sg_query_pass_state(sg_pass pass);
  1707. /* get runtime information about a resource */
  1708. SOKOL_API_DECL sg_buffer_info sg_query_buffer_info(sg_buffer buf);
  1709. SOKOL_API_DECL sg_image_info sg_query_image_info(sg_image img);
  1710. SOKOL_API_DECL sg_shader_info sg_query_shader_info(sg_shader shd);
  1711. SOKOL_API_DECL sg_pipeline_info sg_query_pipeline_info(sg_pipeline pip);
  1712. SOKOL_API_DECL sg_pass_info sg_query_pass_info(sg_pass pass);
  1713. /* get resource creation desc struct with their default values replaced */
  1714. SOKOL_API_DECL sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc* desc);
  1715. SOKOL_API_DECL sg_image_desc sg_query_image_defaults(const sg_image_desc* desc);
  1716. SOKOL_API_DECL sg_shader_desc sg_query_shader_defaults(const sg_shader_desc* desc);
  1717. SOKOL_API_DECL sg_pipeline_desc sg_query_pipeline_defaults(const sg_pipeline_desc* desc);
  1718. SOKOL_API_DECL sg_pass_desc sg_query_pass_defaults(const sg_pass_desc* desc);
  1719. /* separate resource allocation and initialization (for async setup) */
  1720. SOKOL_API_DECL sg_buffer sg_alloc_buffer(void);
  1721. SOKOL_API_DECL sg_image sg_alloc_image(void);
  1722. SOKOL_API_DECL sg_shader sg_alloc_shader(void);
  1723. SOKOL_API_DECL sg_pipeline sg_alloc_pipeline(void);
  1724. SOKOL_API_DECL sg_pass sg_alloc_pass(void);
  1725. SOKOL_API_DECL void sg_init_buffer(sg_buffer buf_id, const sg_buffer_desc* desc);
  1726. SOKOL_API_DECL void sg_init_image(sg_image img_id, const sg_image_desc* desc);
  1727. SOKOL_API_DECL void sg_init_shader(sg_shader shd_id, const sg_shader_desc* desc);
  1728. SOKOL_API_DECL void sg_init_pipeline(sg_pipeline pip_id, const sg_pipeline_desc* desc);
  1729. SOKOL_API_DECL void sg_init_pass(sg_pass pass_id, const sg_pass_desc* desc);
  1730. SOKOL_API_DECL void sg_fail_buffer(sg_buffer buf_id);
  1731. SOKOL_API_DECL void sg_fail_image(sg_image img_id);
  1732. SOKOL_API_DECL void sg_fail_shader(sg_shader shd_id);
  1733. SOKOL_API_DECL void sg_fail_pipeline(sg_pipeline pip_id);
  1734. SOKOL_API_DECL void sg_fail_pass(sg_pass pass_id);
  1735. /* rendering contexts (optional) */
  1736. SOKOL_API_DECL sg_context sg_setup_context(void);
  1737. SOKOL_API_DECL void sg_activate_context(sg_context ctx_id);
  1738. SOKOL_API_DECL void sg_discard_context(sg_context ctx_id);
  1739. #ifdef _MSC_VER
  1740. #pragma warning(pop)
  1741. #endif
  1742. #ifdef __cplusplus
  1743. } /* extern "C" */
  1744. #endif
  1745. #endif // SOKOL_GFX_INCLUDED
  1746. /*--- IMPLEMENTATION ---------------------------------------------------------*/
  1747. #ifdef SOKOL_IMPL
  1748. #define SOKOL_GFX_IMPL_INCLUDED (1)
  1749. #if !(defined(SOKOL_GLCORE33)||defined(SOKOL_GLES2)||defined(SOKOL_GLES3)||defined(SOKOL_D3D11)||defined(SOKOL_METAL)||defined(SOKOL_DUMMY_BACKEND))
  1750. #error "Please select a backend with SOKOL_GLCORE33, SOKOL_GLES2, SOKOL_GLES3, SOKOL_D3D11, SOKOL_METAL or SOKOL_DUMMY_BACKEND"
  1751. #endif
  1752. #include <string.h> /* memset */
  1753. #include <float.h> /* FLT_MAX */
  1754. #ifndef SOKOL_API_IMPL
  1755. #define SOKOL_API_IMPL
  1756. #endif
  1757. #ifndef SOKOL_DEBUG
  1758. #ifndef NDEBUG
  1759. #define SOKOL_DEBUG (1)
  1760. #endif
  1761. #endif
  1762. #ifndef SOKOL_ASSERT
  1763. #include <assert.h>
  1764. #define SOKOL_ASSERT(c) assert(c)
  1765. #endif
  1766. #ifndef SOKOL_VALIDATE_BEGIN
  1767. #define SOKOL_VALIDATE_BEGIN() _sg_validate_begin()
  1768. #endif
  1769. #ifndef SOKOL_VALIDATE
  1770. #define SOKOL_VALIDATE(cond, err) _sg_validate((cond), err)
  1771. #endif
  1772. #ifndef SOKOL_VALIDATE_END
  1773. #define SOKOL_VALIDATE_END() _sg_validate_end()
  1774. #endif
  1775. #ifndef SOKOL_UNREACHABLE
  1776. #define SOKOL_UNREACHABLE SOKOL_ASSERT(false)
  1777. #endif
  1778. #ifndef SOKOL_MALLOC
  1779. #include <stdlib.h>
  1780. #define SOKOL_MALLOC(s) malloc(s)
  1781. #define SOKOL_FREE(p) free(p)
  1782. #endif
  1783. #ifndef SOKOL_LOG
  1784. #ifdef SOKOL_DEBUG
  1785. #include <stdio.h>
  1786. #define SOKOL_LOG(s) { SOKOL_ASSERT(s); puts(s); }
  1787. #else
  1788. #define SOKOL_LOG(s)
  1789. #endif
  1790. #endif
  1791. #ifndef _SOKOL_PRIVATE
  1792. #if defined(__GNUC__)
  1793. #define _SOKOL_PRIVATE __attribute__((unused)) static
  1794. #else
  1795. #define _SOKOL_PRIVATE static
  1796. #endif
  1797. #endif
  1798. #ifndef _SOKOL_UNUSED
  1799. #define _SOKOL_UNUSED(x) (void)(x)
  1800. #endif
  1801. #if defined(SOKOL_TRACE_HOOKS)
  1802. #define _SG_TRACE_ARGS(fn, ...) if (_sg.hooks.fn) { _sg.hooks.fn(__VA_ARGS__, _sg.hooks.user_data); }
  1803. #define _SG_TRACE_NOARGS(fn) if (_sg.hooks.fn) { _sg.hooks.fn(_sg.hooks.user_data); }
  1804. #else
  1805. #define _SG_TRACE_ARGS(fn, ...)
  1806. #define _SG_TRACE_NOARGS(fn)
  1807. #endif
  1808. /* default clear values */
  1809. #ifndef SG_DEFAULT_CLEAR_RED
  1810. #define SG_DEFAULT_CLEAR_RED (0.5f)
  1811. #endif
  1812. #ifndef SG_DEFAULT_CLEAR_GREEN
  1813. #define SG_DEFAULT_CLEAR_GREEN (0.5f)
  1814. #endif
  1815. #ifndef SG_DEFAULT_CLEAR_BLUE
  1816. #define SG_DEFAULT_CLEAR_BLUE (0.5f)
  1817. #endif
  1818. #ifndef SG_DEFAULT_CLEAR_ALPHA
  1819. #define SG_DEFAULT_CLEAR_ALPHA (1.0f)
  1820. #endif
  1821. #ifndef SG_DEFAULT_CLEAR_DEPTH
  1822. #define SG_DEFAULT_CLEAR_DEPTH (1.0f)
  1823. #endif
  1824. #ifndef SG_DEFAULT_CLEAR_STENCIL
  1825. #define SG_DEFAULT_CLEAR_STENCIL (0)
  1826. #endif
  1827. #ifdef _MSC_VER
  1828. #pragma warning(push)
  1829. #pragma warning(disable:4201) /* nonstandard extension used: nameless struct/union */
  1830. #pragma warning(disable:4115) /* named type definition in parentheses */
  1831. #pragma warning(disable:4505) /* unreferenced local function has been removed */
  1832. #endif
  1833. #if defined(SOKOL_GLCORE33) || defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
  1834. #define _SOKOL_ANY_GL (1)
  1835. #ifndef GL_UNSIGNED_INT_2_10_10_10_REV
  1836. #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
  1837. #endif
  1838. #ifndef GL_UNSIGNED_INT_24_8
  1839. #define GL_UNSIGNED_INT_24_8 0x84FA
  1840. #endif
  1841. #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
  1842. #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
  1843. #endif
  1844. #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
  1845. #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
  1846. #endif
  1847. #ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
  1848. #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
  1849. #endif
  1850. #ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
  1851. #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
  1852. #endif
  1853. #ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
  1854. #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
  1855. #endif
  1856. #ifndef GL_COMPRESSED_RED_RGTC1
  1857. #define GL_COMPRESSED_RED_RGTC1 0x8DBB
  1858. #endif
  1859. #ifndef GL_COMPRESSED_SIGNED_RED_RGTC1
  1860. #define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
  1861. #endif
  1862. #ifndef GL_COMPRESSED_RED_GREEN_RGTC2
  1863. #define GL_COMPRESSED_RED_GREEN_RGTC2 0x8DBD
  1864. #endif
  1865. #ifndef GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2
  1866. #define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2 0x8DBE
  1867. #endif
  1868. #ifndef GL_COMPRESSED_RGBA_BPTC_UNORM_ARB
  1869. #define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
  1870. #endif
  1871. #ifndef GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB
  1872. #define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
  1873. #endif
  1874. #ifndef GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB
  1875. #define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
  1876. #endif
  1877. #ifndef GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB
  1878. #define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
  1879. #endif
  1880. #ifndef GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
  1881. #define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
  1882. #endif
  1883. #ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
  1884. #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
  1885. #endif
  1886. #ifndef GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
  1887. #define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
  1888. #endif
  1889. #ifndef GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
  1890. #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
  1891. #endif
  1892. #ifndef GL_COMPRESSED_RGB8_ETC2
  1893. #define GL_COMPRESSED_RGB8_ETC2 0x9274
  1894. #endif
  1895. #ifndef GL_COMPRESSED_RGBA8_ETC2_EAC
  1896. #define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
  1897. #endif
  1898. #ifndef GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
  1899. #define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
  1900. #endif
  1901. #ifndef GL_COMPRESSED_RG11_EAC
  1902. #define GL_COMPRESSED_RG11_EAC 0x9272
  1903. #endif
  1904. #ifndef GL_COMPRESSED_SIGNED_RG11_EAC
  1905. #define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
  1906. #endif
  1907. #ifndef GL_DEPTH24_STENCIL8
  1908. #define GL_DEPTH24_STENCIL8 0x88F0
  1909. #endif
  1910. #ifndef GL_HALF_FLOAT
  1911. #define GL_HALF_FLOAT 0x140B
  1912. #endif
  1913. #ifndef GL_DEPTH_STENCIL
  1914. #define GL_DEPTH_STENCIL 0x84F9
  1915. #endif
  1916. #ifndef GL_LUMINANCE
  1917. #define GL_LUMINANCE 0x1909
  1918. #endif
  1919. #ifdef SOKOL_GLES2
  1920. # ifdef GL_ANGLE_instanced_arrays
  1921. # define SOKOL_INSTANCING_ENABLED
  1922. # define glDrawArraysInstanced(mode, first, count, instancecount) glDrawArraysInstancedANGLE(mode, first, count, instancecount)
  1923. # define glDrawElementsInstanced(mode, count, type, indices, instancecount) glDrawElementsInstancedANGLE(mode, count, type, indices, instancecount)
  1924. # define glVertexAttribDivisor(index, divisor) glVertexAttribDivisorANGLE(index, divisor)
  1925. # elif defined(GL_EXT_draw_instanced) && defined(GL_EXT_instanced_arrays)
  1926. # define SOKOL_INSTANCING_ENABLED
  1927. # define glDrawArraysInstanced(mode, first, count, instancecount) glDrawArraysInstancedEXT(mode, first, count, instancecount)
  1928. # define glDrawElementsInstanced(mode, count, type, indices, instancecount) glDrawElementsInstancedEXT(mode, count, type, indices, instancecount)
  1929. # define glVertexAttribDivisor(index, divisor) glVertexAttribDivisorEXT(index, divisor)
  1930. # else
  1931. # define SOKOL_GLES2_INSTANCING_ERROR "Select GL_ANGLE_instanced_arrays or (GL_EXT_draw_instanced & GL_EXT_instanced_arrays) to enable instancing in GLES2"
  1932. # define glDrawArraysInstanced(mode, first, count, instancecount) SOKOL_ASSERT(0 && SOKOL_GLES2_INSTANCING_ERROR)
  1933. # define glDrawElementsInstanced(mode, count, type, indices, instancecount) SOKOL_ASSERT(0 && SOKOL_GLES2_INSTANCING_ERROR)
  1934. # define glVertexAttribDivisor(index, divisor) SOKOL_ASSERT(0 && SOKOL_GLES2_INSTANCING_ERROR)
  1935. # endif
  1936. #else
  1937. # define SOKOL_INSTANCING_ENABLED
  1938. #endif
  1939. #define _SG_GL_CHECK_ERROR() { SOKOL_ASSERT(glGetError() == GL_NO_ERROR); }
  1940. #elif defined(SOKOL_D3D11)
  1941. #ifndef D3D11_NO_HELPERS
  1942. #define D3D11_NO_HELPERS
  1943. #endif
  1944. #ifndef CINTERFACE
  1945. #define CINTERFACE
  1946. #endif
  1947. #ifndef COBJMACROS
  1948. #define COBJMACROS
  1949. #endif
  1950. #ifndef WIN32_LEAN_AND_MEAN
  1951. #define WIN32_LEAN_AND_MEAN
  1952. #endif
  1953. #include <windows.h>
  1954. #include <d3d11.h>
  1955. #include <d3dcompiler.h>
  1956. #if (defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
  1957. #pragma comment (lib, "WindowsApp.lib")
  1958. #else
  1959. #pragma comment (lib, "user32.lib")
  1960. #pragma comment (lib, "dxgi.lib")
  1961. #pragma comment (lib, "d3d11.lib")
  1962. #pragma comment (lib, "dxguid.lib")
  1963. #endif
  1964. #elif defined(SOKOL_METAL)
  1965. #if !__has_feature(objc_arc)
  1966. #error "Please enable ARC when using the Metal backend"
  1967. #endif
  1968. #include <TargetConditionals.h>
  1969. #import <Metal/Metal.h>
  1970. #if defined(TARGET_OS_IPHONE) && !TARGET_OS_IPHONE
  1971. #define _SG_TARGET_MACOS (1)
  1972. #else
  1973. #define _SG_TARGET_IOS (1)
  1974. #if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
  1975. #define _SG_TARGET_IOS_SIMULATOR (1)
  1976. #endif
  1977. #endif
  1978. #endif
  1979. /*=== COMMON BACKEND STUFF ===================================================*/
  1980. /* resource pool slots */
  1981. typedef struct {
  1982. uint32_t id;
  1983. uint32_t ctx_id;
  1984. sg_resource_state state;
  1985. } _sg_slot_t;
  1986. /* constants */
  1987. enum {
  1988. _SG_STRING_SIZE = 16,
  1989. _SG_SLOT_SHIFT = 16,
  1990. _SG_SLOT_MASK = (1<<_SG_SLOT_SHIFT)-1,
  1991. _SG_MAX_POOL_SIZE = (1<<_SG_SLOT_SHIFT),
  1992. _SG_DEFAULT_BUFFER_POOL_SIZE = 128,
  1993. _SG_DEFAULT_IMAGE_POOL_SIZE = 128,
  1994. _SG_DEFAULT_SHADER_POOL_SIZE = 32,
  1995. _SG_DEFAULT_PIPELINE_POOL_SIZE = 64,
  1996. _SG_DEFAULT_PASS_POOL_SIZE = 16,
  1997. _SG_DEFAULT_CONTEXT_POOL_SIZE = 16,
  1998. _SG_MTL_DEFAULT_UB_SIZE = 4 * 1024 * 1024,
  1999. _SG_MTL_DEFAULT_SAMPLER_CACHE_CAPACITY = 64,
  2000. };
  2001. /* fixed-size string */
  2002. typedef struct {
  2003. char buf[_SG_STRING_SIZE];
  2004. } _sg_str_t;
  2005. /* helper macros */
  2006. #define _sg_def(val, def) (((val) == 0) ? (def) : (val))
  2007. #define _sg_def_flt(val, def) (((val) == 0.0f) ? (def) : (val))
  2008. #define _sg_min(a,b) ((a<b)?a:b)
  2009. #define _sg_max(a,b) ((a>b)?a:b)
  2010. #define _sg_clamp(v,v0,v1) ((v<v0)?(v0):((v>v1)?(v1):(v)))
  2011. #define _sg_fequal(val,cmp,delta) (((val-cmp)> -delta)&&((val-cmp)<delta))
  2012. typedef struct {
  2013. int size;
  2014. int append_pos;
  2015. bool append_overflow;
  2016. sg_buffer_type type;
  2017. sg_usage usage;
  2018. uint32_t update_frame_index;
  2019. uint32_t append_frame_index;
  2020. int num_slots;
  2021. int active_slot;
  2022. } _sg_buffer_common_t;
  2023. _SOKOL_PRIVATE void _sg_buffer_common_init(_sg_buffer_common_t* cmn, const sg_buffer_desc* desc) {
  2024. cmn->size = desc->size;
  2025. cmn->append_pos = 0;
  2026. cmn->append_overflow = false;
  2027. cmn->type = desc->type;
  2028. cmn->usage = desc->usage;
  2029. cmn->update_frame_index = 0;
  2030. cmn->append_frame_index = 0;
  2031. cmn->num_slots = (cmn->usage == SG_USAGE_IMMUTABLE) ? 1 : SG_NUM_INFLIGHT_FRAMES;
  2032. cmn->active_slot = 0;
  2033. }
  2034. typedef struct {
  2035. sg_image_type type;
  2036. bool render_target;
  2037. int width;
  2038. int height;
  2039. int depth;
  2040. int num_mipmaps;
  2041. sg_usage usage;
  2042. sg_pixel_format pixel_format;
  2043. int sample_count;
  2044. sg_filter min_filter;
  2045. sg_filter mag_filter;
  2046. sg_wrap wrap_u;
  2047. sg_wrap wrap_v;
  2048. sg_wrap wrap_w;
  2049. sg_border_color border_color;
  2050. uint32_t max_anisotropy;
  2051. uint32_t upd_frame_index;
  2052. int num_slots;
  2053. int active_slot;
  2054. } _sg_image_common_t;
  2055. _SOKOL_PRIVATE void _sg_image_common_init(_sg_image_common_t* cmn, const sg_image_desc* desc) {
  2056. cmn->type = desc->type;
  2057. cmn->render_target = desc->render_target;
  2058. cmn->width = desc->width;
  2059. cmn->height = desc->height;
  2060. cmn->depth = desc->depth;
  2061. cmn->num_mipmaps = desc->num_mipmaps;
  2062. cmn->usage = desc->usage;
  2063. cmn->pixel_format = desc->pixel_format;
  2064. cmn->sample_count = desc->sample_count;
  2065. cmn->min_filter = desc->min_filter;
  2066. cmn->mag_filter = desc->mag_filter;
  2067. cmn->wrap_u = desc->wrap_u;
  2068. cmn->wrap_v = desc->wrap_v;
  2069. cmn->wrap_w = desc->wrap_w;
  2070. cmn->border_color = desc->border_color;
  2071. cmn->max_anisotropy = desc->max_anisotropy;
  2072. cmn->upd_frame_index = 0;
  2073. cmn->num_slots = (cmn->usage == SG_USAGE_IMMUTABLE) ? 1 : SG_NUM_INFLIGHT_FRAMES;
  2074. cmn->active_slot = 0;
  2075. }
  2076. typedef struct {
  2077. int size;
  2078. } _sg_uniform_block_t;
  2079. typedef struct {
  2080. sg_image_type type;
  2081. } _sg_shader_image_t;
  2082. typedef struct {
  2083. int num_uniform_blocks;
  2084. int num_images;
  2085. _sg_uniform_block_t uniform_blocks[SG_MAX_SHADERSTAGE_UBS];
  2086. _sg_shader_image_t images[SG_MAX_SHADERSTAGE_IMAGES];
  2087. } _sg_shader_stage_t;
  2088. typedef struct {
  2089. _sg_shader_stage_t stage[SG_NUM_SHADER_STAGES];
  2090. } _sg_shader_common_t;
  2091. _SOKOL_PRIVATE void _sg_shader_common_init(_sg_shader_common_t* cmn, const sg_shader_desc* desc) {
  2092. for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {
  2093. const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs;
  2094. _sg_shader_stage_t* stage = &cmn->stage[stage_index];
  2095. SOKOL_ASSERT(stage->num_uniform_blocks == 0);
  2096. for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {
  2097. const sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_index];
  2098. if (0 == ub_desc->size) {
  2099. break;
  2100. }
  2101. stage->uniform_blocks[ub_index].size = ub_desc->size;
  2102. stage->num_uniform_blocks++;
  2103. }
  2104. SOKOL_ASSERT(stage->num_images == 0);
  2105. for (int img_index = 0; img_index < SG_MAX_SHADERSTAGE_IMAGES; img_index++) {
  2106. const sg_shader_image_desc* img_desc = &stage_desc->images[img_index];
  2107. if (img_desc->type == _SG_IMAGETYPE_DEFAULT) {
  2108. break;
  2109. }
  2110. stage->images[img_index].type = img_desc->type;
  2111. stage->num_images++;
  2112. }
  2113. }
  2114. }
  2115. typedef struct {
  2116. sg_shader shader_id;
  2117. sg_index_type index_type;
  2118. bool vertex_layout_valid[SG_MAX_SHADERSTAGE_BUFFERS];
  2119. int color_attachment_count;
  2120. sg_pixel_format color_format;
  2121. sg_pixel_format depth_format;
  2122. int sample_count;
  2123. float depth_bias;
  2124. float depth_bias_slope_scale;
  2125. float depth_bias_clamp;
  2126. float blend_color[4];
  2127. } _sg_pipeline_common_t;
  2128. _SOKOL_PRIVATE void _sg_pipeline_common_init(_sg_pipeline_common_t* cmn, const sg_pipeline_desc* desc) {
  2129. cmn->shader_id = desc->shader;
  2130. cmn->index_type = desc->index_type;
  2131. for (int i = 0; i < SG_MAX_SHADERSTAGE_BUFFERS; i++) {
  2132. cmn->vertex_layout_valid[i] = false;
  2133. }
  2134. cmn->color_attachment_count = desc->blend.color_attachment_count;
  2135. cmn->color_format = desc->blend.color_format;
  2136. cmn->depth_format = desc->blend.depth_format;
  2137. cmn->sample_count = desc->rasterizer.sample_count;
  2138. cmn->depth_bias = desc->rasterizer.depth_bias;
  2139. cmn->depth_bias_slope_scale = desc->rasterizer.depth_bias_slope_scale;
  2140. cmn->depth_bias_clamp = desc->rasterizer.depth_bias_clamp;
  2141. for (int i = 0; i < 4; i++) {
  2142. cmn->blend_color[i] = desc->blend.blend_color[i];
  2143. }
  2144. }
  2145. typedef struct {
  2146. sg_image image_id;
  2147. int mip_level;
  2148. int slice;
  2149. } _sg_attachment_common_t;
  2150. typedef struct {
  2151. int num_color_atts;
  2152. _sg_attachment_common_t color_atts[SG_MAX_COLOR_ATTACHMENTS];
  2153. _sg_attachment_common_t ds_att;
  2154. } _sg_pass_common_t;
  2155. _SOKOL_PRIVATE void _sg_pass_common_init(_sg_pass_common_t* cmn, const sg_pass_desc* desc) {
  2156. const sg_attachment_desc* att_desc;
  2157. _sg_attachment_common_t* att;
  2158. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  2159. att_desc = &desc->color_attachments[i];
  2160. if (att_desc->image.id != SG_INVALID_ID) {
  2161. cmn->num_color_atts++;
  2162. att = &cmn->color_atts[i];
  2163. att->image_id = att_desc->image;
  2164. att->mip_level = att_desc->mip_level;
  2165. att->slice = att_desc->slice;
  2166. }
  2167. }
  2168. att_desc = &desc->depth_stencil_attachment;
  2169. if (att_desc->image.id != SG_INVALID_ID) {
  2170. att = &cmn->ds_att;
  2171. att->image_id = att_desc->image;
  2172. att->mip_level = att_desc->mip_level;
  2173. att->slice = att_desc->slice;
  2174. }
  2175. }
  2176. /*=== DUMMY BACKEND DECLARATIONS =============================================*/
  2177. #if defined(SOKOL_DUMMY_BACKEND)
  2178. typedef struct {
  2179. _sg_slot_t slot;
  2180. _sg_buffer_common_t cmn;
  2181. } _sg_dummy_buffer_t;
  2182. typedef _sg_dummy_buffer_t _sg_buffer_t;
  2183. typedef struct {
  2184. _sg_slot_t slot;
  2185. _sg_image_common_t cmn;
  2186. } _sg_dummy_image_t;
  2187. typedef _sg_dummy_image_t _sg_image_t;
  2188. typedef struct {
  2189. _sg_slot_t slot;
  2190. _sg_shader_common_t cmn;
  2191. } _sg_dummy_shader_t;
  2192. typedef _sg_dummy_shader_t _sg_shader_t;
  2193. typedef struct {
  2194. _sg_slot_t slot;
  2195. _sg_shader_t* shader;
  2196. _sg_pipeline_common_t cmn;
  2197. } _sg_dummy_pipeline_t;
  2198. typedef _sg_dummy_pipeline_t _sg_pipeline_t;
  2199. typedef struct {
  2200. _sg_image_t* image;
  2201. } _sg_dummy_attachment_t;
  2202. typedef struct {
  2203. _sg_slot_t slot;
  2204. _sg_pass_common_t cmn;
  2205. struct {
  2206. _sg_dummy_attachment_t color_atts[SG_MAX_COLOR_ATTACHMENTS];
  2207. _sg_dummy_attachment_t ds_att;
  2208. } dmy;
  2209. } _sg_dummy_pass_t;
  2210. typedef _sg_dummy_pass_t _sg_pass_t;
  2211. typedef _sg_attachment_common_t _sg_attachment_t;
  2212. typedef struct {
  2213. _sg_slot_t slot;
  2214. } _sg_dummy_context_t;
  2215. typedef _sg_dummy_context_t _sg_context_t;
  2216. /*== GL BACKEND DECLARATIONS =================================================*/
  2217. #elif defined(_SOKOL_ANY_GL)
  2218. typedef struct {
  2219. _sg_slot_t slot;
  2220. _sg_buffer_common_t cmn;
  2221. struct {
  2222. GLuint buf[SG_NUM_INFLIGHT_FRAMES];
  2223. bool ext_buffers; /* if true, external buffers were injected with sg_buffer_desc.gl_buffers */
  2224. } gl;
  2225. } _sg_gl_buffer_t;
  2226. typedef _sg_gl_buffer_t _sg_buffer_t;
  2227. typedef struct {
  2228. _sg_slot_t slot;
  2229. _sg_image_common_t cmn;
  2230. struct {
  2231. GLenum target;
  2232. GLuint depth_render_buffer;
  2233. GLuint msaa_render_buffer;
  2234. GLuint tex[SG_NUM_INFLIGHT_FRAMES];
  2235. bool ext_textures; /* if true, external textures were injected with sg_image_desc.gl_textures */
  2236. } gl;
  2237. } _sg_gl_image_t;
  2238. typedef _sg_gl_image_t _sg_image_t;
  2239. typedef struct {
  2240. GLint gl_loc;
  2241. sg_uniform_type type;
  2242. uint8_t count;
  2243. uint16_t offset;
  2244. } _sg_gl_uniform_t;
  2245. typedef struct {
  2246. int num_uniforms;
  2247. _sg_gl_uniform_t uniforms[SG_MAX_UB_MEMBERS];
  2248. } _sg_gl_uniform_block_t;
  2249. typedef struct {
  2250. GLint gl_loc;
  2251. int gl_tex_slot;
  2252. } _sg_gl_shader_image_t;
  2253. typedef struct {
  2254. _sg_str_t name;
  2255. } _sg_gl_shader_attr_t;
  2256. typedef struct {
  2257. _sg_gl_uniform_block_t uniform_blocks[SG_MAX_SHADERSTAGE_UBS];
  2258. _sg_gl_shader_image_t images[SG_MAX_SHADERSTAGE_IMAGES];
  2259. } _sg_gl_shader_stage_t;
  2260. typedef struct {
  2261. _sg_slot_t slot;
  2262. _sg_shader_common_t cmn;
  2263. struct {
  2264. GLuint prog;
  2265. _sg_gl_shader_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];
  2266. _sg_gl_shader_stage_t stage[SG_NUM_SHADER_STAGES];
  2267. } gl;
  2268. } _sg_gl_shader_t;
  2269. typedef _sg_gl_shader_t _sg_shader_t;
  2270. typedef struct {
  2271. int8_t vb_index; /* -1 if attr is not enabled */
  2272. int8_t divisor; /* -1 if not initialized */
  2273. uint8_t stride;
  2274. uint8_t size;
  2275. uint8_t normalized;
  2276. int offset;
  2277. GLenum type;
  2278. } _sg_gl_attr_t;
  2279. typedef struct {
  2280. _sg_slot_t slot;
  2281. _sg_pipeline_common_t cmn;
  2282. _sg_shader_t* shader;
  2283. struct {
  2284. _sg_gl_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];
  2285. sg_depth_stencil_state depth_stencil;
  2286. sg_primitive_type primitive_type;
  2287. sg_blend_state blend;
  2288. sg_rasterizer_state rast;
  2289. } gl;
  2290. } _sg_gl_pipeline_t;
  2291. typedef _sg_gl_pipeline_t _sg_pipeline_t;
  2292. typedef struct {
  2293. _sg_image_t* image;
  2294. GLuint gl_msaa_resolve_buffer;
  2295. } _sg_gl_attachment_t;
  2296. typedef struct {
  2297. _sg_slot_t slot;
  2298. _sg_pass_common_t cmn;
  2299. struct {
  2300. GLuint fb;
  2301. _sg_gl_attachment_t color_atts[SG_MAX_COLOR_ATTACHMENTS];
  2302. _sg_gl_attachment_t ds_att;
  2303. } gl;
  2304. } _sg_gl_pass_t;
  2305. typedef _sg_gl_pass_t _sg_pass_t;
  2306. typedef _sg_attachment_common_t _sg_attachment_t;
  2307. typedef struct {
  2308. _sg_slot_t slot;
  2309. #if !defined(SOKOL_GLES2)
  2310. GLuint vao;
  2311. #endif
  2312. GLuint default_framebuffer;
  2313. } _sg_gl_context_t;
  2314. typedef _sg_gl_context_t _sg_context_t;
  2315. typedef struct {
  2316. _sg_gl_attr_t gl_attr;
  2317. GLuint gl_vbuf;
  2318. } _sg_gl_cache_attr_t;
  2319. typedef struct {
  2320. GLenum target;
  2321. GLuint texture;
  2322. } _sg_gl_texture_bind_slot;
  2323. typedef struct {
  2324. sg_depth_stencil_state ds;
  2325. sg_blend_state blend;
  2326. sg_rasterizer_state rast;
  2327. bool polygon_offset_enabled;
  2328. _sg_gl_cache_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];
  2329. GLuint vertex_buffer;
  2330. GLuint index_buffer;
  2331. GLuint stored_vertex_buffer;
  2332. GLuint stored_index_buffer;
  2333. _sg_gl_texture_bind_slot textures[SG_MAX_SHADERSTAGE_IMAGES];
  2334. _sg_gl_texture_bind_slot stored_texture;
  2335. int cur_ib_offset;
  2336. GLenum cur_primitive_type;
  2337. GLenum cur_index_type;
  2338. _sg_pipeline_t* cur_pipeline;
  2339. sg_pipeline cur_pipeline_id;
  2340. } _sg_gl_state_cache_t;
  2341. typedef struct {
  2342. bool valid;
  2343. bool gles2;
  2344. bool in_pass;
  2345. int cur_pass_width;
  2346. int cur_pass_height;
  2347. _sg_context_t* cur_context;
  2348. _sg_pass_t* cur_pass;
  2349. sg_pass cur_pass_id;
  2350. _sg_gl_state_cache_t cache;
  2351. bool ext_anisotropic;
  2352. GLint max_anisotropy;
  2353. GLint max_combined_texture_image_units;
  2354. } _sg_gl_backend_t;
  2355. /*== D3D11 BACKEND DECLARATIONS ==============================================*/
  2356. #elif defined(SOKOL_D3D11)
  2357. typedef struct {
  2358. _sg_slot_t slot;
  2359. _sg_buffer_common_t cmn;
  2360. struct {
  2361. ID3D11Buffer* buf;
  2362. } d3d11;
  2363. } _sg_d3d11_buffer_t;
  2364. typedef _sg_d3d11_buffer_t _sg_buffer_t;
  2365. typedef struct {
  2366. _sg_slot_t slot;
  2367. _sg_image_common_t cmn;
  2368. struct {
  2369. DXGI_FORMAT format;
  2370. ID3D11Texture2D* tex2d;
  2371. ID3D11Texture3D* tex3d;
  2372. ID3D11Texture2D* texds;
  2373. ID3D11Texture2D* texmsaa;
  2374. ID3D11ShaderResourceView* srv;
  2375. ID3D11SamplerState* smp;
  2376. } d3d11;
  2377. } _sg_d3d11_image_t;
  2378. typedef _sg_d3d11_image_t _sg_image_t;
  2379. typedef struct {
  2380. _sg_str_t sem_name;
  2381. int sem_index;
  2382. } _sg_d3d11_shader_attr_t;
  2383. typedef struct {
  2384. ID3D11Buffer* cbufs[SG_MAX_SHADERSTAGE_UBS];
  2385. } _sg_d3d11_shader_stage_t;
  2386. typedef struct {
  2387. _sg_slot_t slot;
  2388. _sg_shader_common_t cmn;
  2389. struct {
  2390. _sg_d3d11_shader_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];
  2391. _sg_d3d11_shader_stage_t stage[SG_NUM_SHADER_STAGES];
  2392. ID3D11VertexShader* vs;
  2393. ID3D11PixelShader* fs;
  2394. void* vs_blob;
  2395. int vs_blob_length;
  2396. } d3d11;
  2397. } _sg_d3d11_shader_t;
  2398. typedef _sg_d3d11_shader_t _sg_shader_t;
  2399. typedef struct {
  2400. _sg_slot_t slot;
  2401. _sg_pipeline_common_t cmn;
  2402. _sg_shader_t* shader;
  2403. struct {
  2404. UINT stencil_ref;
  2405. UINT vb_strides[SG_MAX_SHADERSTAGE_BUFFERS];
  2406. D3D_PRIMITIVE_TOPOLOGY topology;
  2407. DXGI_FORMAT index_format;
  2408. ID3D11InputLayout* il;
  2409. ID3D11RasterizerState* rs;
  2410. ID3D11DepthStencilState* dss;
  2411. ID3D11BlendState* bs;
  2412. } d3d11;
  2413. } _sg_d3d11_pipeline_t;
  2414. typedef _sg_d3d11_pipeline_t _sg_pipeline_t;
  2415. typedef struct {
  2416. _sg_image_t* image;
  2417. ID3D11RenderTargetView* rtv;
  2418. } _sg_d3d11_color_attachment_t;
  2419. typedef struct {
  2420. _sg_image_t* image;
  2421. ID3D11DepthStencilView* dsv;
  2422. } _sg_d3d11_ds_attachment_t;
  2423. typedef struct {
  2424. _sg_slot_t slot;
  2425. _sg_pass_common_t cmn;
  2426. struct {
  2427. _sg_d3d11_color_attachment_t color_atts[SG_MAX_COLOR_ATTACHMENTS];
  2428. _sg_d3d11_ds_attachment_t ds_att;
  2429. } d3d11;
  2430. } _sg_d3d11_pass_t;
  2431. typedef _sg_d3d11_pass_t _sg_pass_t;
  2432. typedef _sg_attachment_common_t _sg_attachment_t;
  2433. typedef struct {
  2434. _sg_slot_t slot;
  2435. } _sg_d3d11_context_t;
  2436. typedef _sg_d3d11_context_t _sg_context_t;
  2437. typedef struct {
  2438. bool valid;
  2439. ID3D11Device* dev;
  2440. ID3D11DeviceContext* ctx;
  2441. const void* (*rtv_cb)(void);
  2442. const void* (*dsv_cb)(void);
  2443. bool in_pass;
  2444. bool use_indexed_draw;
  2445. int cur_width;
  2446. int cur_height;
  2447. int num_rtvs;
  2448. _sg_pass_t* cur_pass;
  2449. sg_pass cur_pass_id;
  2450. _sg_pipeline_t* cur_pipeline;
  2451. sg_pipeline cur_pipeline_id;
  2452. ID3D11RenderTargetView* cur_rtvs[SG_MAX_COLOR_ATTACHMENTS];
  2453. ID3D11DepthStencilView* cur_dsv;
  2454. /* on-demand loaded d3dcompiler_47.dll handles */
  2455. HINSTANCE d3dcompiler_dll;
  2456. bool d3dcompiler_dll_load_failed;
  2457. pD3DCompile D3DCompile_func;
  2458. /* the following arrays are used for unbinding resources, they will always contain zeroes */
  2459. ID3D11RenderTargetView* zero_rtvs[SG_MAX_COLOR_ATTACHMENTS];
  2460. ID3D11Buffer* zero_vbs[SG_MAX_SHADERSTAGE_BUFFERS];
  2461. UINT zero_vb_offsets[SG_MAX_SHADERSTAGE_BUFFERS];
  2462. UINT zero_vb_strides[SG_MAX_SHADERSTAGE_BUFFERS];
  2463. ID3D11Buffer* zero_cbs[SG_MAX_SHADERSTAGE_UBS];
  2464. ID3D11ShaderResourceView* zero_srvs[SG_MAX_SHADERSTAGE_IMAGES];
  2465. ID3D11SamplerState* zero_smps[SG_MAX_SHADERSTAGE_IMAGES];
  2466. /* global subresourcedata array for texture updates */
  2467. D3D11_SUBRESOURCE_DATA subres_data[SG_MAX_MIPMAPS * SG_MAX_TEXTUREARRAY_LAYERS];
  2468. } _sg_d3d11_backend_t;
  2469. /*=== METAL BACKEND DECLARATIONS =============================================*/
  2470. #elif defined(SOKOL_METAL)
  2471. enum {
  2472. #if defined(_SG_TARGET_MACOS) || defined(_SG_TARGET_IOS_SIMULATOR)
  2473. _SG_MTL_UB_ALIGN = 256,
  2474. #else
  2475. _SG_MTL_UB_ALIGN = 16,
  2476. #endif
  2477. _SG_MTL_INVALID_SLOT_INDEX = 0
  2478. };
  2479. /* note that there's a free-standing _sg_mtl_idpool NSMutableArray,
  2480. this can't be part of a C struct before Xcode10.x
  2481. */
  2482. typedef struct {
  2483. uint32_t frame_index; /* frame index at which it is safe to release this resource */
  2484. uint32_t slot_index;
  2485. } _sg_mtl_release_item_t;
  2486. typedef struct {
  2487. uint32_t num_slots;
  2488. uint32_t free_queue_top;
  2489. uint32_t* free_queue;
  2490. uint32_t release_queue_front;
  2491. uint32_t release_queue_back;
  2492. _sg_mtl_release_item_t* release_queue;
  2493. } _sg_mtl_idpool_t;
  2494. /* Metal sampler cache */
  2495. typedef struct {
  2496. sg_filter min_filter;
  2497. sg_filter mag_filter;
  2498. sg_wrap wrap_u;
  2499. sg_wrap wrap_v;
  2500. sg_wrap wrap_w;
  2501. sg_border_color border_color;
  2502. uint32_t max_anisotropy;
  2503. int min_lod; /* orig min/max_lod is float, this is int(min/max_lod*1000.0) */
  2504. int max_lod;
  2505. uint32_t mtl_sampler_state;
  2506. } _sg_mtl_sampler_cache_item_t;
  2507. typedef struct {
  2508. int capacity;
  2509. int num_items;
  2510. _sg_mtl_sampler_cache_item_t* items;
  2511. } _sg_mtl_sampler_cache_t;
  2512. typedef struct {
  2513. _sg_slot_t slot;
  2514. _sg_buffer_common_t cmn;
  2515. struct {
  2516. uint32_t buf[SG_NUM_INFLIGHT_FRAMES]; /* index into _sg_mtl_pool */
  2517. } mtl;
  2518. } _sg_mtl_buffer_t;
  2519. typedef _sg_mtl_buffer_t _sg_buffer_t;
  2520. typedef struct {
  2521. _sg_slot_t slot;
  2522. _sg_image_common_t cmn;
  2523. struct {
  2524. uint32_t tex[SG_NUM_INFLIGHT_FRAMES];
  2525. uint32_t depth_tex;
  2526. uint32_t msaa_tex;
  2527. uint32_t sampler_state;
  2528. } mtl;
  2529. } _sg_mtl_image_t;
  2530. typedef _sg_mtl_image_t _sg_image_t;
  2531. typedef struct {
  2532. uint32_t mtl_lib;
  2533. uint32_t mtl_func;
  2534. } _sg_mtl_shader_stage_t;
  2535. typedef struct {
  2536. _sg_slot_t slot;
  2537. _sg_shader_common_t cmn;
  2538. struct {
  2539. _sg_mtl_shader_stage_t stage[SG_NUM_SHADER_STAGES];
  2540. } mtl;
  2541. } _sg_mtl_shader_t;
  2542. typedef _sg_mtl_shader_t _sg_shader_t;
  2543. typedef struct {
  2544. _sg_slot_t slot;
  2545. _sg_pipeline_common_t cmn;
  2546. _sg_shader_t* shader;
  2547. struct {
  2548. MTLPrimitiveType prim_type;
  2549. NSUInteger index_size;
  2550. MTLIndexType index_type;
  2551. MTLCullMode cull_mode;
  2552. MTLWinding winding;
  2553. uint32_t stencil_ref;
  2554. uint32_t rps;
  2555. uint32_t dss;
  2556. } mtl;
  2557. } _sg_mtl_pipeline_t;
  2558. typedef _sg_mtl_pipeline_t _sg_pipeline_t;
  2559. typedef struct {
  2560. _sg_image_t* image;
  2561. } _sg_mtl_attachment_t;
  2562. typedef struct {
  2563. _sg_slot_t slot;
  2564. _sg_pass_common_t cmn;
  2565. struct {
  2566. _sg_mtl_attachment_t color_atts[SG_MAX_COLOR_ATTACHMENTS];
  2567. _sg_mtl_attachment_t ds_att;
  2568. } mtl;
  2569. } _sg_mtl_pass_t;
  2570. typedef _sg_mtl_pass_t _sg_pass_t;
  2571. typedef _sg_attachment_common_t _sg_attachment_t;
  2572. typedef struct {
  2573. _sg_slot_t slot;
  2574. } _sg_mtl_context_t;
  2575. typedef _sg_mtl_context_t _sg_context_t;
  2576. /* resouce binding state cache */
  2577. typedef struct {
  2578. const _sg_pipeline_t* cur_pipeline;
  2579. sg_pipeline cur_pipeline_id;
  2580. const _sg_buffer_t* cur_indexbuffer;
  2581. int cur_indexbuffer_offset;
  2582. sg_buffer cur_indexbuffer_id;
  2583. const _sg_buffer_t* cur_vertexbuffers[SG_MAX_SHADERSTAGE_BUFFERS];
  2584. int cur_vertexbuffer_offsets[SG_MAX_SHADERSTAGE_BUFFERS];
  2585. sg_buffer cur_vertexbuffer_ids[SG_MAX_SHADERSTAGE_BUFFERS];
  2586. const _sg_image_t* cur_vs_images[SG_MAX_SHADERSTAGE_IMAGES];
  2587. sg_image cur_vs_image_ids[SG_MAX_SHADERSTAGE_IMAGES];
  2588. const _sg_image_t* cur_fs_images[SG_MAX_SHADERSTAGE_IMAGES];
  2589. sg_image cur_fs_image_ids[SG_MAX_SHADERSTAGE_IMAGES];
  2590. } _sg_mtl_state_cache_t;
  2591. typedef struct {
  2592. bool valid;
  2593. const void*(*renderpass_descriptor_cb)(void);
  2594. const void*(*drawable_cb)(void);
  2595. uint32_t frame_index;
  2596. uint32_t cur_frame_rotate_index;
  2597. uint32_t ub_size;
  2598. uint32_t cur_ub_offset;
  2599. uint8_t* cur_ub_base_ptr;
  2600. bool in_pass;
  2601. bool pass_valid;
  2602. int cur_width;
  2603. int cur_height;
  2604. _sg_mtl_state_cache_t state_cache;
  2605. _sg_mtl_sampler_cache_t sampler_cache;
  2606. _sg_mtl_idpool_t idpool;
  2607. } _sg_mtl_backend_t;
  2608. /* keep Objective-C 'smart data' in a separate static objects, these can't be in a C struct until Xcode10 or so */
  2609. static NSMutableArray* _sg_mtl_idpool;
  2610. static id<MTLDevice> _sg_mtl_device;
  2611. static id<MTLCommandQueue> _sg_mtl_cmd_queue;
  2612. static id<MTLCommandBuffer> _sg_mtl_cmd_buffer;
  2613. static id<MTLBuffer> _sg_mtl_uniform_buffers[SG_NUM_INFLIGHT_FRAMES];
  2614. static id<MTLRenderCommandEncoder> _sg_mtl_cmd_encoder;
  2615. static dispatch_semaphore_t _sg_mtl_sem;
  2616. #endif /* SOKOL_METAL */
  2617. /*=== RESOURCE POOL DECLARATIONS =============================================*/
  2618. /* this *MUST* remain 0 */
  2619. #define _SG_INVALID_SLOT_INDEX (0)
  2620. typedef struct {
  2621. int size;
  2622. int queue_top;
  2623. uint32_t* gen_ctrs;
  2624. int* free_queue;
  2625. } _sg_pool_t;
  2626. typedef struct {
  2627. _sg_pool_t buffer_pool;
  2628. _sg_pool_t image_pool;
  2629. _sg_pool_t shader_pool;
  2630. _sg_pool_t pipeline_pool;
  2631. _sg_pool_t pass_pool;
  2632. _sg_pool_t context_pool;
  2633. _sg_buffer_t* buffers;
  2634. _sg_image_t* images;
  2635. _sg_shader_t* shaders;
  2636. _sg_pipeline_t* pipelines;
  2637. _sg_pass_t* passes;
  2638. _sg_context_t* contexts;
  2639. } _sg_pools_t;
  2640. /*=== VALIDATION LAYER DECLARATIONS ==========================================*/
  2641. typedef enum {
  2642. /* special case 'validation was successful' */
  2643. _SG_VALIDATE_SUCCESS,
  2644. /* buffer creation */
  2645. _SG_VALIDATE_BUFFERDESC_CANARY,
  2646. _SG_VALIDATE_BUFFERDESC_SIZE,
  2647. _SG_VALIDATE_BUFFERDESC_CONTENT,
  2648. _SG_VALIDATE_BUFFERDESC_NO_CONTENT,
  2649. /* image creation */
  2650. _SG_VALIDATE_IMAGEDESC_CANARY,
  2651. _SG_VALIDATE_IMAGEDESC_WIDTH,
  2652. _SG_VALIDATE_IMAGEDESC_HEIGHT,
  2653. _SG_VALIDATE_IMAGEDESC_RT_PIXELFORMAT,
  2654. _SG_VALIDATE_IMAGEDESC_NONRT_PIXELFORMAT,
  2655. _SG_VALIDATE_IMAGEDESC_MSAA_BUT_NO_RT,
  2656. _SG_VALIDATE_IMAGEDESC_NO_MSAA_RT_SUPPORT,
  2657. _SG_VALIDATE_IMAGEDESC_RT_IMMUTABLE,
  2658. _SG_VALIDATE_IMAGEDESC_RT_NO_CONTENT,
  2659. _SG_VALIDATE_IMAGEDESC_CONTENT,
  2660. _SG_VALIDATE_IMAGEDESC_NO_CONTENT,
  2661. /* shader creation */
  2662. _SG_VALIDATE_SHADERDESC_CANARY,
  2663. _SG_VALIDATE_SHADERDESC_SOURCE,
  2664. _SG_VALIDATE_SHADERDESC_BYTECODE,
  2665. _SG_VALIDATE_SHADERDESC_SOURCE_OR_BYTECODE,
  2666. _SG_VALIDATE_SHADERDESC_NO_BYTECODE_SIZE,
  2667. _SG_VALIDATE_SHADERDESC_NO_CONT_UBS,
  2668. _SG_VALIDATE_SHADERDESC_NO_CONT_IMGS,
  2669. _SG_VALIDATE_SHADERDESC_NO_CONT_UB_MEMBERS,
  2670. _SG_VALIDATE_SHADERDESC_NO_UB_MEMBERS,
  2671. _SG_VALIDATE_SHADERDESC_UB_MEMBER_NAME,
  2672. _SG_VALIDATE_SHADERDESC_UB_SIZE_MISMATCH,
  2673. _SG_VALIDATE_SHADERDESC_IMG_NAME,
  2674. _SG_VALIDATE_SHADERDESC_ATTR_NAMES,
  2675. _SG_VALIDATE_SHADERDESC_ATTR_SEMANTICS,
  2676. _SG_VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG,
  2677. /* pipeline creation */
  2678. _SG_VALIDATE_PIPELINEDESC_CANARY,
  2679. _SG_VALIDATE_PIPELINEDESC_SHADER,
  2680. _SG_VALIDATE_PIPELINEDESC_NO_ATTRS,
  2681. _SG_VALIDATE_PIPELINEDESC_LAYOUT_STRIDE4,
  2682. _SG_VALIDATE_PIPELINEDESC_ATTR_NAME,
  2683. _SG_VALIDATE_PIPELINEDESC_ATTR_SEMANTICS,
  2684. /* pass creation */
  2685. _SG_VALIDATE_PASSDESC_CANARY,
  2686. _SG_VALIDATE_PASSDESC_NO_COLOR_ATTS,
  2687. _SG_VALIDATE_PASSDESC_NO_CONT_COLOR_ATTS,
  2688. _SG_VALIDATE_PASSDESC_IMAGE,
  2689. _SG_VALIDATE_PASSDESC_MIPLEVEL,
  2690. _SG_VALIDATE_PASSDESC_FACE,
  2691. _SG_VALIDATE_PASSDESC_LAYER,
  2692. _SG_VALIDATE_PASSDESC_SLICE,
  2693. _SG_VALIDATE_PASSDESC_IMAGE_NO_RT,
  2694. _SG_VALIDATE_PASSDESC_COLOR_PIXELFORMATS,
  2695. _SG_VALIDATE_PASSDESC_COLOR_INV_PIXELFORMAT,
  2696. _SG_VALIDATE_PASSDESC_DEPTH_INV_PIXELFORMAT,
  2697. _SG_VALIDATE_PASSDESC_IMAGE_SIZES,
  2698. _SG_VALIDATE_PASSDESC_IMAGE_SAMPLE_COUNTS,
  2699. /* sg_begin_pass validation */
  2700. _SG_VALIDATE_BEGINPASS_PASS,
  2701. _SG_VALIDATE_BEGINPASS_IMAGE,
  2702. /* sg_apply_pipeline validation */
  2703. _SG_VALIDATE_APIP_PIPELINE_VALID_ID,
  2704. _SG_VALIDATE_APIP_PIPELINE_EXISTS,
  2705. _SG_VALIDATE_APIP_PIPELINE_VALID,
  2706. _SG_VALIDATE_APIP_SHADER_EXISTS,
  2707. _SG_VALIDATE_APIP_SHADER_VALID,
  2708. _SG_VALIDATE_APIP_ATT_COUNT,
  2709. _SG_VALIDATE_APIP_COLOR_FORMAT,
  2710. _SG_VALIDATE_APIP_DEPTH_FORMAT,
  2711. _SG_VALIDATE_APIP_SAMPLE_COUNT,
  2712. /* sg_apply_bindings validation */
  2713. _SG_VALIDATE_ABND_PIPELINE,
  2714. _SG_VALIDATE_ABND_PIPELINE_EXISTS,
  2715. _SG_VALIDATE_ABND_PIPELINE_VALID,
  2716. _SG_VALIDATE_ABND_VBS,
  2717. _SG_VALIDATE_ABND_VB_EXISTS,
  2718. _SG_VALIDATE_ABND_VB_TYPE,
  2719. _SG_VALIDATE_ABND_VB_OVERFLOW,
  2720. _SG_VALIDATE_ABND_NO_IB,
  2721. _SG_VALIDATE_ABND_IB,
  2722. _SG_VALIDATE_ABND_IB_EXISTS,
  2723. _SG_VALIDATE_ABND_IB_TYPE,
  2724. _SG_VALIDATE_ABND_IB_OVERFLOW,
  2725. _SG_VALIDATE_ABND_VS_IMGS,
  2726. _SG_VALIDATE_ABND_VS_IMG_EXISTS,
  2727. _SG_VALIDATE_ABND_VS_IMG_TYPES,
  2728. _SG_VALIDATE_ABND_FS_IMGS,
  2729. _SG_VALIDATE_ABND_FS_IMG_EXISTS,
  2730. _SG_VALIDATE_ABND_FS_IMG_TYPES,
  2731. /* sg_apply_uniforms validation */
  2732. _SG_VALIDATE_AUB_NO_PIPELINE,
  2733. _SG_VALIDATE_AUB_NO_UB_AT_SLOT,
  2734. _SG_VALIDATE_AUB_SIZE,
  2735. /* sg_update_buffer validation */
  2736. _SG_VALIDATE_UPDATEBUF_USAGE,
  2737. _SG_VALIDATE_UPDATEBUF_SIZE,
  2738. _SG_VALIDATE_UPDATEBUF_ONCE,
  2739. _SG_VALIDATE_UPDATEBUF_APPEND,
  2740. /* sg_append_buffer validation */
  2741. _SG_VALIDATE_APPENDBUF_USAGE,
  2742. _SG_VALIDATE_APPENDBUF_SIZE,
  2743. _SG_VALIDATE_APPENDBUF_UPDATE,
  2744. /* sg_update_image validation */
  2745. _SG_VALIDATE_UPDIMG_USAGE,
  2746. _SG_VALIDATE_UPDIMG_NOTENOUGHDATA,
  2747. _SG_VALIDATE_UPDIMG_SIZE,
  2748. _SG_VALIDATE_UPDIMG_COMPRESSED,
  2749. _SG_VALIDATE_UPDIMG_ONCE
  2750. } _sg_validate_error_t;
  2751. /*=== GENERIC BACKEND STATE ==================================================*/
  2752. typedef struct {
  2753. bool valid;
  2754. sg_desc desc; /* original desc with default values patched in */
  2755. uint32_t frame_index;
  2756. sg_context active_context;
  2757. sg_pass cur_pass;
  2758. sg_pipeline cur_pipeline;
  2759. bool pass_valid;
  2760. bool bindings_valid;
  2761. bool next_draw_valid;
  2762. #if defined(SOKOL_DEBUG)
  2763. _sg_validate_error_t validate_error;
  2764. #endif
  2765. _sg_pools_t pools;
  2766. sg_backend backend;
  2767. sg_features features;
  2768. sg_limits limits;
  2769. sg_pixelformat_info formats[_SG_PIXELFORMAT_NUM];
  2770. #if defined(_SOKOL_ANY_GL)
  2771. _sg_gl_backend_t gl;
  2772. #elif defined(SOKOL_METAL)
  2773. _sg_mtl_backend_t mtl;
  2774. #elif defined(SOKOL_D3D11)
  2775. _sg_d3d11_backend_t d3d11;
  2776. #endif
  2777. #if defined(SOKOL_TRACE_HOOKS)
  2778. sg_trace_hooks hooks;
  2779. #endif
  2780. } _sg_state_t;
  2781. static _sg_state_t _sg;
  2782. /*-- helper functions --------------------------------------------------------*/
  2783. _SOKOL_PRIVATE bool _sg_strempty(const _sg_str_t* str) {
  2784. return 0 == str->buf[0];
  2785. }
  2786. _SOKOL_PRIVATE const char* _sg_strptr(const _sg_str_t* str) {
  2787. return &str->buf[0];
  2788. }
  2789. _SOKOL_PRIVATE void _sg_strcpy(_sg_str_t* dst, const char* src) {
  2790. SOKOL_ASSERT(dst);
  2791. if (src) {
  2792. #if defined(_MSC_VER)
  2793. strncpy_s(dst->buf, _SG_STRING_SIZE, src, (_SG_STRING_SIZE-1));
  2794. #else
  2795. strncpy(dst->buf, src, _SG_STRING_SIZE);
  2796. #endif
  2797. dst->buf[_SG_STRING_SIZE-1] = 0;
  2798. }
  2799. else {
  2800. memset(dst->buf, 0, _SG_STRING_SIZE);
  2801. }
  2802. }
  2803. /* return byte size of a vertex format */
  2804. _SOKOL_PRIVATE int _sg_vertexformat_bytesize(sg_vertex_format fmt) {
  2805. switch (fmt) {
  2806. case SG_VERTEXFORMAT_FLOAT: return 4;
  2807. case SG_VERTEXFORMAT_FLOAT2: return 8;
  2808. case SG_VERTEXFORMAT_FLOAT3: return 12;
  2809. case SG_VERTEXFORMAT_FLOAT4: return 16;
  2810. case SG_VERTEXFORMAT_BYTE4: return 4;
  2811. case SG_VERTEXFORMAT_BYTE4N: return 4;
  2812. case SG_VERTEXFORMAT_UBYTE4: return 4;
  2813. case SG_VERTEXFORMAT_UBYTE4N: return 4;
  2814. case SG_VERTEXFORMAT_SHORT2: return 4;
  2815. case SG_VERTEXFORMAT_SHORT2N: return 4;
  2816. case SG_VERTEXFORMAT_USHORT2N: return 4;
  2817. case SG_VERTEXFORMAT_SHORT4: return 8;
  2818. case SG_VERTEXFORMAT_SHORT4N: return 8;
  2819. case SG_VERTEXFORMAT_USHORT4N: return 8;
  2820. case SG_VERTEXFORMAT_UINT10_N2: return 4;
  2821. case SG_VERTEXFORMAT_INVALID: return 0;
  2822. default:
  2823. SOKOL_UNREACHABLE;
  2824. return -1;
  2825. }
  2826. }
  2827. /* return the byte size of a shader uniform */
  2828. _SOKOL_PRIVATE int _sg_uniform_size(sg_uniform_type type, int count) {
  2829. switch (type) {
  2830. case SG_UNIFORMTYPE_INVALID: return 0;
  2831. case SG_UNIFORMTYPE_FLOAT: return 4 * count;
  2832. case SG_UNIFORMTYPE_FLOAT2: return 8 * count;
  2833. case SG_UNIFORMTYPE_FLOAT3: return 12 * count; /* FIXME: std140??? */
  2834. case SG_UNIFORMTYPE_FLOAT4: return 16 * count;
  2835. case SG_UNIFORMTYPE_MAT4: return 64 * count;
  2836. default:
  2837. SOKOL_UNREACHABLE;
  2838. return -1;
  2839. }
  2840. }
  2841. /* the default color pixelformat for render targets */
  2842. _SOKOL_PRIVATE sg_pixel_format _sg_default_rendertarget_colorformat(void) {
  2843. #if defined(SOKOL_METAL) || defined(SOKOL_D3D11)
  2844. return SG_PIXELFORMAT_BGRA8;
  2845. #else
  2846. return SG_PIXELFORMAT_RGBA8;
  2847. #endif
  2848. }
  2849. _SOKOL_PRIVATE sg_pixel_format _sg_default_rendertarget_depthformat(void) {
  2850. return SG_PIXELFORMAT_DEPTH_STENCIL;
  2851. }
  2852. /* return true if pixel format is a compressed format */
  2853. _SOKOL_PRIVATE bool _sg_is_compressed_pixel_format(sg_pixel_format fmt) {
  2854. switch (fmt) {
  2855. case SG_PIXELFORMAT_BC1_RGBA:
  2856. case SG_PIXELFORMAT_BC2_RGBA:
  2857. case SG_PIXELFORMAT_BC3_RGBA:
  2858. case SG_PIXELFORMAT_BC4_R:
  2859. case SG_PIXELFORMAT_BC4_RSN:
  2860. case SG_PIXELFORMAT_BC5_RG:
  2861. case SG_PIXELFORMAT_BC5_RGSN:
  2862. case SG_PIXELFORMAT_BC6H_RGBF:
  2863. case SG_PIXELFORMAT_BC6H_RGBUF:
  2864. case SG_PIXELFORMAT_BC7_RGBA:
  2865. case SG_PIXELFORMAT_PVRTC_RGB_2BPP:
  2866. case SG_PIXELFORMAT_PVRTC_RGB_4BPP:
  2867. case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:
  2868. case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:
  2869. case SG_PIXELFORMAT_ETC2_RGB8:
  2870. case SG_PIXELFORMAT_ETC2_RGB8A1:
  2871. case SG_PIXELFORMAT_ETC2_RGBA8:
  2872. case SG_PIXELFORMAT_ETC2_RG11:
  2873. case SG_PIXELFORMAT_ETC2_RG11SN:
  2874. return true;
  2875. default:
  2876. return false;
  2877. }
  2878. }
  2879. /* return true if pixel format is a valid render target format */
  2880. _SOKOL_PRIVATE bool _sg_is_valid_rendertarget_color_format(sg_pixel_format fmt) {
  2881. const int fmt_index = (int) fmt;
  2882. SOKOL_ASSERT((fmt_index >= 0) && (fmt_index < _SG_PIXELFORMAT_NUM));
  2883. return _sg.formats[fmt_index].render && !_sg.formats[fmt_index].depth;
  2884. }
  2885. /* return true if pixel format is a valid depth format */
  2886. _SOKOL_PRIVATE bool _sg_is_valid_rendertarget_depth_format(sg_pixel_format fmt) {
  2887. const int fmt_index = (int) fmt;
  2888. SOKOL_ASSERT((fmt_index >= 0) && (fmt_index < _SG_PIXELFORMAT_NUM));
  2889. return _sg.formats[fmt_index].render && _sg.formats[fmt_index].depth;
  2890. }
  2891. /* return true if pixel format is a depth-stencil format */
  2892. _SOKOL_PRIVATE bool _sg_is_depth_stencil_format(sg_pixel_format fmt) {
  2893. return (SG_PIXELFORMAT_DEPTH_STENCIL == fmt);
  2894. }
  2895. /* return the bytes-per-pixel for a pixel format */
  2896. _SOKOL_PRIVATE int _sg_pixelformat_bytesize(sg_pixel_format fmt) {
  2897. switch (fmt) {
  2898. case SG_PIXELFORMAT_R8:
  2899. case SG_PIXELFORMAT_R8SN:
  2900. case SG_PIXELFORMAT_R8UI:
  2901. case SG_PIXELFORMAT_R8SI:
  2902. return 1;
  2903. case SG_PIXELFORMAT_R16:
  2904. case SG_PIXELFORMAT_R16SN:
  2905. case SG_PIXELFORMAT_R16UI:
  2906. case SG_PIXELFORMAT_R16SI:
  2907. case SG_PIXELFORMAT_R16F:
  2908. case SG_PIXELFORMAT_RG8:
  2909. case SG_PIXELFORMAT_RG8SN:
  2910. case SG_PIXELFORMAT_RG8UI:
  2911. case SG_PIXELFORMAT_RG8SI:
  2912. return 2;
  2913. case SG_PIXELFORMAT_R32UI:
  2914. case SG_PIXELFORMAT_R32SI:
  2915. case SG_PIXELFORMAT_R32F:
  2916. case SG_PIXELFORMAT_RG16:
  2917. case SG_PIXELFORMAT_RG16SN:
  2918. case SG_PIXELFORMAT_RG16UI:
  2919. case SG_PIXELFORMAT_RG16SI:
  2920. case SG_PIXELFORMAT_RG16F:
  2921. case SG_PIXELFORMAT_RGBA8:
  2922. case SG_PIXELFORMAT_RGBA8SN:
  2923. case SG_PIXELFORMAT_RGBA8UI:
  2924. case SG_PIXELFORMAT_RGBA8SI:
  2925. case SG_PIXELFORMAT_BGRA8:
  2926. case SG_PIXELFORMAT_RGB10A2:
  2927. case SG_PIXELFORMAT_RG11B10F:
  2928. return 4;
  2929. case SG_PIXELFORMAT_RG32UI:
  2930. case SG_PIXELFORMAT_RG32SI:
  2931. case SG_PIXELFORMAT_RG32F:
  2932. case SG_PIXELFORMAT_RGBA16:
  2933. case SG_PIXELFORMAT_RGBA16SN:
  2934. case SG_PIXELFORMAT_RGBA16UI:
  2935. case SG_PIXELFORMAT_RGBA16SI:
  2936. case SG_PIXELFORMAT_RGBA16F:
  2937. return 8;
  2938. case SG_PIXELFORMAT_RGBA32UI:
  2939. case SG_PIXELFORMAT_RGBA32SI:
  2940. case SG_PIXELFORMAT_RGBA32F:
  2941. return 16;
  2942. default:
  2943. SOKOL_UNREACHABLE;
  2944. return 0;
  2945. }
  2946. }
  2947. /* return row pitch for an image
  2948. see ComputePitch in https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexUtil.cpp
  2949. */
  2950. _SOKOL_PRIVATE int _sg_row_pitch(sg_pixel_format fmt, int width) {
  2951. int pitch;
  2952. switch (fmt) {
  2953. case SG_PIXELFORMAT_BC1_RGBA:
  2954. case SG_PIXELFORMAT_BC4_R:
  2955. case SG_PIXELFORMAT_BC4_RSN:
  2956. case SG_PIXELFORMAT_ETC2_RGB8:
  2957. case SG_PIXELFORMAT_ETC2_RGB8A1:
  2958. pitch = ((width + 3) / 4) * 8;
  2959. pitch = pitch < 8 ? 8 : pitch;
  2960. break;
  2961. case SG_PIXELFORMAT_BC2_RGBA:
  2962. case SG_PIXELFORMAT_BC3_RGBA:
  2963. case SG_PIXELFORMAT_BC5_RG:
  2964. case SG_PIXELFORMAT_BC5_RGSN:
  2965. case SG_PIXELFORMAT_BC6H_RGBF:
  2966. case SG_PIXELFORMAT_BC6H_RGBUF:
  2967. case SG_PIXELFORMAT_BC7_RGBA:
  2968. case SG_PIXELFORMAT_ETC2_RGBA8:
  2969. case SG_PIXELFORMAT_ETC2_RG11:
  2970. case SG_PIXELFORMAT_ETC2_RG11SN:
  2971. pitch = ((width + 3) / 4) * 16;
  2972. pitch = pitch < 16 ? 16 : pitch;
  2973. break;
  2974. case SG_PIXELFORMAT_PVRTC_RGB_4BPP:
  2975. case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:
  2976. {
  2977. const int block_size = 4*4;
  2978. const int bpp = 4;
  2979. int width_blocks = width / 4;
  2980. width_blocks = width_blocks < 2 ? 2 : width_blocks;
  2981. pitch = width_blocks * ((block_size * bpp) / 8);
  2982. }
  2983. break;
  2984. case SG_PIXELFORMAT_PVRTC_RGB_2BPP:
  2985. case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:
  2986. {
  2987. const int block_size = 8*4;
  2988. const int bpp = 2;
  2989. int width_blocks = width / 4;
  2990. width_blocks = width_blocks < 2 ? 2 : width_blocks;
  2991. pitch = width_blocks * ((block_size * bpp) / 8);
  2992. }
  2993. break;
  2994. default:
  2995. pitch = width * _sg_pixelformat_bytesize(fmt);
  2996. break;
  2997. }
  2998. return pitch;
  2999. }
  3000. /* return pitch of a 2D subimage / texture slice
  3001. see ComputePitch in https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexUtil.cpp
  3002. */
  3003. _SOKOL_PRIVATE int _sg_surface_pitch(sg_pixel_format fmt, int width, int height) {
  3004. int num_rows = 0;
  3005. switch (fmt) {
  3006. case SG_PIXELFORMAT_BC1_RGBA:
  3007. case SG_PIXELFORMAT_BC4_R:
  3008. case SG_PIXELFORMAT_BC4_RSN:
  3009. case SG_PIXELFORMAT_ETC2_RGB8:
  3010. case SG_PIXELFORMAT_ETC2_RGB8A1:
  3011. case SG_PIXELFORMAT_ETC2_RGBA8:
  3012. case SG_PIXELFORMAT_ETC2_RG11:
  3013. case SG_PIXELFORMAT_ETC2_RG11SN:
  3014. case SG_PIXELFORMAT_BC2_RGBA:
  3015. case SG_PIXELFORMAT_BC3_RGBA:
  3016. case SG_PIXELFORMAT_BC5_RG:
  3017. case SG_PIXELFORMAT_BC5_RGSN:
  3018. case SG_PIXELFORMAT_BC6H_RGBF:
  3019. case SG_PIXELFORMAT_BC6H_RGBUF:
  3020. case SG_PIXELFORMAT_BC7_RGBA:
  3021. case SG_PIXELFORMAT_PVRTC_RGB_4BPP:
  3022. case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:
  3023. case SG_PIXELFORMAT_PVRTC_RGB_2BPP:
  3024. case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:
  3025. num_rows = ((height + 3) / 4);
  3026. break;
  3027. default:
  3028. num_rows = height;
  3029. break;
  3030. }
  3031. if (num_rows < 1) {
  3032. num_rows = 1;
  3033. }
  3034. return num_rows * _sg_row_pitch(fmt, width);
  3035. }
  3036. /* capability table pixel format helper functions */
  3037. _SOKOL_PRIVATE void _sg_pixelformat_all(sg_pixelformat_info* pfi) {
  3038. pfi->sample = true;
  3039. pfi->filter = true;
  3040. pfi->blend = true;
  3041. pfi->render = true;
  3042. pfi->msaa = true;
  3043. }
  3044. _SOKOL_PRIVATE void _sg_pixelformat_s(sg_pixelformat_info* pfi) {
  3045. pfi->sample = true;
  3046. }
  3047. _SOKOL_PRIVATE void _sg_pixelformat_sf(sg_pixelformat_info* pfi) {
  3048. pfi->sample = true;
  3049. pfi->filter = true;
  3050. }
  3051. _SOKOL_PRIVATE void _sg_pixelformat_sr(sg_pixelformat_info* pfi) {
  3052. pfi->sample = true;
  3053. pfi->render = true;
  3054. }
  3055. _SOKOL_PRIVATE void _sg_pixelformat_srmd(sg_pixelformat_info* pfi) {
  3056. pfi->sample = true;
  3057. pfi->render = true;
  3058. pfi->msaa = true;
  3059. pfi->depth = true;
  3060. }
  3061. _SOKOL_PRIVATE void _sg_pixelformat_srm(sg_pixelformat_info* pfi) {
  3062. pfi->sample = true;
  3063. pfi->render = true;
  3064. pfi->msaa = true;
  3065. }
  3066. _SOKOL_PRIVATE void _sg_pixelformat_sfrm(sg_pixelformat_info* pfi) {
  3067. pfi->sample = true;
  3068. pfi->filter = true;
  3069. pfi->render = true;
  3070. pfi->msaa = true;
  3071. }
  3072. _SOKOL_PRIVATE void _sg_pixelformat_sbrm(sg_pixelformat_info* pfi) {
  3073. pfi->sample = true;
  3074. pfi->blend = true;
  3075. pfi->render = true;
  3076. pfi->msaa = true;
  3077. }
  3078. _SOKOL_PRIVATE void _sg_pixelformat_sbr(sg_pixelformat_info* pfi) {
  3079. pfi->sample = true;
  3080. pfi->blend = true;
  3081. pfi->render = true;
  3082. }
  3083. _SOKOL_PRIVATE void _sg_pixelformat_sfbr(sg_pixelformat_info* pfi) {
  3084. pfi->sample = true;
  3085. pfi->filter = true;
  3086. pfi->blend = true;
  3087. pfi->render = true;
  3088. }
  3089. /* resolve pass action defaults into a new pass action struct */
  3090. _SOKOL_PRIVATE void _sg_resolve_default_pass_action(const sg_pass_action* from, sg_pass_action* to) {
  3091. SOKOL_ASSERT(from && to);
  3092. *to = *from;
  3093. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  3094. if (to->colors[i].action == _SG_ACTION_DEFAULT) {
  3095. to->colors[i].action = SG_ACTION_CLEAR;
  3096. to->colors[i].val[0] = SG_DEFAULT_CLEAR_RED;
  3097. to->colors[i].val[1] = SG_DEFAULT_CLEAR_GREEN;
  3098. to->colors[i].val[2] = SG_DEFAULT_CLEAR_BLUE;
  3099. to->colors[i].val[3] = SG_DEFAULT_CLEAR_ALPHA;
  3100. }
  3101. }
  3102. if (to->depth.action == _SG_ACTION_DEFAULT) {
  3103. to->depth.action = SG_ACTION_CLEAR;
  3104. to->depth.val = SG_DEFAULT_CLEAR_DEPTH;
  3105. }
  3106. if (to->stencil.action == _SG_ACTION_DEFAULT) {
  3107. to->stencil.action = SG_ACTION_CLEAR;
  3108. to->stencil.val = SG_DEFAULT_CLEAR_STENCIL;
  3109. }
  3110. }
  3111. /*== DUMMY BACKEND IMPL ======================================================*/
  3112. #if defined(SOKOL_DUMMY_BACKEND)
  3113. _SOKOL_PRIVATE void _sg_dummy_setup_backend(const sg_desc* desc) {
  3114. SOKOL_ASSERT(desc);
  3115. _SOKOL_UNUSED(desc);
  3116. _sg.backend = SG_BACKEND_DUMMY;
  3117. for (int i = SG_PIXELFORMAT_R8; i < SG_PIXELFORMAT_BC1_RGBA; i++) {
  3118. _sg.formats[i].sample = true;
  3119. _sg.formats[i].filter = true;
  3120. _sg.formats[i].render = true;
  3121. _sg.formats[i].blend = true;
  3122. _sg.formats[i].msaa = true;
  3123. }
  3124. _sg.formats[SG_PIXELFORMAT_DEPTH].depth = true;
  3125. _sg.formats[SG_PIXELFORMAT_DEPTH_STENCIL].depth = true;
  3126. }
  3127. _SOKOL_PRIVATE void _sg_dummy_discard_backend(void) {
  3128. /* empty */
  3129. }
  3130. _SOKOL_PRIVATE void _sg_dummy_reset_state_cache(void) {
  3131. /* empty*/
  3132. }
  3133. _SOKOL_PRIVATE sg_resource_state _sg_dummy_create_context(_sg_context_t* ctx) {
  3134. SOKOL_ASSERT(ctx);
  3135. _SOKOL_UNUSED(ctx);
  3136. return SG_RESOURCESTATE_VALID;
  3137. }
  3138. _SOKOL_PRIVATE void _sg_dummy_destroy_context(_sg_context_t* ctx) {
  3139. SOKOL_ASSERT(ctx);
  3140. _SOKOL_UNUSED(ctx);
  3141. }
  3142. _SOKOL_PRIVATE void _sg_dummy_activate_context(_sg_context_t* ctx) {
  3143. SOKOL_ASSERT(ctx);
  3144. _SOKOL_UNUSED(ctx);
  3145. }
  3146. _SOKOL_PRIVATE sg_resource_state _sg_dummy_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {
  3147. SOKOL_ASSERT(buf && desc);
  3148. _sg_buffer_common_init(&buf->cmn, desc);
  3149. return SG_RESOURCESTATE_VALID;
  3150. }
  3151. _SOKOL_PRIVATE void _sg_dummy_destroy_buffer(_sg_buffer_t* buf) {
  3152. SOKOL_ASSERT(buf);
  3153. _SOKOL_UNUSED(buf);
  3154. }
  3155. _SOKOL_PRIVATE sg_resource_state _sg_dummy_create_image(_sg_image_t* img, const sg_image_desc* desc) {
  3156. SOKOL_ASSERT(img && desc);
  3157. _sg_image_common_init(&img->cmn, desc);
  3158. return SG_RESOURCESTATE_VALID;
  3159. }
  3160. _SOKOL_PRIVATE void _sg_dummy_destroy_image(_sg_image_t* img) {
  3161. SOKOL_ASSERT(img);
  3162. _SOKOL_UNUSED(img);
  3163. }
  3164. _SOKOL_PRIVATE sg_resource_state _sg_dummy_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {
  3165. SOKOL_ASSERT(shd && desc);
  3166. _sg_shader_common_init(&shd->cmn, desc);
  3167. return SG_RESOURCESTATE_VALID;
  3168. }
  3169. _SOKOL_PRIVATE void _sg_dummy_destroy_shader(_sg_shader_t* shd) {
  3170. SOKOL_ASSERT(shd);
  3171. _SOKOL_UNUSED(shd);
  3172. }
  3173. _SOKOL_PRIVATE sg_resource_state _sg_dummy_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {
  3174. SOKOL_ASSERT(pip && desc);
  3175. pip->shader = shd;
  3176. _sg_pipeline_common_init(&pip->cmn, desc);
  3177. for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
  3178. const sg_vertex_attr_desc* a_desc = &desc->layout.attrs[attr_index];
  3179. if (a_desc->format == SG_VERTEXFORMAT_INVALID) {
  3180. break;
  3181. }
  3182. SOKOL_ASSERT((a_desc->buffer_index >= 0) && (a_desc->buffer_index < SG_MAX_SHADERSTAGE_BUFFERS));
  3183. pip->cmn.vertex_layout_valid[a_desc->buffer_index] = true;
  3184. }
  3185. return SG_RESOURCESTATE_VALID;
  3186. }
  3187. _SOKOL_PRIVATE void _sg_dummy_destroy_pipeline(_sg_pipeline_t* pip) {
  3188. SOKOL_ASSERT(pip);
  3189. _SOKOL_UNUSED(pip);
  3190. }
  3191. _SOKOL_PRIVATE sg_resource_state _sg_dummy_create_pass(_sg_pass_t* pass, _sg_image_t** att_images, const sg_pass_desc* desc) {
  3192. SOKOL_ASSERT(pass && desc);
  3193. SOKOL_ASSERT(att_images && att_images[0]);
  3194. _sg_pass_common_init(&pass->cmn, desc);
  3195. const sg_attachment_desc* att_desc;
  3196. for (int i = 0; i < pass->cmn.num_color_atts; i++) {
  3197. att_desc = &desc->color_attachments[i];
  3198. SOKOL_ASSERT(att_desc->image.id != SG_INVALID_ID);
  3199. SOKOL_ASSERT(0 == pass->dmy.color_atts[i].image);
  3200. SOKOL_ASSERT(att_images[i] && (att_images[i]->slot.id == att_desc->image.id));
  3201. SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(att_images[i]->cmn.pixel_format));
  3202. pass->dmy.color_atts[i].image = att_images[i];
  3203. }
  3204. SOKOL_ASSERT(0 == pass->dmy.ds_att.image);
  3205. att_desc = &desc->depth_stencil_attachment;
  3206. if (att_desc->image.id != SG_INVALID_ID) {
  3207. const int ds_img_index = SG_MAX_COLOR_ATTACHMENTS;
  3208. SOKOL_ASSERT(att_images[ds_img_index] && (att_images[ds_img_index]->slot.id == att_desc->image.id));
  3209. SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(att_images[ds_img_index]->cmn.pixel_format));
  3210. pass->dmy.ds_att.image = att_images[ds_img_index];
  3211. }
  3212. return SG_RESOURCESTATE_VALID;
  3213. }
  3214. _SOKOL_PRIVATE void _sg_dummy_destroy_pass(_sg_pass_t* pass) {
  3215. SOKOL_ASSERT(pass);
  3216. _SOKOL_UNUSED(pass);
  3217. }
  3218. _SOKOL_PRIVATE _sg_image_t* _sg_dummy_pass_color_image(const _sg_pass_t* pass, int index) {
  3219. SOKOL_ASSERT(pass && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));
  3220. /* NOTE: may return null */
  3221. return pass->dmy.color_atts[index].image;
  3222. }
  3223. _SOKOL_PRIVATE _sg_image_t* _sg_dummy_pass_ds_image(const _sg_pass_t* pass) {
  3224. /* NOTE: may return null */
  3225. SOKOL_ASSERT(pass);
  3226. return pass->dmy.ds_att.image;
  3227. }
  3228. _SOKOL_PRIVATE void _sg_dummy_begin_pass(_sg_pass_t* pass, const sg_pass_action* action, int w, int h) {
  3229. SOKOL_ASSERT(action);
  3230. _SOKOL_UNUSED(pass);
  3231. _SOKOL_UNUSED(action);
  3232. _SOKOL_UNUSED(w);
  3233. _SOKOL_UNUSED(h);
  3234. }
  3235. _SOKOL_PRIVATE void _sg_dummy_end_pass(void) {
  3236. /* empty */
  3237. }
  3238. _SOKOL_PRIVATE void _sg_dummy_commit(void) {
  3239. /* empty */
  3240. }
  3241. _SOKOL_PRIVATE void _sg_dummy_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {
  3242. _SOKOL_UNUSED(x);
  3243. _SOKOL_UNUSED(y);
  3244. _SOKOL_UNUSED(w);
  3245. _SOKOL_UNUSED(h);
  3246. _SOKOL_UNUSED(origin_top_left);
  3247. }
  3248. _SOKOL_PRIVATE void _sg_dummy_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {
  3249. _SOKOL_UNUSED(x);
  3250. _SOKOL_UNUSED(y);
  3251. _SOKOL_UNUSED(w);
  3252. _SOKOL_UNUSED(h);
  3253. _SOKOL_UNUSED(origin_top_left);
  3254. }
  3255. _SOKOL_PRIVATE void _sg_dummy_apply_pipeline(_sg_pipeline_t* pip) {
  3256. SOKOL_ASSERT(pip);
  3257. _SOKOL_UNUSED(pip);
  3258. }
  3259. _SOKOL_PRIVATE void _sg_dummy_apply_bindings(
  3260. _sg_pipeline_t* pip,
  3261. _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs,
  3262. _sg_buffer_t* ib, int ib_offset,
  3263. _sg_image_t** vs_imgs, int num_vs_imgs,
  3264. _sg_image_t** fs_imgs, int num_fs_imgs)
  3265. {
  3266. SOKOL_ASSERT(pip);
  3267. SOKOL_ASSERT(vbs && vb_offsets);
  3268. SOKOL_ASSERT(vs_imgs);
  3269. SOKOL_ASSERT(fs_imgs);
  3270. _SOKOL_UNUSED(pip);
  3271. _SOKOL_UNUSED(vbs); _SOKOL_UNUSED(vb_offsets); _SOKOL_UNUSED(num_vbs);
  3272. _SOKOL_UNUSED(ib); _SOKOL_UNUSED(ib_offset);
  3273. _SOKOL_UNUSED(vs_imgs); _SOKOL_UNUSED(num_vs_imgs);
  3274. _SOKOL_UNUSED(fs_imgs); _SOKOL_UNUSED(num_fs_imgs);
  3275. }
  3276. _SOKOL_PRIVATE void _sg_dummy_apply_uniforms(sg_shader_stage stage_index, int ub_index, const void* data, int num_bytes) {
  3277. SOKOL_ASSERT(data && (num_bytes > 0));
  3278. SOKOL_ASSERT((stage_index >= 0) && ((int)stage_index < SG_NUM_SHADER_STAGES));
  3279. SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS));
  3280. _SOKOL_UNUSED(stage_index);
  3281. _SOKOL_UNUSED(ub_index);
  3282. _SOKOL_UNUSED(data);
  3283. _SOKOL_UNUSED(num_bytes);
  3284. }
  3285. _SOKOL_PRIVATE void _sg_dummy_draw(int base_element, int num_elements, int num_instances) {
  3286. _SOKOL_UNUSED(base_element);
  3287. _SOKOL_UNUSED(num_elements);
  3288. _SOKOL_UNUSED(num_instances);
  3289. }
  3290. _SOKOL_PRIVATE void _sg_dummy_update_buffer(_sg_buffer_t* buf, const void* data, int data_size) {
  3291. SOKOL_ASSERT(buf && data && (data_size > 0));
  3292. _SOKOL_UNUSED(data);
  3293. _SOKOL_UNUSED(data_size);
  3294. if (++buf->cmn.active_slot >= buf->cmn.num_slots) {
  3295. buf->cmn.active_slot = 0;
  3296. }
  3297. }
  3298. _SOKOL_PRIVATE void _sg_dummy_append_buffer(_sg_buffer_t* buf, const void* data, int data_size, bool new_frame) {
  3299. SOKOL_ASSERT(buf && data && (data_size > 0));
  3300. _SOKOL_UNUSED(data);
  3301. _SOKOL_UNUSED(data_size);
  3302. if (new_frame) {
  3303. if (++buf->cmn.active_slot >= buf->cmn.num_slots) {
  3304. buf->cmn.active_slot = 0;
  3305. }
  3306. }
  3307. }
  3308. _SOKOL_PRIVATE void _sg_dummy_update_image(_sg_image_t* img, const sg_image_content* data) {
  3309. SOKOL_ASSERT(img && data);
  3310. _SOKOL_UNUSED(data);
  3311. if (++img->cmn.active_slot >= img->cmn.num_slots) {
  3312. img->cmn.active_slot = 0;
  3313. }
  3314. }
  3315. /*== GL BACKEND ==============================================================*/
  3316. #elif defined(_SOKOL_ANY_GL)
  3317. /*-- type translation --------------------------------------------------------*/
  3318. _SOKOL_PRIVATE GLenum _sg_gl_buffer_target(sg_buffer_type t) {
  3319. switch (t) {
  3320. case SG_BUFFERTYPE_VERTEXBUFFER: return GL_ARRAY_BUFFER;
  3321. case SG_BUFFERTYPE_INDEXBUFFER: return GL_ELEMENT_ARRAY_BUFFER;
  3322. default: SOKOL_UNREACHABLE; return 0;
  3323. }
  3324. }
  3325. _SOKOL_PRIVATE GLenum _sg_gl_texture_target(sg_image_type t) {
  3326. switch (t) {
  3327. case SG_IMAGETYPE_2D: return GL_TEXTURE_2D;
  3328. case SG_IMAGETYPE_CUBE: return GL_TEXTURE_CUBE_MAP;
  3329. #if !defined(SOKOL_GLES2)
  3330. case SG_IMAGETYPE_3D: return GL_TEXTURE_3D;
  3331. case SG_IMAGETYPE_ARRAY: return GL_TEXTURE_2D_ARRAY;
  3332. #endif
  3333. default: SOKOL_UNREACHABLE; return 0;
  3334. }
  3335. }
  3336. _SOKOL_PRIVATE GLenum _sg_gl_usage(sg_usage u) {
  3337. switch (u) {
  3338. case SG_USAGE_IMMUTABLE: return GL_STATIC_DRAW;
  3339. case SG_USAGE_DYNAMIC: return GL_DYNAMIC_DRAW;
  3340. case SG_USAGE_STREAM: return GL_STREAM_DRAW;
  3341. default: SOKOL_UNREACHABLE; return 0;
  3342. }
  3343. }
  3344. _SOKOL_PRIVATE GLenum _sg_gl_shader_stage(sg_shader_stage stage) {
  3345. switch (stage) {
  3346. case SG_SHADERSTAGE_VS: return GL_VERTEX_SHADER;
  3347. case SG_SHADERSTAGE_FS: return GL_FRAGMENT_SHADER;
  3348. default: SOKOL_UNREACHABLE; return 0;
  3349. }
  3350. }
  3351. _SOKOL_PRIVATE GLint _sg_gl_vertexformat_size(sg_vertex_format fmt) {
  3352. switch (fmt) {
  3353. case SG_VERTEXFORMAT_FLOAT: return 1;
  3354. case SG_VERTEXFORMAT_FLOAT2: return 2;
  3355. case SG_VERTEXFORMAT_FLOAT3: return 3;
  3356. case SG_VERTEXFORMAT_FLOAT4: return 4;
  3357. case SG_VERTEXFORMAT_BYTE4: return 4;
  3358. case SG_VERTEXFORMAT_BYTE4N: return 4;
  3359. case SG_VERTEXFORMAT_UBYTE4: return 4;
  3360. case SG_VERTEXFORMAT_UBYTE4N: return 4;
  3361. case SG_VERTEXFORMAT_SHORT2: return 2;
  3362. case SG_VERTEXFORMAT_SHORT2N: return 2;
  3363. case SG_VERTEXFORMAT_USHORT2N: return 2;
  3364. case SG_VERTEXFORMAT_SHORT4: return 4;
  3365. case SG_VERTEXFORMAT_SHORT4N: return 4;
  3366. case SG_VERTEXFORMAT_USHORT4N: return 4;
  3367. case SG_VERTEXFORMAT_UINT10_N2: return 4;
  3368. default: SOKOL_UNREACHABLE; return 0;
  3369. }
  3370. }
  3371. _SOKOL_PRIVATE GLenum _sg_gl_vertexformat_type(sg_vertex_format fmt) {
  3372. switch (fmt) {
  3373. case SG_VERTEXFORMAT_FLOAT:
  3374. case SG_VERTEXFORMAT_FLOAT2:
  3375. case SG_VERTEXFORMAT_FLOAT3:
  3376. case SG_VERTEXFORMAT_FLOAT4:
  3377. return GL_FLOAT;
  3378. case SG_VERTEXFORMAT_BYTE4:
  3379. case SG_VERTEXFORMAT_BYTE4N:
  3380. return GL_BYTE;
  3381. case SG_VERTEXFORMAT_UBYTE4:
  3382. case SG_VERTEXFORMAT_UBYTE4N:
  3383. return GL_UNSIGNED_BYTE;
  3384. case SG_VERTEXFORMAT_SHORT2:
  3385. case SG_VERTEXFORMAT_SHORT2N:
  3386. case SG_VERTEXFORMAT_SHORT4:
  3387. case SG_VERTEXFORMAT_SHORT4N:
  3388. return GL_SHORT;
  3389. case SG_VERTEXFORMAT_USHORT2N:
  3390. case SG_VERTEXFORMAT_USHORT4N:
  3391. return GL_UNSIGNED_SHORT;
  3392. case SG_VERTEXFORMAT_UINT10_N2:
  3393. return GL_UNSIGNED_INT_2_10_10_10_REV;
  3394. default:
  3395. SOKOL_UNREACHABLE; return 0;
  3396. }
  3397. }
  3398. _SOKOL_PRIVATE GLboolean _sg_gl_vertexformat_normalized(sg_vertex_format fmt) {
  3399. switch (fmt) {
  3400. case SG_VERTEXFORMAT_BYTE4N:
  3401. case SG_VERTEXFORMAT_UBYTE4N:
  3402. case SG_VERTEXFORMAT_SHORT2N:
  3403. case SG_VERTEXFORMAT_USHORT2N:
  3404. case SG_VERTEXFORMAT_SHORT4N:
  3405. case SG_VERTEXFORMAT_USHORT4N:
  3406. case SG_VERTEXFORMAT_UINT10_N2:
  3407. return GL_TRUE;
  3408. default:
  3409. return GL_FALSE;
  3410. }
  3411. }
  3412. _SOKOL_PRIVATE GLenum _sg_gl_primitive_type(sg_primitive_type t) {
  3413. switch (t) {
  3414. case SG_PRIMITIVETYPE_POINTS: return GL_POINTS;
  3415. case SG_PRIMITIVETYPE_LINES: return GL_LINES;
  3416. case SG_PRIMITIVETYPE_LINE_STRIP: return GL_LINE_STRIP;
  3417. case SG_PRIMITIVETYPE_TRIANGLES: return GL_TRIANGLES;
  3418. case SG_PRIMITIVETYPE_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP;
  3419. default: SOKOL_UNREACHABLE; return 0;
  3420. }
  3421. }
  3422. _SOKOL_PRIVATE GLenum _sg_gl_index_type(sg_index_type t) {
  3423. switch (t) {
  3424. case SG_INDEXTYPE_NONE: return 0;
  3425. case SG_INDEXTYPE_UINT16: return GL_UNSIGNED_SHORT;
  3426. case SG_INDEXTYPE_UINT32: return GL_UNSIGNED_INT;
  3427. default: SOKOL_UNREACHABLE; return 0;
  3428. }
  3429. }
  3430. _SOKOL_PRIVATE GLenum _sg_gl_compare_func(sg_compare_func cmp) {
  3431. switch (cmp) {
  3432. case SG_COMPAREFUNC_NEVER: return GL_NEVER;
  3433. case SG_COMPAREFUNC_LESS: return GL_LESS;
  3434. case SG_COMPAREFUNC_EQUAL: return GL_EQUAL;
  3435. case SG_COMPAREFUNC_LESS_EQUAL: return GL_LEQUAL;
  3436. case SG_COMPAREFUNC_GREATER: return GL_GREATER;
  3437. case SG_COMPAREFUNC_NOT_EQUAL: return GL_NOTEQUAL;
  3438. case SG_COMPAREFUNC_GREATER_EQUAL: return GL_GEQUAL;
  3439. case SG_COMPAREFUNC_ALWAYS: return GL_ALWAYS;
  3440. default: SOKOL_UNREACHABLE; return 0;
  3441. }
  3442. }
  3443. _SOKOL_PRIVATE GLenum _sg_gl_stencil_op(sg_stencil_op op) {
  3444. switch (op) {
  3445. case SG_STENCILOP_KEEP: return GL_KEEP;
  3446. case SG_STENCILOP_ZERO: return GL_ZERO;
  3447. case SG_STENCILOP_REPLACE: return GL_REPLACE;
  3448. case SG_STENCILOP_INCR_CLAMP: return GL_INCR;
  3449. case SG_STENCILOP_DECR_CLAMP: return GL_DECR;
  3450. case SG_STENCILOP_INVERT: return GL_INVERT;
  3451. case SG_STENCILOP_INCR_WRAP: return GL_INCR_WRAP;
  3452. case SG_STENCILOP_DECR_WRAP: return GL_DECR_WRAP;
  3453. default: SOKOL_UNREACHABLE; return 0;
  3454. }
  3455. }
  3456. _SOKOL_PRIVATE GLenum _sg_gl_blend_factor(sg_blend_factor f) {
  3457. switch (f) {
  3458. case SG_BLENDFACTOR_ZERO: return GL_ZERO;
  3459. case SG_BLENDFACTOR_ONE: return GL_ONE;
  3460. case SG_BLENDFACTOR_SRC_COLOR: return GL_SRC_COLOR;
  3461. case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR;
  3462. case SG_BLENDFACTOR_SRC_ALPHA: return GL_SRC_ALPHA;
  3463. case SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA;
  3464. case SG_BLENDFACTOR_DST_COLOR: return GL_DST_COLOR;
  3465. case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR: return GL_ONE_MINUS_DST_COLOR;
  3466. case SG_BLENDFACTOR_DST_ALPHA: return GL_DST_ALPHA;
  3467. case SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA;
  3468. case SG_BLENDFACTOR_SRC_ALPHA_SATURATED: return GL_SRC_ALPHA_SATURATE;
  3469. case SG_BLENDFACTOR_BLEND_COLOR: return GL_CONSTANT_COLOR;
  3470. case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR: return GL_ONE_MINUS_CONSTANT_COLOR;
  3471. case SG_BLENDFACTOR_BLEND_ALPHA: return GL_CONSTANT_ALPHA;
  3472. case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA: return GL_ONE_MINUS_CONSTANT_ALPHA;
  3473. default: SOKOL_UNREACHABLE; return 0;
  3474. }
  3475. }
  3476. _SOKOL_PRIVATE GLenum _sg_gl_blend_op(sg_blend_op op) {
  3477. switch (op) {
  3478. case SG_BLENDOP_ADD: return GL_FUNC_ADD;
  3479. case SG_BLENDOP_SUBTRACT: return GL_FUNC_SUBTRACT;
  3480. case SG_BLENDOP_REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT;
  3481. default: SOKOL_UNREACHABLE; return 0;
  3482. }
  3483. }
  3484. _SOKOL_PRIVATE GLenum _sg_gl_filter(sg_filter f) {
  3485. switch (f) {
  3486. case SG_FILTER_NEAREST: return GL_NEAREST;
  3487. case SG_FILTER_LINEAR: return GL_LINEAR;
  3488. case SG_FILTER_NEAREST_MIPMAP_NEAREST: return GL_NEAREST_MIPMAP_NEAREST;
  3489. case SG_FILTER_NEAREST_MIPMAP_LINEAR: return GL_NEAREST_MIPMAP_LINEAR;
  3490. case SG_FILTER_LINEAR_MIPMAP_NEAREST: return GL_LINEAR_MIPMAP_NEAREST;
  3491. case SG_FILTER_LINEAR_MIPMAP_LINEAR: return GL_LINEAR_MIPMAP_LINEAR;
  3492. default: SOKOL_UNREACHABLE; return 0;
  3493. }
  3494. }
  3495. _SOKOL_PRIVATE GLenum _sg_gl_wrap(sg_wrap w) {
  3496. switch (w) {
  3497. case SG_WRAP_CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE;
  3498. #if defined(SOKOL_GLCORE33)
  3499. case SG_WRAP_CLAMP_TO_BORDER: return GL_CLAMP_TO_BORDER;
  3500. #else
  3501. case SG_WRAP_CLAMP_TO_BORDER: return GL_CLAMP_TO_EDGE;
  3502. #endif
  3503. case SG_WRAP_REPEAT: return GL_REPEAT;
  3504. case SG_WRAP_MIRRORED_REPEAT: return GL_MIRRORED_REPEAT;
  3505. default: SOKOL_UNREACHABLE; return 0;
  3506. }
  3507. }
  3508. _SOKOL_PRIVATE GLenum _sg_gl_teximage_type(sg_pixel_format fmt) {
  3509. switch (fmt) {
  3510. case SG_PIXELFORMAT_R8:
  3511. case SG_PIXELFORMAT_R8UI:
  3512. case SG_PIXELFORMAT_RG8:
  3513. case SG_PIXELFORMAT_RG8UI:
  3514. case SG_PIXELFORMAT_RGBA8:
  3515. case SG_PIXELFORMAT_RGBA8UI:
  3516. case SG_PIXELFORMAT_BGRA8:
  3517. return GL_UNSIGNED_BYTE;
  3518. case SG_PIXELFORMAT_R8SN:
  3519. case SG_PIXELFORMAT_R8SI:
  3520. case SG_PIXELFORMAT_RG8SN:
  3521. case SG_PIXELFORMAT_RG8SI:
  3522. case SG_PIXELFORMAT_RGBA8SN:
  3523. case SG_PIXELFORMAT_RGBA8SI:
  3524. return GL_BYTE;
  3525. case SG_PIXELFORMAT_R16:
  3526. case SG_PIXELFORMAT_R16UI:
  3527. case SG_PIXELFORMAT_RG16:
  3528. case SG_PIXELFORMAT_RG16UI:
  3529. case SG_PIXELFORMAT_RGBA16:
  3530. case SG_PIXELFORMAT_RGBA16UI:
  3531. return GL_UNSIGNED_SHORT;
  3532. case SG_PIXELFORMAT_R16SN:
  3533. case SG_PIXELFORMAT_R16SI:
  3534. case SG_PIXELFORMAT_RG16SN:
  3535. case SG_PIXELFORMAT_RG16SI:
  3536. case SG_PIXELFORMAT_RGBA16SN:
  3537. case SG_PIXELFORMAT_RGBA16SI:
  3538. return GL_SHORT;
  3539. case SG_PIXELFORMAT_R16F:
  3540. case SG_PIXELFORMAT_RG16F:
  3541. case SG_PIXELFORMAT_RGBA16F:
  3542. return GL_HALF_FLOAT;
  3543. case SG_PIXELFORMAT_R32UI:
  3544. case SG_PIXELFORMAT_RG32UI:
  3545. case SG_PIXELFORMAT_RGBA32UI:
  3546. return GL_UNSIGNED_INT;
  3547. case SG_PIXELFORMAT_R32SI:
  3548. case SG_PIXELFORMAT_RG32SI:
  3549. case SG_PIXELFORMAT_RGBA32SI:
  3550. return GL_INT;
  3551. case SG_PIXELFORMAT_R32F:
  3552. case SG_PIXELFORMAT_RG32F:
  3553. case SG_PIXELFORMAT_RGBA32F:
  3554. return GL_FLOAT;
  3555. #if !defined(SOKOL_GLES2)
  3556. case SG_PIXELFORMAT_RGB10A2:
  3557. return GL_UNSIGNED_INT_2_10_10_10_REV;
  3558. case SG_PIXELFORMAT_RG11B10F:
  3559. return GL_UNSIGNED_INT_10F_11F_11F_REV;
  3560. #endif
  3561. case SG_PIXELFORMAT_DEPTH:
  3562. return GL_UNSIGNED_SHORT;
  3563. case SG_PIXELFORMAT_DEPTH_STENCIL:
  3564. return GL_UNSIGNED_INT_24_8;
  3565. default:
  3566. SOKOL_UNREACHABLE; return 0;
  3567. }
  3568. }
  3569. _SOKOL_PRIVATE GLenum _sg_gl_teximage_format(sg_pixel_format fmt) {
  3570. switch (fmt) {
  3571. case SG_PIXELFORMAT_R8:
  3572. case SG_PIXELFORMAT_R8SN:
  3573. case SG_PIXELFORMAT_R16:
  3574. case SG_PIXELFORMAT_R16SN:
  3575. case SG_PIXELFORMAT_R16F:
  3576. case SG_PIXELFORMAT_R32F:
  3577. #if defined(SOKOL_GLES2)
  3578. return GL_LUMINANCE;
  3579. #else
  3580. if (_sg.gl.gles2) {
  3581. return GL_LUMINANCE;
  3582. }
  3583. else {
  3584. return GL_RED;
  3585. }
  3586. #endif
  3587. #if !defined(SOKOL_GLES2)
  3588. case SG_PIXELFORMAT_R8UI:
  3589. case SG_PIXELFORMAT_R8SI:
  3590. case SG_PIXELFORMAT_R16UI:
  3591. case SG_PIXELFORMAT_R16SI:
  3592. case SG_PIXELFORMAT_R32UI:
  3593. case SG_PIXELFORMAT_R32SI:
  3594. return GL_RED_INTEGER;
  3595. case SG_PIXELFORMAT_RG8:
  3596. case SG_PIXELFORMAT_RG8SN:
  3597. case SG_PIXELFORMAT_RG16:
  3598. case SG_PIXELFORMAT_RG16SN:
  3599. case SG_PIXELFORMAT_RG16F:
  3600. case SG_PIXELFORMAT_RG32F:
  3601. return GL_RG;
  3602. case SG_PIXELFORMAT_RG8UI:
  3603. case SG_PIXELFORMAT_RG8SI:
  3604. case SG_PIXELFORMAT_RG16UI:
  3605. case SG_PIXELFORMAT_RG16SI:
  3606. case SG_PIXELFORMAT_RG32UI:
  3607. case SG_PIXELFORMAT_RG32SI:
  3608. return GL_RG_INTEGER;
  3609. #endif
  3610. case SG_PIXELFORMAT_RGBA8:
  3611. case SG_PIXELFORMAT_RGBA8SN:
  3612. case SG_PIXELFORMAT_RGBA16:
  3613. case SG_PIXELFORMAT_RGBA16SN:
  3614. case SG_PIXELFORMAT_RGBA16F:
  3615. case SG_PIXELFORMAT_RGBA32F:
  3616. case SG_PIXELFORMAT_RGB10A2:
  3617. return GL_RGBA;
  3618. #if !defined(SOKOL_GLES2)
  3619. case SG_PIXELFORMAT_RGBA8UI:
  3620. case SG_PIXELFORMAT_RGBA8SI:
  3621. case SG_PIXELFORMAT_RGBA16UI:
  3622. case SG_PIXELFORMAT_RGBA16SI:
  3623. case SG_PIXELFORMAT_RGBA32UI:
  3624. case SG_PIXELFORMAT_RGBA32SI:
  3625. return GL_RGBA_INTEGER;
  3626. #endif
  3627. case SG_PIXELFORMAT_RG11B10F:
  3628. return GL_RGB;
  3629. case SG_PIXELFORMAT_DEPTH:
  3630. return GL_DEPTH_COMPONENT;
  3631. case SG_PIXELFORMAT_DEPTH_STENCIL:
  3632. return GL_DEPTH_STENCIL;
  3633. case SG_PIXELFORMAT_BC1_RGBA:
  3634. return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
  3635. case SG_PIXELFORMAT_BC2_RGBA:
  3636. return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
  3637. case SG_PIXELFORMAT_BC3_RGBA:
  3638. return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
  3639. case SG_PIXELFORMAT_BC4_R:
  3640. return GL_COMPRESSED_RED_RGTC1;
  3641. case SG_PIXELFORMAT_BC4_RSN:
  3642. return GL_COMPRESSED_SIGNED_RED_RGTC1;
  3643. case SG_PIXELFORMAT_BC5_RG:
  3644. return GL_COMPRESSED_RED_GREEN_RGTC2;
  3645. case SG_PIXELFORMAT_BC5_RGSN:
  3646. return GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2;
  3647. case SG_PIXELFORMAT_BC6H_RGBF:
  3648. return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;
  3649. case SG_PIXELFORMAT_BC6H_RGBUF:
  3650. return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;
  3651. case SG_PIXELFORMAT_BC7_RGBA:
  3652. return GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
  3653. case SG_PIXELFORMAT_PVRTC_RGB_2BPP:
  3654. return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  3655. case SG_PIXELFORMAT_PVRTC_RGB_4BPP:
  3656. return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  3657. case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:
  3658. return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
  3659. case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:
  3660. return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
  3661. case SG_PIXELFORMAT_ETC2_RGB8:
  3662. return GL_COMPRESSED_RGB8_ETC2;
  3663. case SG_PIXELFORMAT_ETC2_RGB8A1:
  3664. return GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
  3665. case SG_PIXELFORMAT_ETC2_RGBA8:
  3666. return GL_COMPRESSED_RGBA8_ETC2_EAC;
  3667. case SG_PIXELFORMAT_ETC2_RG11:
  3668. return GL_COMPRESSED_RG11_EAC;
  3669. case SG_PIXELFORMAT_ETC2_RG11SN:
  3670. return GL_COMPRESSED_SIGNED_RG11_EAC;
  3671. default:
  3672. SOKOL_UNREACHABLE; return 0;
  3673. }
  3674. }
  3675. _SOKOL_PRIVATE GLenum _sg_gl_teximage_internal_format(sg_pixel_format fmt) {
  3676. #if defined(SOKOL_GLES2)
  3677. return _sg_gl_teximage_format(fmt);
  3678. #else
  3679. if (_sg.gl.gles2) {
  3680. return _sg_gl_teximage_format(fmt);
  3681. }
  3682. else {
  3683. switch (fmt) {
  3684. case SG_PIXELFORMAT_R8: return GL_R8;
  3685. case SG_PIXELFORMAT_R8SN: return GL_R8_SNORM;
  3686. case SG_PIXELFORMAT_R8UI: return GL_R8UI;
  3687. case SG_PIXELFORMAT_R8SI: return GL_R8I;
  3688. #if !defined(SOKOL_GLES3)
  3689. case SG_PIXELFORMAT_R16: return GL_R16;
  3690. case SG_PIXELFORMAT_R16SN: return GL_R16_SNORM;
  3691. #endif
  3692. case SG_PIXELFORMAT_R16UI: return GL_R16UI;
  3693. case SG_PIXELFORMAT_R16SI: return GL_R16I;
  3694. case SG_PIXELFORMAT_R16F: return GL_R16F;
  3695. case SG_PIXELFORMAT_RG8: return GL_RG8;
  3696. case SG_PIXELFORMAT_RG8SN: return GL_RG8_SNORM;
  3697. case SG_PIXELFORMAT_RG8UI: return GL_RG8UI;
  3698. case SG_PIXELFORMAT_RG8SI: return GL_RG8I;
  3699. case SG_PIXELFORMAT_R32UI: return GL_R32UI;
  3700. case SG_PIXELFORMAT_R32SI: return GL_R32I;
  3701. case SG_PIXELFORMAT_R32F: return GL_R32F;
  3702. #if !defined(SOKOL_GLES3)
  3703. case SG_PIXELFORMAT_RG16: return GL_RG16;
  3704. case SG_PIXELFORMAT_RG16SN: return GL_RG16_SNORM;
  3705. #endif
  3706. case SG_PIXELFORMAT_RG16UI: return GL_RG16UI;
  3707. case SG_PIXELFORMAT_RG16SI: return GL_RG16I;
  3708. case SG_PIXELFORMAT_RG16F: return GL_RG16F;
  3709. case SG_PIXELFORMAT_RGBA8: return GL_RGBA8;
  3710. case SG_PIXELFORMAT_RGBA8SN: return GL_RGBA8_SNORM;
  3711. case SG_PIXELFORMAT_RGBA8UI: return GL_RGBA8UI;
  3712. case SG_PIXELFORMAT_RGBA8SI: return GL_RGBA8I;
  3713. case SG_PIXELFORMAT_RGB10A2: return GL_RGB10_A2;
  3714. case SG_PIXELFORMAT_RG11B10F: return GL_R11F_G11F_B10F;
  3715. case SG_PIXELFORMAT_RG32UI: return GL_RG32UI;
  3716. case SG_PIXELFORMAT_RG32SI: return GL_RG32I;
  3717. case SG_PIXELFORMAT_RG32F: return GL_RG32F;
  3718. #if !defined(SOKOL_GLES3)
  3719. case SG_PIXELFORMAT_RGBA16: return GL_RGBA16;
  3720. case SG_PIXELFORMAT_RGBA16SN: return GL_RGBA16_SNORM;
  3721. #endif
  3722. case SG_PIXELFORMAT_RGBA16UI: return GL_RGBA16UI;
  3723. case SG_PIXELFORMAT_RGBA16SI: return GL_RGBA16I;
  3724. case SG_PIXELFORMAT_RGBA16F: return GL_RGBA16F;
  3725. case SG_PIXELFORMAT_RGBA32UI: return GL_RGBA32UI;
  3726. case SG_PIXELFORMAT_RGBA32SI: return GL_RGBA32I;
  3727. case SG_PIXELFORMAT_RGBA32F: return GL_RGBA32F;
  3728. case SG_PIXELFORMAT_DEPTH: return GL_DEPTH_COMPONENT16;
  3729. case SG_PIXELFORMAT_DEPTH_STENCIL: return GL_DEPTH24_STENCIL8;
  3730. case SG_PIXELFORMAT_BC1_RGBA: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
  3731. case SG_PIXELFORMAT_BC2_RGBA: return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
  3732. case SG_PIXELFORMAT_BC3_RGBA: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
  3733. case SG_PIXELFORMAT_BC4_R: return GL_COMPRESSED_RED_RGTC1;
  3734. case SG_PIXELFORMAT_BC4_RSN: return GL_COMPRESSED_SIGNED_RED_RGTC1;
  3735. case SG_PIXELFORMAT_BC5_RG: return GL_COMPRESSED_RED_GREEN_RGTC2;
  3736. case SG_PIXELFORMAT_BC5_RGSN: return GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2;
  3737. case SG_PIXELFORMAT_BC6H_RGBF: return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;
  3738. case SG_PIXELFORMAT_BC6H_RGBUF: return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;
  3739. case SG_PIXELFORMAT_BC7_RGBA: return GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
  3740. case SG_PIXELFORMAT_PVRTC_RGB_2BPP: return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  3741. case SG_PIXELFORMAT_PVRTC_RGB_4BPP: return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  3742. case SG_PIXELFORMAT_PVRTC_RGBA_2BPP: return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
  3743. case SG_PIXELFORMAT_PVRTC_RGBA_4BPP: return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
  3744. case SG_PIXELFORMAT_ETC2_RGB8: return GL_COMPRESSED_RGB8_ETC2;
  3745. case SG_PIXELFORMAT_ETC2_RGB8A1: return GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
  3746. case SG_PIXELFORMAT_ETC2_RGBA8: return GL_COMPRESSED_RGBA8_ETC2_EAC;
  3747. case SG_PIXELFORMAT_ETC2_RG11: return GL_COMPRESSED_RG11_EAC;
  3748. case SG_PIXELFORMAT_ETC2_RG11SN: return GL_COMPRESSED_SIGNED_RG11_EAC;
  3749. default: SOKOL_UNREACHABLE; return 0;
  3750. }
  3751. }
  3752. #endif
  3753. }
  3754. _SOKOL_PRIVATE GLenum _sg_gl_cubeface_target(int face_index) {
  3755. switch (face_index) {
  3756. case 0: return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
  3757. case 1: return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
  3758. case 2: return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
  3759. case 3: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
  3760. case 4: return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
  3761. case 5: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
  3762. default: SOKOL_UNREACHABLE; return 0;
  3763. }
  3764. }
  3765. _SOKOL_PRIVATE GLenum _sg_gl_depth_attachment_format(sg_pixel_format fmt) {
  3766. switch (fmt) {
  3767. case SG_PIXELFORMAT_DEPTH: return GL_DEPTH_COMPONENT16;
  3768. case SG_PIXELFORMAT_DEPTH_STENCIL: return GL_DEPTH24_STENCIL8;
  3769. default: SOKOL_UNREACHABLE; return 0;
  3770. }
  3771. }
  3772. _SOKOL_PRIVATE void _sg_gl_init_attr(_sg_gl_attr_t* attr) {
  3773. attr->vb_index = -1;
  3774. attr->divisor = -1;
  3775. }
  3776. _SOKOL_PRIVATE void _sg_gl_init_stencil_state(sg_stencil_state* s) {
  3777. SOKOL_ASSERT(s);
  3778. s->fail_op = SG_STENCILOP_KEEP;
  3779. s->depth_fail_op = SG_STENCILOP_KEEP;
  3780. s->pass_op = SG_STENCILOP_KEEP;
  3781. s->compare_func = SG_COMPAREFUNC_ALWAYS;
  3782. }
  3783. _SOKOL_PRIVATE void _sg_gl_init_depth_stencil_state(sg_depth_stencil_state* s) {
  3784. SOKOL_ASSERT(s);
  3785. _sg_gl_init_stencil_state(&s->stencil_front);
  3786. _sg_gl_init_stencil_state(&s->stencil_back);
  3787. s->depth_compare_func = SG_COMPAREFUNC_ALWAYS;
  3788. }
  3789. _SOKOL_PRIVATE void _sg_gl_init_blend_state(sg_blend_state* s) {
  3790. SOKOL_ASSERT(s);
  3791. s->src_factor_rgb = SG_BLENDFACTOR_ONE;
  3792. s->dst_factor_rgb = SG_BLENDFACTOR_ZERO;
  3793. s->op_rgb = SG_BLENDOP_ADD;
  3794. s->src_factor_alpha = SG_BLENDFACTOR_ONE;
  3795. s->dst_factor_alpha = SG_BLENDFACTOR_ZERO;
  3796. s->op_alpha = SG_BLENDOP_ADD;
  3797. s->color_write_mask = SG_COLORMASK_RGBA;
  3798. }
  3799. _SOKOL_PRIVATE void _sg_gl_init_rasterizer_state(sg_rasterizer_state* s) {
  3800. SOKOL_ASSERT(s);
  3801. s->cull_mode = SG_CULLMODE_NONE;
  3802. s->face_winding = SG_FACEWINDING_CW;
  3803. s->sample_count = 1;
  3804. }
  3805. /* see: https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml */
  3806. _SOKOL_PRIVATE void _sg_gl_init_pixelformats(bool has_bgra) {
  3807. #if !defined(SOKOL_GLES2)
  3808. if (!_sg.gl.gles2) {
  3809. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8]);
  3810. }
  3811. else {
  3812. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R8]);
  3813. }
  3814. #else
  3815. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R8]);
  3816. #endif
  3817. #if !defined(SOKOL_GLES2)
  3818. if (!_sg.gl.gles2) {
  3819. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R8SN]);
  3820. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8UI]);
  3821. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8SI]);
  3822. #if !defined(SOKOL_GLES3)
  3823. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16]);
  3824. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16SN]);
  3825. #endif
  3826. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16UI]);
  3827. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16SI]);
  3828. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG8]);
  3829. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG8SN]);
  3830. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8UI]);
  3831. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8SI]);
  3832. _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32UI]);
  3833. _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32SI]);
  3834. #if !defined(SOKOL_GLES3)
  3835. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16]);
  3836. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16SN]);
  3837. #endif
  3838. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16UI]);
  3839. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16SI]);
  3840. }
  3841. #endif
  3842. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA8]);
  3843. #if !defined(SOKOL_GLES2)
  3844. if (!_sg.gl.gles2) {
  3845. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA8SN]);
  3846. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8UI]);
  3847. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8SI]);
  3848. }
  3849. #endif
  3850. if (has_bgra) {
  3851. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_BGRA8]);
  3852. }
  3853. #if !defined(SOKOL_GLES2)
  3854. if (!_sg.gl.gles2) {
  3855. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGB10A2]);
  3856. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG11B10F]);
  3857. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG32UI]);
  3858. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG32SI]);
  3859. #if !defined(SOKOL_GLES3)
  3860. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16]);
  3861. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16SN]);
  3862. #endif
  3863. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16UI]);
  3864. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16SI]);
  3865. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA32UI]);
  3866. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA32SI]);
  3867. }
  3868. #endif
  3869. // FIXME: WEBGL_depth_texture extension?
  3870. _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH]);
  3871. _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH_STENCIL]);
  3872. }
  3873. /* FIXME: OES_half_float_blend */
  3874. _SOKOL_PRIVATE void _sg_gl_init_pixelformats_half_float(bool has_colorbuffer_half_float, bool has_texture_half_float_linear) {
  3875. #if !defined(SOKOL_GLES2)
  3876. if (!_sg.gl.gles2) {
  3877. if (has_texture_half_float_linear) {
  3878. if (has_colorbuffer_half_float) {
  3879. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16F]);
  3880. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16F]);
  3881. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);
  3882. }
  3883. else {
  3884. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R16F]);
  3885. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG16F]);
  3886. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);
  3887. }
  3888. }
  3889. else {
  3890. if (has_colorbuffer_half_float) {
  3891. _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_R16F]);
  3892. _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_RG16F]);
  3893. _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);
  3894. }
  3895. else {
  3896. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_R16F]);
  3897. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_RG16F]);
  3898. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);
  3899. }
  3900. }
  3901. }
  3902. else {
  3903. #endif
  3904. /* GLES2 can only render to RGBA, and there's no RG format */
  3905. if (has_texture_half_float_linear) {
  3906. if (has_colorbuffer_half_float) {
  3907. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);
  3908. }
  3909. else {
  3910. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);
  3911. }
  3912. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R16F]);
  3913. }
  3914. else {
  3915. if (has_colorbuffer_half_float) {
  3916. _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);
  3917. }
  3918. else {
  3919. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);
  3920. }
  3921. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_R16F]);
  3922. }
  3923. #if !defined(SOKOL_GLES2)
  3924. }
  3925. #endif
  3926. }
  3927. _SOKOL_PRIVATE void _sg_gl_init_pixelformats_float(bool has_colorbuffer_float, bool has_texture_float_linear, bool has_float_blend) {
  3928. #if !defined(SOKOL_GLES2)
  3929. if (!_sg.gl.gles2) {
  3930. if (has_texture_float_linear) {
  3931. if (has_colorbuffer_float) {
  3932. if (has_float_blend) {
  3933. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R32F]);
  3934. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG32F]);
  3935. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3936. }
  3937. else {
  3938. _sg_pixelformat_sfrm(&_sg.formats[SG_PIXELFORMAT_R32F]);
  3939. _sg_pixelformat_sfrm(&_sg.formats[SG_PIXELFORMAT_RG32F]);
  3940. _sg_pixelformat_sfrm(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3941. }
  3942. }
  3943. else {
  3944. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R32F]);
  3945. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG32F]);
  3946. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3947. }
  3948. }
  3949. else {
  3950. if (has_colorbuffer_float) {
  3951. _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_R32F]);
  3952. _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_RG32F]);
  3953. _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3954. }
  3955. else {
  3956. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_R32F]);
  3957. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_RG32F]);
  3958. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3959. }
  3960. }
  3961. }
  3962. else {
  3963. #endif
  3964. /* GLES2 can only render to RGBA, and there's no RG format */
  3965. if (has_texture_float_linear) {
  3966. if (has_colorbuffer_float) {
  3967. if (has_float_blend) {
  3968. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3969. }
  3970. else {
  3971. _sg_pixelformat_sfrm(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3972. }
  3973. }
  3974. else {
  3975. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3976. }
  3977. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R32F]);
  3978. }
  3979. else {
  3980. if (has_colorbuffer_float) {
  3981. _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3982. }
  3983. else {
  3984. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  3985. }
  3986. _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_R32F]);
  3987. }
  3988. #if !defined(SOKOL_GLES2)
  3989. }
  3990. #endif
  3991. }
  3992. _SOKOL_PRIVATE void _sg_gl_init_pixelformats_s3tc(void) {
  3993. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC1_RGBA]);
  3994. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC2_RGBA]);
  3995. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_RGBA]);
  3996. }
  3997. _SOKOL_PRIVATE void _sg_gl_init_pixelformats_rgtc(void) {
  3998. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_R]);
  3999. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_RSN]);
  4000. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RG]);
  4001. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RGSN]);
  4002. }
  4003. _SOKOL_PRIVATE void _sg_gl_init_pixelformats_bptc(void) {
  4004. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBF]);
  4005. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBUF]);
  4006. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_RGBA]);
  4007. }
  4008. _SOKOL_PRIVATE void _sg_gl_init_pixelformats_pvrtc(void) {
  4009. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGB_2BPP]);
  4010. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGB_4BPP]);
  4011. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGBA_2BPP]);
  4012. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGBA_4BPP]);
  4013. }
  4014. _SOKOL_PRIVATE void _sg_gl_init_pixelformats_etc2(void) {
  4015. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8]);
  4016. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8A1]);
  4017. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGBA8]);
  4018. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RG11]);
  4019. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RG11SN]);
  4020. }
  4021. _SOKOL_PRIVATE void _sg_gl_init_limits(void) {
  4022. _SG_GL_CHECK_ERROR();
  4023. GLint gl_int;
  4024. glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_int);
  4025. _SG_GL_CHECK_ERROR();
  4026. _sg.limits.max_image_size_2d = gl_int;
  4027. _sg.limits.max_image_size_array = gl_int;
  4028. glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &gl_int);
  4029. _SG_GL_CHECK_ERROR();
  4030. _sg.limits.max_image_size_cube = gl_int;
  4031. glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_int);
  4032. _SG_GL_CHECK_ERROR();
  4033. if (gl_int > SG_MAX_VERTEX_ATTRIBUTES) {
  4034. gl_int = SG_MAX_VERTEX_ATTRIBUTES;
  4035. }
  4036. _sg.limits.max_vertex_attrs = gl_int;
  4037. #if !defined(SOKOL_GLES2)
  4038. if (!_sg.gl.gles2) {
  4039. glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &gl_int);
  4040. _SG_GL_CHECK_ERROR();
  4041. _sg.limits.max_image_size_3d = gl_int;
  4042. glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &gl_int);
  4043. _SG_GL_CHECK_ERROR();
  4044. _sg.limits.max_image_array_layers = gl_int;
  4045. }
  4046. #endif
  4047. if (_sg.gl.ext_anisotropic) {
  4048. glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_int);
  4049. _SG_GL_CHECK_ERROR();
  4050. _sg.gl.max_anisotropy = gl_int;
  4051. }
  4052. else {
  4053. _sg.gl.max_anisotropy = 1;
  4054. }
  4055. glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &gl_int);
  4056. _SG_GL_CHECK_ERROR();
  4057. _sg.gl.max_combined_texture_image_units = gl_int;
  4058. }
  4059. #if defined(SOKOL_GLCORE33)
  4060. _SOKOL_PRIVATE void _sg_gl_init_caps_glcore33(void) {
  4061. _sg.backend = SG_BACKEND_GLCORE33;
  4062. _sg.features.origin_top_left = false;
  4063. _sg.features.instancing = true;
  4064. _sg.features.multiple_render_targets = true;
  4065. _sg.features.msaa_render_targets = true;
  4066. _sg.features.imagetype_3d = true;
  4067. _sg.features.imagetype_array = true;
  4068. _sg.features.image_clamp_to_border = true;
  4069. /* scan extensions */
  4070. bool has_s3tc = false; /* BC1..BC3 */
  4071. bool has_rgtc = false; /* BC4 and BC5 */
  4072. bool has_bptc = false; /* BC6H and BC7 */
  4073. bool has_pvrtc = false;
  4074. bool has_etc2 = false;
  4075. GLint num_ext = 0;
  4076. glGetIntegerv(GL_NUM_EXTENSIONS, &num_ext);
  4077. for (int i = 0; i < num_ext; i++) {
  4078. const char* ext = (const char*) glGetStringi(GL_EXTENSIONS, i);
  4079. if (ext) {
  4080. if (strstr(ext, "_texture_compression_s3tc")) {
  4081. has_s3tc = true;
  4082. }
  4083. else if (strstr(ext, "_texture_compression_rgtc")) {
  4084. has_rgtc = true;
  4085. }
  4086. else if (strstr(ext, "_texture_compression_bptc")) {
  4087. has_bptc = true;
  4088. }
  4089. else if (strstr(ext, "_texture_compression_pvrtc")) {
  4090. has_pvrtc = true;
  4091. }
  4092. else if (strstr(ext, "_ES3_compatibility")) {
  4093. has_etc2 = true;
  4094. }
  4095. else if (strstr(ext, "_texture_filter_anisotropic")) {
  4096. _sg.gl.ext_anisotropic = true;
  4097. }
  4098. }
  4099. }
  4100. /* limits */
  4101. _sg_gl_init_limits();
  4102. /* pixel formats */
  4103. const bool has_bgra = false; /* not a bug */
  4104. const bool has_colorbuffer_float = true;
  4105. const bool has_colorbuffer_half_float = true;
  4106. const bool has_texture_float_linear = true; /* FIXME??? */
  4107. const bool has_texture_half_float_linear = true;
  4108. const bool has_float_blend = true;
  4109. _sg_gl_init_pixelformats(has_bgra);
  4110. _sg_gl_init_pixelformats_float(has_colorbuffer_float, has_texture_float_linear, has_float_blend);
  4111. _sg_gl_init_pixelformats_half_float(has_colorbuffer_half_float, has_texture_half_float_linear);
  4112. if (has_s3tc) {
  4113. _sg_gl_init_pixelformats_s3tc();
  4114. }
  4115. if (has_rgtc) {
  4116. _sg_gl_init_pixelformats_rgtc();
  4117. }
  4118. if (has_bptc) {
  4119. _sg_gl_init_pixelformats_bptc();
  4120. }
  4121. if (has_pvrtc) {
  4122. _sg_gl_init_pixelformats_pvrtc();
  4123. }
  4124. if (has_etc2) {
  4125. _sg_gl_init_pixelformats_etc2();
  4126. }
  4127. }
  4128. #endif
  4129. #if defined(SOKOL_GLES3)
  4130. _SOKOL_PRIVATE void _sg_gl_init_caps_gles3(void) {
  4131. _sg.backend = SG_BACKEND_GLES3;
  4132. _sg.features.origin_top_left = false;
  4133. _sg.features.instancing = true;
  4134. _sg.features.multiple_render_targets = true;
  4135. _sg.features.msaa_render_targets = true;
  4136. _sg.features.imagetype_3d = true;
  4137. _sg.features.imagetype_array = true;
  4138. _sg.features.image_clamp_to_border = false;
  4139. bool has_s3tc = false; /* BC1..BC3 */
  4140. bool has_rgtc = false; /* BC4 and BC5 */
  4141. bool has_bptc = false; /* BC6H and BC7 */
  4142. bool has_pvrtc = false;
  4143. #if defined(__EMSCRIPTEN__)
  4144. bool has_etc2 = false;
  4145. #else
  4146. bool has_etc2 = true;
  4147. #endif
  4148. bool has_colorbuffer_float = false;
  4149. bool has_colorbuffer_half_float = false;
  4150. bool has_texture_float_linear = false;
  4151. bool has_float_blend = false;
  4152. GLint num_ext = 0;
  4153. glGetIntegerv(GL_NUM_EXTENSIONS, &num_ext);
  4154. for (int i = 0; i < num_ext; i++) {
  4155. const char* ext = (const char*) glGetStringi(GL_EXTENSIONS, i);
  4156. if (ext) {
  4157. if (strstr(ext, "_texture_compression_s3tc")) {
  4158. has_s3tc = true;
  4159. }
  4160. else if (strstr(ext, "_compressed_texture_s3tc")) {
  4161. has_s3tc = true;
  4162. }
  4163. else if (strstr(ext, "_texture_compression_rgtc")) {
  4164. has_rgtc = true;
  4165. }
  4166. else if (strstr(ext, "_texture_compression_bptc")) {
  4167. has_bptc = true;
  4168. }
  4169. else if (strstr(ext, "_texture_compression_pvrtc")) {
  4170. has_pvrtc = true;
  4171. }
  4172. else if (strstr(ext, "_compressed_texture_etc")) {
  4173. has_etc2 = true;
  4174. }
  4175. else if (strstr(ext, "_color_buffer_float")) {
  4176. has_colorbuffer_float = true;
  4177. }
  4178. else if (strstr(ext, "_color_buffer_half_float")) {
  4179. has_colorbuffer_half_float = true;
  4180. }
  4181. else if (strstr(ext, "_texture_float_linear")) {
  4182. has_texture_float_linear = true;
  4183. }
  4184. else if (strstr(ext, "_float_blend")) {
  4185. has_float_blend = true;
  4186. }
  4187. else if (strstr(ext, "_texture_filter_anisotropic")) {
  4188. _sg.gl.ext_anisotropic = true;
  4189. }
  4190. }
  4191. }
  4192. /* limits */
  4193. _sg_gl_init_limits();
  4194. /* pixel formats */
  4195. const bool has_texture_half_float_linear = true;
  4196. const bool has_bgra = false; /* not a bug */
  4197. _sg_gl_init_pixelformats(has_bgra);
  4198. _sg_gl_init_pixelformats_float(has_colorbuffer_float, has_texture_float_linear, has_float_blend);
  4199. _sg_gl_init_pixelformats_half_float(has_colorbuffer_half_float, has_texture_half_float_linear);
  4200. if (has_s3tc) {
  4201. _sg_gl_init_pixelformats_s3tc();
  4202. }
  4203. if (has_rgtc) {
  4204. _sg_gl_init_pixelformats_rgtc();
  4205. }
  4206. if (has_bptc) {
  4207. _sg_gl_init_pixelformats_bptc();
  4208. }
  4209. if (has_pvrtc) {
  4210. _sg_gl_init_pixelformats_pvrtc();
  4211. }
  4212. if (has_etc2) {
  4213. _sg_gl_init_pixelformats_etc2();
  4214. }
  4215. }
  4216. #endif
  4217. #if defined(SOKOL_GLES3) || defined(SOKOL_GLES2)
  4218. _SOKOL_PRIVATE void _sg_gl_init_caps_gles2(void) {
  4219. _sg.backend = SG_BACKEND_GLES2;
  4220. bool has_s3tc = false; /* BC1..BC3 */
  4221. bool has_rgtc = false; /* BC4 and BC5 */
  4222. bool has_bptc = false; /* BC6H and BC7 */
  4223. bool has_pvrtc = false;
  4224. bool has_etc2 = false;
  4225. bool has_texture_float = false;
  4226. bool has_texture_float_linear = false;
  4227. bool has_colorbuffer_float = false;
  4228. bool has_float_blend = false;
  4229. bool has_instancing = false;
  4230. const char* ext = (const char*) glGetString(GL_EXTENSIONS);
  4231. if (ext) {
  4232. has_s3tc = strstr(ext, "_texture_compression_s3tc") || strstr(ext, "_compressed_texture_s3tc");
  4233. has_rgtc = strstr(ext, "_texture_compression_rgtc");
  4234. has_bptc = strstr(ext, "_texture_compression_bptc");
  4235. has_pvrtc = strstr(ext, "_texture_compression_pvrtc");
  4236. has_etc2 = strstr(ext, "_compressed_texture_etc");
  4237. has_texture_float = strstr(ext, "_texture_float");
  4238. has_texture_float_linear = strstr(ext, "_texture_float_linear");
  4239. has_colorbuffer_float = strstr(ext, "_color_buffer_float");
  4240. has_float_blend = strstr(ext, "_float_blend");
  4241. /* don't bother with half_float support on WebGL1
  4242. has_texture_half_float = strstr(ext, "_texture_half_float");
  4243. has_texture_half_float_linear = strstr(ext, "_texture_half_float_linear");
  4244. has_colorbuffer_half_float = strstr(ext, "_color_buffer_half_float");
  4245. */
  4246. has_instancing = strstr(ext, "_instanced_arrays");
  4247. _sg.gl.ext_anisotropic = strstr(ext, "ext_anisotropic");
  4248. }
  4249. _sg.features.origin_top_left = false;
  4250. #if defined(SOKOL_INSTANCING_ENABLED)
  4251. _sg.features.instancing = has_instancing;
  4252. #endif
  4253. _sg.features.multiple_render_targets = false;
  4254. _sg.features.msaa_render_targets = false;
  4255. _sg.features.imagetype_3d = false;
  4256. _sg.features.imagetype_array = false;
  4257. _sg.features.image_clamp_to_border = false;
  4258. /* limits */
  4259. _sg_gl_init_limits();
  4260. /* pixel formats */
  4261. const bool has_bgra = false; /* not a bug */
  4262. const bool has_texture_half_float = false;
  4263. const bool has_texture_half_float_linear = false;
  4264. const bool has_colorbuffer_half_float = false;
  4265. _sg_gl_init_pixelformats(has_bgra);
  4266. if (has_texture_float) {
  4267. _sg_gl_init_pixelformats_float(has_colorbuffer_float, has_texture_float_linear, has_float_blend);
  4268. }
  4269. if (has_texture_half_float) {
  4270. _sg_gl_init_pixelformats_half_float(has_colorbuffer_half_float, has_texture_half_float_linear);
  4271. }
  4272. if (has_s3tc) {
  4273. _sg_gl_init_pixelformats_s3tc();
  4274. }
  4275. if (has_rgtc) {
  4276. _sg_gl_init_pixelformats_rgtc();
  4277. }
  4278. if (has_bptc) {
  4279. _sg_gl_init_pixelformats_bptc();
  4280. }
  4281. if (has_pvrtc) {
  4282. _sg_gl_init_pixelformats_pvrtc();
  4283. }
  4284. if (has_etc2) {
  4285. _sg_gl_init_pixelformats_etc2();
  4286. }
  4287. /* GLES2 doesn't allow multi-sampled render targets at all */
  4288. for (int i = 0; i < _SG_PIXELFORMAT_NUM; i++) {
  4289. _sg.formats[i].msaa = false;
  4290. }
  4291. }
  4292. #endif
  4293. /*-- state cache implementation ----------------------------------------------*/
  4294. _SOKOL_PRIVATE void _sg_gl_clear_buffer_bindings(bool force) {
  4295. if (force || (_sg.gl.cache.vertex_buffer != 0)) {
  4296. glBindBuffer(GL_ARRAY_BUFFER, 0);
  4297. _sg.gl.cache.vertex_buffer = 0;
  4298. }
  4299. if (force || (_sg.gl.cache.index_buffer != 0)) {
  4300. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  4301. _sg.gl.cache.index_buffer = 0;
  4302. }
  4303. }
  4304. _SOKOL_PRIVATE void _sg_gl_bind_buffer(GLenum target, GLuint buffer) {
  4305. SOKOL_ASSERT((GL_ARRAY_BUFFER == target) || (GL_ELEMENT_ARRAY_BUFFER == target));
  4306. if (target == GL_ARRAY_BUFFER) {
  4307. if (_sg.gl.cache.vertex_buffer != buffer) {
  4308. _sg.gl.cache.vertex_buffer = buffer;
  4309. glBindBuffer(target, buffer);
  4310. }
  4311. }
  4312. else {
  4313. if (_sg.gl.cache.index_buffer != buffer) {
  4314. _sg.gl.cache.index_buffer = buffer;
  4315. glBindBuffer(target, buffer);
  4316. }
  4317. }
  4318. }
  4319. _SOKOL_PRIVATE void _sg_gl_store_buffer_binding(GLenum target) {
  4320. if (target == GL_ARRAY_BUFFER) {
  4321. _sg.gl.cache.stored_vertex_buffer = _sg.gl.cache.vertex_buffer;
  4322. }
  4323. else {
  4324. _sg.gl.cache.stored_index_buffer = _sg.gl.cache.index_buffer;
  4325. }
  4326. }
  4327. _SOKOL_PRIVATE void _sg_gl_restore_buffer_binding(GLenum target) {
  4328. if (target == GL_ARRAY_BUFFER) {
  4329. _sg_gl_bind_buffer(target, _sg.gl.cache.stored_vertex_buffer);
  4330. }
  4331. else {
  4332. _sg_gl_bind_buffer(target, _sg.gl.cache.stored_index_buffer);
  4333. }
  4334. }
  4335. _SOKOL_PRIVATE void _sg_gl_clear_texture_bindings(bool force) {
  4336. for (int i = 0; (i < SG_MAX_SHADERSTAGE_IMAGES) && (i < _sg.gl.max_combined_texture_image_units); i++) {
  4337. if (force || (_sg.gl.cache.textures[i].texture != 0)) {
  4338. glActiveTexture(GL_TEXTURE0 + i);
  4339. glBindTexture(GL_TEXTURE_2D, 0);
  4340. glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  4341. #if !defined(SOKOL_GLES2)
  4342. if (!_sg.gl.gles2) {
  4343. glBindTexture(GL_TEXTURE_3D, 0);
  4344. glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
  4345. }
  4346. #endif
  4347. _sg.gl.cache.textures[i].target = 0;
  4348. _sg.gl.cache.textures[i].texture = 0;
  4349. }
  4350. }
  4351. }
  4352. _SOKOL_PRIVATE void _sg_gl_bind_texture(int slot_index, GLenum target, GLuint texture) {
  4353. /* it's valid to call this function with target=0 and/or texture=0
  4354. target=0 will unbind the previous binding, texture=0 will clear
  4355. the new binding
  4356. */
  4357. SOKOL_ASSERT(slot_index < SG_MAX_SHADERSTAGE_IMAGES);
  4358. if (slot_index >= _sg.gl.max_combined_texture_image_units) {
  4359. return;
  4360. }
  4361. _sg_gl_texture_bind_slot* slot = &_sg.gl.cache.textures[slot_index];
  4362. if ((slot->target != target) || (slot->texture != texture)) {
  4363. glActiveTexture(GL_TEXTURE0 + slot_index);
  4364. /* if the target has changed, clear the previous binding on that target */
  4365. if ((target != slot->target) && (slot->target != 0)) {
  4366. glBindTexture(slot->target, 0);
  4367. }
  4368. /* apply new binding (texture can be 0 to unbind) */
  4369. if (target != 0) {
  4370. glBindTexture(target, texture);
  4371. }
  4372. slot->target = target;
  4373. slot->texture = texture;
  4374. }
  4375. }
  4376. _SOKOL_PRIVATE void _sg_gl_store_texture_binding(int slot_index) {
  4377. SOKOL_ASSERT(slot_index < SG_MAX_SHADERSTAGE_IMAGES);
  4378. _sg.gl.cache.stored_texture = _sg.gl.cache.textures[slot_index];
  4379. }
  4380. _SOKOL_PRIVATE void _sg_gl_restore_texture_binding(int slot_index) {
  4381. SOKOL_ASSERT(slot_index < SG_MAX_SHADERSTAGE_IMAGES);
  4382. const _sg_gl_texture_bind_slot* slot = &_sg.gl.cache.stored_texture;
  4383. _sg_gl_bind_texture(slot_index, slot->target, slot->texture);
  4384. }
  4385. _SOKOL_PRIVATE void _sg_gl_setup_backend(const sg_desc* desc) {
  4386. /* assumes that _sg.gl is already zero-initialized */
  4387. _sg.gl.valid = true;
  4388. #if defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
  4389. _sg.gl.gles2 = desc->gl_force_gles2;
  4390. #else
  4391. _SOKOL_UNUSED(desc);
  4392. _sg.gl.gles2 = false;
  4393. #endif
  4394. /* clear initial GL error state */
  4395. #if defined(SOKOL_DEBUG)
  4396. while (glGetError() != GL_NO_ERROR);
  4397. #endif
  4398. #if defined(SOKOL_GLCORE33)
  4399. _sg_gl_init_caps_glcore33();
  4400. #elif defined(SOKOL_GLES3)
  4401. if (_sg.gl.gles2) {
  4402. _sg_gl_init_caps_gles2();
  4403. }
  4404. else {
  4405. _sg_gl_init_caps_gles3();
  4406. }
  4407. #else
  4408. _sg_gl_init_caps_gles2();
  4409. #endif
  4410. }
  4411. _SOKOL_PRIVATE void _sg_gl_discard_backend(void) {
  4412. SOKOL_ASSERT(_sg.gl.valid);
  4413. _sg.gl.valid = false;
  4414. }
  4415. _SOKOL_PRIVATE void _sg_gl_reset_state_cache(void) {
  4416. if (_sg.gl.cur_context) {
  4417. _SG_GL_CHECK_ERROR();
  4418. #if !defined(SOKOL_GLES2)
  4419. if (!_sg.gl.gles2) {
  4420. glBindVertexArray(_sg.gl.cur_context->vao);
  4421. _SG_GL_CHECK_ERROR();
  4422. }
  4423. #endif
  4424. memset(&_sg.gl.cache, 0, sizeof(_sg.gl.cache));
  4425. _sg_gl_clear_buffer_bindings(true);
  4426. _SG_GL_CHECK_ERROR();
  4427. _sg_gl_clear_texture_bindings(true);
  4428. _SG_GL_CHECK_ERROR();
  4429. for (uint32_t i = 0; i < _sg.limits.max_vertex_attrs; i++) {
  4430. _sg_gl_init_attr(&_sg.gl.cache.attrs[i].gl_attr);
  4431. glDisableVertexAttribArray(i);
  4432. _SG_GL_CHECK_ERROR();
  4433. }
  4434. _sg.gl.cache.cur_primitive_type = GL_TRIANGLES;
  4435. /* depth-stencil state */
  4436. _sg_gl_init_depth_stencil_state(&_sg.gl.cache.ds);
  4437. glEnable(GL_DEPTH_TEST);
  4438. glDepthFunc(GL_ALWAYS);
  4439. glDepthMask(GL_FALSE);
  4440. glDisable(GL_STENCIL_TEST);
  4441. glStencilFunc(GL_ALWAYS, 0, 0);
  4442. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  4443. glStencilMask(0);
  4444. /* blend state */
  4445. _sg_gl_init_blend_state(&_sg.gl.cache.blend);
  4446. glDisable(GL_BLEND);
  4447. glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
  4448. glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
  4449. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  4450. glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);
  4451. /* rasterizer state */
  4452. _sg_gl_init_rasterizer_state(&_sg.gl.cache.rast);
  4453. glPolygonOffset(0.0f, 0.0f);
  4454. glDisable(GL_POLYGON_OFFSET_FILL);
  4455. glDisable(GL_CULL_FACE);
  4456. glFrontFace(GL_CW);
  4457. glCullFace(GL_BACK);
  4458. glEnable(GL_SCISSOR_TEST);
  4459. glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
  4460. glEnable(GL_DITHER);
  4461. glDisable(GL_POLYGON_OFFSET_FILL);
  4462. #if defined(SOKOL_GLCORE33)
  4463. glEnable(GL_MULTISAMPLE);
  4464. glEnable(GL_PROGRAM_POINT_SIZE);
  4465. #endif
  4466. }
  4467. }
  4468. _SOKOL_PRIVATE void _sg_gl_activate_context(_sg_context_t* ctx) {
  4469. SOKOL_ASSERT(_sg.gl.valid);
  4470. /* NOTE: ctx can be 0 to unset the current context */
  4471. _sg.gl.cur_context = ctx;
  4472. _sg_gl_reset_state_cache();
  4473. }
  4474. /*-- GL backend resource creation and destruction ----------------------------*/
  4475. _SOKOL_PRIVATE sg_resource_state _sg_gl_create_context(_sg_context_t* ctx) {
  4476. SOKOL_ASSERT(ctx);
  4477. SOKOL_ASSERT(0 == ctx->default_framebuffer);
  4478. _SG_GL_CHECK_ERROR();
  4479. glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&ctx->default_framebuffer);
  4480. _SG_GL_CHECK_ERROR();
  4481. #if !defined(SOKOL_GLES2)
  4482. if (!_sg.gl.gles2) {
  4483. SOKOL_ASSERT(0 == ctx->vao);
  4484. glGenVertexArrays(1, &ctx->vao);
  4485. glBindVertexArray(ctx->vao);
  4486. _SG_GL_CHECK_ERROR();
  4487. }
  4488. #endif
  4489. return SG_RESOURCESTATE_VALID;
  4490. }
  4491. _SOKOL_PRIVATE void _sg_gl_destroy_context(_sg_context_t* ctx) {
  4492. SOKOL_ASSERT(ctx);
  4493. #if !defined(SOKOL_GLES2)
  4494. if (!_sg.gl.gles2) {
  4495. if (ctx->vao) {
  4496. glDeleteVertexArrays(1, &ctx->vao);
  4497. }
  4498. _SG_GL_CHECK_ERROR();
  4499. }
  4500. #endif
  4501. }
  4502. _SOKOL_PRIVATE sg_resource_state _sg_gl_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {
  4503. SOKOL_ASSERT(buf && desc);
  4504. _SG_GL_CHECK_ERROR();
  4505. _sg_buffer_common_init(&buf->cmn, desc);
  4506. buf->gl.ext_buffers = (0 != desc->gl_buffers[0]);
  4507. GLenum gl_target = _sg_gl_buffer_target(buf->cmn.type);
  4508. GLenum gl_usage = _sg_gl_usage(buf->cmn.usage);
  4509. for (int slot = 0; slot < buf->cmn.num_slots; slot++) {
  4510. GLuint gl_buf = 0;
  4511. if (buf->gl.ext_buffers) {
  4512. SOKOL_ASSERT(desc->gl_buffers[slot]);
  4513. gl_buf = desc->gl_buffers[slot];
  4514. }
  4515. else {
  4516. glGenBuffers(1, &gl_buf);
  4517. _sg_gl_store_buffer_binding(gl_target);
  4518. _sg_gl_bind_buffer(gl_target, gl_buf);
  4519. glBufferData(gl_target, buf->cmn.size, 0, gl_usage);
  4520. if (buf->cmn.usage == SG_USAGE_IMMUTABLE) {
  4521. SOKOL_ASSERT(desc->content);
  4522. glBufferSubData(gl_target, 0, buf->cmn.size, desc->content);
  4523. }
  4524. _sg_gl_restore_buffer_binding(gl_target);
  4525. }
  4526. buf->gl.buf[slot] = gl_buf;
  4527. }
  4528. _SG_GL_CHECK_ERROR();
  4529. return SG_RESOURCESTATE_VALID;
  4530. }
  4531. _SOKOL_PRIVATE void _sg_gl_destroy_buffer(_sg_buffer_t* buf) {
  4532. SOKOL_ASSERT(buf);
  4533. _SG_GL_CHECK_ERROR();
  4534. if (!buf->gl.ext_buffers) {
  4535. for (int slot = 0; slot < buf->cmn.num_slots; slot++) {
  4536. if (buf->gl.buf[slot]) {
  4537. glDeleteBuffers(1, &buf->gl.buf[slot]);
  4538. }
  4539. }
  4540. _SG_GL_CHECK_ERROR();
  4541. }
  4542. }
  4543. _SOKOL_PRIVATE bool _sg_gl_supported_texture_format(sg_pixel_format fmt) {
  4544. const int fmt_index = (int) fmt;
  4545. SOKOL_ASSERT((fmt_index > SG_PIXELFORMAT_NONE) && (fmt_index < _SG_PIXELFORMAT_NUM));
  4546. return _sg.formats[fmt_index].sample;
  4547. }
  4548. _SOKOL_PRIVATE sg_resource_state _sg_gl_create_image(_sg_image_t* img, const sg_image_desc* desc) {
  4549. SOKOL_ASSERT(img && desc);
  4550. _SG_GL_CHECK_ERROR();
  4551. _sg_image_common_init(&img->cmn, desc);
  4552. img->gl.ext_textures = (0 != desc->gl_textures[0]);
  4553. /* check if texture format is support */
  4554. if (!_sg_gl_supported_texture_format(img->cmn.pixel_format)) {
  4555. SOKOL_LOG("texture format not supported by GL context\n");
  4556. return SG_RESOURCESTATE_FAILED;
  4557. }
  4558. /* check for optional texture types */
  4559. if ((img->cmn.type == SG_IMAGETYPE_3D) && !_sg.features.imagetype_3d) {
  4560. SOKOL_LOG("3D textures not supported by GL context\n");
  4561. return SG_RESOURCESTATE_FAILED;
  4562. }
  4563. if ((img->cmn.type == SG_IMAGETYPE_ARRAY) && !_sg.features.imagetype_array) {
  4564. SOKOL_LOG("array textures not supported by GL context\n");
  4565. return SG_RESOURCESTATE_FAILED;
  4566. }
  4567. #if !defined(SOKOL_GLES2)
  4568. bool msaa = false;
  4569. if (!_sg.gl.gles2) {
  4570. msaa = (img->cmn.sample_count > 1) && (_sg.features.msaa_render_targets);
  4571. }
  4572. #endif
  4573. if (_sg_is_valid_rendertarget_depth_format(img->cmn.pixel_format)) {
  4574. /* special case depth-stencil-buffer? */
  4575. SOKOL_ASSERT((img->cmn.usage == SG_USAGE_IMMUTABLE) && (img->cmn.num_slots == 1));
  4576. SOKOL_ASSERT(!img->gl.ext_textures); /* cannot provide external texture for depth images */
  4577. glGenRenderbuffers(1, &img->gl.depth_render_buffer);
  4578. glBindRenderbuffer(GL_RENDERBUFFER, img->gl.depth_render_buffer);
  4579. GLenum gl_depth_format = _sg_gl_depth_attachment_format(img->cmn.pixel_format);
  4580. #if !defined(SOKOL_GLES2)
  4581. if (!_sg.gl.gles2 && msaa) {
  4582. glRenderbufferStorageMultisample(GL_RENDERBUFFER, img->cmn.sample_count, gl_depth_format, img->cmn.width, img->cmn.height);
  4583. }
  4584. else
  4585. #endif
  4586. {
  4587. glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format, img->cmn.width, img->cmn.height);
  4588. }
  4589. }
  4590. else {
  4591. /* regular color texture */
  4592. img->gl.target = _sg_gl_texture_target(img->cmn.type);
  4593. const GLenum gl_internal_format = _sg_gl_teximage_internal_format(img->cmn.pixel_format);
  4594. /* if this is a MSAA render target, need to create a separate render buffer */
  4595. #if !defined(SOKOL_GLES2)
  4596. if (!_sg.gl.gles2 && img->cmn.render_target && msaa) {
  4597. glGenRenderbuffers(1, &img->gl.msaa_render_buffer);
  4598. glBindRenderbuffer(GL_RENDERBUFFER, img->gl.msaa_render_buffer);
  4599. glRenderbufferStorageMultisample(GL_RENDERBUFFER, img->cmn.sample_count, gl_internal_format, img->cmn.width, img->cmn.height);
  4600. }
  4601. #endif
  4602. if (img->gl.ext_textures) {
  4603. /* inject externally GL textures */
  4604. for (int slot = 0; slot < img->cmn.num_slots; slot++) {
  4605. SOKOL_ASSERT(desc->gl_textures[slot]);
  4606. img->gl.tex[slot] = desc->gl_textures[slot];
  4607. }
  4608. }
  4609. else {
  4610. /* create our own GL texture(s) */
  4611. const GLenum gl_format = _sg_gl_teximage_format(img->cmn.pixel_format);
  4612. const bool is_compressed = _sg_is_compressed_pixel_format(img->cmn.pixel_format);
  4613. for (int slot = 0; slot < img->cmn.num_slots; slot++) {
  4614. glGenTextures(1, &img->gl.tex[slot]);
  4615. _sg_gl_store_texture_binding(0);
  4616. _sg_gl_bind_texture(0, img->gl.target, img->gl.tex[slot]);
  4617. GLenum gl_min_filter = _sg_gl_filter(img->cmn.min_filter);
  4618. GLenum gl_mag_filter = _sg_gl_filter(img->cmn.mag_filter);
  4619. glTexParameteri(img->gl.target, GL_TEXTURE_MIN_FILTER, gl_min_filter);
  4620. glTexParameteri(img->gl.target, GL_TEXTURE_MAG_FILTER, gl_mag_filter);
  4621. if (_sg.gl.ext_anisotropic && (img->cmn.max_anisotropy > 1)) {
  4622. GLint max_aniso = (GLint) img->cmn.max_anisotropy;
  4623. if (max_aniso > _sg.gl.max_anisotropy) {
  4624. max_aniso = _sg.gl.max_anisotropy;
  4625. }
  4626. glTexParameteri(img->gl.target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso);
  4627. }
  4628. if (img->cmn.type == SG_IMAGETYPE_CUBE) {
  4629. glTexParameteri(img->gl.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  4630. glTexParameteri(img->gl.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  4631. }
  4632. else {
  4633. glTexParameteri(img->gl.target, GL_TEXTURE_WRAP_S, _sg_gl_wrap(img->cmn.wrap_u));
  4634. glTexParameteri(img->gl.target, GL_TEXTURE_WRAP_T, _sg_gl_wrap(img->cmn.wrap_v));
  4635. #if !defined(SOKOL_GLES2)
  4636. if (!_sg.gl.gles2 && (img->cmn.type == SG_IMAGETYPE_3D)) {
  4637. glTexParameteri(img->gl.target, GL_TEXTURE_WRAP_R, _sg_gl_wrap(img->cmn.wrap_w));
  4638. }
  4639. #endif
  4640. #if defined(SOKOL_GLCORE33)
  4641. float border[4];
  4642. switch (img->cmn.border_color) {
  4643. case SG_BORDERCOLOR_TRANSPARENT_BLACK:
  4644. border[0] = 0.0f; border[1] = 0.0f; border[2] = 0.0f; border[3] = 0.0f;
  4645. break;
  4646. case SG_BORDERCOLOR_OPAQUE_WHITE:
  4647. border[0] = 1.0f; border[1] = 1.0f; border[2] = 1.0f; border[3] = 1.0f;
  4648. break;
  4649. default:
  4650. border[0] = 0.0f; border[1] = 0.0f; border[2] = 0.0f; border[3] = 1.0f;
  4651. break;
  4652. }
  4653. glTexParameterfv(img->gl.target, GL_TEXTURE_BORDER_COLOR, border);
  4654. #endif
  4655. }
  4656. #if !defined(SOKOL_GLES2)
  4657. if (!_sg.gl.gles2) {
  4658. /* GL spec has strange defaults for mipmap min/max lod: -1000 to +1000 */
  4659. const float min_lod = _sg_clamp(desc->min_lod, 0.0f, 1000.0f);
  4660. const float max_lod = _sg_clamp(desc->max_lod, 0.0f, 1000.0f);
  4661. glTexParameterf(img->gl.target, GL_TEXTURE_MIN_LOD, min_lod);
  4662. glTexParameterf(img->gl.target, GL_TEXTURE_MAX_LOD, max_lod);
  4663. }
  4664. #endif
  4665. const int num_faces = img->cmn.type == SG_IMAGETYPE_CUBE ? 6 : 1;
  4666. int data_index = 0;
  4667. for (int face_index = 0; face_index < num_faces; face_index++) {
  4668. for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++, data_index++) {
  4669. GLenum gl_img_target = img->gl.target;
  4670. if (SG_IMAGETYPE_CUBE == img->cmn.type) {
  4671. gl_img_target = _sg_gl_cubeface_target(face_index);
  4672. }
  4673. const GLvoid* data_ptr = desc->content.subimage[face_index][mip_index].ptr;
  4674. const int data_size = desc->content.subimage[face_index][mip_index].size;
  4675. int mip_width = img->cmn.width >> mip_index;
  4676. if (mip_width == 0) {
  4677. mip_width = 1;
  4678. }
  4679. int mip_height = img->cmn.height >> mip_index;
  4680. if (mip_height == 0) {
  4681. mip_height = 1;
  4682. }
  4683. if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {
  4684. if (is_compressed) {
  4685. glCompressedTexImage2D(gl_img_target, mip_index, gl_internal_format,
  4686. mip_width, mip_height, 0, data_size, data_ptr);
  4687. }
  4688. else {
  4689. const GLenum gl_type = _sg_gl_teximage_type(img->cmn.pixel_format);
  4690. glTexImage2D(gl_img_target, mip_index, gl_internal_format,
  4691. mip_width, mip_height, 0, gl_format, gl_type, data_ptr);
  4692. }
  4693. }
  4694. #if !defined(SOKOL_GLES2)
  4695. else if (!_sg.gl.gles2 && ((SG_IMAGETYPE_3D == img->cmn.type) || (SG_IMAGETYPE_ARRAY == img->cmn.type))) {
  4696. int mip_depth = img->cmn.depth;
  4697. if (SG_IMAGETYPE_3D == img->cmn.type) {
  4698. mip_depth >>= mip_index;
  4699. }
  4700. if (mip_depth == 0) {
  4701. mip_depth = 1;
  4702. }
  4703. if (is_compressed) {
  4704. glCompressedTexImage3D(gl_img_target, mip_index, gl_internal_format,
  4705. mip_width, mip_height, mip_depth, 0, data_size, data_ptr);
  4706. }
  4707. else {
  4708. const GLenum gl_type = _sg_gl_teximage_type(img->cmn.pixel_format);
  4709. glTexImage3D(gl_img_target, mip_index, gl_internal_format,
  4710. mip_width, mip_height, mip_depth, 0, gl_format, gl_type, data_ptr);
  4711. }
  4712. }
  4713. #endif
  4714. }
  4715. }
  4716. _sg_gl_restore_texture_binding(0);
  4717. }
  4718. }
  4719. }
  4720. _SG_GL_CHECK_ERROR();
  4721. return SG_RESOURCESTATE_VALID;
  4722. }
  4723. _SOKOL_PRIVATE void _sg_gl_destroy_image(_sg_image_t* img) {
  4724. SOKOL_ASSERT(img);
  4725. _SG_GL_CHECK_ERROR();
  4726. if (!img->gl.ext_textures) {
  4727. for (int slot = 0; slot < img->cmn.num_slots; slot++) {
  4728. if (img->gl.tex[slot]) {
  4729. glDeleteTextures(1, &img->gl.tex[slot]);
  4730. }
  4731. }
  4732. }
  4733. if (img->gl.depth_render_buffer) {
  4734. glDeleteRenderbuffers(1, &img->gl.depth_render_buffer);
  4735. }
  4736. if (img->gl.msaa_render_buffer) {
  4737. glDeleteRenderbuffers(1, &img->gl.msaa_render_buffer);
  4738. }
  4739. _SG_GL_CHECK_ERROR();
  4740. }
  4741. _SOKOL_PRIVATE GLuint _sg_gl_compile_shader(sg_shader_stage stage, const char* src) {
  4742. SOKOL_ASSERT(src);
  4743. _SG_GL_CHECK_ERROR();
  4744. GLuint gl_shd = glCreateShader(_sg_gl_shader_stage(stage));
  4745. glShaderSource(gl_shd, 1, &src, 0);
  4746. glCompileShader(gl_shd);
  4747. GLint compile_status = 0;
  4748. glGetShaderiv(gl_shd, GL_COMPILE_STATUS, &compile_status);
  4749. if (!compile_status) {
  4750. /* compilation failed, log error and delete shader */
  4751. GLint log_len = 0;
  4752. glGetShaderiv(gl_shd, GL_INFO_LOG_LENGTH, &log_len);
  4753. if (log_len > 0) {
  4754. GLchar* log_buf = (GLchar*) SOKOL_MALLOC(log_len);
  4755. glGetShaderInfoLog(gl_shd, log_len, &log_len, log_buf);
  4756. SOKOL_LOG(log_buf);
  4757. SOKOL_FREE(log_buf);
  4758. }
  4759. glDeleteShader(gl_shd);
  4760. gl_shd = 0;
  4761. }
  4762. _SG_GL_CHECK_ERROR();
  4763. return gl_shd;
  4764. }
  4765. _SOKOL_PRIVATE sg_resource_state _sg_gl_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {
  4766. SOKOL_ASSERT(shd && desc);
  4767. SOKOL_ASSERT(!shd->gl.prog);
  4768. _SG_GL_CHECK_ERROR();
  4769. _sg_shader_common_init(&shd->cmn, desc);
  4770. /* copy vertex attribute names over, these are required for GLES2, and optional for GLES3 and GL3.x */
  4771. for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
  4772. _sg_strcpy(&shd->gl.attrs[i].name, desc->attrs[i].name);
  4773. }
  4774. GLuint gl_vs = _sg_gl_compile_shader(SG_SHADERSTAGE_VS, desc->vs.source);
  4775. GLuint gl_fs = _sg_gl_compile_shader(SG_SHADERSTAGE_FS, desc->fs.source);
  4776. if (!(gl_vs && gl_fs)) {
  4777. return SG_RESOURCESTATE_FAILED;
  4778. }
  4779. GLuint gl_prog = glCreateProgram();
  4780. glAttachShader(gl_prog, gl_vs);
  4781. glAttachShader(gl_prog, gl_fs);
  4782. glLinkProgram(gl_prog);
  4783. glDeleteShader(gl_vs);
  4784. glDeleteShader(gl_fs);
  4785. _SG_GL_CHECK_ERROR();
  4786. GLint link_status;
  4787. glGetProgramiv(gl_prog, GL_LINK_STATUS, &link_status);
  4788. if (!link_status) {
  4789. GLint log_len = 0;
  4790. glGetProgramiv(gl_prog, GL_INFO_LOG_LENGTH, &log_len);
  4791. if (log_len > 0) {
  4792. GLchar* log_buf = (GLchar*) SOKOL_MALLOC(log_len);
  4793. glGetProgramInfoLog(gl_prog, log_len, &log_len, log_buf);
  4794. SOKOL_LOG(log_buf);
  4795. SOKOL_FREE(log_buf);
  4796. }
  4797. glDeleteProgram(gl_prog);
  4798. return SG_RESOURCESTATE_FAILED;
  4799. }
  4800. shd->gl.prog = gl_prog;
  4801. /* resolve uniforms */
  4802. _SG_GL_CHECK_ERROR();
  4803. for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {
  4804. const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS)? &desc->vs : &desc->fs;
  4805. _sg_gl_shader_stage_t* gl_stage = &shd->gl.stage[stage_index];
  4806. for (int ub_index = 0; ub_index < shd->cmn.stage[stage_index].num_uniform_blocks; ub_index++) {
  4807. const sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_index];
  4808. SOKOL_ASSERT(ub_desc->size > 0);
  4809. _sg_gl_uniform_block_t* ub = &gl_stage->uniform_blocks[ub_index];
  4810. SOKOL_ASSERT(ub->num_uniforms == 0);
  4811. int cur_uniform_offset = 0;
  4812. for (int u_index = 0; u_index < SG_MAX_UB_MEMBERS; u_index++) {
  4813. const sg_shader_uniform_desc* u_desc = &ub_desc->uniforms[u_index];
  4814. if (u_desc->type == SG_UNIFORMTYPE_INVALID) {
  4815. break;
  4816. }
  4817. _sg_gl_uniform_t* u = &ub->uniforms[u_index];
  4818. u->type = u_desc->type;
  4819. u->count = (uint8_t) u_desc->array_count;
  4820. u->offset = (uint16_t) cur_uniform_offset;
  4821. cur_uniform_offset += _sg_uniform_size(u->type, u->count);
  4822. if (u_desc->name) {
  4823. u->gl_loc = glGetUniformLocation(gl_prog, u_desc->name);
  4824. }
  4825. else {
  4826. u->gl_loc = u_index;
  4827. }
  4828. ub->num_uniforms++;
  4829. }
  4830. SOKOL_ASSERT(ub_desc->size == cur_uniform_offset);
  4831. }
  4832. }
  4833. /* resolve image locations */
  4834. _SG_GL_CHECK_ERROR();
  4835. int gl_tex_slot = 0;
  4836. for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {
  4837. const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS)? &desc->vs : &desc->fs;
  4838. _sg_gl_shader_stage_t* gl_stage = &shd->gl.stage[stage_index];
  4839. for (int img_index = 0; img_index < shd->cmn.stage[stage_index].num_images; img_index++) {
  4840. const sg_shader_image_desc* img_desc = &stage_desc->images[img_index];
  4841. SOKOL_ASSERT(img_desc->type != _SG_IMAGETYPE_DEFAULT);
  4842. _sg_gl_shader_image_t* gl_img = &gl_stage->images[img_index];
  4843. gl_img->gl_loc = img_index;
  4844. if (img_desc->name) {
  4845. gl_img->gl_loc = glGetUniformLocation(gl_prog, img_desc->name);
  4846. }
  4847. if (gl_img->gl_loc != -1) {
  4848. gl_img->gl_tex_slot = gl_tex_slot++;
  4849. }
  4850. else {
  4851. gl_img->gl_tex_slot = -1;
  4852. }
  4853. }
  4854. }
  4855. _SG_GL_CHECK_ERROR();
  4856. return SG_RESOURCESTATE_VALID;
  4857. }
  4858. _SOKOL_PRIVATE void _sg_gl_destroy_shader(_sg_shader_t* shd) {
  4859. SOKOL_ASSERT(shd);
  4860. _SG_GL_CHECK_ERROR();
  4861. if (shd->gl.prog) {
  4862. glDeleteProgram(shd->gl.prog);
  4863. }
  4864. _SG_GL_CHECK_ERROR();
  4865. }
  4866. _SOKOL_PRIVATE sg_resource_state _sg_gl_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {
  4867. SOKOL_ASSERT(pip && shd && desc);
  4868. SOKOL_ASSERT(!pip->shader && pip->cmn.shader_id.id == SG_INVALID_ID);
  4869. SOKOL_ASSERT(desc->shader.id == shd->slot.id);
  4870. SOKOL_ASSERT(shd->gl.prog);
  4871. pip->shader = shd;
  4872. _sg_pipeline_common_init(&pip->cmn, desc);
  4873. pip->gl.primitive_type = desc->primitive_type;
  4874. pip->gl.depth_stencil = desc->depth_stencil;
  4875. pip->gl.blend = desc->blend;
  4876. pip->gl.rast = desc->rasterizer;
  4877. /* resolve vertex attributes */
  4878. for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
  4879. pip->gl.attrs[attr_index].vb_index = -1;
  4880. }
  4881. for (uint32_t attr_index = 0; attr_index < _sg.limits.max_vertex_attrs; attr_index++) {
  4882. const sg_vertex_attr_desc* a_desc = &desc->layout.attrs[attr_index];
  4883. if (a_desc->format == SG_VERTEXFORMAT_INVALID) {
  4884. break;
  4885. }
  4886. SOKOL_ASSERT((a_desc->buffer_index >= 0) && (a_desc->buffer_index < SG_MAX_SHADERSTAGE_BUFFERS));
  4887. const sg_buffer_layout_desc* l_desc = &desc->layout.buffers[a_desc->buffer_index];
  4888. const sg_vertex_step step_func = l_desc->step_func;
  4889. const int step_rate = l_desc->step_rate;
  4890. GLint attr_loc = attr_index;
  4891. if (!_sg_strempty(&shd->gl.attrs[attr_index].name)) {
  4892. attr_loc = glGetAttribLocation(pip->shader->gl.prog, _sg_strptr(&shd->gl.attrs[attr_index].name));
  4893. }
  4894. SOKOL_ASSERT(attr_loc < (GLint)_sg.limits.max_vertex_attrs);
  4895. if (attr_loc != -1) {
  4896. _sg_gl_attr_t* gl_attr = &pip->gl.attrs[attr_loc];
  4897. SOKOL_ASSERT(gl_attr->vb_index == -1);
  4898. gl_attr->vb_index = (int8_t) a_desc->buffer_index;
  4899. if (step_func == SG_VERTEXSTEP_PER_VERTEX) {
  4900. gl_attr->divisor = 0;
  4901. }
  4902. else {
  4903. gl_attr->divisor = (int8_t) step_rate;
  4904. }
  4905. SOKOL_ASSERT(l_desc->stride > 0);
  4906. gl_attr->stride = (uint8_t) l_desc->stride;
  4907. gl_attr->offset = a_desc->offset;
  4908. gl_attr->size = (uint8_t) _sg_gl_vertexformat_size(a_desc->format);
  4909. gl_attr->type = _sg_gl_vertexformat_type(a_desc->format);
  4910. gl_attr->normalized = _sg_gl_vertexformat_normalized(a_desc->format);
  4911. pip->cmn.vertex_layout_valid[a_desc->buffer_index] = true;
  4912. }
  4913. else {
  4914. SOKOL_LOG("Vertex attribute not found in shader: ");
  4915. SOKOL_LOG(_sg_strptr(&shd->gl.attrs[attr_index].name));
  4916. }
  4917. }
  4918. return SG_RESOURCESTATE_VALID;
  4919. }
  4920. _SOKOL_PRIVATE void _sg_gl_destroy_pipeline(_sg_pipeline_t* pip) {
  4921. SOKOL_ASSERT(pip);
  4922. /* empty */
  4923. }
  4924. /*
  4925. _sg_create_pass
  4926. att_imgs must point to a _sg_image* att_imgs[SG_MAX_COLOR_ATTACHMENTS+1] array,
  4927. first entries are the color attachment images (or nullptr), last entry
  4928. is the depth-stencil image (or nullptr).
  4929. */
  4930. _SOKOL_PRIVATE sg_resource_state _sg_gl_create_pass(_sg_pass_t* pass, _sg_image_t** att_images, const sg_pass_desc* desc) {
  4931. SOKOL_ASSERT(pass && att_images && desc);
  4932. SOKOL_ASSERT(att_images && att_images[0]);
  4933. _SG_GL_CHECK_ERROR();
  4934. _sg_pass_common_init(&pass->cmn, desc);
  4935. /* copy image pointers */
  4936. const sg_attachment_desc* att_desc;
  4937. for (int i = 0; i < pass->cmn.num_color_atts; i++) {
  4938. att_desc = &desc->color_attachments[i];
  4939. SOKOL_ASSERT(att_desc->image.id != SG_INVALID_ID);
  4940. SOKOL_ASSERT(0 == pass->gl.color_atts[i].image);
  4941. SOKOL_ASSERT(att_images[i] && (att_images[i]->slot.id == att_desc->image.id));
  4942. SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(att_images[i]->cmn.pixel_format));
  4943. pass->gl.color_atts[i].image = att_images[i];
  4944. }
  4945. SOKOL_ASSERT(0 == pass->gl.ds_att.image);
  4946. att_desc = &desc->depth_stencil_attachment;
  4947. if (att_desc->image.id != SG_INVALID_ID) {
  4948. const int ds_img_index = SG_MAX_COLOR_ATTACHMENTS;
  4949. SOKOL_ASSERT(att_images[ds_img_index] && (att_images[ds_img_index]->slot.id == att_desc->image.id));
  4950. SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(att_images[ds_img_index]->cmn.pixel_format));
  4951. pass->gl.ds_att.image = att_images[ds_img_index];
  4952. }
  4953. /* store current framebuffer binding (restored at end of function) */
  4954. GLuint gl_orig_fb;
  4955. glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&gl_orig_fb);
  4956. /* create a framebuffer object */
  4957. glGenFramebuffers(1, &pass->gl.fb);
  4958. glBindFramebuffer(GL_FRAMEBUFFER, pass->gl.fb);
  4959. /* attach msaa render buffer or textures */
  4960. const bool is_msaa = (0 != att_images[0]->gl.msaa_render_buffer);
  4961. if (is_msaa) {
  4962. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  4963. const _sg_image_t* att_img = pass->gl.color_atts[i].image;
  4964. if (att_img) {
  4965. const GLuint gl_render_buffer = att_img->gl.msaa_render_buffer;
  4966. SOKOL_ASSERT(gl_render_buffer);
  4967. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, gl_render_buffer);
  4968. }
  4969. }
  4970. }
  4971. else {
  4972. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  4973. const _sg_image_t* att_img = pass->gl.color_atts[i].image;
  4974. const int mip_level = pass->cmn.color_atts[i].mip_level;
  4975. const int slice = pass->cmn.color_atts[i].slice;
  4976. if (att_img) {
  4977. const GLuint gl_tex = att_img->gl.tex[0];
  4978. SOKOL_ASSERT(gl_tex);
  4979. const GLenum gl_att = GL_COLOR_ATTACHMENT0 + i;
  4980. switch (att_img->cmn.type) {
  4981. case SG_IMAGETYPE_2D:
  4982. glFramebufferTexture2D(GL_FRAMEBUFFER, gl_att, GL_TEXTURE_2D, gl_tex, mip_level);
  4983. break;
  4984. case SG_IMAGETYPE_CUBE:
  4985. glFramebufferTexture2D(GL_FRAMEBUFFER, gl_att, _sg_gl_cubeface_target(slice), gl_tex, mip_level);
  4986. break;
  4987. default:
  4988. /* 3D- or array-texture */
  4989. #if !defined(SOKOL_GLES2)
  4990. if (!_sg.gl.gles2) {
  4991. glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_att, gl_tex, mip_level, slice);
  4992. }
  4993. #endif
  4994. break;
  4995. }
  4996. }
  4997. }
  4998. }
  4999. /* attach depth-stencil buffer to framebuffer */
  5000. if (pass->gl.ds_att.image) {
  5001. const GLuint gl_render_buffer = pass->gl.ds_att.image->gl.depth_render_buffer;
  5002. SOKOL_ASSERT(gl_render_buffer);
  5003. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, gl_render_buffer);
  5004. if (_sg_is_depth_stencil_format(pass->gl.ds_att.image->cmn.pixel_format)) {
  5005. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gl_render_buffer);
  5006. }
  5007. }
  5008. /* check if framebuffer is complete */
  5009. if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
  5010. SOKOL_LOG("Framebuffer completeness check failed!\n");
  5011. return SG_RESOURCESTATE_FAILED;
  5012. }
  5013. /* create MSAA resolve framebuffers if necessary */
  5014. if (is_msaa) {
  5015. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  5016. _sg_gl_attachment_t* gl_att = &pass->gl.color_atts[i];
  5017. _sg_attachment_t* cmn_att = &pass->cmn.color_atts[i];
  5018. if (gl_att->image) {
  5019. SOKOL_ASSERT(0 == gl_att->gl_msaa_resolve_buffer);
  5020. glGenFramebuffers(1, &gl_att->gl_msaa_resolve_buffer);
  5021. glBindFramebuffer(GL_FRAMEBUFFER, gl_att->gl_msaa_resolve_buffer);
  5022. const GLuint gl_tex = gl_att->image->gl.tex[0];
  5023. SOKOL_ASSERT(gl_tex);
  5024. switch (gl_att->image->cmn.type) {
  5025. case SG_IMAGETYPE_2D:
  5026. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  5027. GL_TEXTURE_2D, gl_tex, cmn_att->mip_level);
  5028. break;
  5029. case SG_IMAGETYPE_CUBE:
  5030. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  5031. _sg_gl_cubeface_target(cmn_att->slice), gl_tex, cmn_att->mip_level);
  5032. break;
  5033. default:
  5034. #if !defined(SOKOL_GLES2)
  5035. if (!_sg.gl.gles2) {
  5036. glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, gl_tex, cmn_att->mip_level, cmn_att->slice);
  5037. }
  5038. #endif
  5039. break;
  5040. }
  5041. /* check if framebuffer is complete */
  5042. if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
  5043. SOKOL_LOG("Framebuffer completeness check failed (msaa resolve buffer)!\n");
  5044. return SG_RESOURCESTATE_FAILED;
  5045. }
  5046. }
  5047. }
  5048. }
  5049. /* restore original framebuffer binding */
  5050. glBindFramebuffer(GL_FRAMEBUFFER, gl_orig_fb);
  5051. _SG_GL_CHECK_ERROR();
  5052. return SG_RESOURCESTATE_VALID;
  5053. }
  5054. _SOKOL_PRIVATE void _sg_gl_destroy_pass(_sg_pass_t* pass) {
  5055. SOKOL_ASSERT(pass);
  5056. _SG_GL_CHECK_ERROR();
  5057. if (0 != pass->gl.fb) {
  5058. glDeleteFramebuffers(1, &pass->gl.fb);
  5059. }
  5060. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  5061. if (pass->gl.color_atts[i].gl_msaa_resolve_buffer) {
  5062. glDeleteFramebuffers(1, &pass->gl.color_atts[i].gl_msaa_resolve_buffer);
  5063. }
  5064. }
  5065. if (pass->gl.ds_att.gl_msaa_resolve_buffer) {
  5066. glDeleteFramebuffers(1, &pass->gl.ds_att.gl_msaa_resolve_buffer);
  5067. }
  5068. _SG_GL_CHECK_ERROR();
  5069. }
  5070. _SOKOL_PRIVATE _sg_image_t* _sg_gl_pass_color_image(const _sg_pass_t* pass, int index) {
  5071. SOKOL_ASSERT(pass && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));
  5072. /* NOTE: may return null */
  5073. return pass->gl.color_atts[index].image;
  5074. }
  5075. _SOKOL_PRIVATE _sg_image_t* _sg_gl_pass_ds_image(const _sg_pass_t* pass) {
  5076. /* NOTE: may return null */
  5077. SOKOL_ASSERT(pass);
  5078. return pass->gl.ds_att.image;
  5079. }
  5080. _SOKOL_PRIVATE void _sg_gl_begin_pass(_sg_pass_t* pass, const sg_pass_action* action, int w, int h) {
  5081. /* FIXME: what if a texture used as render target is still bound, should we
  5082. unbind all currently bound textures in begin pass? */
  5083. SOKOL_ASSERT(action);
  5084. SOKOL_ASSERT(!_sg.gl.in_pass);
  5085. _SG_GL_CHECK_ERROR();
  5086. _sg.gl.in_pass = true;
  5087. _sg.gl.cur_pass = pass; /* can be 0 */
  5088. if (pass) {
  5089. _sg.gl.cur_pass_id.id = pass->slot.id;
  5090. }
  5091. else {
  5092. _sg.gl.cur_pass_id.id = SG_INVALID_ID;
  5093. }
  5094. _sg.gl.cur_pass_width = w;
  5095. _sg.gl.cur_pass_height = h;
  5096. if (pass) {
  5097. /* offscreen pass */
  5098. SOKOL_ASSERT(pass->gl.fb);
  5099. glBindFramebuffer(GL_FRAMEBUFFER, pass->gl.fb);
  5100. #if !defined(SOKOL_GLES2)
  5101. if (!_sg.gl.gles2) {
  5102. GLenum att[SG_MAX_COLOR_ATTACHMENTS] = {
  5103. GL_COLOR_ATTACHMENT0,
  5104. GL_COLOR_ATTACHMENT1,
  5105. GL_COLOR_ATTACHMENT2,
  5106. GL_COLOR_ATTACHMENT3
  5107. };
  5108. int num_attrs = 0;
  5109. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  5110. if (pass->gl.color_atts[num_attrs].image) {
  5111. num_attrs++;
  5112. }
  5113. else {
  5114. break;
  5115. }
  5116. }
  5117. glDrawBuffers(num_attrs, att);
  5118. }
  5119. #endif
  5120. }
  5121. else {
  5122. /* default pass */
  5123. SOKOL_ASSERT(_sg.gl.cur_context);
  5124. glBindFramebuffer(GL_FRAMEBUFFER, _sg.gl.cur_context->default_framebuffer);
  5125. }
  5126. glViewport(0, 0, w, h);
  5127. glScissor(0, 0, w, h);
  5128. bool need_pip_cache_flush = false;
  5129. if (_sg.gl.cache.blend.color_write_mask != SG_COLORMASK_RGBA) {
  5130. need_pip_cache_flush = true;
  5131. _sg.gl.cache.blend.color_write_mask = SG_COLORMASK_RGBA;
  5132. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  5133. }
  5134. if (!_sg.gl.cache.ds.depth_write_enabled) {
  5135. need_pip_cache_flush = true;
  5136. _sg.gl.cache.ds.depth_write_enabled = true;
  5137. glDepthMask(GL_TRUE);
  5138. }
  5139. if (_sg.gl.cache.ds.depth_compare_func != SG_COMPAREFUNC_ALWAYS) {
  5140. need_pip_cache_flush = true;
  5141. _sg.gl.cache.ds.depth_compare_func = SG_COMPAREFUNC_ALWAYS;
  5142. glDepthFunc(GL_ALWAYS);
  5143. }
  5144. if (_sg.gl.cache.ds.stencil_write_mask != 0xFF) {
  5145. need_pip_cache_flush = true;
  5146. _sg.gl.cache.ds.stencil_write_mask = 0xFF;
  5147. glStencilMask(0xFF);
  5148. }
  5149. if (need_pip_cache_flush) {
  5150. /* we messed with the state cache directly, need to clear cached
  5151. pipeline to force re-evaluation in next sg_apply_pipeline() */
  5152. _sg.gl.cache.cur_pipeline = 0;
  5153. _sg.gl.cache.cur_pipeline_id.id = SG_INVALID_ID;
  5154. }
  5155. bool use_mrt_clear = (0 != pass);
  5156. #if defined(SOKOL_GLES2)
  5157. use_mrt_clear = false;
  5158. #else
  5159. if (_sg.gl.gles2) {
  5160. use_mrt_clear = false;
  5161. }
  5162. #endif
  5163. if (!use_mrt_clear) {
  5164. GLbitfield clear_mask = 0;
  5165. if (action->colors[0].action == SG_ACTION_CLEAR) {
  5166. clear_mask |= GL_COLOR_BUFFER_BIT;
  5167. const float* c = action->colors[0].val;
  5168. glClearColor(c[0], c[1], c[2], c[3]);
  5169. }
  5170. if (action->depth.action == SG_ACTION_CLEAR) {
  5171. clear_mask |= GL_DEPTH_BUFFER_BIT;
  5172. #ifdef SOKOL_GLCORE33
  5173. glClearDepth(action->depth.val);
  5174. #else
  5175. glClearDepthf(action->depth.val);
  5176. #endif
  5177. }
  5178. if (action->stencil.action == SG_ACTION_CLEAR) {
  5179. clear_mask |= GL_STENCIL_BUFFER_BIT;
  5180. glClearStencil(action->stencil.val);
  5181. }
  5182. if (0 != clear_mask) {
  5183. glClear(clear_mask);
  5184. }
  5185. }
  5186. #if !defined SOKOL_GLES2
  5187. else {
  5188. SOKOL_ASSERT(pass);
  5189. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  5190. if (pass->gl.color_atts[i].image) {
  5191. if (action->colors[i].action == SG_ACTION_CLEAR) {
  5192. glClearBufferfv(GL_COLOR, i, action->colors[i].val);
  5193. }
  5194. }
  5195. else {
  5196. break;
  5197. }
  5198. }
  5199. if (pass->gl.ds_att.image) {
  5200. if ((action->depth.action == SG_ACTION_CLEAR) && (action->stencil.action == SG_ACTION_CLEAR)) {
  5201. glClearBufferfi(GL_DEPTH_STENCIL, 0, action->depth.val, action->stencil.val);
  5202. }
  5203. else if (action->depth.action == SG_ACTION_CLEAR) {
  5204. glClearBufferfv(GL_DEPTH, 0, &action->depth.val);
  5205. }
  5206. else if (action->stencil.action == SG_ACTION_CLEAR) {
  5207. GLuint val = action->stencil.val;
  5208. glClearBufferuiv(GL_STENCIL, 0, &val);
  5209. }
  5210. }
  5211. }
  5212. #endif
  5213. _SG_GL_CHECK_ERROR();
  5214. }
  5215. _SOKOL_PRIVATE void _sg_gl_end_pass(void) {
  5216. SOKOL_ASSERT(_sg.gl.in_pass);
  5217. _SG_GL_CHECK_ERROR();
  5218. /* if this was an offscreen pass, and MSAA rendering was used, need
  5219. to resolve into the pass images */
  5220. #if !defined(SOKOL_GLES2)
  5221. if (!_sg.gl.gles2 && _sg.gl.cur_pass) {
  5222. /* check if the pass object is still valid */
  5223. const _sg_pass_t* pass = _sg.gl.cur_pass;
  5224. SOKOL_ASSERT(pass->slot.id == _sg.gl.cur_pass_id.id);
  5225. bool is_msaa = (0 != _sg.gl.cur_pass->gl.color_atts[0].gl_msaa_resolve_buffer);
  5226. if (is_msaa) {
  5227. SOKOL_ASSERT(pass->gl.fb);
  5228. glBindFramebuffer(GL_READ_FRAMEBUFFER, pass->gl.fb);
  5229. SOKOL_ASSERT(pass->gl.color_atts[0].image);
  5230. const int w = pass->gl.color_atts[0].image->cmn.width;
  5231. const int h = pass->gl.color_atts[0].image->cmn.height;
  5232. for (int att_index = 0; att_index < SG_MAX_COLOR_ATTACHMENTS; att_index++) {
  5233. const _sg_gl_attachment_t* gl_att = &pass->gl.color_atts[att_index];
  5234. if (gl_att->image) {
  5235. SOKOL_ASSERT(gl_att->gl_msaa_resolve_buffer);
  5236. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gl_att->gl_msaa_resolve_buffer);
  5237. glReadBuffer(GL_COLOR_ATTACHMENT0 + att_index);
  5238. const GLenum gl_draw_bufs = GL_COLOR_ATTACHMENT0;
  5239. glDrawBuffers(1, &gl_draw_bufs);
  5240. glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
  5241. }
  5242. else {
  5243. break;
  5244. }
  5245. }
  5246. }
  5247. }
  5248. #endif
  5249. _sg.gl.cur_pass = 0;
  5250. _sg.gl.cur_pass_id.id = SG_INVALID_ID;
  5251. _sg.gl.cur_pass_width = 0;
  5252. _sg.gl.cur_pass_height = 0;
  5253. SOKOL_ASSERT(_sg.gl.cur_context);
  5254. glBindFramebuffer(GL_FRAMEBUFFER, _sg.gl.cur_context->default_framebuffer);
  5255. _sg.gl.in_pass = false;
  5256. _SG_GL_CHECK_ERROR();
  5257. }
  5258. _SOKOL_PRIVATE void _sg_gl_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {
  5259. SOKOL_ASSERT(_sg.gl.in_pass);
  5260. y = origin_top_left ? (_sg.gl.cur_pass_height - (y+h)) : y;
  5261. glViewport(x, y, w, h);
  5262. }
  5263. _SOKOL_PRIVATE void _sg_gl_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {
  5264. SOKOL_ASSERT(_sg.gl.in_pass);
  5265. y = origin_top_left ? (_sg.gl.cur_pass_height - (y+h)) : y;
  5266. glScissor(x, y, w, h);
  5267. }
  5268. _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) {
  5269. SOKOL_ASSERT(pip);
  5270. SOKOL_ASSERT(pip->shader);
  5271. _SG_GL_CHECK_ERROR();
  5272. if ((_sg.gl.cache.cur_pipeline != pip) || (_sg.gl.cache.cur_pipeline_id.id != pip->slot.id)) {
  5273. _sg.gl.cache.cur_pipeline = pip;
  5274. _sg.gl.cache.cur_pipeline_id.id = pip->slot.id;
  5275. _sg.gl.cache.cur_primitive_type = _sg_gl_primitive_type(pip->gl.primitive_type);
  5276. _sg.gl.cache.cur_index_type = _sg_gl_index_type(pip->cmn.index_type);
  5277. /* update depth-stencil state */
  5278. const sg_depth_stencil_state* new_ds = &pip->gl.depth_stencil;
  5279. sg_depth_stencil_state* cache_ds = &_sg.gl.cache.ds;
  5280. if (new_ds->depth_compare_func != cache_ds->depth_compare_func) {
  5281. cache_ds->depth_compare_func = new_ds->depth_compare_func;
  5282. glDepthFunc(_sg_gl_compare_func(new_ds->depth_compare_func));
  5283. }
  5284. if (new_ds->depth_write_enabled != cache_ds->depth_write_enabled) {
  5285. cache_ds->depth_write_enabled = new_ds->depth_write_enabled;
  5286. glDepthMask(new_ds->depth_write_enabled);
  5287. }
  5288. if (new_ds->stencil_enabled != cache_ds->stencil_enabled) {
  5289. cache_ds->stencil_enabled = new_ds->stencil_enabled;
  5290. if (new_ds->stencil_enabled) glEnable(GL_STENCIL_TEST);
  5291. else glDisable(GL_STENCIL_TEST);
  5292. }
  5293. if (new_ds->stencil_write_mask != cache_ds->stencil_write_mask) {
  5294. cache_ds->stencil_write_mask = new_ds->stencil_write_mask;
  5295. glStencilMask(new_ds->stencil_write_mask);
  5296. }
  5297. for (int i = 0; i < 2; i++) {
  5298. const sg_stencil_state* new_ss = (i==0)? &new_ds->stencil_front : &new_ds->stencil_back;
  5299. sg_stencil_state* cache_ss = (i==0)? &cache_ds->stencil_front : &cache_ds->stencil_back;
  5300. GLenum gl_face = (i==0)? GL_FRONT : GL_BACK;
  5301. if ((new_ss->compare_func != cache_ss->compare_func) ||
  5302. (new_ds->stencil_read_mask != cache_ds->stencil_read_mask) ||
  5303. (new_ds->stencil_ref != cache_ds->stencil_ref))
  5304. {
  5305. cache_ss->compare_func = new_ss->compare_func;
  5306. glStencilFuncSeparate(gl_face,
  5307. _sg_gl_compare_func(new_ss->compare_func),
  5308. new_ds->stencil_ref,
  5309. new_ds->stencil_read_mask);
  5310. }
  5311. if ((new_ss->fail_op != cache_ss->fail_op) ||
  5312. (new_ss->depth_fail_op != cache_ss->depth_fail_op) ||
  5313. (new_ss->pass_op != cache_ss->pass_op))
  5314. {
  5315. cache_ss->fail_op = new_ss->fail_op;
  5316. cache_ss->depth_fail_op = new_ss->depth_fail_op;
  5317. cache_ss->pass_op = new_ss->pass_op;
  5318. glStencilOpSeparate(gl_face,
  5319. _sg_gl_stencil_op(new_ss->fail_op),
  5320. _sg_gl_stencil_op(new_ss->depth_fail_op),
  5321. _sg_gl_stencil_op(new_ss->pass_op));
  5322. }
  5323. }
  5324. cache_ds->stencil_read_mask = new_ds->stencil_read_mask;
  5325. cache_ds->stencil_ref = new_ds->stencil_ref;
  5326. /* update blend state */
  5327. const sg_blend_state* new_b = &pip->gl.blend;
  5328. sg_blend_state* cache_b = &_sg.gl.cache.blend;
  5329. if (new_b->enabled != cache_b->enabled) {
  5330. cache_b->enabled = new_b->enabled;
  5331. if (new_b->enabled) glEnable(GL_BLEND);
  5332. else glDisable(GL_BLEND);
  5333. }
  5334. if ((new_b->src_factor_rgb != cache_b->src_factor_rgb) ||
  5335. (new_b->dst_factor_rgb != cache_b->dst_factor_rgb) ||
  5336. (new_b->src_factor_alpha != cache_b->src_factor_alpha) ||
  5337. (new_b->dst_factor_alpha != cache_b->dst_factor_alpha))
  5338. {
  5339. cache_b->src_factor_rgb = new_b->src_factor_rgb;
  5340. cache_b->dst_factor_rgb = new_b->dst_factor_rgb;
  5341. cache_b->src_factor_alpha = new_b->src_factor_alpha;
  5342. cache_b->dst_factor_alpha = new_b->dst_factor_alpha;
  5343. glBlendFuncSeparate(_sg_gl_blend_factor(new_b->src_factor_rgb),
  5344. _sg_gl_blend_factor(new_b->dst_factor_rgb),
  5345. _sg_gl_blend_factor(new_b->src_factor_alpha),
  5346. _sg_gl_blend_factor(new_b->dst_factor_alpha));
  5347. }
  5348. if ((new_b->op_rgb != cache_b->op_rgb) || (new_b->op_alpha != cache_b->op_alpha)) {
  5349. cache_b->op_rgb = new_b->op_rgb;
  5350. cache_b->op_alpha = new_b->op_alpha;
  5351. glBlendEquationSeparate(_sg_gl_blend_op(new_b->op_rgb), _sg_gl_blend_op(new_b->op_alpha));
  5352. }
  5353. if (new_b->color_write_mask != cache_b->color_write_mask) {
  5354. cache_b->color_write_mask = new_b->color_write_mask;
  5355. glColorMask((new_b->color_write_mask & SG_COLORMASK_R) != 0,
  5356. (new_b->color_write_mask & SG_COLORMASK_G) != 0,
  5357. (new_b->color_write_mask & SG_COLORMASK_B) != 0,
  5358. (new_b->color_write_mask & SG_COLORMASK_A) != 0);
  5359. }
  5360. if (!_sg_fequal(new_b->blend_color[0], cache_b->blend_color[0], 0.0001f) ||
  5361. !_sg_fequal(new_b->blend_color[1], cache_b->blend_color[1], 0.0001f) ||
  5362. !_sg_fequal(new_b->blend_color[2], cache_b->blend_color[2], 0.0001f) ||
  5363. !_sg_fequal(new_b->blend_color[3], cache_b->blend_color[3], 0.0001f))
  5364. {
  5365. const float* bc = new_b->blend_color;
  5366. for (int i=0; i<4; i++) {
  5367. cache_b->blend_color[i] = bc[i];
  5368. }
  5369. glBlendColor(bc[0], bc[1], bc[2], bc[3]);
  5370. }
  5371. /* update rasterizer state */
  5372. const sg_rasterizer_state* new_r = &pip->gl.rast;
  5373. sg_rasterizer_state* cache_r = &_sg.gl.cache.rast;
  5374. if (new_r->cull_mode != cache_r->cull_mode) {
  5375. cache_r->cull_mode = new_r->cull_mode;
  5376. if (SG_CULLMODE_NONE == new_r->cull_mode) {
  5377. glDisable(GL_CULL_FACE);
  5378. }
  5379. else {
  5380. glEnable(GL_CULL_FACE);
  5381. GLenum gl_mode = (SG_CULLMODE_FRONT == new_r->cull_mode) ? GL_FRONT : GL_BACK;
  5382. glCullFace(gl_mode);
  5383. }
  5384. }
  5385. if (new_r->face_winding != cache_r->face_winding) {
  5386. cache_r->face_winding = new_r->face_winding;
  5387. GLenum gl_winding = (SG_FACEWINDING_CW == new_r->face_winding) ? GL_CW : GL_CCW;
  5388. glFrontFace(gl_winding);
  5389. }
  5390. if (new_r->alpha_to_coverage_enabled != cache_r->alpha_to_coverage_enabled) {
  5391. cache_r->alpha_to_coverage_enabled = new_r->alpha_to_coverage_enabled;
  5392. if (new_r->alpha_to_coverage_enabled) glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
  5393. else glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
  5394. }
  5395. #ifdef SOKOL_GLCORE33
  5396. if (new_r->sample_count != cache_r->sample_count) {
  5397. cache_r->sample_count = new_r->sample_count;
  5398. if (new_r->sample_count > 1) glEnable(GL_MULTISAMPLE);
  5399. else glDisable(GL_MULTISAMPLE);
  5400. }
  5401. #endif
  5402. if (!_sg_fequal(new_r->depth_bias, cache_r->depth_bias, 0.000001f) ||
  5403. !_sg_fequal(new_r->depth_bias_slope_scale, cache_r->depth_bias_slope_scale, 0.000001f))
  5404. {
  5405. /* according to ANGLE's D3D11 backend:
  5406. D3D11 SlopeScaledDepthBias ==> GL polygonOffsetFactor
  5407. D3D11 DepthBias ==> GL polygonOffsetUnits
  5408. DepthBiasClamp has no meaning on GL
  5409. */
  5410. cache_r->depth_bias = new_r->depth_bias;
  5411. cache_r->depth_bias_slope_scale = new_r->depth_bias_slope_scale;
  5412. glPolygonOffset(new_r->depth_bias_slope_scale, new_r->depth_bias);
  5413. bool po_enabled = true;
  5414. if (_sg_fequal(new_r->depth_bias, 0.0f, 0.000001f) &&
  5415. _sg_fequal(new_r->depth_bias_slope_scale, 0.0f, 0.000001f))
  5416. {
  5417. po_enabled = false;
  5418. }
  5419. if (po_enabled != _sg.gl.cache.polygon_offset_enabled) {
  5420. _sg.gl.cache.polygon_offset_enabled = po_enabled;
  5421. if (po_enabled) glEnable(GL_POLYGON_OFFSET_FILL);
  5422. else glDisable(GL_POLYGON_OFFSET_FILL);
  5423. }
  5424. }
  5425. /* bind shader program */
  5426. glUseProgram(pip->shader->gl.prog);
  5427. }
  5428. }
  5429. _SOKOL_PRIVATE void _sg_gl_apply_bindings(
  5430. _sg_pipeline_t* pip,
  5431. _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs,
  5432. _sg_buffer_t* ib, int ib_offset,
  5433. _sg_image_t** vs_imgs, int num_vs_imgs,
  5434. _sg_image_t** fs_imgs, int num_fs_imgs)
  5435. {
  5436. SOKOL_ASSERT(pip);
  5437. _SOKOL_UNUSED(num_fs_imgs);
  5438. _SOKOL_UNUSED(num_vs_imgs);
  5439. _SOKOL_UNUSED(num_vbs);
  5440. _SG_GL_CHECK_ERROR();
  5441. /* bind textures */
  5442. _SG_GL_CHECK_ERROR();
  5443. for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {
  5444. const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[stage_index];
  5445. const _sg_gl_shader_stage_t* gl_stage = &pip->shader->gl.stage[stage_index];
  5446. _sg_image_t** imgs = (stage_index == SG_SHADERSTAGE_VS)? vs_imgs : fs_imgs;
  5447. SOKOL_ASSERT(((stage_index == SG_SHADERSTAGE_VS)? num_vs_imgs : num_fs_imgs) == stage->num_images);
  5448. for (int img_index = 0; img_index < stage->num_images; img_index++) {
  5449. const _sg_gl_shader_image_t* gl_shd_img = &gl_stage->images[img_index];
  5450. if (gl_shd_img->gl_loc != -1) {
  5451. _sg_image_t* img = imgs[img_index];
  5452. const GLuint gl_tex = img->gl.tex[img->cmn.active_slot];
  5453. SOKOL_ASSERT(img && img->gl.target);
  5454. SOKOL_ASSERT((gl_shd_img->gl_tex_slot != -1) && gl_tex);
  5455. glUniform1i(gl_shd_img->gl_loc, gl_shd_img->gl_tex_slot);
  5456. _sg_gl_bind_texture(gl_shd_img->gl_tex_slot, img->gl.target, gl_tex);
  5457. }
  5458. }
  5459. }
  5460. _SG_GL_CHECK_ERROR();
  5461. /* index buffer (can be 0) */
  5462. const GLuint gl_ib = ib ? ib->gl.buf[ib->cmn.active_slot] : 0;
  5463. _sg_gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, gl_ib);
  5464. _sg.gl.cache.cur_ib_offset = ib_offset;
  5465. /* vertex attributes */
  5466. for (uint32_t attr_index = 0; attr_index < _sg.limits.max_vertex_attrs; attr_index++) {
  5467. _sg_gl_attr_t* attr = &pip->gl.attrs[attr_index];
  5468. _sg_gl_cache_attr_t* cache_attr = &_sg.gl.cache.attrs[attr_index];
  5469. bool cache_attr_dirty = false;
  5470. int vb_offset = 0;
  5471. GLuint gl_vb = 0;
  5472. if (attr->vb_index >= 0) {
  5473. /* attribute is enabled */
  5474. SOKOL_ASSERT(attr->vb_index < num_vbs);
  5475. _sg_buffer_t* vb = vbs[attr->vb_index];
  5476. SOKOL_ASSERT(vb);
  5477. gl_vb = vb->gl.buf[vb->cmn.active_slot];
  5478. vb_offset = vb_offsets[attr->vb_index] + attr->offset;
  5479. if ((gl_vb != cache_attr->gl_vbuf) ||
  5480. (attr->size != cache_attr->gl_attr.size) ||
  5481. (attr->type != cache_attr->gl_attr.type) ||
  5482. (attr->normalized != cache_attr->gl_attr.normalized) ||
  5483. (attr->stride != cache_attr->gl_attr.stride) ||
  5484. (vb_offset != cache_attr->gl_attr.offset) ||
  5485. (cache_attr->gl_attr.divisor != attr->divisor))
  5486. {
  5487. _sg_gl_bind_buffer(GL_ARRAY_BUFFER, gl_vb);
  5488. glVertexAttribPointer(attr_index, attr->size, attr->type,
  5489. attr->normalized, attr->stride,
  5490. (const GLvoid*)(GLintptr)vb_offset);
  5491. #ifdef SOKOL_INSTANCING_ENABLED
  5492. if (_sg.features.instancing) {
  5493. glVertexAttribDivisor(attr_index, attr->divisor);
  5494. }
  5495. #endif
  5496. cache_attr_dirty = true;
  5497. }
  5498. if (cache_attr->gl_attr.vb_index == -1) {
  5499. glEnableVertexAttribArray(attr_index);
  5500. cache_attr_dirty = true;
  5501. }
  5502. }
  5503. else {
  5504. /* attribute is disabled */
  5505. if (cache_attr->gl_attr.vb_index != -1) {
  5506. glDisableVertexAttribArray(attr_index);
  5507. cache_attr_dirty = true;
  5508. }
  5509. }
  5510. if (cache_attr_dirty) {
  5511. cache_attr->gl_attr = *attr;
  5512. cache_attr->gl_attr.offset = vb_offset;
  5513. cache_attr->gl_vbuf = gl_vb;
  5514. }
  5515. }
  5516. _SG_GL_CHECK_ERROR();
  5517. }
  5518. _SOKOL_PRIVATE void _sg_gl_apply_uniforms(sg_shader_stage stage_index, int ub_index, const void* data, int num_bytes) {
  5519. _SOKOL_UNUSED(num_bytes);
  5520. SOKOL_ASSERT(data && (num_bytes > 0));
  5521. SOKOL_ASSERT((stage_index >= 0) && ((int)stage_index < SG_NUM_SHADER_STAGES));
  5522. SOKOL_ASSERT(_sg.gl.cache.cur_pipeline);
  5523. SOKOL_ASSERT(_sg.gl.cache.cur_pipeline->slot.id == _sg.gl.cache.cur_pipeline_id.id);
  5524. SOKOL_ASSERT(_sg.gl.cache.cur_pipeline->shader->slot.id == _sg.gl.cache.cur_pipeline->cmn.shader_id.id);
  5525. SOKOL_ASSERT(_sg.gl.cache.cur_pipeline->shader->cmn.stage[stage_index].num_uniform_blocks > ub_index);
  5526. SOKOL_ASSERT(_sg.gl.cache.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size == num_bytes);
  5527. const _sg_gl_shader_stage_t* gl_stage = &_sg.gl.cache.cur_pipeline->shader->gl.stage[stage_index];
  5528. const _sg_gl_uniform_block_t* gl_ub = &gl_stage->uniform_blocks[ub_index];
  5529. for (int u_index = 0; u_index < gl_ub->num_uniforms; u_index++) {
  5530. const _sg_gl_uniform_t* u = &gl_ub->uniforms[u_index];
  5531. SOKOL_ASSERT(u->type != SG_UNIFORMTYPE_INVALID);
  5532. if (u->gl_loc == -1) {
  5533. continue;
  5534. }
  5535. GLfloat* ptr = (GLfloat*) (((uint8_t*)data) + u->offset);
  5536. switch (u->type) {
  5537. case SG_UNIFORMTYPE_INVALID:
  5538. break;
  5539. case SG_UNIFORMTYPE_FLOAT:
  5540. glUniform1fv(u->gl_loc, u->count, ptr);
  5541. break;
  5542. case SG_UNIFORMTYPE_FLOAT2:
  5543. glUniform2fv(u->gl_loc, u->count, ptr);
  5544. break;
  5545. case SG_UNIFORMTYPE_FLOAT3:
  5546. glUniform3fv(u->gl_loc, u->count, ptr);
  5547. break;
  5548. case SG_UNIFORMTYPE_FLOAT4:
  5549. glUniform4fv(u->gl_loc, u->count, ptr);
  5550. break;
  5551. case SG_UNIFORMTYPE_MAT4:
  5552. glUniformMatrix4fv(u->gl_loc, u->count, GL_FALSE, ptr);
  5553. break;
  5554. default:
  5555. SOKOL_UNREACHABLE;
  5556. break;
  5557. }
  5558. }
  5559. }
  5560. _SOKOL_PRIVATE void _sg_gl_draw(int base_element, int num_elements, int num_instances) {
  5561. const GLenum i_type = _sg.gl.cache.cur_index_type;
  5562. const GLenum p_type = _sg.gl.cache.cur_primitive_type;
  5563. if (0 != i_type) {
  5564. /* indexed rendering */
  5565. const int i_size = (i_type == GL_UNSIGNED_SHORT) ? 2 : 4;
  5566. const int ib_offset = _sg.gl.cache.cur_ib_offset;
  5567. const GLvoid* indices = (const GLvoid*)(GLintptr)(base_element*i_size+ib_offset);
  5568. if (num_instances == 1) {
  5569. glDrawElements(p_type, num_elements, i_type, indices);
  5570. }
  5571. else {
  5572. if (_sg.features.instancing) {
  5573. glDrawElementsInstanced(p_type, num_elements, i_type, indices, num_instances);
  5574. }
  5575. }
  5576. }
  5577. else {
  5578. /* non-indexed rendering */
  5579. if (num_instances == 1) {
  5580. glDrawArrays(p_type, base_element, num_elements);
  5581. }
  5582. else {
  5583. if (_sg.features.instancing) {
  5584. glDrawArraysInstanced(p_type, base_element, num_elements, num_instances);
  5585. }
  5586. }
  5587. }
  5588. }
  5589. _SOKOL_PRIVATE void _sg_gl_commit(void) {
  5590. SOKOL_ASSERT(!_sg.gl.in_pass);
  5591. /* "soft" clear bindings (only those that are actually bound) */
  5592. _sg_gl_clear_buffer_bindings(false);
  5593. _sg_gl_clear_texture_bindings(false);
  5594. }
  5595. _SOKOL_PRIVATE void _sg_gl_update_buffer(_sg_buffer_t* buf, const void* data_ptr, int data_size) {
  5596. SOKOL_ASSERT(buf && data_ptr && (data_size > 0));
  5597. /* only one update per buffer per frame allowed */
  5598. if (++buf->cmn.active_slot >= buf->cmn.num_slots) {
  5599. buf->cmn.active_slot = 0;
  5600. }
  5601. GLenum gl_tgt = _sg_gl_buffer_target(buf->cmn.type);
  5602. SOKOL_ASSERT(buf->cmn.active_slot < SG_NUM_INFLIGHT_FRAMES);
  5603. GLuint gl_buf = buf->gl.buf[buf->cmn.active_slot];
  5604. SOKOL_ASSERT(gl_buf);
  5605. _SG_GL_CHECK_ERROR();
  5606. _sg_gl_store_buffer_binding(gl_tgt);
  5607. _sg_gl_bind_buffer(gl_tgt, gl_buf);
  5608. glBufferSubData(gl_tgt, 0, data_size, data_ptr);
  5609. _sg_gl_restore_buffer_binding(gl_tgt);
  5610. _SG_GL_CHECK_ERROR();
  5611. }
  5612. _SOKOL_PRIVATE void _sg_gl_append_buffer(_sg_buffer_t* buf, const void* data_ptr, int data_size, bool new_frame) {
  5613. SOKOL_ASSERT(buf && data_ptr && (data_size > 0));
  5614. if (new_frame) {
  5615. if (++buf->cmn.active_slot >= buf->cmn.num_slots) {
  5616. buf->cmn.active_slot = 0;
  5617. }
  5618. }
  5619. GLenum gl_tgt = _sg_gl_buffer_target(buf->cmn.type);
  5620. SOKOL_ASSERT(buf->cmn.active_slot < SG_NUM_INFLIGHT_FRAMES);
  5621. GLuint gl_buf = buf->gl.buf[buf->cmn.active_slot];
  5622. SOKOL_ASSERT(gl_buf);
  5623. _SG_GL_CHECK_ERROR();
  5624. _sg_gl_store_buffer_binding(gl_tgt);
  5625. _sg_gl_bind_buffer(gl_tgt, gl_buf);
  5626. glBufferSubData(gl_tgt, buf->cmn.append_pos, data_size, data_ptr);
  5627. _sg_gl_restore_buffer_binding(gl_tgt);
  5628. _SG_GL_CHECK_ERROR();
  5629. }
  5630. _SOKOL_PRIVATE void _sg_gl_update_image(_sg_image_t* img, const sg_image_content* data) {
  5631. SOKOL_ASSERT(img && data);
  5632. /* only one update per image per frame allowed */
  5633. if (++img->cmn.active_slot >= img->cmn.num_slots) {
  5634. img->cmn.active_slot = 0;
  5635. }
  5636. SOKOL_ASSERT(img->cmn.active_slot < SG_NUM_INFLIGHT_FRAMES);
  5637. SOKOL_ASSERT(0 != img->gl.tex[img->cmn.active_slot]);
  5638. _sg_gl_store_texture_binding(0);
  5639. _sg_gl_bind_texture(0, img->gl.target, img->gl.tex[img->cmn.active_slot]);
  5640. const GLenum gl_img_format = _sg_gl_teximage_format(img->cmn.pixel_format);
  5641. const GLenum gl_img_type = _sg_gl_teximage_type(img->cmn.pixel_format);
  5642. const int num_faces = img->cmn.type == SG_IMAGETYPE_CUBE ? 6 : 1;
  5643. const int num_mips = img->cmn.num_mipmaps;
  5644. for (int face_index = 0; face_index < num_faces; face_index++) {
  5645. for (int mip_index = 0; mip_index < num_mips; mip_index++) {
  5646. GLenum gl_img_target = img->gl.target;
  5647. if (SG_IMAGETYPE_CUBE == img->cmn.type) {
  5648. gl_img_target = _sg_gl_cubeface_target(face_index);
  5649. }
  5650. const GLvoid* data_ptr = data->subimage[face_index][mip_index].ptr;
  5651. int mip_width = img->cmn.width >> mip_index;
  5652. if (mip_width == 0) {
  5653. mip_width = 1;
  5654. }
  5655. int mip_height = img->cmn.height >> mip_index;
  5656. if (mip_height == 0) {
  5657. mip_height = 1;
  5658. }
  5659. if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {
  5660. glTexSubImage2D(gl_img_target, mip_index,
  5661. 0, 0,
  5662. mip_width, mip_height,
  5663. gl_img_format, gl_img_type,
  5664. data_ptr);
  5665. }
  5666. #if !defined(SOKOL_GLES2)
  5667. else if (!_sg.gl.gles2 && ((SG_IMAGETYPE_3D == img->cmn.type) || (SG_IMAGETYPE_ARRAY == img->cmn.type))) {
  5668. int mip_depth = img->cmn.depth >> mip_index;
  5669. if (mip_depth == 0) {
  5670. mip_depth = 1;
  5671. }
  5672. glTexSubImage3D(gl_img_target, mip_index,
  5673. 0, 0, 0,
  5674. mip_width, mip_height, mip_depth,
  5675. gl_img_format, gl_img_type,
  5676. data_ptr);
  5677. }
  5678. #endif
  5679. }
  5680. }
  5681. _sg_gl_restore_texture_binding(0);
  5682. }
  5683. /*== D3D11 BACKEND IMPLEMENTATION ============================================*/
  5684. #elif defined(SOKOL_D3D11)
  5685. /*-- enum translation functions ----------------------------------------------*/
  5686. _SOKOL_PRIVATE D3D11_USAGE _sg_d3d11_usage(sg_usage usg) {
  5687. switch (usg) {
  5688. case SG_USAGE_IMMUTABLE:
  5689. return D3D11_USAGE_IMMUTABLE;
  5690. case SG_USAGE_DYNAMIC:
  5691. case SG_USAGE_STREAM:
  5692. return D3D11_USAGE_DYNAMIC;
  5693. default:
  5694. SOKOL_UNREACHABLE;
  5695. return (D3D11_USAGE) 0;
  5696. }
  5697. }
  5698. _SOKOL_PRIVATE UINT _sg_d3d11_cpu_access_flags(sg_usage usg) {
  5699. switch (usg) {
  5700. case SG_USAGE_IMMUTABLE:
  5701. return 0;
  5702. case SG_USAGE_DYNAMIC:
  5703. case SG_USAGE_STREAM:
  5704. return D3D11_CPU_ACCESS_WRITE;
  5705. default:
  5706. SOKOL_UNREACHABLE;
  5707. return 0;
  5708. }
  5709. }
  5710. _SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_pixel_format(sg_pixel_format fmt) {
  5711. switch (fmt) {
  5712. case SG_PIXELFORMAT_R8: return DXGI_FORMAT_R8_UNORM;
  5713. case SG_PIXELFORMAT_R8SN: return DXGI_FORMAT_R8_SNORM;
  5714. case SG_PIXELFORMAT_R8UI: return DXGI_FORMAT_R8_UINT;
  5715. case SG_PIXELFORMAT_R8SI: return DXGI_FORMAT_R8_SINT;
  5716. case SG_PIXELFORMAT_R16: return DXGI_FORMAT_R16_UNORM;
  5717. case SG_PIXELFORMAT_R16SN: return DXGI_FORMAT_R16_SNORM;
  5718. case SG_PIXELFORMAT_R16UI: return DXGI_FORMAT_R16_UINT;
  5719. case SG_PIXELFORMAT_R16SI: return DXGI_FORMAT_R16_SINT;
  5720. case SG_PIXELFORMAT_R16F: return DXGI_FORMAT_R16_FLOAT;
  5721. case SG_PIXELFORMAT_RG8: return DXGI_FORMAT_R8G8_UNORM;
  5722. case SG_PIXELFORMAT_RG8SN: return DXGI_FORMAT_R8G8_SNORM;
  5723. case SG_PIXELFORMAT_RG8UI: return DXGI_FORMAT_R8G8_UINT;
  5724. case SG_PIXELFORMAT_RG8SI: return DXGI_FORMAT_R8G8_SINT;
  5725. case SG_PIXELFORMAT_R32UI: return DXGI_FORMAT_R32_UINT;
  5726. case SG_PIXELFORMAT_R32SI: return DXGI_FORMAT_R32_SINT;
  5727. case SG_PIXELFORMAT_R32F: return DXGI_FORMAT_R32_FLOAT;
  5728. case SG_PIXELFORMAT_RG16: return DXGI_FORMAT_R16G16_UNORM;
  5729. case SG_PIXELFORMAT_RG16SN: return DXGI_FORMAT_R16G16_SNORM;
  5730. case SG_PIXELFORMAT_RG16UI: return DXGI_FORMAT_R16G16_UINT;
  5731. case SG_PIXELFORMAT_RG16SI: return DXGI_FORMAT_R16G16_SINT;
  5732. case SG_PIXELFORMAT_RG16F: return DXGI_FORMAT_R16G16_FLOAT;
  5733. case SG_PIXELFORMAT_RGBA8: return DXGI_FORMAT_R8G8B8A8_UNORM;
  5734. case SG_PIXELFORMAT_RGBA8SN: return DXGI_FORMAT_R8G8B8A8_SNORM;
  5735. case SG_PIXELFORMAT_RGBA8UI: return DXGI_FORMAT_R8G8B8A8_UINT;
  5736. case SG_PIXELFORMAT_RGBA8SI: return DXGI_FORMAT_R8G8B8A8_SINT;
  5737. case SG_PIXELFORMAT_BGRA8: return DXGI_FORMAT_B8G8R8A8_UNORM;
  5738. case SG_PIXELFORMAT_RGB10A2: return DXGI_FORMAT_R10G10B10A2_UNORM;
  5739. case SG_PIXELFORMAT_RG11B10F: return DXGI_FORMAT_R11G11B10_FLOAT;
  5740. case SG_PIXELFORMAT_RG32UI: return DXGI_FORMAT_R32G32_UINT;
  5741. case SG_PIXELFORMAT_RG32SI: return DXGI_FORMAT_R32G32_SINT;
  5742. case SG_PIXELFORMAT_RG32F: return DXGI_FORMAT_R32G32_FLOAT;
  5743. case SG_PIXELFORMAT_RGBA16: return DXGI_FORMAT_R16G16B16A16_UNORM;
  5744. case SG_PIXELFORMAT_RGBA16SN: return DXGI_FORMAT_R16G16B16A16_SNORM;
  5745. case SG_PIXELFORMAT_RGBA16UI: return DXGI_FORMAT_R16G16B16A16_UINT;
  5746. case SG_PIXELFORMAT_RGBA16SI: return DXGI_FORMAT_R16G16B16A16_SINT;
  5747. case SG_PIXELFORMAT_RGBA16F: return DXGI_FORMAT_R16G16B16A16_FLOAT;
  5748. case SG_PIXELFORMAT_RGBA32UI: return DXGI_FORMAT_R32G32B32A32_UINT;
  5749. case SG_PIXELFORMAT_RGBA32SI: return DXGI_FORMAT_R32G32B32A32_SINT;
  5750. case SG_PIXELFORMAT_RGBA32F: return DXGI_FORMAT_R32G32B32A32_FLOAT;
  5751. case SG_PIXELFORMAT_DEPTH: return DXGI_FORMAT_D32_FLOAT;
  5752. case SG_PIXELFORMAT_DEPTH_STENCIL: return DXGI_FORMAT_D24_UNORM_S8_UINT;
  5753. case SG_PIXELFORMAT_BC1_RGBA: return DXGI_FORMAT_BC1_UNORM;
  5754. case SG_PIXELFORMAT_BC2_RGBA: return DXGI_FORMAT_BC2_UNORM;
  5755. case SG_PIXELFORMAT_BC3_RGBA: return DXGI_FORMAT_BC3_UNORM;
  5756. case SG_PIXELFORMAT_BC4_R: return DXGI_FORMAT_BC4_UNORM;
  5757. case SG_PIXELFORMAT_BC4_RSN: return DXGI_FORMAT_BC4_SNORM;
  5758. case SG_PIXELFORMAT_BC5_RG: return DXGI_FORMAT_BC5_UNORM;
  5759. case SG_PIXELFORMAT_BC5_RGSN: return DXGI_FORMAT_BC5_SNORM;
  5760. case SG_PIXELFORMAT_BC6H_RGBF: return DXGI_FORMAT_BC6H_SF16;
  5761. case SG_PIXELFORMAT_BC6H_RGBUF: return DXGI_FORMAT_BC6H_UF16;
  5762. case SG_PIXELFORMAT_BC7_RGBA: return DXGI_FORMAT_BC7_UNORM;
  5763. default: return DXGI_FORMAT_UNKNOWN;
  5764. };
  5765. }
  5766. _SOKOL_PRIVATE D3D11_PRIMITIVE_TOPOLOGY _sg_d3d11_primitive_topology(sg_primitive_type prim_type) {
  5767. switch (prim_type) {
  5768. case SG_PRIMITIVETYPE_POINTS: return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
  5769. case SG_PRIMITIVETYPE_LINES: return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
  5770. case SG_PRIMITIVETYPE_LINE_STRIP: return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
  5771. case SG_PRIMITIVETYPE_TRIANGLES: return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  5772. case SG_PRIMITIVETYPE_TRIANGLE_STRIP: return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
  5773. default: SOKOL_UNREACHABLE; return (D3D11_PRIMITIVE_TOPOLOGY) 0;
  5774. }
  5775. }
  5776. _SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_index_format(sg_index_type index_type) {
  5777. switch (index_type) {
  5778. case SG_INDEXTYPE_NONE: return DXGI_FORMAT_UNKNOWN;
  5779. case SG_INDEXTYPE_UINT16: return DXGI_FORMAT_R16_UINT;
  5780. case SG_INDEXTYPE_UINT32: return DXGI_FORMAT_R32_UINT;
  5781. default: SOKOL_UNREACHABLE; return (DXGI_FORMAT) 0;
  5782. }
  5783. }
  5784. _SOKOL_PRIVATE D3D11_FILTER _sg_d3d11_filter(sg_filter min_f, sg_filter mag_f, uint32_t max_anisotropy) {
  5785. if (max_anisotropy > 1) {
  5786. return D3D11_FILTER_ANISOTROPIC;
  5787. }
  5788. else if (mag_f == SG_FILTER_NEAREST) {
  5789. switch (min_f) {
  5790. case SG_FILTER_NEAREST:
  5791. case SG_FILTER_NEAREST_MIPMAP_NEAREST:
  5792. return D3D11_FILTER_MIN_MAG_MIP_POINT;
  5793. case SG_FILTER_LINEAR:
  5794. case SG_FILTER_LINEAR_MIPMAP_NEAREST:
  5795. return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
  5796. case SG_FILTER_NEAREST_MIPMAP_LINEAR:
  5797. return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
  5798. case SG_FILTER_LINEAR_MIPMAP_LINEAR:
  5799. return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
  5800. default:
  5801. SOKOL_UNREACHABLE; break;
  5802. }
  5803. }
  5804. else if (mag_f == SG_FILTER_LINEAR) {
  5805. switch (min_f) {
  5806. case SG_FILTER_NEAREST:
  5807. case SG_FILTER_NEAREST_MIPMAP_NEAREST:
  5808. return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
  5809. case SG_FILTER_LINEAR:
  5810. case SG_FILTER_LINEAR_MIPMAP_NEAREST:
  5811. return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
  5812. case SG_FILTER_NEAREST_MIPMAP_LINEAR:
  5813. return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
  5814. case SG_FILTER_LINEAR_MIPMAP_LINEAR:
  5815. return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  5816. default:
  5817. SOKOL_UNREACHABLE; break;
  5818. }
  5819. }
  5820. /* invalid value for mag filter */
  5821. SOKOL_UNREACHABLE;
  5822. return D3D11_FILTER_MIN_MAG_MIP_POINT;
  5823. }
  5824. _SOKOL_PRIVATE D3D11_TEXTURE_ADDRESS_MODE _sg_d3d11_address_mode(sg_wrap m) {
  5825. switch (m) {
  5826. case SG_WRAP_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP;
  5827. case SG_WRAP_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP;
  5828. case SG_WRAP_CLAMP_TO_BORDER: return D3D11_TEXTURE_ADDRESS_BORDER;
  5829. case SG_WRAP_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR;
  5830. default: SOKOL_UNREACHABLE; return (D3D11_TEXTURE_ADDRESS_MODE) 0;
  5831. }
  5832. }
  5833. _SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_vertex_format(sg_vertex_format fmt) {
  5834. switch (fmt) {
  5835. case SG_VERTEXFORMAT_FLOAT: return DXGI_FORMAT_R32_FLOAT;
  5836. case SG_VERTEXFORMAT_FLOAT2: return DXGI_FORMAT_R32G32_FLOAT;
  5837. case SG_VERTEXFORMAT_FLOAT3: return DXGI_FORMAT_R32G32B32_FLOAT;
  5838. case SG_VERTEXFORMAT_FLOAT4: return DXGI_FORMAT_R32G32B32A32_FLOAT;
  5839. case SG_VERTEXFORMAT_BYTE4: return DXGI_FORMAT_R8G8B8A8_SINT;
  5840. case SG_VERTEXFORMAT_BYTE4N: return DXGI_FORMAT_R8G8B8A8_SNORM;
  5841. case SG_VERTEXFORMAT_UBYTE4: return DXGI_FORMAT_R8G8B8A8_UINT;
  5842. case SG_VERTEXFORMAT_UBYTE4N: return DXGI_FORMAT_R8G8B8A8_UNORM;
  5843. case SG_VERTEXFORMAT_SHORT2: return DXGI_FORMAT_R16G16_SINT;
  5844. case SG_VERTEXFORMAT_SHORT2N: return DXGI_FORMAT_R16G16_SNORM;
  5845. case SG_VERTEXFORMAT_USHORT2N: return DXGI_FORMAT_R16G16_UNORM;
  5846. case SG_VERTEXFORMAT_SHORT4: return DXGI_FORMAT_R16G16B16A16_SINT;
  5847. case SG_VERTEXFORMAT_SHORT4N: return DXGI_FORMAT_R16G16B16A16_SNORM;
  5848. case SG_VERTEXFORMAT_USHORT4N: return DXGI_FORMAT_R16G16B16A16_UNORM;
  5849. case SG_VERTEXFORMAT_UINT10_N2: return DXGI_FORMAT_R10G10B10A2_UNORM;
  5850. default: SOKOL_UNREACHABLE; return (DXGI_FORMAT) 0;
  5851. }
  5852. }
  5853. _SOKOL_PRIVATE D3D11_INPUT_CLASSIFICATION _sg_d3d11_input_classification(sg_vertex_step step) {
  5854. switch (step) {
  5855. case SG_VERTEXSTEP_PER_VERTEX: return D3D11_INPUT_PER_VERTEX_DATA;
  5856. case SG_VERTEXSTEP_PER_INSTANCE: return D3D11_INPUT_PER_INSTANCE_DATA;
  5857. default: SOKOL_UNREACHABLE; return (D3D11_INPUT_CLASSIFICATION) 0;
  5858. }
  5859. }
  5860. _SOKOL_PRIVATE D3D11_CULL_MODE _sg_d3d11_cull_mode(sg_cull_mode m) {
  5861. switch (m) {
  5862. case SG_CULLMODE_NONE: return D3D11_CULL_NONE;
  5863. case SG_CULLMODE_FRONT: return D3D11_CULL_FRONT;
  5864. case SG_CULLMODE_BACK: return D3D11_CULL_BACK;
  5865. default: SOKOL_UNREACHABLE; return (D3D11_CULL_MODE) 0;
  5866. }
  5867. }
  5868. _SOKOL_PRIVATE D3D11_COMPARISON_FUNC _sg_d3d11_compare_func(sg_compare_func f) {
  5869. switch (f) {
  5870. case SG_COMPAREFUNC_NEVER: return D3D11_COMPARISON_NEVER;
  5871. case SG_COMPAREFUNC_LESS: return D3D11_COMPARISON_LESS;
  5872. case SG_COMPAREFUNC_EQUAL: return D3D11_COMPARISON_EQUAL;
  5873. case SG_COMPAREFUNC_LESS_EQUAL: return D3D11_COMPARISON_LESS_EQUAL;
  5874. case SG_COMPAREFUNC_GREATER: return D3D11_COMPARISON_GREATER;
  5875. case SG_COMPAREFUNC_NOT_EQUAL: return D3D11_COMPARISON_NOT_EQUAL;
  5876. case SG_COMPAREFUNC_GREATER_EQUAL: return D3D11_COMPARISON_GREATER_EQUAL;
  5877. case SG_COMPAREFUNC_ALWAYS: return D3D11_COMPARISON_ALWAYS;
  5878. default: SOKOL_UNREACHABLE; return (D3D11_COMPARISON_FUNC) 0;
  5879. }
  5880. }
  5881. _SOKOL_PRIVATE D3D11_STENCIL_OP _sg_d3d11_stencil_op(sg_stencil_op op) {
  5882. switch (op) {
  5883. case SG_STENCILOP_KEEP: return D3D11_STENCIL_OP_KEEP;
  5884. case SG_STENCILOP_ZERO: return D3D11_STENCIL_OP_ZERO;
  5885. case SG_STENCILOP_REPLACE: return D3D11_STENCIL_OP_REPLACE;
  5886. case SG_STENCILOP_INCR_CLAMP: return D3D11_STENCIL_OP_INCR_SAT;
  5887. case SG_STENCILOP_DECR_CLAMP: return D3D11_STENCIL_OP_DECR_SAT;
  5888. case SG_STENCILOP_INVERT: return D3D11_STENCIL_OP_INVERT;
  5889. case SG_STENCILOP_INCR_WRAP: return D3D11_STENCIL_OP_INCR;
  5890. case SG_STENCILOP_DECR_WRAP: return D3D11_STENCIL_OP_DECR;
  5891. default: SOKOL_UNREACHABLE; return (D3D11_STENCIL_OP) 0;
  5892. }
  5893. }
  5894. _SOKOL_PRIVATE D3D11_BLEND _sg_d3d11_blend_factor(sg_blend_factor f) {
  5895. switch (f) {
  5896. case SG_BLENDFACTOR_ZERO: return D3D11_BLEND_ZERO;
  5897. case SG_BLENDFACTOR_ONE: return D3D11_BLEND_ONE;
  5898. case SG_BLENDFACTOR_SRC_COLOR: return D3D11_BLEND_SRC_COLOR;
  5899. case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR: return D3D11_BLEND_INV_SRC_COLOR;
  5900. case SG_BLENDFACTOR_SRC_ALPHA: return D3D11_BLEND_SRC_ALPHA;
  5901. case SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA: return D3D11_BLEND_INV_SRC_ALPHA;
  5902. case SG_BLENDFACTOR_DST_COLOR: return D3D11_BLEND_DEST_COLOR;
  5903. case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR: return D3D11_BLEND_INV_DEST_COLOR;
  5904. case SG_BLENDFACTOR_DST_ALPHA: return D3D11_BLEND_DEST_ALPHA;
  5905. case SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA: return D3D11_BLEND_INV_DEST_ALPHA;
  5906. case SG_BLENDFACTOR_SRC_ALPHA_SATURATED: return D3D11_BLEND_SRC_ALPHA_SAT;
  5907. case SG_BLENDFACTOR_BLEND_COLOR: return D3D11_BLEND_BLEND_FACTOR;
  5908. case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR: return D3D11_BLEND_INV_BLEND_FACTOR;
  5909. case SG_BLENDFACTOR_BLEND_ALPHA: return D3D11_BLEND_BLEND_FACTOR;
  5910. case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA: return D3D11_BLEND_INV_BLEND_FACTOR;
  5911. default: SOKOL_UNREACHABLE; return (D3D11_BLEND) 0;
  5912. }
  5913. }
  5914. _SOKOL_PRIVATE D3D11_BLEND_OP _sg_d3d11_blend_op(sg_blend_op op) {
  5915. switch (op) {
  5916. case SG_BLENDOP_ADD: return D3D11_BLEND_OP_ADD;
  5917. case SG_BLENDOP_SUBTRACT: return D3D11_BLEND_OP_SUBTRACT;
  5918. case SG_BLENDOP_REVERSE_SUBTRACT: return D3D11_BLEND_OP_REV_SUBTRACT;
  5919. default: SOKOL_UNREACHABLE; return (D3D11_BLEND_OP) 0;
  5920. }
  5921. }
  5922. _SOKOL_PRIVATE UINT8 _sg_d3d11_color_write_mask(sg_color_mask m) {
  5923. UINT8 res = 0;
  5924. if (m & SG_COLORMASK_R) {
  5925. res |= D3D11_COLOR_WRITE_ENABLE_RED;
  5926. }
  5927. if (m & SG_COLORMASK_G) {
  5928. res |= D3D11_COLOR_WRITE_ENABLE_GREEN;
  5929. }
  5930. if (m & SG_COLORMASK_B) {
  5931. res |= D3D11_COLOR_WRITE_ENABLE_BLUE;
  5932. }
  5933. if (m & SG_COLORMASK_A) {
  5934. res |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
  5935. }
  5936. return res;
  5937. }
  5938. /* see: https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-limits#resource-limits-for-feature-level-11-hardware */
  5939. _SOKOL_PRIVATE void _sg_d3d11_init_caps(void) {
  5940. _sg.backend = SG_BACKEND_D3D11;
  5941. _sg.features.instancing = true;
  5942. _sg.features.origin_top_left = true;
  5943. _sg.features.multiple_render_targets = true;
  5944. _sg.features.msaa_render_targets = true;
  5945. _sg.features.imagetype_3d = true;
  5946. _sg.features.imagetype_array = true;
  5947. _sg.features.image_clamp_to_border = true;
  5948. _sg.limits.max_image_size_2d = 16 * 1024;
  5949. _sg.limits.max_image_size_cube = 16 * 1024;
  5950. _sg.limits.max_image_size_3d = 2 * 1024;
  5951. _sg.limits.max_image_size_array = 16 * 1024;
  5952. _sg.limits.max_image_array_layers = 2 * 1024;
  5953. _sg.limits.max_vertex_attrs = SG_MAX_VERTEX_ATTRIBUTES;
  5954. /* see: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_format_support */
  5955. UINT dxgi_fmt_caps = 0;
  5956. for (int fmt = (SG_PIXELFORMAT_NONE+1); fmt < _SG_PIXELFORMAT_NUM; fmt++) {
  5957. DXGI_FORMAT dxgi_fmt = _sg_d3d11_pixel_format((sg_pixel_format)fmt);
  5958. HRESULT hr = ID3D11Device_CheckFormatSupport(_sg.d3d11.dev, dxgi_fmt, &dxgi_fmt_caps);
  5959. SOKOL_ASSERT(SUCCEEDED(hr));
  5960. sg_pixelformat_info* info = &_sg.formats[fmt];
  5961. info->sample = 0 != (dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_TEXTURE2D);
  5962. info->filter = 0 != (dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE);
  5963. info->render = 0 != (dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_RENDER_TARGET);
  5964. info->blend = 0 != (dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_BLENDABLE);
  5965. info->msaa = 0 != (dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET);
  5966. info->depth = 0 != (dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL);
  5967. if (info->depth) {
  5968. info->render = true;
  5969. }
  5970. }
  5971. }
  5972. _SOKOL_PRIVATE void _sg_d3d11_setup_backend(const sg_desc* desc) {
  5973. /* assume _sg.d3d11 already is zero-initialized */
  5974. SOKOL_ASSERT(desc);
  5975. SOKOL_ASSERT(desc->d3d11_device);
  5976. SOKOL_ASSERT(desc->d3d11_device_context);
  5977. SOKOL_ASSERT(desc->d3d11_render_target_view_cb);
  5978. SOKOL_ASSERT(desc->d3d11_depth_stencil_view_cb);
  5979. SOKOL_ASSERT(desc->d3d11_render_target_view_cb != desc->d3d11_depth_stencil_view_cb);
  5980. _sg.d3d11.valid = true;
  5981. _sg.d3d11.dev = (ID3D11Device*) desc->d3d11_device;
  5982. _sg.d3d11.ctx = (ID3D11DeviceContext*) desc->d3d11_device_context;
  5983. _sg.d3d11.rtv_cb = desc->d3d11_render_target_view_cb;
  5984. _sg.d3d11.dsv_cb = desc->d3d11_depth_stencil_view_cb;
  5985. _sg_d3d11_init_caps();
  5986. }
  5987. _SOKOL_PRIVATE void _sg_d3d11_discard_backend(void) {
  5988. SOKOL_ASSERT(_sg.d3d11.valid);
  5989. _sg.d3d11.valid = false;
  5990. }
  5991. _SOKOL_PRIVATE void _sg_d3d11_clear_state(void) {
  5992. /* clear all the device context state, so that resource refs don't keep stuck in the d3d device context */
  5993. ID3D11DeviceContext_OMSetRenderTargets(_sg.d3d11.ctx, SG_MAX_COLOR_ATTACHMENTS, _sg.d3d11.zero_rtvs, NULL);
  5994. ID3D11DeviceContext_RSSetState(_sg.d3d11.ctx, NULL);
  5995. ID3D11DeviceContext_OMSetDepthStencilState(_sg.d3d11.ctx, NULL, 0);
  5996. ID3D11DeviceContext_OMSetBlendState(_sg.d3d11.ctx, NULL, NULL, 0xFFFFFFFF);
  5997. ID3D11DeviceContext_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_BUFFERS, _sg.d3d11.zero_vbs, _sg.d3d11.zero_vb_strides, _sg.d3d11.zero_vb_offsets);
  5998. ID3D11DeviceContext_IASetIndexBuffer(_sg.d3d11.ctx, NULL, DXGI_FORMAT_UNKNOWN, 0);
  5999. ID3D11DeviceContext_IASetInputLayout(_sg.d3d11.ctx, NULL);
  6000. ID3D11DeviceContext_VSSetShader(_sg.d3d11.ctx, NULL, NULL, 0);
  6001. ID3D11DeviceContext_PSSetShader(_sg.d3d11.ctx, NULL, NULL, 0);
  6002. ID3D11DeviceContext_VSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, _sg.d3d11.zero_cbs);
  6003. ID3D11DeviceContext_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, _sg.d3d11.zero_cbs);
  6004. ID3D11DeviceContext_VSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_srvs);
  6005. ID3D11DeviceContext_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_srvs);
  6006. ID3D11DeviceContext_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_smps);
  6007. ID3D11DeviceContext_PSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, _sg.d3d11.zero_smps);
  6008. }
  6009. _SOKOL_PRIVATE void _sg_d3d11_reset_state_cache(void) {
  6010. /* just clear the d3d11 device context state */
  6011. _sg_d3d11_clear_state();
  6012. }
  6013. _SOKOL_PRIVATE void _sg_d3d11_activate_context(_sg_context_t* ctx) {
  6014. _SOKOL_UNUSED(ctx);
  6015. _sg_d3d11_clear_state();
  6016. }
  6017. _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_context(_sg_context_t* ctx) {
  6018. SOKOL_ASSERT(ctx);
  6019. _SOKOL_UNUSED(ctx);
  6020. return SG_RESOURCESTATE_VALID;
  6021. }
  6022. _SOKOL_PRIVATE void _sg_d3d11_destroy_context(_sg_context_t* ctx) {
  6023. SOKOL_ASSERT(ctx);
  6024. _SOKOL_UNUSED(ctx);
  6025. /* empty */
  6026. }
  6027. _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {
  6028. SOKOL_ASSERT(buf && desc);
  6029. SOKOL_ASSERT(!buf->d3d11.buf);
  6030. _sg_buffer_common_init(&buf->cmn, desc);
  6031. const bool injected = (0 != desc->d3d11_buffer);
  6032. if (injected) {
  6033. buf->d3d11.buf = (ID3D11Buffer*) desc->d3d11_buffer;
  6034. ID3D11Buffer_AddRef(buf->d3d11.buf);
  6035. }
  6036. else {
  6037. D3D11_BUFFER_DESC d3d11_desc;
  6038. memset(&d3d11_desc, 0, sizeof(d3d11_desc));
  6039. d3d11_desc.ByteWidth = buf->cmn.size;
  6040. d3d11_desc.Usage = _sg_d3d11_usage(buf->cmn.usage);
  6041. d3d11_desc.BindFlags = buf->cmn.type == SG_BUFFERTYPE_VERTEXBUFFER ? D3D11_BIND_VERTEX_BUFFER : D3D11_BIND_INDEX_BUFFER;
  6042. d3d11_desc.CPUAccessFlags = _sg_d3d11_cpu_access_flags(buf->cmn.usage);
  6043. D3D11_SUBRESOURCE_DATA* init_data_ptr = 0;
  6044. D3D11_SUBRESOURCE_DATA init_data;
  6045. memset(&init_data, 0, sizeof(init_data));
  6046. if (buf->cmn.usage == SG_USAGE_IMMUTABLE) {
  6047. SOKOL_ASSERT(desc->content);
  6048. init_data.pSysMem = desc->content;
  6049. init_data_ptr = &init_data;
  6050. }
  6051. HRESULT hr = ID3D11Device_CreateBuffer(_sg.d3d11.dev, &d3d11_desc, init_data_ptr, &buf->d3d11.buf);
  6052. _SOKOL_UNUSED(hr);
  6053. SOKOL_ASSERT(SUCCEEDED(hr) && buf->d3d11.buf);
  6054. }
  6055. return SG_RESOURCESTATE_VALID;
  6056. }
  6057. _SOKOL_PRIVATE void _sg_d3d11_destroy_buffer(_sg_buffer_t* buf) {
  6058. SOKOL_ASSERT(buf);
  6059. if (buf->d3d11.buf) {
  6060. ID3D11Buffer_Release(buf->d3d11.buf);
  6061. }
  6062. }
  6063. _SOKOL_PRIVATE void _sg_d3d11_fill_subres_data(const _sg_image_t* img, const sg_image_content* content) {
  6064. const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1;
  6065. const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.depth:1;
  6066. int subres_index = 0;
  6067. for (int face_index = 0; face_index < num_faces; face_index++) {
  6068. for (int slice_index = 0; slice_index < num_slices; slice_index++) {
  6069. for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++, subres_index++) {
  6070. SOKOL_ASSERT(subres_index < (SG_MAX_MIPMAPS * SG_MAX_TEXTUREARRAY_LAYERS));
  6071. D3D11_SUBRESOURCE_DATA* subres_data = &_sg.d3d11.subres_data[subres_index];
  6072. const int mip_width = ((img->cmn.width>>mip_index)>0) ? img->cmn.width>>mip_index : 1;
  6073. const int mip_height = ((img->cmn.height>>mip_index)>0) ? img->cmn.height>>mip_index : 1;
  6074. const sg_subimage_content* subimg_content = &(content->subimage[face_index][mip_index]);
  6075. const int slice_size = subimg_content->size / num_slices;
  6076. const int slice_offset = slice_size * slice_index;
  6077. const uint8_t* ptr = (const uint8_t*) subimg_content->ptr;
  6078. subres_data->pSysMem = ptr + slice_offset;
  6079. subres_data->SysMemPitch = _sg_row_pitch(img->cmn.pixel_format, mip_width);
  6080. if (img->cmn.type == SG_IMAGETYPE_3D) {
  6081. /* FIXME? const int mip_depth = ((img->depth>>mip_index)>0) ? img->depth>>mip_index : 1; */
  6082. subres_data->SysMemSlicePitch = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height);
  6083. }
  6084. else {
  6085. subres_data->SysMemSlicePitch = 0;
  6086. }
  6087. }
  6088. }
  6089. }
  6090. }
  6091. _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const sg_image_desc* desc) {
  6092. SOKOL_ASSERT(img && desc);
  6093. SOKOL_ASSERT(!img->d3d11.tex2d && !img->d3d11.tex3d && !img->d3d11.texds && !img->d3d11.texmsaa);
  6094. SOKOL_ASSERT(!img->d3d11.srv && !img->d3d11.smp);
  6095. HRESULT hr;
  6096. _sg_image_common_init(&img->cmn, desc);
  6097. const bool injected = (0 != desc->d3d11_texture);
  6098. const bool msaa = (img->cmn.sample_count > 1);
  6099. /* special case depth-stencil buffer? */
  6100. if (_sg_is_valid_rendertarget_depth_format(img->cmn.pixel_format)) {
  6101. /* create only a depth-texture */
  6102. SOKOL_ASSERT(!injected);
  6103. img->d3d11.format = _sg_d3d11_pixel_format(img->cmn.pixel_format);
  6104. if (img->d3d11.format == DXGI_FORMAT_UNKNOWN) {
  6105. SOKOL_LOG("trying to create a D3D11 depth-texture with unsupported pixel format\n");
  6106. return SG_RESOURCESTATE_FAILED;
  6107. }
  6108. D3D11_TEXTURE2D_DESC d3d11_desc;
  6109. memset(&d3d11_desc, 0, sizeof(d3d11_desc));
  6110. d3d11_desc.Width = img->cmn.width;
  6111. d3d11_desc.Height = img->cmn.height;
  6112. d3d11_desc.MipLevels = 1;
  6113. d3d11_desc.ArraySize = 1;
  6114. d3d11_desc.Format = img->d3d11.format;
  6115. d3d11_desc.Usage = D3D11_USAGE_DEFAULT;
  6116. d3d11_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
  6117. d3d11_desc.SampleDesc.Count = img->cmn.sample_count;
  6118. d3d11_desc.SampleDesc.Quality = msaa ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0;
  6119. hr = ID3D11Device_CreateTexture2D(_sg.d3d11.dev, &d3d11_desc, NULL, &img->d3d11.texds);
  6120. SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.texds);
  6121. }
  6122. else {
  6123. /* create (or inject) color texture */
  6124. /* prepare initial content pointers */
  6125. D3D11_SUBRESOURCE_DATA* init_data = 0;
  6126. if (!injected && (img->cmn.usage == SG_USAGE_IMMUTABLE) && !img->cmn.render_target) {
  6127. _sg_d3d11_fill_subres_data(img, &desc->content);
  6128. init_data = _sg.d3d11.subres_data;
  6129. }
  6130. if (img->cmn.type != SG_IMAGETYPE_3D) {
  6131. /* 2D-, cube- or array-texture */
  6132. /* if this is an MSAA render target, the following texture will be the 'resolve-texture' */
  6133. D3D11_TEXTURE2D_DESC d3d11_tex_desc;
  6134. memset(&d3d11_tex_desc, 0, sizeof(d3d11_tex_desc));
  6135. d3d11_tex_desc.Width = img->cmn.width;
  6136. d3d11_tex_desc.Height = img->cmn.height;
  6137. d3d11_tex_desc.MipLevels = img->cmn.num_mipmaps;
  6138. switch (img->cmn.type) {
  6139. case SG_IMAGETYPE_ARRAY: d3d11_tex_desc.ArraySize = img->cmn.depth; break;
  6140. case SG_IMAGETYPE_CUBE: d3d11_tex_desc.ArraySize = 6; break;
  6141. default: d3d11_tex_desc.ArraySize = 1; break;
  6142. }
  6143. d3d11_tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
  6144. if (img->cmn.render_target) {
  6145. img->d3d11.format = _sg_d3d11_pixel_format(img->cmn.pixel_format);
  6146. d3d11_tex_desc.Format = img->d3d11.format;
  6147. d3d11_tex_desc.Usage = D3D11_USAGE_DEFAULT;
  6148. if (!msaa) {
  6149. d3d11_tex_desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
  6150. }
  6151. d3d11_tex_desc.CPUAccessFlags = 0;
  6152. }
  6153. else {
  6154. img->d3d11.format = _sg_d3d11_pixel_format(img->cmn.pixel_format);
  6155. d3d11_tex_desc.Format = img->d3d11.format;
  6156. d3d11_tex_desc.Usage = _sg_d3d11_usage(img->cmn.usage);
  6157. d3d11_tex_desc.CPUAccessFlags = _sg_d3d11_cpu_access_flags(img->cmn.usage);
  6158. }
  6159. if (img->d3d11.format == DXGI_FORMAT_UNKNOWN) {
  6160. /* trying to create a texture format that's not supported by D3D */
  6161. SOKOL_LOG("trying to create a D3D11 texture with unsupported pixel format\n");
  6162. return SG_RESOURCESTATE_FAILED;
  6163. }
  6164. d3d11_tex_desc.SampleDesc.Count = 1;
  6165. d3d11_tex_desc.SampleDesc.Quality = 0;
  6166. d3d11_tex_desc.MiscFlags = (img->cmn.type == SG_IMAGETYPE_CUBE) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
  6167. if (injected) {
  6168. img->d3d11.tex2d = (ID3D11Texture2D*) desc->d3d11_texture;
  6169. ID3D11Texture2D_AddRef(img->d3d11.tex2d);
  6170. }
  6171. else {
  6172. hr = ID3D11Device_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex2d);
  6173. SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.tex2d);
  6174. }
  6175. /* shader-resource-view */
  6176. D3D11_SHADER_RESOURCE_VIEW_DESC d3d11_srv_desc;
  6177. memset(&d3d11_srv_desc, 0, sizeof(d3d11_srv_desc));
  6178. d3d11_srv_desc.Format = d3d11_tex_desc.Format;
  6179. switch (img->cmn.type) {
  6180. case SG_IMAGETYPE_2D:
  6181. d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
  6182. d3d11_srv_desc.Texture2D.MipLevels = img->cmn.num_mipmaps;
  6183. break;
  6184. case SG_IMAGETYPE_CUBE:
  6185. d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
  6186. d3d11_srv_desc.TextureCube.MipLevels = img->cmn.num_mipmaps;
  6187. break;
  6188. case SG_IMAGETYPE_ARRAY:
  6189. d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
  6190. d3d11_srv_desc.Texture2DArray.MipLevels = img->cmn.num_mipmaps;
  6191. d3d11_srv_desc.Texture2DArray.ArraySize = img->cmn.depth;
  6192. break;
  6193. default:
  6194. SOKOL_UNREACHABLE; break;
  6195. }
  6196. hr = ID3D11Device_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex2d, &d3d11_srv_desc, &img->d3d11.srv);
  6197. SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.srv);
  6198. }
  6199. else {
  6200. /* 3D texture */
  6201. D3D11_TEXTURE3D_DESC d3d11_tex_desc;
  6202. memset(&d3d11_tex_desc, 0, sizeof(d3d11_tex_desc));
  6203. d3d11_tex_desc.Width = img->cmn.width;
  6204. d3d11_tex_desc.Height = img->cmn.height;
  6205. d3d11_tex_desc.Depth = img->cmn.depth;
  6206. d3d11_tex_desc.MipLevels = img->cmn.num_mipmaps;
  6207. d3d11_tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
  6208. if (img->cmn.render_target) {
  6209. img->d3d11.format = _sg_d3d11_pixel_format(img->cmn.pixel_format);
  6210. d3d11_tex_desc.Format = img->d3d11.format;
  6211. d3d11_tex_desc.Usage = D3D11_USAGE_DEFAULT;
  6212. if (!msaa) {
  6213. d3d11_tex_desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
  6214. }
  6215. d3d11_tex_desc.CPUAccessFlags = 0;
  6216. }
  6217. else {
  6218. img->d3d11.format = _sg_d3d11_pixel_format(img->cmn.pixel_format);
  6219. d3d11_tex_desc.Format = img->d3d11.format;
  6220. d3d11_tex_desc.Usage = _sg_d3d11_usage(img->cmn.usage);
  6221. d3d11_tex_desc.CPUAccessFlags = _sg_d3d11_cpu_access_flags(img->cmn.usage);
  6222. }
  6223. if (img->d3d11.format == DXGI_FORMAT_UNKNOWN) {
  6224. /* trying to create a texture format that's not supported by D3D */
  6225. SOKOL_LOG("trying to create a D3D11 texture with unsupported pixel format\n");
  6226. return SG_RESOURCESTATE_FAILED;
  6227. }
  6228. if (injected) {
  6229. img->d3d11.tex3d = (ID3D11Texture3D*) desc->d3d11_texture;
  6230. ID3D11Texture3D_AddRef(img->d3d11.tex3d);
  6231. }
  6232. else {
  6233. hr = ID3D11Device_CreateTexture3D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex3d);
  6234. SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.tex3d);
  6235. }
  6236. /* shader resource view for 3d texture */
  6237. D3D11_SHADER_RESOURCE_VIEW_DESC d3d11_srv_desc;
  6238. memset(&d3d11_srv_desc, 0, sizeof(d3d11_srv_desc));
  6239. d3d11_srv_desc.Format = d3d11_tex_desc.Format;
  6240. d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
  6241. d3d11_srv_desc.Texture3D.MipLevels = img->cmn.num_mipmaps;
  6242. hr = ID3D11Device_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex3d, &d3d11_srv_desc, &img->d3d11.srv);
  6243. SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.srv);
  6244. }
  6245. /* also need to create a separate MSAA render target texture? */
  6246. if (msaa) {
  6247. D3D11_TEXTURE2D_DESC d3d11_tex_desc;
  6248. memset(&d3d11_tex_desc, 0, sizeof(d3d11_tex_desc));
  6249. d3d11_tex_desc.Width = img->cmn.width;
  6250. d3d11_tex_desc.Height = img->cmn.height;
  6251. d3d11_tex_desc.MipLevels = 1;
  6252. d3d11_tex_desc.ArraySize = 1;
  6253. d3d11_tex_desc.Format = img->d3d11.format;
  6254. d3d11_tex_desc.Usage = D3D11_USAGE_DEFAULT;
  6255. d3d11_tex_desc.BindFlags = D3D11_BIND_RENDER_TARGET;
  6256. d3d11_tex_desc.CPUAccessFlags = 0;
  6257. d3d11_tex_desc.SampleDesc.Count = img->cmn.sample_count;
  6258. d3d11_tex_desc.SampleDesc.Quality = (UINT)D3D11_STANDARD_MULTISAMPLE_PATTERN;
  6259. hr = ID3D11Device_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, NULL, &img->d3d11.texmsaa);
  6260. SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.texmsaa);
  6261. }
  6262. /* sampler state object, note D3D11 implements an internal shared-pool for sampler objects */
  6263. D3D11_SAMPLER_DESC d3d11_smp_desc;
  6264. memset(&d3d11_smp_desc, 0, sizeof(d3d11_smp_desc));
  6265. d3d11_smp_desc.Filter = _sg_d3d11_filter(img->cmn.min_filter, img->cmn.mag_filter, img->cmn.max_anisotropy);
  6266. d3d11_smp_desc.AddressU = _sg_d3d11_address_mode(img->cmn.wrap_u);
  6267. d3d11_smp_desc.AddressV = _sg_d3d11_address_mode(img->cmn.wrap_v);
  6268. d3d11_smp_desc.AddressW = _sg_d3d11_address_mode(img->cmn.wrap_w);
  6269. switch (img->cmn.border_color) {
  6270. case SG_BORDERCOLOR_TRANSPARENT_BLACK:
  6271. /* all 0.0f */
  6272. break;
  6273. case SG_BORDERCOLOR_OPAQUE_WHITE:
  6274. for (int i = 0; i < 4; i++) {
  6275. d3d11_smp_desc.BorderColor[i] = 1.0f;
  6276. }
  6277. break;
  6278. default:
  6279. /* opaque black */
  6280. d3d11_smp_desc.BorderColor[3] = 1.0f;
  6281. break;
  6282. }
  6283. d3d11_smp_desc.MaxAnisotropy = img->cmn.max_anisotropy;
  6284. d3d11_smp_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
  6285. d3d11_smp_desc.MinLOD = desc->min_lod;
  6286. d3d11_smp_desc.MaxLOD = desc->max_lod;
  6287. hr = ID3D11Device_CreateSamplerState(_sg.d3d11.dev, &d3d11_smp_desc, &img->d3d11.smp);
  6288. SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.smp);
  6289. }
  6290. return SG_RESOURCESTATE_VALID;
  6291. }
  6292. _SOKOL_PRIVATE void _sg_d3d11_destroy_image(_sg_image_t* img) {
  6293. SOKOL_ASSERT(img);
  6294. if (img->d3d11.tex2d) {
  6295. ID3D11Texture2D_Release(img->d3d11.tex2d);
  6296. }
  6297. if (img->d3d11.tex3d) {
  6298. ID3D11Texture3D_Release(img->d3d11.tex3d);
  6299. }
  6300. if (img->d3d11.texds) {
  6301. ID3D11Texture2D_Release(img->d3d11.texds);
  6302. }
  6303. if (img->d3d11.texmsaa) {
  6304. ID3D11Texture2D_Release(img->d3d11.texmsaa);
  6305. }
  6306. if (img->d3d11.srv) {
  6307. ID3D11ShaderResourceView_Release(img->d3d11.srv);
  6308. }
  6309. if (img->d3d11.smp) {
  6310. ID3D11SamplerState_Release(img->d3d11.smp);
  6311. }
  6312. }
  6313. _SOKOL_PRIVATE bool _sg_d3d11_load_d3dcompiler_dll(void) {
  6314. /* on UWP, don't do anything (not tested) */
  6315. #if (defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
  6316. return true;
  6317. #else
  6318. /* load DLL on demand */
  6319. if ((0 == _sg.d3d11.d3dcompiler_dll) && !_sg.d3d11.d3dcompiler_dll_load_failed) {
  6320. _sg.d3d11.d3dcompiler_dll = LoadLibraryA("d3dcompiler_47.dll");
  6321. if (0 == _sg.d3d11.d3dcompiler_dll) {
  6322. /* don't attempt to load missing DLL in the future */
  6323. SOKOL_LOG("failed to load d3dcompiler_47.dll!\n");
  6324. _sg.d3d11.d3dcompiler_dll_load_failed = true;
  6325. return false;
  6326. }
  6327. /* look up function pointers */
  6328. _sg.d3d11.D3DCompile_func = (pD3DCompile) GetProcAddress(_sg.d3d11.d3dcompiler_dll, "D3DCompile");
  6329. SOKOL_ASSERT(_sg.d3d11.D3DCompile_func);
  6330. }
  6331. return 0 != _sg.d3d11.d3dcompiler_dll;
  6332. #endif
  6333. }
  6334. #if (defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
  6335. #define _sg_d3d11_D3DCompile D3DCompile
  6336. #else
  6337. #define _sg_d3d11_D3DCompile _sg.d3d11.D3DCompile_func
  6338. #endif
  6339. _SOKOL_PRIVATE ID3DBlob* _sg_d3d11_compile_shader(const sg_shader_stage_desc* stage_desc, const char* target) {
  6340. if (!_sg_d3d11_load_d3dcompiler_dll()) {
  6341. return NULL;
  6342. }
  6343. ID3DBlob* output = NULL;
  6344. ID3DBlob* errors_or_warnings = NULL;
  6345. HRESULT hr = _sg_d3d11_D3DCompile(
  6346. stage_desc->source, /* pSrcData */
  6347. strlen(stage_desc->source), /* SrcDataSize */
  6348. NULL, /* pSourceName */
  6349. NULL, /* pDefines */
  6350. NULL, /* pInclude */
  6351. stage_desc->entry ? stage_desc->entry : "main", /* pEntryPoint */
  6352. target, /* pTarget (vs_5_0 or ps_5_0) */
  6353. D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR | D3DCOMPILE_OPTIMIZATION_LEVEL3, /* Flags1 */
  6354. 0, /* Flags2 */
  6355. &output, /* ppCode */
  6356. &errors_or_warnings); /* ppErrorMsgs */
  6357. if (errors_or_warnings) {
  6358. SOKOL_LOG((LPCSTR)ID3D10Blob_GetBufferPointer(errors_or_warnings));
  6359. ID3D10Blob_Release(errors_or_warnings); errors_or_warnings = NULL;
  6360. }
  6361. if (FAILED(hr)) {
  6362. /* just in case, usually output is NULL here */
  6363. if (output) {
  6364. ID3D10Blob_Release(output);
  6365. output = NULL;
  6366. }
  6367. }
  6368. return output;
  6369. }
  6370. #define _sg_d3d11_roundup(val, round_to) (((val)+((round_to)-1))&~((round_to)-1))
  6371. _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {
  6372. SOKOL_ASSERT(shd && desc);
  6373. SOKOL_ASSERT(!shd->d3d11.vs && !shd->d3d11.fs && !shd->d3d11.vs_blob);
  6374. HRESULT hr;
  6375. _sg_shader_common_init(&shd->cmn, desc);
  6376. /* copy vertex attribute semantic names and indices */
  6377. for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
  6378. _sg_strcpy(&shd->d3d11.attrs[i].sem_name, desc->attrs[i].sem_name);
  6379. shd->d3d11.attrs[i].sem_index = desc->attrs[i].sem_index;
  6380. }
  6381. /* shader stage uniform blocks and image slots */
  6382. for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {
  6383. _sg_shader_stage_t* cmn_stage = &shd->cmn.stage[stage_index];
  6384. _sg_d3d11_shader_stage_t* d3d11_stage = &shd->d3d11.stage[stage_index];
  6385. for (int ub_index = 0; ub_index < cmn_stage->num_uniform_blocks; ub_index++) {
  6386. const _sg_uniform_block_t* ub = &cmn_stage->uniform_blocks[ub_index];
  6387. /* create a D3D constant buffer for each uniform block */
  6388. SOKOL_ASSERT(0 == d3d11_stage->cbufs[ub_index]);
  6389. D3D11_BUFFER_DESC cb_desc;
  6390. memset(&cb_desc, 0, sizeof(cb_desc));
  6391. cb_desc.ByteWidth = _sg_d3d11_roundup(ub->size, 16);
  6392. cb_desc.Usage = D3D11_USAGE_DEFAULT;
  6393. cb_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
  6394. hr = ID3D11Device_CreateBuffer(_sg.d3d11.dev, &cb_desc, NULL, &d3d11_stage->cbufs[ub_index]);
  6395. SOKOL_ASSERT(SUCCEEDED(hr) && d3d11_stage->cbufs[ub_index]);
  6396. }
  6397. }
  6398. const void* vs_ptr = 0, *fs_ptr = 0;
  6399. SIZE_T vs_length = 0, fs_length = 0;
  6400. ID3DBlob* vs_blob = 0, *fs_blob = 0;
  6401. if (desc->vs.byte_code && desc->fs.byte_code) {
  6402. /* create from shader byte code */
  6403. vs_ptr = desc->vs.byte_code;
  6404. fs_ptr = desc->fs.byte_code;
  6405. vs_length = desc->vs.byte_code_size;
  6406. fs_length = desc->fs.byte_code_size;
  6407. }
  6408. else {
  6409. /* compile from shader source code */
  6410. vs_blob = _sg_d3d11_compile_shader(&desc->vs, "vs_5_0");
  6411. fs_blob = _sg_d3d11_compile_shader(&desc->fs, "ps_5_0");
  6412. if (vs_blob && fs_blob) {
  6413. vs_ptr = ID3D10Blob_GetBufferPointer(vs_blob);
  6414. vs_length = ID3D10Blob_GetBufferSize(vs_blob);
  6415. fs_ptr = ID3D10Blob_GetBufferPointer(fs_blob);
  6416. fs_length = ID3D10Blob_GetBufferSize(fs_blob);
  6417. }
  6418. }
  6419. sg_resource_state result = SG_RESOURCESTATE_FAILED;
  6420. if (vs_ptr && fs_ptr && (vs_length > 0) && (fs_length > 0)) {
  6421. /* create the D3D vertex- and pixel-shader objects */
  6422. hr = ID3D11Device_CreateVertexShader(_sg.d3d11.dev, vs_ptr, vs_length, NULL, &shd->d3d11.vs);
  6423. SOKOL_ASSERT(SUCCEEDED(hr) && shd->d3d11.vs);
  6424. hr = ID3D11Device_CreatePixelShader(_sg.d3d11.dev, fs_ptr, fs_length, NULL, &shd->d3d11.fs);
  6425. SOKOL_ASSERT(SUCCEEDED(hr) && shd->d3d11.fs);
  6426. /* need to store the vertex shader byte code, this is needed later in sg_create_pipeline */
  6427. shd->d3d11.vs_blob_length = (int)vs_length;
  6428. shd->d3d11.vs_blob = SOKOL_MALLOC((int)vs_length);
  6429. SOKOL_ASSERT(shd->d3d11.vs_blob);
  6430. memcpy(shd->d3d11.vs_blob, vs_ptr, vs_length);
  6431. result = SG_RESOURCESTATE_VALID;
  6432. }
  6433. if (vs_blob) {
  6434. ID3D10Blob_Release(vs_blob); vs_blob = 0;
  6435. }
  6436. if (fs_blob) {
  6437. ID3D10Blob_Release(fs_blob); fs_blob = 0;
  6438. }
  6439. return result;
  6440. }
  6441. _SOKOL_PRIVATE void _sg_d3d11_destroy_shader(_sg_shader_t* shd) {
  6442. SOKOL_ASSERT(shd);
  6443. if (shd->d3d11.vs) {
  6444. ID3D11VertexShader_Release(shd->d3d11.vs);
  6445. }
  6446. if (shd->d3d11.fs) {
  6447. ID3D11PixelShader_Release(shd->d3d11.fs);
  6448. }
  6449. if (shd->d3d11.vs_blob) {
  6450. SOKOL_FREE(shd->d3d11.vs_blob);
  6451. }
  6452. for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {
  6453. _sg_shader_stage_t* cmn_stage = &shd->cmn.stage[stage_index];
  6454. _sg_d3d11_shader_stage_t* d3d11_stage = &shd->d3d11.stage[stage_index];
  6455. for (int ub_index = 0; ub_index < cmn_stage->num_uniform_blocks; ub_index++) {
  6456. if (d3d11_stage->cbufs[ub_index]) {
  6457. ID3D11Buffer_Release(d3d11_stage->cbufs[ub_index]);
  6458. }
  6459. }
  6460. }
  6461. }
  6462. _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {
  6463. SOKOL_ASSERT(pip && shd && desc);
  6464. SOKOL_ASSERT(desc->shader.id == shd->slot.id);
  6465. SOKOL_ASSERT(shd->slot.state == SG_RESOURCESTATE_VALID);
  6466. SOKOL_ASSERT(shd->d3d11.vs_blob && shd->d3d11.vs_blob_length > 0);
  6467. SOKOL_ASSERT(!pip->d3d11.il && !pip->d3d11.rs && !pip->d3d11.dss && !pip->d3d11.bs);
  6468. pip->shader = shd;
  6469. _sg_pipeline_common_init(&pip->cmn, desc);
  6470. pip->d3d11.index_format = _sg_d3d11_index_format(pip->cmn.index_type);
  6471. pip->d3d11.topology = _sg_d3d11_primitive_topology(desc->primitive_type);
  6472. pip->d3d11.stencil_ref = desc->depth_stencil.stencil_ref;
  6473. /* create input layout object */
  6474. HRESULT hr;
  6475. D3D11_INPUT_ELEMENT_DESC d3d11_comps[SG_MAX_VERTEX_ATTRIBUTES];
  6476. memset(d3d11_comps, 0, sizeof(d3d11_comps));
  6477. int attr_index = 0;
  6478. for (; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
  6479. const sg_vertex_attr_desc* a_desc = &desc->layout.attrs[attr_index];
  6480. if (a_desc->format == SG_VERTEXFORMAT_INVALID) {
  6481. break;
  6482. }
  6483. SOKOL_ASSERT((a_desc->buffer_index >= 0) && (a_desc->buffer_index < SG_MAX_SHADERSTAGE_BUFFERS));
  6484. const sg_buffer_layout_desc* l_desc = &desc->layout.buffers[a_desc->buffer_index];
  6485. const sg_vertex_step step_func = l_desc->step_func;
  6486. const int step_rate = l_desc->step_rate;
  6487. D3D11_INPUT_ELEMENT_DESC* d3d11_comp = &d3d11_comps[attr_index];
  6488. d3d11_comp->SemanticName = _sg_strptr(&shd->d3d11.attrs[attr_index].sem_name);
  6489. d3d11_comp->SemanticIndex = shd->d3d11.attrs[attr_index].sem_index;
  6490. d3d11_comp->Format = _sg_d3d11_vertex_format(a_desc->format);
  6491. d3d11_comp->InputSlot = a_desc->buffer_index;
  6492. d3d11_comp->AlignedByteOffset = a_desc->offset;
  6493. d3d11_comp->InputSlotClass = _sg_d3d11_input_classification(step_func);
  6494. if (SG_VERTEXSTEP_PER_INSTANCE == step_func) {
  6495. d3d11_comp->InstanceDataStepRate = step_rate;
  6496. }
  6497. pip->cmn.vertex_layout_valid[a_desc->buffer_index] = true;
  6498. }
  6499. for (int layout_index = 0; layout_index < SG_MAX_SHADERSTAGE_BUFFERS; layout_index++) {
  6500. if (pip->cmn.vertex_layout_valid[layout_index]) {
  6501. const sg_buffer_layout_desc* l_desc = &desc->layout.buffers[layout_index];
  6502. SOKOL_ASSERT(l_desc->stride > 0);
  6503. pip->d3d11.vb_strides[layout_index] = l_desc->stride;
  6504. }
  6505. else {
  6506. pip->d3d11.vb_strides[layout_index] = 0;
  6507. }
  6508. }
  6509. hr = ID3D11Device_CreateInputLayout(_sg.d3d11.dev,
  6510. d3d11_comps, /* pInputElementDesc */
  6511. attr_index, /* NumElements */
  6512. shd->d3d11.vs_blob, /* pShaderByteCodeWithInputSignature */
  6513. shd->d3d11.vs_blob_length, /* BytecodeLength */
  6514. &pip->d3d11.il);
  6515. SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.il);
  6516. /* create rasterizer state */
  6517. D3D11_RASTERIZER_DESC rs_desc;
  6518. memset(&rs_desc, 0, sizeof(rs_desc));
  6519. rs_desc.FillMode = D3D11_FILL_SOLID;
  6520. rs_desc.CullMode = _sg_d3d11_cull_mode(desc->rasterizer.cull_mode);
  6521. rs_desc.FrontCounterClockwise = desc->rasterizer.face_winding == SG_FACEWINDING_CCW;
  6522. rs_desc.DepthBias = (INT) pip->cmn.depth_bias;
  6523. rs_desc.DepthBiasClamp = pip->cmn.depth_bias_clamp;
  6524. rs_desc.SlopeScaledDepthBias = pip->cmn.depth_bias_slope_scale;
  6525. rs_desc.DepthClipEnable = TRUE;
  6526. rs_desc.ScissorEnable = TRUE;
  6527. rs_desc.MultisampleEnable = desc->rasterizer.sample_count > 1;
  6528. rs_desc.AntialiasedLineEnable = FALSE;
  6529. hr = ID3D11Device_CreateRasterizerState(_sg.d3d11.dev, &rs_desc, &pip->d3d11.rs);
  6530. SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.rs);
  6531. /* create depth-stencil state */
  6532. D3D11_DEPTH_STENCIL_DESC dss_desc;
  6533. memset(&dss_desc, 0, sizeof(dss_desc));
  6534. dss_desc.DepthEnable = TRUE;
  6535. dss_desc.DepthWriteMask = desc->depth_stencil.depth_write_enabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
  6536. dss_desc.DepthFunc = _sg_d3d11_compare_func(desc->depth_stencil.depth_compare_func);
  6537. dss_desc.StencilEnable = desc->depth_stencil.stencil_enabled;
  6538. dss_desc.StencilReadMask = desc->depth_stencil.stencil_read_mask;
  6539. dss_desc.StencilWriteMask = desc->depth_stencil.stencil_write_mask;
  6540. const sg_stencil_state* sf = &desc->depth_stencil.stencil_front;
  6541. dss_desc.FrontFace.StencilFailOp = _sg_d3d11_stencil_op(sf->fail_op);
  6542. dss_desc.FrontFace.StencilDepthFailOp = _sg_d3d11_stencil_op(sf->depth_fail_op);
  6543. dss_desc.FrontFace.StencilPassOp = _sg_d3d11_stencil_op(sf->pass_op);
  6544. dss_desc.FrontFace.StencilFunc = _sg_d3d11_compare_func(sf->compare_func);
  6545. const sg_stencil_state* sb = &desc->depth_stencil.stencil_back;
  6546. dss_desc.BackFace.StencilFailOp = _sg_d3d11_stencil_op(sb->fail_op);
  6547. dss_desc.BackFace.StencilDepthFailOp = _sg_d3d11_stencil_op(sb->depth_fail_op);
  6548. dss_desc.BackFace.StencilPassOp = _sg_d3d11_stencil_op(sb->pass_op);
  6549. dss_desc.BackFace.StencilFunc = _sg_d3d11_compare_func(sb->compare_func);
  6550. hr = ID3D11Device_CreateDepthStencilState(_sg.d3d11.dev, &dss_desc, &pip->d3d11.dss);
  6551. SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.dss);
  6552. /* create blend state */
  6553. D3D11_BLEND_DESC bs_desc;
  6554. memset(&bs_desc, 0, sizeof(bs_desc));
  6555. bs_desc.AlphaToCoverageEnable = desc->rasterizer.alpha_to_coverage_enabled;
  6556. bs_desc.IndependentBlendEnable = FALSE;
  6557. bs_desc.RenderTarget[0].BlendEnable = desc->blend.enabled;
  6558. bs_desc.RenderTarget[0].SrcBlend = _sg_d3d11_blend_factor(desc->blend.src_factor_rgb);
  6559. bs_desc.RenderTarget[0].DestBlend = _sg_d3d11_blend_factor(desc->blend.dst_factor_rgb);
  6560. bs_desc.RenderTarget[0].BlendOp = _sg_d3d11_blend_op(desc->blend.op_rgb);
  6561. bs_desc.RenderTarget[0].SrcBlendAlpha = _sg_d3d11_blend_factor(desc->blend.src_factor_alpha);
  6562. bs_desc.RenderTarget[0].DestBlendAlpha = _sg_d3d11_blend_factor(desc->blend.dst_factor_alpha);
  6563. bs_desc.RenderTarget[0].BlendOpAlpha = _sg_d3d11_blend_op(desc->blend.op_alpha);
  6564. bs_desc.RenderTarget[0].RenderTargetWriteMask = _sg_d3d11_color_write_mask((sg_color_mask)desc->blend.color_write_mask);
  6565. hr = ID3D11Device_CreateBlendState(_sg.d3d11.dev, &bs_desc, &pip->d3d11.bs);
  6566. SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.bs);
  6567. return SG_RESOURCESTATE_VALID;
  6568. }
  6569. _SOKOL_PRIVATE void _sg_d3d11_destroy_pipeline(_sg_pipeline_t* pip) {
  6570. SOKOL_ASSERT(pip);
  6571. if (pip->d3d11.il) {
  6572. ID3D11InputLayout_Release(pip->d3d11.il);
  6573. }
  6574. if (pip->d3d11.rs) {
  6575. ID3D11RasterizerState_Release(pip->d3d11.rs);
  6576. }
  6577. if (pip->d3d11.dss) {
  6578. ID3D11DepthStencilState_Release(pip->d3d11.dss);
  6579. }
  6580. if (pip->d3d11.bs) {
  6581. ID3D11BlendState_Release(pip->d3d11.bs);
  6582. }
  6583. }
  6584. _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pass(_sg_pass_t* pass, _sg_image_t** att_images, const sg_pass_desc* desc) {
  6585. SOKOL_ASSERT(pass && desc);
  6586. SOKOL_ASSERT(att_images && att_images[0]);
  6587. SOKOL_ASSERT(_sg.d3d11.dev);
  6588. _sg_pass_common_init(&pass->cmn, desc);
  6589. for (int i = 0; i < pass->cmn.num_color_atts; i++) {
  6590. const sg_attachment_desc* att_desc = &desc->color_attachments[i];
  6591. SOKOL_ASSERT(att_desc->image.id != SG_INVALID_ID);
  6592. _sg_image_t* att_img = att_images[i];
  6593. SOKOL_ASSERT(att_img && (att_img->slot.id == att_desc->image.id));
  6594. SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(att_img->cmn.pixel_format));
  6595. SOKOL_ASSERT(0 == pass->d3d11.color_atts[i].image);
  6596. pass->d3d11.color_atts[i].image = att_img;
  6597. /* create D3D11 render-target-view */
  6598. const _sg_attachment_t* cmn_att = &pass->cmn.color_atts[i];
  6599. SOKOL_ASSERT(0 == pass->d3d11.color_atts[i].rtv);
  6600. ID3D11Resource* d3d11_res = 0;
  6601. const bool is_msaa = att_img->cmn.sample_count > 1;
  6602. D3D11_RENDER_TARGET_VIEW_DESC d3d11_rtv_desc;
  6603. memset(&d3d11_rtv_desc, 0, sizeof(d3d11_rtv_desc));
  6604. d3d11_rtv_desc.Format = att_img->d3d11.format;
  6605. if ((att_img->cmn.type == SG_IMAGETYPE_2D) || is_msaa) {
  6606. if (is_msaa) {
  6607. d3d11_res = (ID3D11Resource*) att_img->d3d11.texmsaa;
  6608. d3d11_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
  6609. }
  6610. else {
  6611. d3d11_res = (ID3D11Resource*) att_img->d3d11.tex2d;
  6612. d3d11_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
  6613. d3d11_rtv_desc.Texture2D.MipSlice = cmn_att->mip_level;
  6614. }
  6615. }
  6616. else if ((att_img->cmn.type == SG_IMAGETYPE_CUBE) || (att_img->cmn.type == SG_IMAGETYPE_ARRAY)) {
  6617. d3d11_res = (ID3D11Resource*) att_img->d3d11.tex2d;
  6618. d3d11_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
  6619. d3d11_rtv_desc.Texture2DArray.MipSlice = cmn_att->mip_level;
  6620. d3d11_rtv_desc.Texture2DArray.FirstArraySlice = cmn_att->slice;
  6621. d3d11_rtv_desc.Texture2DArray.ArraySize = 1;
  6622. }
  6623. else {
  6624. SOKOL_ASSERT(att_img->cmn.type == SG_IMAGETYPE_3D);
  6625. d3d11_res = (ID3D11Resource*) att_img->d3d11.tex3d;
  6626. d3d11_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
  6627. d3d11_rtv_desc.Texture3D.MipSlice = cmn_att->mip_level;
  6628. d3d11_rtv_desc.Texture3D.FirstWSlice = cmn_att->slice;
  6629. d3d11_rtv_desc.Texture3D.WSize = 1;
  6630. }
  6631. SOKOL_ASSERT(d3d11_res);
  6632. HRESULT hr = ID3D11Device_CreateRenderTargetView(_sg.d3d11.dev, d3d11_res, &d3d11_rtv_desc, &pass->d3d11.color_atts[i].rtv);
  6633. _SOKOL_UNUSED(hr);
  6634. SOKOL_ASSERT(SUCCEEDED(hr) && pass->d3d11.color_atts[i].rtv);
  6635. }
  6636. /* optional depth-stencil image */
  6637. SOKOL_ASSERT(0 == pass->d3d11.ds_att.image);
  6638. SOKOL_ASSERT(0 == pass->d3d11.ds_att.dsv);
  6639. if (desc->depth_stencil_attachment.image.id != SG_INVALID_ID) {
  6640. const int ds_img_index = SG_MAX_COLOR_ATTACHMENTS;
  6641. const sg_attachment_desc* att_desc = &desc->depth_stencil_attachment;
  6642. _sg_image_t* att_img = att_images[ds_img_index];
  6643. SOKOL_ASSERT(att_img && (att_img->slot.id == att_desc->image.id));
  6644. SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(att_img->cmn.pixel_format));
  6645. SOKOL_ASSERT(0 == pass->d3d11.ds_att.image);
  6646. pass->d3d11.ds_att.image = att_img;
  6647. /* create D3D11 depth-stencil-view */
  6648. D3D11_DEPTH_STENCIL_VIEW_DESC d3d11_dsv_desc;
  6649. memset(&d3d11_dsv_desc, 0, sizeof(d3d11_dsv_desc));
  6650. d3d11_dsv_desc.Format = att_img->d3d11.format;
  6651. const bool is_msaa = att_img->cmn.sample_count > 1;
  6652. if (is_msaa) {
  6653. d3d11_dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
  6654. }
  6655. else {
  6656. d3d11_dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
  6657. }
  6658. ID3D11Resource* d3d11_res = (ID3D11Resource*) att_img->d3d11.texds;
  6659. SOKOL_ASSERT(d3d11_res);
  6660. HRESULT hr = ID3D11Device_CreateDepthStencilView(_sg.d3d11.dev, d3d11_res, &d3d11_dsv_desc, &pass->d3d11.ds_att.dsv);
  6661. _SOKOL_UNUSED(hr);
  6662. SOKOL_ASSERT(SUCCEEDED(hr) && pass->d3d11.ds_att.dsv);
  6663. }
  6664. return SG_RESOURCESTATE_VALID;
  6665. }
  6666. _SOKOL_PRIVATE void _sg_d3d11_destroy_pass(_sg_pass_t* pass) {
  6667. SOKOL_ASSERT(pass);
  6668. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  6669. if (pass->d3d11.color_atts[i].rtv) {
  6670. ID3D11RenderTargetView_Release(pass->d3d11.color_atts[i].rtv);
  6671. }
  6672. }
  6673. if (pass->d3d11.ds_att.dsv) {
  6674. ID3D11DepthStencilView_Release(pass->d3d11.ds_att.dsv);
  6675. }
  6676. }
  6677. _SOKOL_PRIVATE _sg_image_t* _sg_d3d11_pass_color_image(const _sg_pass_t* pass, int index) {
  6678. SOKOL_ASSERT(pass && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));
  6679. /* NOTE: may return null */
  6680. return pass->d3d11.color_atts[index].image;
  6681. }
  6682. _SOKOL_PRIVATE _sg_image_t* _sg_d3d11_pass_ds_image(const _sg_pass_t* pass) {
  6683. /* NOTE: may return null */
  6684. SOKOL_ASSERT(pass);
  6685. return pass->d3d11.ds_att.image;
  6686. }
  6687. _SOKOL_PRIVATE void _sg_d3d11_begin_pass(_sg_pass_t* pass, const sg_pass_action* action, int w, int h) {
  6688. SOKOL_ASSERT(action);
  6689. SOKOL_ASSERT(!_sg.d3d11.in_pass);
  6690. _sg.d3d11.in_pass = true;
  6691. _sg.d3d11.cur_width = w;
  6692. _sg.d3d11.cur_height = h;
  6693. if (pass) {
  6694. _sg.d3d11.cur_pass = pass;
  6695. _sg.d3d11.cur_pass_id.id = pass->slot.id;
  6696. _sg.d3d11.num_rtvs = 0;
  6697. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  6698. _sg.d3d11.cur_rtvs[i] = pass->d3d11.color_atts[i].rtv;
  6699. if (_sg.d3d11.cur_rtvs[i]) {
  6700. _sg.d3d11.num_rtvs++;
  6701. }
  6702. }
  6703. _sg.d3d11.cur_dsv = pass->d3d11.ds_att.dsv;
  6704. }
  6705. else {
  6706. /* render to default frame buffer */
  6707. _sg.d3d11.cur_pass = 0;
  6708. _sg.d3d11.cur_pass_id.id = SG_INVALID_ID;
  6709. _sg.d3d11.num_rtvs = 1;
  6710. _sg.d3d11.cur_rtvs[0] = (ID3D11RenderTargetView*) _sg.d3d11.rtv_cb();
  6711. for (int i = 1; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  6712. _sg.d3d11.cur_rtvs[i] = 0;
  6713. }
  6714. _sg.d3d11.cur_dsv = (ID3D11DepthStencilView*) _sg.d3d11.dsv_cb();
  6715. SOKOL_ASSERT(_sg.d3d11.cur_rtvs[0] && _sg.d3d11.cur_dsv);
  6716. }
  6717. /* apply the render-target- and depth-stencil-views */
  6718. ID3D11DeviceContext_OMSetRenderTargets(_sg.d3d11.ctx, SG_MAX_COLOR_ATTACHMENTS, _sg.d3d11.cur_rtvs, _sg.d3d11.cur_dsv);
  6719. /* set viewport and scissor rect to cover whole screen */
  6720. D3D11_VIEWPORT vp;
  6721. memset(&vp, 0, sizeof(vp));
  6722. vp.Width = (FLOAT) w;
  6723. vp.Height = (FLOAT) h;
  6724. vp.MaxDepth = 1.0f;
  6725. ID3D11DeviceContext_RSSetViewports(_sg.d3d11.ctx, 1, &vp);
  6726. D3D11_RECT rect;
  6727. rect.left = 0;
  6728. rect.top = 0;
  6729. rect.right = w;
  6730. rect.bottom = h;
  6731. ID3D11DeviceContext_RSSetScissorRects(_sg.d3d11.ctx, 1, &rect);
  6732. /* perform clear action */
  6733. for (int i = 0; i < _sg.d3d11.num_rtvs; i++) {
  6734. if (action->colors[i].action == SG_ACTION_CLEAR) {
  6735. ID3D11DeviceContext_ClearRenderTargetView(_sg.d3d11.ctx, _sg.d3d11.cur_rtvs[i], action->colors[i].val);
  6736. }
  6737. }
  6738. UINT ds_flags = 0;
  6739. if (action->depth.action == SG_ACTION_CLEAR) {
  6740. ds_flags |= D3D11_CLEAR_DEPTH;
  6741. }
  6742. if (action->stencil.action == SG_ACTION_CLEAR) {
  6743. ds_flags |= D3D11_CLEAR_STENCIL;
  6744. }
  6745. if ((0 != ds_flags) && _sg.d3d11.cur_dsv) {
  6746. ID3D11DeviceContext_ClearDepthStencilView(_sg.d3d11.ctx, _sg.d3d11.cur_dsv, ds_flags, action->depth.val, action->stencil.val);
  6747. }
  6748. }
  6749. /* D3D11CalcSubresource only exists for C++ */
  6750. _SOKOL_PRIVATE UINT _sg_d3d11_calcsubresource(UINT mip_slice, UINT array_slice, UINT mip_levels) {
  6751. return mip_slice + array_slice * mip_levels;
  6752. }
  6753. _SOKOL_PRIVATE void _sg_d3d11_end_pass(void) {
  6754. SOKOL_ASSERT(_sg.d3d11.in_pass && _sg.d3d11.ctx);
  6755. _sg.d3d11.in_pass = false;
  6756. /* need to resolve MSAA render target into texture? */
  6757. if (_sg.d3d11.cur_pass) {
  6758. SOKOL_ASSERT(_sg.d3d11.cur_pass->slot.id == _sg.d3d11.cur_pass_id.id);
  6759. for (int i = 0; i < _sg.d3d11.num_rtvs; i++) {
  6760. _sg_attachment_t* cmn_att = &_sg.d3d11.cur_pass->cmn.color_atts[i];
  6761. _sg_image_t* att_img = _sg.d3d11.cur_pass->d3d11.color_atts[i].image;
  6762. SOKOL_ASSERT(att_img && (att_img->slot.id == cmn_att->image_id.id));
  6763. if (att_img->cmn.sample_count > 1) {
  6764. /* FIXME: support MSAA resolve into 3D texture */
  6765. SOKOL_ASSERT(att_img->d3d11.tex2d && att_img->d3d11.texmsaa && !att_img->d3d11.tex3d);
  6766. SOKOL_ASSERT(DXGI_FORMAT_UNKNOWN != att_img->d3d11.format);
  6767. UINT dst_subres = _sg_d3d11_calcsubresource(cmn_att->mip_level, cmn_att->slice, att_img->cmn.num_mipmaps);
  6768. ID3D11DeviceContext_ResolveSubresource(_sg.d3d11.ctx,
  6769. (ID3D11Resource*) att_img->d3d11.tex2d, /* pDstResource */
  6770. dst_subres, /* DstSubresource */
  6771. (ID3D11Resource*) att_img->d3d11.texmsaa, /* pSrcResource */
  6772. 0, /* SrcSubresource */
  6773. att_img->d3d11.format);
  6774. }
  6775. }
  6776. }
  6777. _sg.d3d11.cur_pass = 0;
  6778. _sg.d3d11.cur_pass_id.id = SG_INVALID_ID;
  6779. _sg.d3d11.cur_pipeline = 0;
  6780. _sg.d3d11.cur_pipeline_id.id = SG_INVALID_ID;
  6781. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  6782. _sg.d3d11.cur_rtvs[i] = 0;
  6783. }
  6784. _sg.d3d11.cur_dsv = 0;
  6785. _sg_d3d11_clear_state();
  6786. }
  6787. _SOKOL_PRIVATE void _sg_d3d11_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {
  6788. SOKOL_ASSERT(_sg.d3d11.ctx);
  6789. SOKOL_ASSERT(_sg.d3d11.in_pass);
  6790. D3D11_VIEWPORT vp;
  6791. vp.TopLeftX = (FLOAT) x;
  6792. vp.TopLeftY = (FLOAT) (origin_top_left ? y : (_sg.d3d11.cur_height - (y + h)));
  6793. vp.Width = (FLOAT) w;
  6794. vp.Height = (FLOAT) h;
  6795. vp.MinDepth = 0.0f;
  6796. vp.MaxDepth = 1.0f;
  6797. ID3D11DeviceContext_RSSetViewports(_sg.d3d11.ctx, 1, &vp);
  6798. }
  6799. _SOKOL_PRIVATE void _sg_d3d11_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {
  6800. SOKOL_ASSERT(_sg.d3d11.ctx);
  6801. SOKOL_ASSERT(_sg.d3d11.in_pass);
  6802. D3D11_RECT rect;
  6803. rect.left = x;
  6804. rect.top = (origin_top_left ? y : (_sg.d3d11.cur_height - (y + h)));
  6805. rect.right = x + w;
  6806. rect.bottom = origin_top_left ? (y + h) : (_sg.d3d11.cur_height - y);
  6807. ID3D11DeviceContext_RSSetScissorRects(_sg.d3d11.ctx, 1, &rect);
  6808. }
  6809. _SOKOL_PRIVATE void _sg_d3d11_apply_pipeline(_sg_pipeline_t* pip) {
  6810. SOKOL_ASSERT(pip);
  6811. SOKOL_ASSERT(pip->shader);
  6812. SOKOL_ASSERT(_sg.d3d11.ctx);
  6813. SOKOL_ASSERT(_sg.d3d11.in_pass);
  6814. SOKOL_ASSERT(pip->d3d11.rs && pip->d3d11.bs && pip->d3d11.dss && pip->d3d11.il);
  6815. _sg.d3d11.cur_pipeline = pip;
  6816. _sg.d3d11.cur_pipeline_id.id = pip->slot.id;
  6817. _sg.d3d11.use_indexed_draw = (pip->d3d11.index_format != DXGI_FORMAT_UNKNOWN);
  6818. ID3D11DeviceContext_RSSetState(_sg.d3d11.ctx, pip->d3d11.rs);
  6819. ID3D11DeviceContext_OMSetDepthStencilState(_sg.d3d11.ctx, pip->d3d11.dss, pip->d3d11.stencil_ref);
  6820. ID3D11DeviceContext_OMSetBlendState(_sg.d3d11.ctx, pip->d3d11.bs, pip->cmn.blend_color, 0xFFFFFFFF);
  6821. ID3D11DeviceContext_IASetPrimitiveTopology(_sg.d3d11.ctx, pip->d3d11.topology);
  6822. ID3D11DeviceContext_IASetInputLayout(_sg.d3d11.ctx, pip->d3d11.il);
  6823. ID3D11DeviceContext_VSSetShader(_sg.d3d11.ctx, pip->shader->d3d11.vs, NULL, 0);
  6824. ID3D11DeviceContext_VSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_VS].cbufs);
  6825. ID3D11DeviceContext_PSSetShader(_sg.d3d11.ctx, pip->shader->d3d11.fs, NULL, 0);
  6826. ID3D11DeviceContext_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_FS].cbufs);
  6827. }
  6828. _SOKOL_PRIVATE void _sg_d3d11_apply_bindings(
  6829. _sg_pipeline_t* pip,
  6830. _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs,
  6831. _sg_buffer_t* ib, int ib_offset,
  6832. _sg_image_t** vs_imgs, int num_vs_imgs,
  6833. _sg_image_t** fs_imgs, int num_fs_imgs)
  6834. {
  6835. SOKOL_ASSERT(pip);
  6836. SOKOL_ASSERT(_sg.d3d11.ctx);
  6837. SOKOL_ASSERT(_sg.d3d11.in_pass);
  6838. /* gather all the D3D11 resources into arrays */
  6839. ID3D11Buffer* d3d11_ib = ib ? ib->d3d11.buf : 0;
  6840. ID3D11Buffer* d3d11_vbs[SG_MAX_SHADERSTAGE_BUFFERS];
  6841. UINT d3d11_vb_offsets[SG_MAX_SHADERSTAGE_BUFFERS];
  6842. ID3D11ShaderResourceView* d3d11_vs_srvs[SG_MAX_SHADERSTAGE_IMAGES];
  6843. ID3D11SamplerState* d3d11_vs_smps[SG_MAX_SHADERSTAGE_IMAGES];
  6844. ID3D11ShaderResourceView* d3d11_fs_srvs[SG_MAX_SHADERSTAGE_IMAGES];
  6845. ID3D11SamplerState* d3d11_fs_smps[SG_MAX_SHADERSTAGE_IMAGES];
  6846. int i;
  6847. for (i = 0; i < num_vbs; i++) {
  6848. SOKOL_ASSERT(vbs[i]->d3d11.buf);
  6849. d3d11_vbs[i] = vbs[i]->d3d11.buf;
  6850. d3d11_vb_offsets[i] = vb_offsets[i];
  6851. }
  6852. for (; i < SG_MAX_SHADERSTAGE_BUFFERS; i++) {
  6853. d3d11_vbs[i] = 0;
  6854. d3d11_vb_offsets[i] = 0;
  6855. }
  6856. for (i = 0; i < num_vs_imgs; i++) {
  6857. SOKOL_ASSERT(vs_imgs[i]->d3d11.srv);
  6858. SOKOL_ASSERT(vs_imgs[i]->d3d11.smp);
  6859. d3d11_vs_srvs[i] = vs_imgs[i]->d3d11.srv;
  6860. d3d11_vs_smps[i] = vs_imgs[i]->d3d11.smp;
  6861. }
  6862. for (; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  6863. d3d11_vs_srvs[i] = 0;
  6864. d3d11_vs_smps[i] = 0;
  6865. }
  6866. for (i = 0; i < num_fs_imgs; i++) {
  6867. SOKOL_ASSERT(fs_imgs[i]->d3d11.srv);
  6868. SOKOL_ASSERT(fs_imgs[i]->d3d11.smp);
  6869. d3d11_fs_srvs[i] = fs_imgs[i]->d3d11.srv;
  6870. d3d11_fs_smps[i] = fs_imgs[i]->d3d11.smp;
  6871. }
  6872. for (; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  6873. d3d11_fs_srvs[i] = 0;
  6874. d3d11_fs_smps[i] = 0;
  6875. }
  6876. ID3D11DeviceContext_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_BUFFERS, d3d11_vbs, pip->d3d11.vb_strides, d3d11_vb_offsets);
  6877. ID3D11DeviceContext_IASetIndexBuffer(_sg.d3d11.ctx, d3d11_ib, pip->d3d11.index_format, ib_offset);
  6878. ID3D11DeviceContext_VSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_vs_srvs);
  6879. ID3D11DeviceContext_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_vs_smps);
  6880. ID3D11DeviceContext_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_srvs);
  6881. ID3D11DeviceContext_PSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_smps);
  6882. }
  6883. _SOKOL_PRIVATE void _sg_d3d11_apply_uniforms(sg_shader_stage stage_index, int ub_index, const void* data, int num_bytes) {
  6884. _SOKOL_UNUSED(num_bytes);
  6885. SOKOL_ASSERT(_sg.d3d11.ctx && _sg.d3d11.in_pass);
  6886. SOKOL_ASSERT(data && (num_bytes > 0));
  6887. SOKOL_ASSERT((stage_index >= 0) && ((int)stage_index < SG_NUM_SHADER_STAGES));
  6888. SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS));
  6889. SOKOL_ASSERT(_sg.d3d11.cur_pipeline && _sg.d3d11.cur_pipeline->slot.id == _sg.d3d11.cur_pipeline_id.id);
  6890. SOKOL_ASSERT(_sg.d3d11.cur_pipeline->shader && _sg.d3d11.cur_pipeline->shader->slot.id == _sg.d3d11.cur_pipeline->cmn.shader_id.id);
  6891. SOKOL_ASSERT(ub_index < _sg.d3d11.cur_pipeline->shader->cmn.stage[stage_index].num_uniform_blocks);
  6892. SOKOL_ASSERT(num_bytes == _sg.d3d11.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size);
  6893. ID3D11Buffer* cb = _sg.d3d11.cur_pipeline->shader->d3d11.stage[stage_index].cbufs[ub_index];
  6894. SOKOL_ASSERT(cb);
  6895. ID3D11DeviceContext_UpdateSubresource(_sg.d3d11.ctx, (ID3D11Resource*)cb, 0, NULL, data, 0, 0);
  6896. }
  6897. _SOKOL_PRIVATE void _sg_d3d11_draw(int base_element, int num_elements, int num_instances) {
  6898. SOKOL_ASSERT(_sg.d3d11.in_pass);
  6899. if (_sg.d3d11.use_indexed_draw) {
  6900. if (1 == num_instances) {
  6901. ID3D11DeviceContext_DrawIndexed(_sg.d3d11.ctx, num_elements, base_element, 0);
  6902. }
  6903. else {
  6904. ID3D11DeviceContext_DrawIndexedInstanced(_sg.d3d11.ctx, num_elements, num_instances, base_element, 0, 0);
  6905. }
  6906. }
  6907. else {
  6908. if (1 == num_instances) {
  6909. ID3D11DeviceContext_Draw(_sg.d3d11.ctx, num_elements, base_element);
  6910. }
  6911. else {
  6912. ID3D11DeviceContext_DrawInstanced(_sg.d3d11.ctx, num_elements, num_instances, base_element, 0);
  6913. }
  6914. }
  6915. }
  6916. _SOKOL_PRIVATE void _sg_d3d11_commit(void) {
  6917. SOKOL_ASSERT(!_sg.d3d11.in_pass);
  6918. }
  6919. _SOKOL_PRIVATE void _sg_d3d11_update_buffer(_sg_buffer_t* buf, const void* data_ptr, int data_size) {
  6920. SOKOL_ASSERT(buf && data_ptr && (data_size > 0));
  6921. SOKOL_ASSERT(_sg.d3d11.ctx);
  6922. SOKOL_ASSERT(buf->d3d11.buf);
  6923. D3D11_MAPPED_SUBRESOURCE d3d11_msr;
  6924. HRESULT hr = ID3D11DeviceContext_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr);
  6925. _SOKOL_UNUSED(hr);
  6926. SOKOL_ASSERT(SUCCEEDED(hr));
  6927. memcpy(d3d11_msr.pData, data_ptr, data_size);
  6928. ID3D11DeviceContext_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0);
  6929. }
  6930. _SOKOL_PRIVATE void _sg_d3d11_append_buffer(_sg_buffer_t* buf, const void* data_ptr, int data_size, bool new_frame) {
  6931. SOKOL_ASSERT(buf && data_ptr && (data_size > 0));
  6932. SOKOL_ASSERT(_sg.d3d11.ctx);
  6933. SOKOL_ASSERT(buf->d3d11.buf);
  6934. D3D11_MAP map_type = new_frame ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;
  6935. D3D11_MAPPED_SUBRESOURCE d3d11_msr;
  6936. HRESULT hr = ID3D11DeviceContext_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, map_type, 0, &d3d11_msr);
  6937. _SOKOL_UNUSED(hr);
  6938. SOKOL_ASSERT(SUCCEEDED(hr));
  6939. uint8_t* dst_ptr = (uint8_t*)d3d11_msr.pData + buf->cmn.append_pos;
  6940. memcpy(dst_ptr, data_ptr, data_size);
  6941. ID3D11DeviceContext_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0);
  6942. }
  6943. _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_content* data) {
  6944. SOKOL_ASSERT(img && data);
  6945. SOKOL_ASSERT(_sg.d3d11.ctx);
  6946. SOKOL_ASSERT(img->d3d11.tex2d || img->d3d11.tex3d);
  6947. ID3D11Resource* d3d11_res = 0;
  6948. if (img->d3d11.tex3d) {
  6949. d3d11_res = (ID3D11Resource*) img->d3d11.tex3d;
  6950. }
  6951. else {
  6952. d3d11_res = (ID3D11Resource*) img->d3d11.tex2d;
  6953. }
  6954. SOKOL_ASSERT(d3d11_res);
  6955. const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1;
  6956. const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.depth:1;
  6957. int subres_index = 0;
  6958. HRESULT hr;
  6959. D3D11_MAPPED_SUBRESOURCE d3d11_msr;
  6960. for (int face_index = 0; face_index < num_faces; face_index++) {
  6961. for (int slice_index = 0; slice_index < num_slices; slice_index++) {
  6962. for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++, subres_index++) {
  6963. SOKOL_ASSERT(subres_index < (SG_MAX_MIPMAPS * SG_MAX_TEXTUREARRAY_LAYERS));
  6964. const int mip_width = ((img->cmn.width>>mip_index)>0) ? img->cmn.width>>mip_index : 1;
  6965. const int mip_height = ((img->cmn.height>>mip_index)>0) ? img->cmn.height>>mip_index : 1;
  6966. const int src_pitch = _sg_row_pitch(img->cmn.pixel_format, mip_width);
  6967. const sg_subimage_content* subimg_content = &(data->subimage[face_index][mip_index]);
  6968. const int slice_size = subimg_content->size / num_slices;
  6969. const int slice_offset = slice_size * slice_index;
  6970. const uint8_t* slice_ptr = ((const uint8_t*)subimg_content->ptr) + slice_offset;
  6971. hr = ID3D11DeviceContext_Map(_sg.d3d11.ctx, d3d11_res, subres_index, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr);
  6972. SOKOL_ASSERT(SUCCEEDED(hr));
  6973. /* FIXME: need to handle difference in depth-pitch for 3D textures as well! */
  6974. if (src_pitch == (int)d3d11_msr.RowPitch) {
  6975. memcpy(d3d11_msr.pData, slice_ptr, slice_size);
  6976. }
  6977. else {
  6978. SOKOL_ASSERT(src_pitch < (int)d3d11_msr.RowPitch);
  6979. const uint8_t* src_ptr = slice_ptr;
  6980. uint8_t* dst_ptr = (uint8_t*) d3d11_msr.pData;
  6981. for (int row_index = 0; row_index < mip_height; row_index++) {
  6982. memcpy(dst_ptr, src_ptr, src_pitch);
  6983. src_ptr += src_pitch;
  6984. dst_ptr += d3d11_msr.RowPitch;
  6985. }
  6986. }
  6987. ID3D11DeviceContext_Unmap(_sg.d3d11.ctx, d3d11_res, subres_index);
  6988. }
  6989. }
  6990. }
  6991. }
  6992. /*== METAL BACKEND IMPLEMENTATION ============================================*/
  6993. #elif defined(SOKOL_METAL)
  6994. /*-- enum translation functions ----------------------------------------------*/
  6995. _SOKOL_PRIVATE MTLLoadAction _sg_mtl_load_action(sg_action a) {
  6996. switch (a) {
  6997. case SG_ACTION_CLEAR: return MTLLoadActionClear;
  6998. case SG_ACTION_LOAD: return MTLLoadActionLoad;
  6999. case SG_ACTION_DONTCARE: return MTLLoadActionDontCare;
  7000. default: SOKOL_UNREACHABLE; return (MTLLoadAction)0;
  7001. }
  7002. }
  7003. _SOKOL_PRIVATE MTLResourceOptions _sg_mtl_buffer_resource_options(sg_usage usg) {
  7004. switch (usg) {
  7005. case SG_USAGE_IMMUTABLE:
  7006. return MTLResourceStorageModeShared;
  7007. case SG_USAGE_DYNAMIC:
  7008. case SG_USAGE_STREAM:
  7009. #if defined(_SG_TARGET_MACOS)
  7010. return MTLCPUCacheModeWriteCombined|MTLResourceStorageModeManaged;
  7011. #else
  7012. return MTLCPUCacheModeWriteCombined;
  7013. #endif
  7014. default:
  7015. SOKOL_UNREACHABLE;
  7016. return 0;
  7017. }
  7018. }
  7019. _SOKOL_PRIVATE MTLVertexStepFunction _sg_mtl_step_function(sg_vertex_step step) {
  7020. switch (step) {
  7021. case SG_VERTEXSTEP_PER_VERTEX: return MTLVertexStepFunctionPerVertex;
  7022. case SG_VERTEXSTEP_PER_INSTANCE: return MTLVertexStepFunctionPerInstance;
  7023. default: SOKOL_UNREACHABLE; return (MTLVertexStepFunction)0;
  7024. }
  7025. }
  7026. _SOKOL_PRIVATE MTLVertexFormat _sg_mtl_vertex_format(sg_vertex_format fmt) {
  7027. switch (fmt) {
  7028. case SG_VERTEXFORMAT_FLOAT: return MTLVertexFormatFloat;
  7029. case SG_VERTEXFORMAT_FLOAT2: return MTLVertexFormatFloat2;
  7030. case SG_VERTEXFORMAT_FLOAT3: return MTLVertexFormatFloat3;
  7031. case SG_VERTEXFORMAT_FLOAT4: return MTLVertexFormatFloat4;
  7032. case SG_VERTEXFORMAT_BYTE4: return MTLVertexFormatChar4;
  7033. case SG_VERTEXFORMAT_BYTE4N: return MTLVertexFormatChar4Normalized;
  7034. case SG_VERTEXFORMAT_UBYTE4: return MTLVertexFormatUChar4;
  7035. case SG_VERTEXFORMAT_UBYTE4N: return MTLVertexFormatUChar4Normalized;
  7036. case SG_VERTEXFORMAT_SHORT2: return MTLVertexFormatShort2;
  7037. case SG_VERTEXFORMAT_SHORT2N: return MTLVertexFormatShort2Normalized;
  7038. case SG_VERTEXFORMAT_USHORT2N: return MTLVertexFormatUShort2Normalized;
  7039. case SG_VERTEXFORMAT_SHORT4: return MTLVertexFormatShort4;
  7040. case SG_VERTEXFORMAT_SHORT4N: return MTLVertexFormatShort4Normalized;
  7041. case SG_VERTEXFORMAT_USHORT4N: return MTLVertexFormatUShort4Normalized;
  7042. case SG_VERTEXFORMAT_UINT10_N2: return MTLVertexFormatUInt1010102Normalized;
  7043. default: SOKOL_UNREACHABLE; return (MTLVertexFormat)0;
  7044. }
  7045. }
  7046. _SOKOL_PRIVATE MTLPrimitiveType _sg_mtl_primitive_type(sg_primitive_type t) {
  7047. switch (t) {
  7048. case SG_PRIMITIVETYPE_POINTS: return MTLPrimitiveTypePoint;
  7049. case SG_PRIMITIVETYPE_LINES: return MTLPrimitiveTypeLine;
  7050. case SG_PRIMITIVETYPE_LINE_STRIP: return MTLPrimitiveTypeLineStrip;
  7051. case SG_PRIMITIVETYPE_TRIANGLES: return MTLPrimitiveTypeTriangle;
  7052. case SG_PRIMITIVETYPE_TRIANGLE_STRIP: return MTLPrimitiveTypeTriangleStrip;
  7053. default: SOKOL_UNREACHABLE; return (MTLPrimitiveType)0;
  7054. }
  7055. }
  7056. _SOKOL_PRIVATE MTLPixelFormat _sg_mtl_pixel_format(sg_pixel_format fmt) {
  7057. switch (fmt) {
  7058. case SG_PIXELFORMAT_R8: return MTLPixelFormatR8Unorm;
  7059. case SG_PIXELFORMAT_R8SN: return MTLPixelFormatR8Snorm;
  7060. case SG_PIXELFORMAT_R8UI: return MTLPixelFormatR8Uint;
  7061. case SG_PIXELFORMAT_R8SI: return MTLPixelFormatR8Sint;
  7062. case SG_PIXELFORMAT_R16: return MTLPixelFormatR16Unorm;
  7063. case SG_PIXELFORMAT_R16SN: return MTLPixelFormatR16Snorm;
  7064. case SG_PIXELFORMAT_R16UI: return MTLPixelFormatR16Uint;
  7065. case SG_PIXELFORMAT_R16SI: return MTLPixelFormatR16Sint;
  7066. case SG_PIXELFORMAT_R16F: return MTLPixelFormatR16Float;
  7067. case SG_PIXELFORMAT_RG8: return MTLPixelFormatRG8Unorm;
  7068. case SG_PIXELFORMAT_RG8SN: return MTLPixelFormatRG8Snorm;
  7069. case SG_PIXELFORMAT_RG8UI: return MTLPixelFormatRG8Uint;
  7070. case SG_PIXELFORMAT_RG8SI: return MTLPixelFormatRG8Sint;
  7071. case SG_PIXELFORMAT_R32UI: return MTLPixelFormatR32Uint;
  7072. case SG_PIXELFORMAT_R32SI: return MTLPixelFormatR32Sint;
  7073. case SG_PIXELFORMAT_R32F: return MTLPixelFormatR32Float;
  7074. case SG_PIXELFORMAT_RG16: return MTLPixelFormatRG16Unorm;
  7075. case SG_PIXELFORMAT_RG16SN: return MTLPixelFormatRG16Snorm;
  7076. case SG_PIXELFORMAT_RG16UI: return MTLPixelFormatRG16Uint;
  7077. case SG_PIXELFORMAT_RG16SI: return MTLPixelFormatRG16Sint;
  7078. case SG_PIXELFORMAT_RG16F: return MTLPixelFormatRG16Float;
  7079. case SG_PIXELFORMAT_RGBA8: return MTLPixelFormatRGBA8Unorm;
  7080. case SG_PIXELFORMAT_RGBA8SN: return MTLPixelFormatRGBA8Snorm;
  7081. case SG_PIXELFORMAT_RGBA8UI: return MTLPixelFormatRGBA8Uint;
  7082. case SG_PIXELFORMAT_RGBA8SI: return MTLPixelFormatRGBA8Sint;
  7083. case SG_PIXELFORMAT_BGRA8: return MTLPixelFormatBGRA8Unorm;
  7084. case SG_PIXELFORMAT_RGB10A2: return MTLPixelFormatRGB10A2Unorm;
  7085. case SG_PIXELFORMAT_RG11B10F: return MTLPixelFormatRG11B10Float;
  7086. case SG_PIXELFORMAT_RG32UI: return MTLPixelFormatRG32Uint;
  7087. case SG_PIXELFORMAT_RG32SI: return MTLPixelFormatRG32Sint;
  7088. case SG_PIXELFORMAT_RG32F: return MTLPixelFormatRG32Float;
  7089. case SG_PIXELFORMAT_RGBA16: return MTLPixelFormatRGBA16Unorm;
  7090. case SG_PIXELFORMAT_RGBA16SN: return MTLPixelFormatRGBA16Snorm;
  7091. case SG_PIXELFORMAT_RGBA16UI: return MTLPixelFormatRGBA16Uint;
  7092. case SG_PIXELFORMAT_RGBA16SI: return MTLPixelFormatRGBA16Sint;
  7093. case SG_PIXELFORMAT_RGBA16F: return MTLPixelFormatRGBA16Float;
  7094. case SG_PIXELFORMAT_RGBA32UI: return MTLPixelFormatRGBA32Uint;
  7095. case SG_PIXELFORMAT_RGBA32SI: return MTLPixelFormatRGBA32Sint;
  7096. case SG_PIXELFORMAT_RGBA32F: return MTLPixelFormatRGBA32Float;
  7097. case SG_PIXELFORMAT_DEPTH: return MTLPixelFormatDepth32Float;
  7098. case SG_PIXELFORMAT_DEPTH_STENCIL: return MTLPixelFormatDepth32Float_Stencil8;
  7099. #if defined(_SG_TARGET_MACOS)
  7100. case SG_PIXELFORMAT_BC1_RGBA: return MTLPixelFormatBC1_RGBA;
  7101. case SG_PIXELFORMAT_BC2_RGBA: return MTLPixelFormatBC2_RGBA;
  7102. case SG_PIXELFORMAT_BC3_RGBA: return MTLPixelFormatBC3_RGBA;
  7103. case SG_PIXELFORMAT_BC4_R: return MTLPixelFormatBC4_RUnorm;
  7104. case SG_PIXELFORMAT_BC4_RSN: return MTLPixelFormatBC4_RSnorm;
  7105. case SG_PIXELFORMAT_BC5_RG: return MTLPixelFormatBC5_RGUnorm;
  7106. case SG_PIXELFORMAT_BC5_RGSN: return MTLPixelFormatBC5_RGSnorm;
  7107. case SG_PIXELFORMAT_BC6H_RGBF: return MTLPixelFormatBC6H_RGBFloat;
  7108. case SG_PIXELFORMAT_BC6H_RGBUF: return MTLPixelFormatBC6H_RGBUfloat;
  7109. case SG_PIXELFORMAT_BC7_RGBA: return MTLPixelFormatBC7_RGBAUnorm;
  7110. #else
  7111. case SG_PIXELFORMAT_PVRTC_RGB_2BPP: return MTLPixelFormatPVRTC_RGB_2BPP;
  7112. case SG_PIXELFORMAT_PVRTC_RGB_4BPP: return MTLPixelFormatPVRTC_RGB_4BPP;
  7113. case SG_PIXELFORMAT_PVRTC_RGBA_2BPP: return MTLPixelFormatPVRTC_RGBA_2BPP;
  7114. case SG_PIXELFORMAT_PVRTC_RGBA_4BPP: return MTLPixelFormatPVRTC_RGBA_4BPP;
  7115. case SG_PIXELFORMAT_ETC2_RGB8: return MTLPixelFormatETC2_RGB8;
  7116. case SG_PIXELFORMAT_ETC2_RGB8A1: return MTLPixelFormatETC2_RGB8A1;
  7117. case SG_PIXELFORMAT_ETC2_RGBA8: return MTLPixelFormatEAC_RGBA8;
  7118. case SG_PIXELFORMAT_ETC2_RG11: return MTLPixelFormatEAC_RG11Unorm;
  7119. case SG_PIXELFORMAT_ETC2_RG11SN: return MTLPixelFormatEAC_RG11Snorm;
  7120. #endif
  7121. default: return MTLPixelFormatInvalid;
  7122. }
  7123. }
  7124. _SOKOL_PRIVATE MTLColorWriteMask _sg_mtl_color_write_mask(sg_color_mask m) {
  7125. MTLColorWriteMask mtl_mask = MTLColorWriteMaskNone;
  7126. if (m & SG_COLORMASK_R) {
  7127. mtl_mask |= MTLColorWriteMaskRed;
  7128. }
  7129. if (m & SG_COLORMASK_G) {
  7130. mtl_mask |= MTLColorWriteMaskGreen;
  7131. }
  7132. if (m & SG_COLORMASK_B) {
  7133. mtl_mask |= MTLColorWriteMaskBlue;
  7134. }
  7135. if (m & SG_COLORMASK_A) {
  7136. mtl_mask |= MTLColorWriteMaskAlpha;
  7137. }
  7138. return mtl_mask;
  7139. }
  7140. _SOKOL_PRIVATE MTLBlendOperation _sg_mtl_blend_op(sg_blend_op op) {
  7141. switch (op) {
  7142. case SG_BLENDOP_ADD: return MTLBlendOperationAdd;
  7143. case SG_BLENDOP_SUBTRACT: return MTLBlendOperationSubtract;
  7144. case SG_BLENDOP_REVERSE_SUBTRACT: return MTLBlendOperationReverseSubtract;
  7145. default: SOKOL_UNREACHABLE; return (MTLBlendOperation)0;
  7146. }
  7147. }
  7148. _SOKOL_PRIVATE MTLBlendFactor _sg_mtl_blend_factor(sg_blend_factor f) {
  7149. switch (f) {
  7150. case SG_BLENDFACTOR_ZERO: return MTLBlendFactorZero;
  7151. case SG_BLENDFACTOR_ONE: return MTLBlendFactorOne;
  7152. case SG_BLENDFACTOR_SRC_COLOR: return MTLBlendFactorSourceColor;
  7153. case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR: return MTLBlendFactorOneMinusSourceColor;
  7154. case SG_BLENDFACTOR_SRC_ALPHA: return MTLBlendFactorSourceAlpha;
  7155. case SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA: return MTLBlendFactorOneMinusSourceAlpha;
  7156. case SG_BLENDFACTOR_DST_COLOR: return MTLBlendFactorDestinationColor;
  7157. case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR: return MTLBlendFactorOneMinusDestinationColor;
  7158. case SG_BLENDFACTOR_DST_ALPHA: return MTLBlendFactorDestinationAlpha;
  7159. case SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA: return MTLBlendFactorOneMinusDestinationAlpha;
  7160. case SG_BLENDFACTOR_SRC_ALPHA_SATURATED: return MTLBlendFactorSourceAlphaSaturated;
  7161. case SG_BLENDFACTOR_BLEND_COLOR: return MTLBlendFactorBlendColor;
  7162. case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR: return MTLBlendFactorOneMinusBlendColor;
  7163. case SG_BLENDFACTOR_BLEND_ALPHA: return MTLBlendFactorBlendAlpha;
  7164. case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA: return MTLBlendFactorOneMinusBlendAlpha;
  7165. default: SOKOL_UNREACHABLE; return (MTLBlendFactor)0;
  7166. }
  7167. }
  7168. _SOKOL_PRIVATE MTLCompareFunction _sg_mtl_compare_func(sg_compare_func f) {
  7169. switch (f) {
  7170. case SG_COMPAREFUNC_NEVER: return MTLCompareFunctionNever;
  7171. case SG_COMPAREFUNC_LESS: return MTLCompareFunctionLess;
  7172. case SG_COMPAREFUNC_EQUAL: return MTLCompareFunctionEqual;
  7173. case SG_COMPAREFUNC_LESS_EQUAL: return MTLCompareFunctionLessEqual;
  7174. case SG_COMPAREFUNC_GREATER: return MTLCompareFunctionGreater;
  7175. case SG_COMPAREFUNC_NOT_EQUAL: return MTLCompareFunctionNotEqual;
  7176. case SG_COMPAREFUNC_GREATER_EQUAL: return MTLCompareFunctionGreaterEqual;
  7177. case SG_COMPAREFUNC_ALWAYS: return MTLCompareFunctionAlways;
  7178. default: SOKOL_UNREACHABLE; return (MTLCompareFunction)0;
  7179. }
  7180. }
  7181. _SOKOL_PRIVATE MTLStencilOperation _sg_mtl_stencil_op(sg_stencil_op op) {
  7182. switch (op) {
  7183. case SG_STENCILOP_KEEP: return MTLStencilOperationKeep;
  7184. case SG_STENCILOP_ZERO: return MTLStencilOperationZero;
  7185. case SG_STENCILOP_REPLACE: return MTLStencilOperationReplace;
  7186. case SG_STENCILOP_INCR_CLAMP: return MTLStencilOperationIncrementClamp;
  7187. case SG_STENCILOP_DECR_CLAMP: return MTLStencilOperationDecrementClamp;
  7188. case SG_STENCILOP_INVERT: return MTLStencilOperationInvert;
  7189. case SG_STENCILOP_INCR_WRAP: return MTLStencilOperationIncrementWrap;
  7190. case SG_STENCILOP_DECR_WRAP: return MTLStencilOperationDecrementWrap;
  7191. default: SOKOL_UNREACHABLE; return (MTLStencilOperation)0;
  7192. }
  7193. }
  7194. _SOKOL_PRIVATE MTLCullMode _sg_mtl_cull_mode(sg_cull_mode m) {
  7195. switch (m) {
  7196. case SG_CULLMODE_NONE: return MTLCullModeNone;
  7197. case SG_CULLMODE_FRONT: return MTLCullModeFront;
  7198. case SG_CULLMODE_BACK: return MTLCullModeBack;
  7199. default: SOKOL_UNREACHABLE; return (MTLCullMode)0;
  7200. }
  7201. }
  7202. _SOKOL_PRIVATE MTLWinding _sg_mtl_winding(sg_face_winding w) {
  7203. switch (w) {
  7204. case SG_FACEWINDING_CW: return MTLWindingClockwise;
  7205. case SG_FACEWINDING_CCW: return MTLWindingCounterClockwise;
  7206. default: SOKOL_UNREACHABLE; return (MTLWinding)0;
  7207. }
  7208. }
  7209. _SOKOL_PRIVATE MTLIndexType _sg_mtl_index_type(sg_index_type t) {
  7210. switch (t) {
  7211. case SG_INDEXTYPE_UINT16: return MTLIndexTypeUInt16;
  7212. case SG_INDEXTYPE_UINT32: return MTLIndexTypeUInt32;
  7213. default: SOKOL_UNREACHABLE; return (MTLIndexType)0;
  7214. }
  7215. }
  7216. _SOKOL_PRIVATE NSUInteger _sg_mtl_index_size(sg_index_type t) {
  7217. switch (t) {
  7218. case SG_INDEXTYPE_NONE: return 0;
  7219. case SG_INDEXTYPE_UINT16: return 2;
  7220. case SG_INDEXTYPE_UINT32: return 4;
  7221. default: SOKOL_UNREACHABLE; return 0;
  7222. }
  7223. }
  7224. _SOKOL_PRIVATE MTLTextureType _sg_mtl_texture_type(sg_image_type t) {
  7225. switch (t) {
  7226. case SG_IMAGETYPE_2D: return MTLTextureType2D;
  7227. case SG_IMAGETYPE_CUBE: return MTLTextureTypeCube;
  7228. case SG_IMAGETYPE_3D: return MTLTextureType3D;
  7229. case SG_IMAGETYPE_ARRAY: return MTLTextureType2DArray;
  7230. default: SOKOL_UNREACHABLE; return (MTLTextureType)0;
  7231. }
  7232. }
  7233. _SOKOL_PRIVATE bool _sg_mtl_is_pvrtc(sg_pixel_format fmt) {
  7234. switch (fmt) {
  7235. case SG_PIXELFORMAT_PVRTC_RGB_2BPP:
  7236. case SG_PIXELFORMAT_PVRTC_RGB_4BPP:
  7237. case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:
  7238. case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:
  7239. return true;
  7240. default:
  7241. return false;
  7242. }
  7243. }
  7244. _SOKOL_PRIVATE MTLSamplerAddressMode _sg_mtl_address_mode(sg_wrap w) {
  7245. switch (w) {
  7246. case SG_WRAP_REPEAT: return MTLSamplerAddressModeRepeat;
  7247. case SG_WRAP_CLAMP_TO_EDGE: return MTLSamplerAddressModeClampToEdge;
  7248. #if defined(_SG_TARGET_MACOS)
  7249. case SG_WRAP_CLAMP_TO_BORDER: return MTLSamplerAddressModeClampToBorderColor;
  7250. #else
  7251. /* clamp-to-border not supported on iOS, fall back to clamp-to-edge */
  7252. case SG_WRAP_CLAMP_TO_BORDER: return MTLSamplerAddressModeClampToEdge;
  7253. #endif
  7254. case SG_WRAP_MIRRORED_REPEAT: return MTLSamplerAddressModeMirrorRepeat;
  7255. default: SOKOL_UNREACHABLE; return (MTLSamplerAddressMode)0;
  7256. }
  7257. }
  7258. #if defined(_SG_TARGET_MACOS)
  7259. _SOKOL_PRIVATE MTLSamplerBorderColor _sg_mtl_border_color(sg_border_color c) {
  7260. switch (c) {
  7261. case SG_BORDERCOLOR_TRANSPARENT_BLACK: return MTLSamplerBorderColorTransparentBlack;
  7262. case SG_BORDERCOLOR_OPAQUE_BLACK: return MTLSamplerBorderColorOpaqueBlack;
  7263. case SG_BORDERCOLOR_OPAQUE_WHITE: return MTLSamplerBorderColorOpaqueWhite;
  7264. default: SOKOL_UNREACHABLE; return (MTLSamplerBorderColor)0;
  7265. }
  7266. }
  7267. #endif
  7268. _SOKOL_PRIVATE MTLSamplerMinMagFilter _sg_mtl_minmag_filter(sg_filter f) {
  7269. switch (f) {
  7270. case SG_FILTER_NEAREST:
  7271. case SG_FILTER_NEAREST_MIPMAP_NEAREST:
  7272. case SG_FILTER_NEAREST_MIPMAP_LINEAR:
  7273. return MTLSamplerMinMagFilterNearest;
  7274. case SG_FILTER_LINEAR:
  7275. case SG_FILTER_LINEAR_MIPMAP_NEAREST:
  7276. case SG_FILTER_LINEAR_MIPMAP_LINEAR:
  7277. return MTLSamplerMinMagFilterLinear;
  7278. default:
  7279. SOKOL_UNREACHABLE; return (MTLSamplerMinMagFilter)0;
  7280. }
  7281. }
  7282. _SOKOL_PRIVATE MTLSamplerMipFilter _sg_mtl_mip_filter(sg_filter f) {
  7283. switch (f) {
  7284. case SG_FILTER_NEAREST:
  7285. case SG_FILTER_LINEAR:
  7286. return MTLSamplerMipFilterNotMipmapped;
  7287. case SG_FILTER_NEAREST_MIPMAP_NEAREST:
  7288. case SG_FILTER_LINEAR_MIPMAP_NEAREST:
  7289. return MTLSamplerMipFilterNearest;
  7290. case SG_FILTER_NEAREST_MIPMAP_LINEAR:
  7291. case SG_FILTER_LINEAR_MIPMAP_LINEAR:
  7292. return MTLSamplerMipFilterLinear;
  7293. default:
  7294. SOKOL_UNREACHABLE; return (MTLSamplerMipFilter)0;
  7295. }
  7296. }
  7297. /*-- a pool for all Metal resource objects, with deferred release queue -------*/
  7298. _SOKOL_PRIVATE void _sg_mtl_init_pool(const sg_desc* desc) {
  7299. _sg.mtl.idpool.num_slots = 2 *
  7300. (
  7301. 2 * desc->buffer_pool_size +
  7302. 5 * desc->image_pool_size +
  7303. 4 * desc->shader_pool_size +
  7304. 2 * desc->pipeline_pool_size +
  7305. desc->pass_pool_size
  7306. );
  7307. _sg_mtl_idpool = [NSMutableArray arrayWithCapacity:_sg.mtl.idpool.num_slots];
  7308. NSNull* null = [NSNull null];
  7309. for (uint32_t i = 0; i < _sg.mtl.idpool.num_slots; i++) {
  7310. [_sg_mtl_idpool addObject:null];
  7311. }
  7312. SOKOL_ASSERT([_sg_mtl_idpool count] == _sg.mtl.idpool.num_slots);
  7313. /* a queue of currently free slot indices */
  7314. _sg.mtl.idpool.free_queue_top = 0;
  7315. _sg.mtl.idpool.free_queue = (uint32_t*)SOKOL_MALLOC(_sg.mtl.idpool.num_slots * sizeof(uint32_t));
  7316. /* pool slot 0 is reserved! */
  7317. for (int i = _sg.mtl.idpool.num_slots-1; i >= 1; i--) {
  7318. _sg.mtl.idpool.free_queue[_sg.mtl.idpool.free_queue_top++] = (uint32_t)i;
  7319. }
  7320. /* a circular queue which holds release items (frame index
  7321. when a resource is to be released, and the resource's
  7322. pool index
  7323. */
  7324. _sg.mtl.idpool.release_queue_front = 0;
  7325. _sg.mtl.idpool.release_queue_back = 0;
  7326. _sg.mtl.idpool.release_queue = (_sg_mtl_release_item_t*)SOKOL_MALLOC(_sg.mtl.idpool.num_slots * sizeof(_sg_mtl_release_item_t));
  7327. for (uint32_t i = 0; i < _sg.mtl.idpool.num_slots; i++) {
  7328. _sg.mtl.idpool.release_queue[i].frame_index = 0;
  7329. _sg.mtl.idpool.release_queue[i].slot_index = _SG_MTL_INVALID_SLOT_INDEX;
  7330. }
  7331. }
  7332. _SOKOL_PRIVATE void _sg_mtl_destroy_pool(void) {
  7333. SOKOL_FREE(_sg.mtl.idpool.release_queue); _sg.mtl.idpool.release_queue = 0;
  7334. SOKOL_FREE(_sg.mtl.idpool.free_queue); _sg.mtl.idpool.free_queue = 0;
  7335. _sg_mtl_idpool = nil;
  7336. }
  7337. /* get a new free resource pool slot */
  7338. _SOKOL_PRIVATE uint32_t _sg_mtl_alloc_pool_slot(void) {
  7339. SOKOL_ASSERT(_sg.mtl.idpool.free_queue_top > 0);
  7340. const uint32_t slot_index = _sg.mtl.idpool.free_queue[--_sg.mtl.idpool.free_queue_top];
  7341. SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots));
  7342. return slot_index;
  7343. }
  7344. /* put a free resource pool slot back into the free-queue */
  7345. _SOKOL_PRIVATE void _sg_mtl_free_pool_slot(uint32_t slot_index) {
  7346. SOKOL_ASSERT(_sg.mtl.idpool.free_queue_top < _sg.mtl.idpool.num_slots);
  7347. SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots));
  7348. _sg.mtl.idpool.free_queue[_sg.mtl.idpool.free_queue_top++] = slot_index;
  7349. }
  7350. /* add an MTLResource to the pool, return pool index or 0 if input was 'nil' */
  7351. _SOKOL_PRIVATE uint32_t _sg_mtl_add_resource(id res) {
  7352. if (nil == res) {
  7353. return _SG_MTL_INVALID_SLOT_INDEX;
  7354. }
  7355. const uint32_t slot_index = _sg_mtl_alloc_pool_slot();
  7356. SOKOL_ASSERT([NSNull null] == _sg_mtl_idpool[slot_index]);
  7357. _sg_mtl_idpool[slot_index] = res;
  7358. return slot_index;
  7359. }
  7360. /* mark an MTLResource for release, this will put the resource into the
  7361. deferred-release queue, and the resource will then be released N frames later,
  7362. the special pool index 0 will be ignored (this means that a nil
  7363. value was provided to _sg_mtl_add_resource()
  7364. */
  7365. _SOKOL_PRIVATE void _sg_mtl_release_resource(uint32_t frame_index, uint32_t slot_index) {
  7366. if (slot_index == _SG_MTL_INVALID_SLOT_INDEX) {
  7367. return;
  7368. }
  7369. SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots));
  7370. SOKOL_ASSERT([NSNull null] != _sg_mtl_idpool[slot_index]);
  7371. int release_index = _sg.mtl.idpool.release_queue_front++;
  7372. if (_sg.mtl.idpool.release_queue_front >= _sg.mtl.idpool.num_slots) {
  7373. /* wrap-around */
  7374. _sg.mtl.idpool.release_queue_front = 0;
  7375. }
  7376. /* release queue full? */
  7377. SOKOL_ASSERT(_sg.mtl.idpool.release_queue_front != _sg.mtl.idpool.release_queue_back);
  7378. SOKOL_ASSERT(0 == _sg.mtl.idpool.release_queue[release_index].frame_index);
  7379. const uint32_t safe_to_release_frame_index = frame_index + SG_NUM_INFLIGHT_FRAMES + 1;
  7380. _sg.mtl.idpool.release_queue[release_index].frame_index = safe_to_release_frame_index;
  7381. _sg.mtl.idpool.release_queue[release_index].slot_index = slot_index;
  7382. }
  7383. /* run garbage-collection pass on all resources in the release-queue */
  7384. _SOKOL_PRIVATE void _sg_mtl_garbage_collect(uint32_t frame_index) {
  7385. while (_sg.mtl.idpool.release_queue_back != _sg.mtl.idpool.release_queue_front) {
  7386. if (frame_index < _sg.mtl.idpool.release_queue[_sg.mtl.idpool.release_queue_back].frame_index) {
  7387. /* don't need to check further, release-items past this are too young */
  7388. break;
  7389. }
  7390. /* safe to release this resource */
  7391. const uint32_t slot_index = _sg.mtl.idpool.release_queue[_sg.mtl.idpool.release_queue_back].slot_index;
  7392. SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots));
  7393. SOKOL_ASSERT(_sg_mtl_idpool[slot_index] != [NSNull null]);
  7394. _sg_mtl_idpool[slot_index] = [NSNull null];
  7395. /* put the now free pool index back on the free queue */
  7396. _sg_mtl_free_pool_slot(slot_index);
  7397. /* reset the release queue slot and advance the back index */
  7398. _sg.mtl.idpool.release_queue[_sg.mtl.idpool.release_queue_back].frame_index = 0;
  7399. _sg.mtl.idpool.release_queue[_sg.mtl.idpool.release_queue_back].slot_index = _SG_MTL_INVALID_SLOT_INDEX;
  7400. _sg.mtl.idpool.release_queue_back++;
  7401. if (_sg.mtl.idpool.release_queue_back >= _sg.mtl.idpool.num_slots) {
  7402. /* wrap-around */
  7403. _sg.mtl.idpool.release_queue_back = 0;
  7404. }
  7405. }
  7406. }
  7407. /*-- a very simple sampler cache -----------------------------------------------
  7408. since there's only a small number of different samplers, sampler objects
  7409. will never be deleted (except on shutdown), and searching an identical
  7410. sampler is a simple linear search
  7411. */
  7412. /* initialize the sampler cache */
  7413. _SOKOL_PRIVATE void _sg_mtl_init_sampler_cache(const sg_desc* desc) {
  7414. SOKOL_ASSERT(desc->mtl_sampler_cache_size > 0);
  7415. _sg.mtl.sampler_cache.capacity = desc->mtl_sampler_cache_size;
  7416. _sg.mtl.sampler_cache.num_items = 0;
  7417. const int size = _sg.mtl.sampler_cache.capacity * sizeof(_sg_mtl_sampler_cache_item_t);
  7418. _sg.mtl.sampler_cache.items = (_sg_mtl_sampler_cache_item_t*)SOKOL_MALLOC(size);
  7419. memset(_sg.mtl.sampler_cache.items, 0, size);
  7420. }
  7421. /* destroy the sampler cache, and release all sampler objects */
  7422. _SOKOL_PRIVATE void _sg_mtl_destroy_sampler_cache(uint32_t frame_index) {
  7423. SOKOL_ASSERT(_sg.mtl.sampler_cache.items);
  7424. SOKOL_ASSERT(_sg.mtl.sampler_cache.num_items <= _sg.mtl.sampler_cache.capacity);
  7425. for (int i = 0; i < _sg.mtl.sampler_cache.num_items; i++) {
  7426. _sg_mtl_release_resource(frame_index, _sg.mtl.sampler_cache.items[i].mtl_sampler_state);
  7427. }
  7428. SOKOL_FREE(_sg.mtl.sampler_cache.items); _sg.mtl.sampler_cache.items = 0;
  7429. _sg.mtl.sampler_cache.num_items = 0;
  7430. _sg.mtl.sampler_cache.capacity = 0;
  7431. }
  7432. /*
  7433. create and add an MTLSamplerStateObject and return its resource pool index,
  7434. reuse identical sampler state if one exists
  7435. */
  7436. _SOKOL_PRIVATE uint32_t _sg_mtl_create_sampler(id<MTLDevice> mtl_device, const sg_image_desc* img_desc) {
  7437. SOKOL_ASSERT(img_desc);
  7438. SOKOL_ASSERT(_sg.mtl.sampler_cache.items);
  7439. /* sampler state cache is full */
  7440. const sg_filter min_filter = img_desc->min_filter;
  7441. const sg_filter mag_filter = img_desc->mag_filter;
  7442. const sg_wrap wrap_u = img_desc->wrap_u;
  7443. const sg_wrap wrap_v = img_desc->wrap_v;
  7444. const sg_wrap wrap_w = img_desc->wrap_w;
  7445. const sg_border_color border_color = img_desc->border_color;
  7446. const uint32_t max_anisotropy = img_desc->max_anisotropy;
  7447. /* convert floats to valid int for proper comparison */
  7448. const int min_lod = (int)(img_desc->min_lod * 1000.0f);
  7449. const int max_lod = (int)(_sg_clamp(img_desc->max_lod, 0.0f, 1000.0f) * 1000.0f);
  7450. /* first try to find identical sampler, number of samplers will be small, so linear search is ok */
  7451. for (int i = 0; i < _sg.mtl.sampler_cache.num_items; i++) {
  7452. _sg_mtl_sampler_cache_item_t* item = &_sg.mtl.sampler_cache.items[i];
  7453. if ((min_filter == item->min_filter) &&
  7454. (mag_filter == item->mag_filter) &&
  7455. (wrap_u == item->wrap_u) &&
  7456. (wrap_v == item->wrap_v) &&
  7457. (wrap_w == item->wrap_w) &&
  7458. (max_anisotropy == item->max_anisotropy) &&
  7459. (border_color == item->border_color) &&
  7460. (min_lod == item->min_lod) &&
  7461. (max_lod == item->max_lod))
  7462. {
  7463. return item->mtl_sampler_state;
  7464. }
  7465. }
  7466. /* fallthrough: need to create a new MTLSamplerState object */
  7467. SOKOL_ASSERT(_sg.mtl.sampler_cache.num_items < _sg.mtl.sampler_cache.capacity);
  7468. _sg_mtl_sampler_cache_item_t* new_item = &_sg.mtl.sampler_cache.items[_sg.mtl.sampler_cache.num_items++];
  7469. new_item->min_filter = min_filter;
  7470. new_item->mag_filter = mag_filter;
  7471. new_item->wrap_u = wrap_u;
  7472. new_item->wrap_v = wrap_v;
  7473. new_item->wrap_w = wrap_w;
  7474. new_item->min_lod = min_lod;
  7475. new_item->max_lod = max_lod;
  7476. new_item->max_anisotropy = max_anisotropy;
  7477. new_item->border_color = border_color;
  7478. MTLSamplerDescriptor* mtl_desc = [[MTLSamplerDescriptor alloc] init];
  7479. mtl_desc.sAddressMode = _sg_mtl_address_mode(wrap_u);
  7480. mtl_desc.tAddressMode = _sg_mtl_address_mode(wrap_v);
  7481. if (SG_IMAGETYPE_3D == img_desc->type) {
  7482. mtl_desc.rAddressMode = _sg_mtl_address_mode(wrap_w);
  7483. }
  7484. #if defined(_SG_TARGET_MACOS)
  7485. mtl_desc.borderColor = _sg_mtl_border_color(border_color);
  7486. #endif
  7487. mtl_desc.minFilter = _sg_mtl_minmag_filter(min_filter);
  7488. mtl_desc.magFilter = _sg_mtl_minmag_filter(mag_filter);
  7489. mtl_desc.mipFilter = _sg_mtl_mip_filter(min_filter);
  7490. mtl_desc.lodMinClamp = img_desc->min_lod;
  7491. mtl_desc.lodMaxClamp = img_desc->max_lod;
  7492. mtl_desc.maxAnisotropy = max_anisotropy;
  7493. mtl_desc.normalizedCoordinates = YES;
  7494. id<MTLSamplerState> mtl_sampler = [mtl_device newSamplerStateWithDescriptor:mtl_desc];
  7495. new_item->mtl_sampler_state = _sg_mtl_add_resource(mtl_sampler);
  7496. return new_item->mtl_sampler_state;
  7497. }
  7498. _SOKOL_PRIVATE void _sg_mtl_clear_state_cache(void) {
  7499. memset(&_sg.mtl.state_cache, 0, sizeof(_sg.mtl.state_cache));
  7500. }
  7501. /* https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf */
  7502. _SOKOL_PRIVATE void _sg_mtl_init_caps(void) {
  7503. #if defined(_SG_TARGET_MACOS)
  7504. _sg.backend = SG_BACKEND_METAL_MACOS;
  7505. #elif defined(_SG_TARGET_IOS)
  7506. #if defined(_SG_TARGET_IOS_SIMULATOR)
  7507. _sg.backend = SG_BACKEND_METAL_SIMULATOR;
  7508. #else
  7509. _sg.backend = SG_BACKEND_METAL_IOS;
  7510. #endif
  7511. #endif
  7512. _sg.features.instancing = true;
  7513. _sg.features.origin_top_left = true;
  7514. _sg.features.multiple_render_targets = true;
  7515. _sg.features.msaa_render_targets = true;
  7516. _sg.features.imagetype_3d = true;
  7517. _sg.features.imagetype_array = true;
  7518. #if defined(_SG_TARGET_MACOS)
  7519. _sg.features.image_clamp_to_border = true;
  7520. #else
  7521. _sg.features.image_clamp_to_border = false;
  7522. #endif
  7523. #if defined(_SG_TARGET_MACOS)
  7524. _sg.limits.max_image_size_2d = 16 * 1024;
  7525. _sg.limits.max_image_size_cube = 16 * 1024;
  7526. _sg.limits.max_image_size_3d = 2 * 1024;
  7527. _sg.limits.max_image_size_array = 16 * 1024;
  7528. _sg.limits.max_image_array_layers = 2 * 1024;
  7529. #else
  7530. /* newer iOS devices support 16k textures */
  7531. _sg.limits.max_image_size_2d = 8 * 1024;
  7532. _sg.limits.max_image_size_cube = 8 * 1024;
  7533. _sg.limits.max_image_size_3d = 2 * 1024;
  7534. _sg.limits.max_image_size_array = 8 * 1024;
  7535. _sg.limits.max_image_array_layers = 2 * 1024;
  7536. #endif
  7537. _sg.limits.max_vertex_attrs = SG_MAX_VERTEX_ATTRIBUTES;
  7538. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8]);
  7539. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8SN]);
  7540. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8UI]);
  7541. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8SI]);
  7542. #if defined(_SG_TARGET_MACOS)
  7543. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16]);
  7544. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16SN]);
  7545. #else
  7546. _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_R16]);
  7547. _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_R16SN]);
  7548. #endif
  7549. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16UI]);
  7550. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16SI]);
  7551. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16F]);
  7552. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG8]);
  7553. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG8SN]);
  7554. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8UI]);
  7555. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8SI]);
  7556. _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32UI]);
  7557. _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32SI]);
  7558. #if defined(_SG_TARGET_MACOS)
  7559. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R32F]);
  7560. #else
  7561. _sg_pixelformat_sbr(&_sg.formats[SG_PIXELFORMAT_R32F]);
  7562. #endif
  7563. #if defined(_SG_TARGET_MACOS)
  7564. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16]);
  7565. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16SN]);
  7566. #else
  7567. _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_RG16]);
  7568. _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_RG16SN]);
  7569. #endif
  7570. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16UI]);
  7571. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16SI]);
  7572. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16F]);
  7573. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA8]);
  7574. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA8SN]);
  7575. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8UI]);
  7576. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8SI]);
  7577. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_BGRA8]);
  7578. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGB10A2]);
  7579. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG11B10F]);
  7580. #if defined(_SG_TARGET_MACOS)
  7581. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG32UI]);
  7582. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG32SI]);
  7583. #else
  7584. _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32UI]);
  7585. _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32SI]);
  7586. #endif
  7587. #if defined(_SG_TARGET_MACOS)
  7588. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG32F]);
  7589. #else
  7590. _sg_pixelformat_sbr(&_sg.formats[SG_PIXELFORMAT_RG32F]);
  7591. #endif
  7592. #if defined(_SG_TARGET_MACOS)
  7593. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16]);
  7594. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16SN]);
  7595. #else
  7596. _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_RGBA16]);
  7597. _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_RGBA16SN]);
  7598. #endif
  7599. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16UI]);
  7600. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16SI]);
  7601. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);
  7602. #if defined(_SG_TARGET_MACOS)
  7603. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA32UI]);
  7604. _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA32SI]);
  7605. _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  7606. #else
  7607. _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32UI]);
  7608. _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32SI]);
  7609. _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);
  7610. #endif
  7611. _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH]);
  7612. _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH_STENCIL]);
  7613. #if defined(_SG_TARGET_MACOS)
  7614. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC1_RGBA]);
  7615. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC2_RGBA]);
  7616. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_RGBA]);
  7617. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_R]);
  7618. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_RSN]);
  7619. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RG]);
  7620. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RGSN]);
  7621. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBF]);
  7622. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBUF]);
  7623. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_RGBA]);
  7624. #else
  7625. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGB_2BPP]);
  7626. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGB_4BPP]);
  7627. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGBA_2BPP]);
  7628. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGBA_4BPP]);
  7629. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8]);
  7630. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8A1]);
  7631. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGBA8]);
  7632. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RG11]);
  7633. _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RG11SN]);
  7634. #endif
  7635. }
  7636. /*-- main Metal backend state and functions ----------------------------------*/
  7637. _SOKOL_PRIVATE void _sg_mtl_setup_backend(const sg_desc* desc) {
  7638. /* assume already zero-initialized */
  7639. SOKOL_ASSERT(desc);
  7640. SOKOL_ASSERT(desc->mtl_device);
  7641. SOKOL_ASSERT(desc->mtl_renderpass_descriptor_cb);
  7642. SOKOL_ASSERT(desc->mtl_drawable_cb);
  7643. SOKOL_ASSERT(desc->mtl_global_uniform_buffer_size > 0);
  7644. _sg_mtl_init_pool(desc);
  7645. _sg_mtl_init_sampler_cache(desc);
  7646. _sg_mtl_clear_state_cache();
  7647. _sg.mtl.valid = true;
  7648. _sg.mtl.renderpass_descriptor_cb = desc->mtl_renderpass_descriptor_cb;
  7649. _sg.mtl.drawable_cb = desc->mtl_drawable_cb;
  7650. _sg.mtl.frame_index = 1;
  7651. _sg.mtl.ub_size = desc->mtl_global_uniform_buffer_size;
  7652. _sg_mtl_sem = dispatch_semaphore_create(SG_NUM_INFLIGHT_FRAMES);
  7653. _sg_mtl_device = (__bridge id<MTLDevice>) desc->mtl_device;
  7654. _sg_mtl_cmd_queue = [_sg_mtl_device newCommandQueue];
  7655. MTLResourceOptions res_opts = MTLResourceCPUCacheModeWriteCombined;
  7656. #if defined(_SG_TARGET_MACOS)
  7657. res_opts |= MTLResourceStorageModeManaged;
  7658. #endif
  7659. for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {
  7660. _sg_mtl_uniform_buffers[i] = [_sg_mtl_device
  7661. newBufferWithLength:_sg.mtl.ub_size
  7662. options:res_opts
  7663. ];
  7664. }
  7665. _sg_mtl_init_caps();
  7666. }
  7667. _SOKOL_PRIVATE void _sg_mtl_discard_backend(void) {
  7668. SOKOL_ASSERT(_sg.mtl.valid);
  7669. /* wait for the last frame to finish */
  7670. for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {
  7671. dispatch_semaphore_wait(_sg_mtl_sem, DISPATCH_TIME_FOREVER);
  7672. }
  7673. _sg_mtl_destroy_sampler_cache(_sg.mtl.frame_index);
  7674. _sg_mtl_garbage_collect(_sg.mtl.frame_index + SG_NUM_INFLIGHT_FRAMES + 2);
  7675. _sg_mtl_destroy_pool();
  7676. _sg.mtl.valid = false;
  7677. _sg_mtl_cmd_encoder = nil;
  7678. _sg_mtl_cmd_buffer = nil;
  7679. _sg_mtl_cmd_queue = nil;
  7680. for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {
  7681. _sg_mtl_uniform_buffers[i] = nil;
  7682. }
  7683. _sg_mtl_device = nil;
  7684. }
  7685. _SOKOL_PRIVATE void _sg_mtl_reset_state_cache(void) {
  7686. _sg_mtl_clear_state_cache();
  7687. }
  7688. _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_context(_sg_context_t* ctx) {
  7689. SOKOL_ASSERT(ctx);
  7690. _SOKOL_UNUSED(ctx);
  7691. return SG_RESOURCESTATE_VALID;
  7692. }
  7693. _SOKOL_PRIVATE void _sg_mtl_destroy_context(_sg_context_t* ctx) {
  7694. SOKOL_ASSERT(ctx);
  7695. _SOKOL_UNUSED(ctx);
  7696. /* empty */
  7697. }
  7698. _SOKOL_PRIVATE void _sg_mtl_activate_context(_sg_context_t* ctx) {
  7699. _sg_mtl_clear_state_cache();
  7700. }
  7701. _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {
  7702. SOKOL_ASSERT(buf && desc);
  7703. _sg_buffer_common_init(&buf->cmn, desc);
  7704. const bool injected = (0 != desc->mtl_buffers[0]);
  7705. MTLResourceOptions mtl_options = _sg_mtl_buffer_resource_options(buf->cmn.usage);
  7706. for (int slot = 0; slot < buf->cmn.num_slots; slot++) {
  7707. id<MTLBuffer> mtl_buf;
  7708. if (injected) {
  7709. SOKOL_ASSERT(desc->mtl_buffers[slot]);
  7710. mtl_buf = (__bridge id<MTLBuffer>) desc->mtl_buffers[slot];
  7711. }
  7712. else {
  7713. if (buf->cmn.usage == SG_USAGE_IMMUTABLE) {
  7714. SOKOL_ASSERT(desc->content);
  7715. mtl_buf = [_sg_mtl_device newBufferWithBytes:desc->content length:buf->cmn.size options:mtl_options];
  7716. }
  7717. else {
  7718. mtl_buf = [_sg_mtl_device newBufferWithLength:buf->cmn.size options:mtl_options];
  7719. }
  7720. }
  7721. buf->mtl.buf[slot] = _sg_mtl_add_resource(mtl_buf);
  7722. }
  7723. return SG_RESOURCESTATE_VALID;
  7724. }
  7725. _SOKOL_PRIVATE void _sg_mtl_destroy_buffer(_sg_buffer_t* buf) {
  7726. SOKOL_ASSERT(buf);
  7727. for (int slot = 0; slot < buf->cmn.num_slots; slot++) {
  7728. /* it's valid to call release resource with '0' */
  7729. _sg_mtl_release_resource(_sg.mtl.frame_index, buf->mtl.buf[slot]);
  7730. }
  7731. }
  7732. _SOKOL_PRIVATE void _sg_mtl_copy_image_content(const _sg_image_t* img, __unsafe_unretained id<MTLTexture> mtl_tex, const sg_image_content* content) {
  7733. const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1;
  7734. const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.depth : 1;
  7735. for (int face_index = 0; face_index < num_faces; face_index++) {
  7736. for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++) {
  7737. SOKOL_ASSERT(content->subimage[face_index][mip_index].ptr);
  7738. SOKOL_ASSERT(content->subimage[face_index][mip_index].size > 0);
  7739. const uint8_t* data_ptr = (const uint8_t*)content->subimage[face_index][mip_index].ptr;
  7740. const int mip_width = _sg_max(img->cmn.width >> mip_index, 1);
  7741. const int mip_height = _sg_max(img->cmn.height >> mip_index, 1);
  7742. /* special case PVRTC formats: bytePerRow must be 0 */
  7743. int bytes_per_row = 0;
  7744. int bytes_per_slice = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height);
  7745. if (!_sg_mtl_is_pvrtc(img->cmn.pixel_format)) {
  7746. bytes_per_row = _sg_row_pitch(img->cmn.pixel_format, mip_width);
  7747. }
  7748. MTLRegion region;
  7749. if (img->cmn.type == SG_IMAGETYPE_3D) {
  7750. const int mip_depth = _sg_max(img->cmn.depth >> mip_index, 1);
  7751. region = MTLRegionMake3D(0, 0, 0, mip_width, mip_height, mip_depth);
  7752. /* FIXME: apparently the minimal bytes_per_image size for 3D texture
  7753. is 4 KByte... somehow need to handle this */
  7754. }
  7755. else {
  7756. region = MTLRegionMake2D(0, 0, mip_width, mip_height);
  7757. }
  7758. for (int slice_index = 0; slice_index < num_slices; slice_index++) {
  7759. const int mtl_slice_index = (img->cmn.type == SG_IMAGETYPE_CUBE) ? face_index : slice_index;
  7760. const int slice_offset = slice_index * bytes_per_slice;
  7761. SOKOL_ASSERT((slice_offset + bytes_per_slice) <= (int)content->subimage[face_index][mip_index].size);
  7762. [mtl_tex replaceRegion:region
  7763. mipmapLevel:mip_index
  7764. slice:mtl_slice_index
  7765. withBytes:data_ptr + slice_offset
  7766. bytesPerRow:bytes_per_row
  7767. bytesPerImage:bytes_per_slice];
  7768. }
  7769. }
  7770. }
  7771. }
  7772. /*
  7773. FIXME: METAL RESOURCE STORAGE MODE FOR macOS AND iOS
  7774. For immutable textures on macOS, the recommended procedure is to create
  7775. a MTLStorageModeManaged texture with the immutable content first,
  7776. and then use the GPU to blit the content into a MTLStorageModePrivate
  7777. texture before the first use.
  7778. On iOS use the same one-time-blit procedure, but from a
  7779. MTLStorageModeShared to a MTLStorageModePrivate texture.
  7780. It probably makes sense to handle this in a separate 'resource manager'
  7781. with a recycable pool of blit-source-textures?
  7782. */
  7783. /* initialize MTLTextureDescritor with common attributes */
  7784. _SOKOL_PRIVATE bool _sg_mtl_init_texdesc_common(MTLTextureDescriptor* mtl_desc, _sg_image_t* img) {
  7785. mtl_desc.textureType = _sg_mtl_texture_type(img->cmn.type);
  7786. mtl_desc.pixelFormat = _sg_mtl_pixel_format(img->cmn.pixel_format);
  7787. if (MTLPixelFormatInvalid == mtl_desc.pixelFormat) {
  7788. SOKOL_LOG("Unsupported texture pixel format!\n");
  7789. return false;
  7790. }
  7791. mtl_desc.width = img->cmn.width;
  7792. mtl_desc.height = img->cmn.height;
  7793. if (SG_IMAGETYPE_3D == img->cmn.type) {
  7794. mtl_desc.depth = img->cmn.depth;
  7795. }
  7796. else {
  7797. mtl_desc.depth = 1;
  7798. }
  7799. mtl_desc.mipmapLevelCount = img->cmn.num_mipmaps;
  7800. if (SG_IMAGETYPE_ARRAY == img->cmn.type) {
  7801. mtl_desc.arrayLength = img->cmn.depth;
  7802. }
  7803. else {
  7804. mtl_desc.arrayLength = 1;
  7805. }
  7806. mtl_desc.usage = MTLTextureUsageShaderRead;
  7807. if (img->cmn.usage != SG_USAGE_IMMUTABLE) {
  7808. mtl_desc.cpuCacheMode = MTLCPUCacheModeWriteCombined;
  7809. }
  7810. #if defined(_SG_TARGET_MACOS)
  7811. /* macOS: use managed textures */
  7812. mtl_desc.resourceOptions = MTLResourceStorageModeManaged;
  7813. mtl_desc.storageMode = MTLStorageModeManaged;
  7814. #else
  7815. /* iOS: use CPU/GPU shared memory */
  7816. mtl_desc.resourceOptions = MTLResourceStorageModeShared;
  7817. mtl_desc.storageMode = MTLStorageModeShared;
  7818. #endif
  7819. return true;
  7820. }
  7821. /* initialize MTLTextureDescritor with rendertarget attributes */
  7822. _SOKOL_PRIVATE void _sg_mtl_init_texdesc_rt(MTLTextureDescriptor* mtl_desc, _sg_image_t* img) {
  7823. SOKOL_ASSERT(img->cmn.render_target);
  7824. /* reset the cpuCacheMode to 'default' */
  7825. mtl_desc.cpuCacheMode = MTLCPUCacheModeDefaultCache;
  7826. /* render targets are only visible to the GPU */
  7827. mtl_desc.resourceOptions = MTLResourceStorageModePrivate;
  7828. mtl_desc.storageMode = MTLStorageModePrivate;
  7829. /* non-MSAA render targets are shader-readable */
  7830. mtl_desc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
  7831. }
  7832. /* initialize MTLTextureDescritor with MSAA attributes */
  7833. _SOKOL_PRIVATE void _sg_mtl_init_texdesc_rt_msaa(MTLTextureDescriptor* mtl_desc, _sg_image_t* img) {
  7834. SOKOL_ASSERT(img->cmn.sample_count > 1);
  7835. /* reset the cpuCacheMode to 'default' */
  7836. mtl_desc.cpuCacheMode = MTLCPUCacheModeDefaultCache;
  7837. /* render targets are only visible to the GPU */
  7838. mtl_desc.resourceOptions = MTLResourceStorageModePrivate;
  7839. mtl_desc.storageMode = MTLStorageModePrivate;
  7840. /* MSAA render targets are not shader-readable (instead they are resolved) */
  7841. mtl_desc.usage = MTLTextureUsageRenderTarget;
  7842. mtl_desc.textureType = MTLTextureType2DMultisample;
  7843. mtl_desc.depth = 1;
  7844. mtl_desc.arrayLength = 1;
  7845. mtl_desc.mipmapLevelCount = 1;
  7846. mtl_desc.sampleCount = img->cmn.sample_count;
  7847. }
  7848. _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_image(_sg_image_t* img, const sg_image_desc* desc) {
  7849. SOKOL_ASSERT(img && desc);
  7850. _sg_image_common_init(&img->cmn, desc);
  7851. const bool injected = (0 != desc->mtl_textures[0]);
  7852. const bool msaa = (img->cmn.sample_count > 1);
  7853. /* first initialize all Metal resource pool slots to 'empty' */
  7854. for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {
  7855. img->mtl.tex[i] = _sg_mtl_add_resource(nil);
  7856. }
  7857. img->mtl.sampler_state = _sg_mtl_add_resource(nil);
  7858. img->mtl.depth_tex = _sg_mtl_add_resource(nil);
  7859. img->mtl.msaa_tex = _sg_mtl_add_resource(nil);
  7860. /* initialize a Metal texture descriptor with common attributes */
  7861. MTLTextureDescriptor* mtl_desc = [[MTLTextureDescriptor alloc] init];
  7862. if (!_sg_mtl_init_texdesc_common(mtl_desc, img)) {
  7863. return SG_RESOURCESTATE_FAILED;
  7864. }
  7865. /* special case depth-stencil-buffer? */
  7866. if (_sg_is_valid_rendertarget_depth_format(img->cmn.pixel_format)) {
  7867. /* depth-stencil buffer texture must always be a render target */
  7868. SOKOL_ASSERT(img->cmn.render_target);
  7869. SOKOL_ASSERT(img->cmn.type == SG_IMAGETYPE_2D);
  7870. SOKOL_ASSERT(img->cmn.num_mipmaps == 1);
  7871. SOKOL_ASSERT(!injected);
  7872. if (msaa) {
  7873. _sg_mtl_init_texdesc_rt_msaa(mtl_desc, img);
  7874. }
  7875. else {
  7876. _sg_mtl_init_texdesc_rt(mtl_desc, img);
  7877. }
  7878. id<MTLTexture> tex = [_sg_mtl_device newTextureWithDescriptor:mtl_desc];
  7879. SOKOL_ASSERT(nil != tex);
  7880. img->mtl.depth_tex = _sg_mtl_add_resource(tex);
  7881. }
  7882. else {
  7883. /* create the color texture
  7884. In case this is a render target without MSAA, add the relevant
  7885. render-target descriptor attributes.
  7886. In case this is a render target *with* MSAA, the color texture
  7887. will serve as MSAA-resolve target (not as render target), and rendering
  7888. will go into a separate render target texture of type
  7889. MTLTextureType2DMultisample.
  7890. */
  7891. if (img->cmn.render_target && !msaa) {
  7892. _sg_mtl_init_texdesc_rt(mtl_desc, img);
  7893. }
  7894. for (int slot = 0; slot < img->cmn.num_slots; slot++) {
  7895. id<MTLTexture> tex;
  7896. if (injected) {
  7897. SOKOL_ASSERT(desc->mtl_textures[slot]);
  7898. tex = (__bridge id<MTLTexture>) desc->mtl_textures[slot];
  7899. }
  7900. else {
  7901. tex = [_sg_mtl_device newTextureWithDescriptor:mtl_desc];
  7902. if ((img->cmn.usage == SG_USAGE_IMMUTABLE) && !img->cmn.render_target) {
  7903. _sg_mtl_copy_image_content(img, tex, &desc->content);
  7904. }
  7905. }
  7906. img->mtl.tex[slot] = _sg_mtl_add_resource(tex);
  7907. }
  7908. /* if MSAA color render target, create an additional MSAA render-surface texture */
  7909. if (img->cmn.render_target && msaa) {
  7910. _sg_mtl_init_texdesc_rt_msaa(mtl_desc, img);
  7911. id<MTLTexture> tex = [_sg_mtl_device newTextureWithDescriptor:mtl_desc];
  7912. img->mtl.msaa_tex = _sg_mtl_add_resource(tex);
  7913. }
  7914. /* create (possibly shared) sampler state */
  7915. img->mtl.sampler_state = _sg_mtl_create_sampler(_sg_mtl_device, desc);
  7916. }
  7917. return SG_RESOURCESTATE_VALID;
  7918. }
  7919. _SOKOL_PRIVATE void _sg_mtl_destroy_image(_sg_image_t* img) {
  7920. SOKOL_ASSERT(img);
  7921. /* it's valid to call release resource with a 'null resource' */
  7922. for (int slot = 0; slot < img->cmn.num_slots; slot++) {
  7923. _sg_mtl_release_resource(_sg.mtl.frame_index, img->mtl.tex[slot]);
  7924. }
  7925. _sg_mtl_release_resource(_sg.mtl.frame_index, img->mtl.depth_tex);
  7926. _sg_mtl_release_resource(_sg.mtl.frame_index, img->mtl.msaa_tex);
  7927. /* NOTE: sampler state objects are shared and not released until shutdown */
  7928. }
  7929. _SOKOL_PRIVATE id<MTLLibrary> _sg_mtl_compile_library(const char* src) {
  7930. NSError* err = NULL;
  7931. id<MTLLibrary> lib = [_sg_mtl_device
  7932. newLibraryWithSource:[NSString stringWithUTF8String:src]
  7933. options:nil
  7934. error:&err
  7935. ];
  7936. if (err) {
  7937. SOKOL_LOG([err.localizedDescription UTF8String]);
  7938. }
  7939. return lib;
  7940. }
  7941. _SOKOL_PRIVATE id<MTLLibrary> _sg_mtl_library_from_bytecode(const uint8_t* ptr, int num_bytes) {
  7942. NSError* err = NULL;
  7943. dispatch_data_t lib_data = dispatch_data_create(ptr, num_bytes, NULL, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
  7944. id<MTLLibrary> lib = [_sg_mtl_device newLibraryWithData:lib_data error:&err];
  7945. if (err) {
  7946. SOKOL_LOG([err.localizedDescription UTF8String]);
  7947. }
  7948. return lib;
  7949. }
  7950. _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {
  7951. SOKOL_ASSERT(shd && desc);
  7952. _sg_shader_common_init(&shd->cmn, desc);
  7953. /* create metal libray objects and lookup entry functions */
  7954. id<MTLLibrary> vs_lib;
  7955. id<MTLLibrary> fs_lib;
  7956. id<MTLFunction> vs_func;
  7957. id<MTLFunction> fs_func;
  7958. const char* vs_entry = desc->vs.entry;
  7959. const char* fs_entry = desc->fs.entry;
  7960. if (desc->vs.byte_code && desc->fs.byte_code) {
  7961. /* separate byte code provided */
  7962. vs_lib = _sg_mtl_library_from_bytecode(desc->vs.byte_code, desc->vs.byte_code_size);
  7963. fs_lib = _sg_mtl_library_from_bytecode(desc->fs.byte_code, desc->fs.byte_code_size);
  7964. if (nil == vs_lib || nil == fs_lib) {
  7965. return SG_RESOURCESTATE_FAILED;
  7966. }
  7967. vs_func = [vs_lib newFunctionWithName:[NSString stringWithUTF8String:vs_entry]];
  7968. fs_func = [fs_lib newFunctionWithName:[NSString stringWithUTF8String:fs_entry]];
  7969. }
  7970. else if (desc->vs.source && desc->fs.source) {
  7971. /* separate sources provided */
  7972. vs_lib = _sg_mtl_compile_library(desc->vs.source);
  7973. fs_lib = _sg_mtl_compile_library(desc->fs.source);
  7974. if (nil == vs_lib || nil == fs_lib) {
  7975. return SG_RESOURCESTATE_FAILED;
  7976. }
  7977. vs_func = [vs_lib newFunctionWithName:[NSString stringWithUTF8String:vs_entry]];
  7978. fs_func = [fs_lib newFunctionWithName:[NSString stringWithUTF8String:fs_entry]];
  7979. }
  7980. else {
  7981. return SG_RESOURCESTATE_FAILED;
  7982. }
  7983. if (nil == vs_func) {
  7984. SOKOL_LOG("vertex shader entry function not found\n");
  7985. return SG_RESOURCESTATE_FAILED;
  7986. }
  7987. if (nil == fs_func) {
  7988. SOKOL_LOG("fragment shader entry function not found\n");
  7989. return SG_RESOURCESTATE_FAILED;
  7990. }
  7991. /* it is legal to call _sg_mtl_add_resource with a nil value, this will return a special 0xFFFFFFFF index */
  7992. shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_lib = _sg_mtl_add_resource(vs_lib);
  7993. shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_lib = _sg_mtl_add_resource(fs_lib);
  7994. shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func = _sg_mtl_add_resource(vs_func);
  7995. shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func = _sg_mtl_add_resource(fs_func);
  7996. return SG_RESOURCESTATE_VALID;
  7997. }
  7998. _SOKOL_PRIVATE void _sg_mtl_destroy_shader(_sg_shader_t* shd) {
  7999. SOKOL_ASSERT(shd);
  8000. /* it is valid to call _sg_mtl_release_resource with a 'null resource' */
  8001. _sg_mtl_release_resource(_sg.mtl.frame_index, shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func);
  8002. _sg_mtl_release_resource(_sg.mtl.frame_index, shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_lib);
  8003. _sg_mtl_release_resource(_sg.mtl.frame_index, shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func);
  8004. _sg_mtl_release_resource(_sg.mtl.frame_index, shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_lib);
  8005. }
  8006. _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {
  8007. SOKOL_ASSERT(pip && shd && desc);
  8008. SOKOL_ASSERT(desc->shader.id == shd->slot.id);
  8009. pip->shader = shd;
  8010. _sg_pipeline_common_init(&pip->cmn, desc);
  8011. sg_primitive_type prim_type = desc->primitive_type;
  8012. pip->mtl.prim_type = _sg_mtl_primitive_type(prim_type);
  8013. pip->mtl.index_size = _sg_mtl_index_size(pip->cmn.index_type);
  8014. if (SG_INDEXTYPE_NONE != pip->cmn.index_type) {
  8015. pip->mtl.index_type = _sg_mtl_index_type(pip->cmn.index_type);
  8016. }
  8017. pip->mtl.cull_mode = _sg_mtl_cull_mode(desc->rasterizer.cull_mode);
  8018. pip->mtl.winding = _sg_mtl_winding(desc->rasterizer.face_winding);
  8019. pip->mtl.stencil_ref = desc->depth_stencil.stencil_ref;
  8020. /* create vertex-descriptor */
  8021. MTLVertexDescriptor* vtx_desc = [MTLVertexDescriptor vertexDescriptor];
  8022. for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
  8023. const sg_vertex_attr_desc* a_desc = &desc->layout.attrs[attr_index];
  8024. if (a_desc->format == SG_VERTEXFORMAT_INVALID) {
  8025. break;
  8026. }
  8027. SOKOL_ASSERT((a_desc->buffer_index >= 0) && (a_desc->buffer_index < SG_MAX_SHADERSTAGE_BUFFERS));
  8028. vtx_desc.attributes[attr_index].format = _sg_mtl_vertex_format(a_desc->format);
  8029. vtx_desc.attributes[attr_index].offset = a_desc->offset;
  8030. vtx_desc.attributes[attr_index].bufferIndex = a_desc->buffer_index + SG_MAX_SHADERSTAGE_UBS;
  8031. pip->cmn.vertex_layout_valid[a_desc->buffer_index] = true;
  8032. }
  8033. for (int layout_index = 0; layout_index < SG_MAX_SHADERSTAGE_BUFFERS; layout_index++) {
  8034. if (pip->cmn.vertex_layout_valid[layout_index]) {
  8035. const sg_buffer_layout_desc* l_desc = &desc->layout.buffers[layout_index];
  8036. const int mtl_vb_slot = layout_index + SG_MAX_SHADERSTAGE_UBS;
  8037. SOKOL_ASSERT(l_desc->stride > 0);
  8038. vtx_desc.layouts[mtl_vb_slot].stride = l_desc->stride;
  8039. vtx_desc.layouts[mtl_vb_slot].stepFunction = _sg_mtl_step_function(l_desc->step_func);
  8040. vtx_desc.layouts[mtl_vb_slot].stepRate = l_desc->step_rate;
  8041. }
  8042. }
  8043. /* render-pipeline descriptor */
  8044. MTLRenderPipelineDescriptor* rp_desc = [[MTLRenderPipelineDescriptor alloc] init];
  8045. rp_desc.vertexDescriptor = vtx_desc;
  8046. SOKOL_ASSERT(shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func != _SG_MTL_INVALID_SLOT_INDEX);
  8047. rp_desc.vertexFunction = _sg_mtl_idpool[shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func];
  8048. SOKOL_ASSERT(shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func != _SG_MTL_INVALID_SLOT_INDEX);
  8049. rp_desc.fragmentFunction = _sg_mtl_idpool[shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func];
  8050. rp_desc.sampleCount = desc->rasterizer.sample_count;
  8051. rp_desc.alphaToCoverageEnabled = desc->rasterizer.alpha_to_coverage_enabled;
  8052. rp_desc.alphaToOneEnabled = NO;
  8053. rp_desc.rasterizationEnabled = YES;
  8054. rp_desc.depthAttachmentPixelFormat = _sg_mtl_pixel_format(desc->blend.depth_format);
  8055. if (desc->blend.depth_format == SG_PIXELFORMAT_DEPTH_STENCIL) {
  8056. rp_desc.stencilAttachmentPixelFormat = _sg_mtl_pixel_format(desc->blend.depth_format);
  8057. }
  8058. /* FIXME: this only works on macOS 10.13!
  8059. for (int i = 0; i < (SG_MAX_SHADERSTAGE_UBS+SG_MAX_SHADERSTAGE_BUFFERS); i++) {
  8060. rp_desc.vertexBuffers[i].mutability = MTLMutabilityImmutable;
  8061. }
  8062. for (int i = 0; i < SG_MAX_SHADERSTAGE_UBS; i++) {
  8063. rp_desc.fragmentBuffers[i].mutability = MTLMutabilityImmutable;
  8064. }
  8065. */
  8066. const int att_count = desc->blend.color_attachment_count;
  8067. for (int i = 0; i < att_count; i++) {
  8068. rp_desc.colorAttachments[i].pixelFormat = _sg_mtl_pixel_format(desc->blend.color_format);
  8069. rp_desc.colorAttachments[i].writeMask = _sg_mtl_color_write_mask((sg_color_mask)desc->blend.color_write_mask);
  8070. rp_desc.colorAttachments[i].blendingEnabled = desc->blend.enabled;
  8071. rp_desc.colorAttachments[i].alphaBlendOperation = _sg_mtl_blend_op(desc->blend.op_alpha);
  8072. rp_desc.colorAttachments[i].rgbBlendOperation = _sg_mtl_blend_op(desc->blend.op_rgb);
  8073. rp_desc.colorAttachments[i].destinationAlphaBlendFactor = _sg_mtl_blend_factor(desc->blend.dst_factor_alpha);
  8074. rp_desc.colorAttachments[i].destinationRGBBlendFactor = _sg_mtl_blend_factor(desc->blend.dst_factor_rgb);
  8075. rp_desc.colorAttachments[i].sourceAlphaBlendFactor = _sg_mtl_blend_factor(desc->blend.src_factor_alpha);
  8076. rp_desc.colorAttachments[i].sourceRGBBlendFactor = _sg_mtl_blend_factor(desc->blend.src_factor_rgb);
  8077. }
  8078. NSError* err = NULL;
  8079. id<MTLRenderPipelineState> mtl_rps = [_sg_mtl_device newRenderPipelineStateWithDescriptor:rp_desc error:&err];
  8080. if (nil == mtl_rps) {
  8081. SOKOL_ASSERT(err);
  8082. SOKOL_LOG([err.localizedDescription UTF8String]);
  8083. return SG_RESOURCESTATE_FAILED;
  8084. }
  8085. /* depth-stencil-state */
  8086. MTLDepthStencilDescriptor* ds_desc = [[MTLDepthStencilDescriptor alloc] init];
  8087. ds_desc.depthCompareFunction = _sg_mtl_compare_func(desc->depth_stencil.depth_compare_func);
  8088. ds_desc.depthWriteEnabled = desc->depth_stencil.depth_write_enabled;
  8089. if (desc->depth_stencil.stencil_enabled) {
  8090. const sg_stencil_state* sb = &desc->depth_stencil.stencil_back;
  8091. ds_desc.backFaceStencil = [[MTLStencilDescriptor alloc] init];
  8092. ds_desc.backFaceStencil.stencilFailureOperation = _sg_mtl_stencil_op(sb->fail_op);
  8093. ds_desc.backFaceStencil.depthFailureOperation = _sg_mtl_stencil_op(sb->depth_fail_op);
  8094. ds_desc.backFaceStencil.depthStencilPassOperation = _sg_mtl_stencil_op(sb->pass_op);
  8095. ds_desc.backFaceStencil.stencilCompareFunction = _sg_mtl_compare_func(sb->compare_func);
  8096. ds_desc.backFaceStencil.readMask = desc->depth_stencil.stencil_read_mask;
  8097. ds_desc.backFaceStencil.writeMask = desc->depth_stencil.stencil_write_mask;
  8098. const sg_stencil_state* sf = &desc->depth_stencil.stencil_front;
  8099. ds_desc.frontFaceStencil = [[MTLStencilDescriptor alloc] init];
  8100. ds_desc.frontFaceStencil.stencilFailureOperation = _sg_mtl_stencil_op(sf->fail_op);
  8101. ds_desc.frontFaceStencil.depthFailureOperation = _sg_mtl_stencil_op(sf->depth_fail_op);
  8102. ds_desc.frontFaceStencil.depthStencilPassOperation = _sg_mtl_stencil_op(sf->pass_op);
  8103. ds_desc.frontFaceStencil.stencilCompareFunction = _sg_mtl_compare_func(sf->compare_func);
  8104. ds_desc.frontFaceStencil.readMask = desc->depth_stencil.stencil_read_mask;
  8105. ds_desc.frontFaceStencil.writeMask = desc->depth_stencil.stencil_write_mask;
  8106. }
  8107. id<MTLDepthStencilState> mtl_dss = [_sg_mtl_device newDepthStencilStateWithDescriptor:ds_desc];
  8108. pip->mtl.rps = _sg_mtl_add_resource(mtl_rps);
  8109. pip->mtl.dss = _sg_mtl_add_resource(mtl_dss);
  8110. return SG_RESOURCESTATE_VALID;
  8111. }
  8112. _SOKOL_PRIVATE void _sg_mtl_destroy_pipeline(_sg_pipeline_t* pip) {
  8113. SOKOL_ASSERT(pip);
  8114. /* it's valid to call release resource with a 'null resource' */
  8115. _sg_mtl_release_resource(_sg.mtl.frame_index, pip->mtl.rps);
  8116. _sg_mtl_release_resource(_sg.mtl.frame_index, pip->mtl.dss);
  8117. }
  8118. _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_pass(_sg_pass_t* pass, _sg_image_t** att_images, const sg_pass_desc* desc) {
  8119. SOKOL_ASSERT(pass && desc);
  8120. SOKOL_ASSERT(att_images && att_images[0]);
  8121. _sg_pass_common_init(&pass->cmn, desc);
  8122. /* copy image pointers */
  8123. const sg_attachment_desc* att_desc;
  8124. for (int i = 0; i < pass->cmn.num_color_atts; i++) {
  8125. att_desc = &desc->color_attachments[i];
  8126. if (att_desc->image.id != SG_INVALID_ID) {
  8127. SOKOL_ASSERT(att_desc->image.id != SG_INVALID_ID);
  8128. SOKOL_ASSERT(0 == pass->mtl.color_atts[i].image);
  8129. SOKOL_ASSERT(att_images[i] && (att_images[i]->slot.id == att_desc->image.id));
  8130. SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(att_images[i]->cmn.pixel_format));
  8131. pass->mtl.color_atts[i].image = att_images[i];
  8132. }
  8133. }
  8134. SOKOL_ASSERT(0 == pass->mtl.ds_att.image);
  8135. att_desc = &desc->depth_stencil_attachment;
  8136. if (att_desc->image.id != SG_INVALID_ID) {
  8137. const int ds_img_index = SG_MAX_COLOR_ATTACHMENTS;
  8138. SOKOL_ASSERT(att_images[ds_img_index] && (att_images[ds_img_index]->slot.id == att_desc->image.id));
  8139. SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(att_images[ds_img_index]->cmn.pixel_format));
  8140. pass->mtl.ds_att.image = att_images[ds_img_index];
  8141. }
  8142. return SG_RESOURCESTATE_VALID;
  8143. }
  8144. _SOKOL_PRIVATE void _sg_mtl_destroy_pass(_sg_pass_t* pass) {
  8145. SOKOL_ASSERT(pass);
  8146. _SOKOL_UNUSED(pass);
  8147. }
  8148. _SOKOL_PRIVATE _sg_image_t* _sg_mtl_pass_color_image(const _sg_pass_t* pass, int index) {
  8149. SOKOL_ASSERT(pass && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));
  8150. /* NOTE: may return null */
  8151. return pass->mtl.color_atts[index].image;
  8152. }
  8153. _SOKOL_PRIVATE _sg_image_t* _sg_mtl_pass_ds_image(const _sg_pass_t* pass) {
  8154. /* NOTE: may return null */
  8155. SOKOL_ASSERT(pass);
  8156. return pass->mtl.ds_att.image;
  8157. }
  8158. _SOKOL_PRIVATE void _sg_mtl_begin_pass(_sg_pass_t* pass, const sg_pass_action* action, int w, int h) {
  8159. SOKOL_ASSERT(action);
  8160. SOKOL_ASSERT(!_sg.mtl.in_pass);
  8161. SOKOL_ASSERT(_sg_mtl_cmd_queue);
  8162. SOKOL_ASSERT(!_sg_mtl_cmd_encoder);
  8163. SOKOL_ASSERT(_sg.mtl.renderpass_descriptor_cb);
  8164. _sg.mtl.in_pass = true;
  8165. _sg.mtl.cur_width = w;
  8166. _sg.mtl.cur_height = h;
  8167. _sg_mtl_clear_state_cache();
  8168. /* if this is the first pass in the frame, create a command buffer */
  8169. if (nil == _sg_mtl_cmd_buffer) {
  8170. /* block until the oldest frame in flight has finished */
  8171. dispatch_semaphore_wait(_sg_mtl_sem, DISPATCH_TIME_FOREVER);
  8172. _sg_mtl_cmd_buffer = [_sg_mtl_cmd_queue commandBufferWithUnretainedReferences];
  8173. }
  8174. /* if this is first pass in frame, get uniform buffer base pointer */
  8175. if (0 == _sg.mtl.cur_ub_base_ptr) {
  8176. _sg.mtl.cur_ub_base_ptr = (uint8_t*)[_sg_mtl_uniform_buffers[_sg.mtl.cur_frame_rotate_index] contents];
  8177. }
  8178. /* initialize a render pass descriptor */
  8179. MTLRenderPassDescriptor* pass_desc = nil;
  8180. if (pass) {
  8181. /* offscreen render pass */
  8182. pass_desc = [MTLRenderPassDescriptor renderPassDescriptor];
  8183. }
  8184. else {
  8185. /* default render pass, call user-provided callback to provide render pass descriptor */
  8186. pass_desc = (__bridge MTLRenderPassDescriptor*) _sg.mtl.renderpass_descriptor_cb();
  8187. }
  8188. if (pass_desc) {
  8189. _sg.mtl.pass_valid = true;
  8190. }
  8191. else {
  8192. /* default pass descriptor will not be valid if window is minimized,
  8193. don't do any rendering in this case */
  8194. _sg.mtl.pass_valid = false;
  8195. return;
  8196. }
  8197. if (pass) {
  8198. /* setup pass descriptor for offscreen rendering */
  8199. SOKOL_ASSERT(pass->slot.state == SG_RESOURCESTATE_VALID);
  8200. for (int i = 0; i < pass->cmn.num_color_atts; i++) {
  8201. const _sg_attachment_t* cmn_att = &pass->cmn.color_atts[i];
  8202. const _sg_mtl_attachment_t* mtl_att = &pass->mtl.color_atts[i];
  8203. const _sg_image_t* att_img = mtl_att->image;
  8204. SOKOL_ASSERT(att_img->slot.state == SG_RESOURCESTATE_VALID);
  8205. SOKOL_ASSERT(att_img->slot.id == cmn_att->image_id.id);
  8206. const bool is_msaa = (att_img->cmn.sample_count > 1);
  8207. pass_desc.colorAttachments[i].loadAction = _sg_mtl_load_action(action->colors[i].action);
  8208. pass_desc.colorAttachments[i].storeAction = is_msaa ? MTLStoreActionMultisampleResolve : MTLStoreActionStore;
  8209. const float* c = &(action->colors[i].val[0]);
  8210. pass_desc.colorAttachments[i].clearColor = MTLClearColorMake(c[0], c[1], c[2], c[3]);
  8211. if (is_msaa) {
  8212. SOKOL_ASSERT(att_img->mtl.msaa_tex != _SG_MTL_INVALID_SLOT_INDEX);
  8213. SOKOL_ASSERT(att_img->mtl.tex[mtl_att->image->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);
  8214. pass_desc.colorAttachments[i].texture = _sg_mtl_idpool[att_img->mtl.msaa_tex];
  8215. pass_desc.colorAttachments[i].resolveTexture = _sg_mtl_idpool[att_img->mtl.tex[att_img->cmn.active_slot]];
  8216. pass_desc.colorAttachments[i].resolveLevel = cmn_att->mip_level;
  8217. switch (att_img->cmn.type) {
  8218. case SG_IMAGETYPE_CUBE:
  8219. case SG_IMAGETYPE_ARRAY:
  8220. pass_desc.colorAttachments[i].resolveSlice = cmn_att->slice;
  8221. break;
  8222. case SG_IMAGETYPE_3D:
  8223. pass_desc.colorAttachments[i].resolveDepthPlane = cmn_att->slice;
  8224. break;
  8225. default: break;
  8226. }
  8227. }
  8228. else {
  8229. SOKOL_ASSERT(att_img->mtl.tex[att_img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);
  8230. pass_desc.colorAttachments[i].texture = _sg_mtl_idpool[att_img->mtl.tex[att_img->cmn.active_slot]];
  8231. pass_desc.colorAttachments[i].level = cmn_att->mip_level;
  8232. switch (att_img->cmn.type) {
  8233. case SG_IMAGETYPE_CUBE:
  8234. case SG_IMAGETYPE_ARRAY:
  8235. pass_desc.colorAttachments[i].slice = cmn_att->slice;
  8236. break;
  8237. case SG_IMAGETYPE_3D:
  8238. pass_desc.colorAttachments[i].depthPlane = cmn_att->slice;
  8239. break;
  8240. default: break;
  8241. }
  8242. }
  8243. }
  8244. const _sg_image_t* ds_att_img = pass->mtl.ds_att.image;
  8245. if (0 != ds_att_img) {
  8246. SOKOL_ASSERT(ds_att_img->slot.state == SG_RESOURCESTATE_VALID);
  8247. SOKOL_ASSERT(ds_att_img->slot.id == pass->cmn.ds_att.image_id.id);
  8248. SOKOL_ASSERT(ds_att_img->mtl.depth_tex != _SG_MTL_INVALID_SLOT_INDEX);
  8249. pass_desc.depthAttachment.texture = _sg_mtl_idpool[ds_att_img->mtl.depth_tex];
  8250. pass_desc.depthAttachment.loadAction = _sg_mtl_load_action(action->depth.action);
  8251. pass_desc.depthAttachment.clearDepth = action->depth.val;
  8252. if (_sg_is_depth_stencil_format(ds_att_img->cmn.pixel_format)) {
  8253. pass_desc.stencilAttachment.texture = _sg_mtl_idpool[ds_att_img->mtl.depth_tex];
  8254. pass_desc.stencilAttachment.loadAction = _sg_mtl_load_action(action->stencil.action);
  8255. pass_desc.stencilAttachment.clearStencil = action->stencil.val;
  8256. }
  8257. }
  8258. }
  8259. else {
  8260. /* setup pass descriptor for default rendering */
  8261. pass_desc.colorAttachments[0].loadAction = _sg_mtl_load_action(action->colors[0].action);
  8262. const float* c = &(action->colors[0].val[0]);
  8263. pass_desc.colorAttachments[0].clearColor = MTLClearColorMake(c[0], c[1], c[2], c[3]);
  8264. pass_desc.depthAttachment.loadAction = _sg_mtl_load_action(action->depth.action);
  8265. pass_desc.depthAttachment.clearDepth = action->depth.val;
  8266. pass_desc.stencilAttachment.loadAction = _sg_mtl_load_action(action->stencil.action);
  8267. pass_desc.stencilAttachment.clearStencil = action->stencil.val;
  8268. }
  8269. /* create a render command encoder, this might return nil if window is minimized */
  8270. _sg_mtl_cmd_encoder = [_sg_mtl_cmd_buffer renderCommandEncoderWithDescriptor:pass_desc];
  8271. if (_sg_mtl_cmd_encoder == nil) {
  8272. _sg.mtl.pass_valid = false;
  8273. return;
  8274. }
  8275. /* bind the global uniform buffer, this only happens once per pass */
  8276. for (int slot = 0; slot < SG_MAX_SHADERSTAGE_UBS; slot++) {
  8277. [_sg_mtl_cmd_encoder
  8278. setVertexBuffer:_sg_mtl_uniform_buffers[_sg.mtl.cur_frame_rotate_index]
  8279. offset:0
  8280. atIndex:slot];
  8281. [_sg_mtl_cmd_encoder
  8282. setFragmentBuffer:_sg_mtl_uniform_buffers[_sg.mtl.cur_frame_rotate_index]
  8283. offset:0
  8284. atIndex:slot];
  8285. }
  8286. }
  8287. _SOKOL_PRIVATE void _sg_mtl_end_pass(void) {
  8288. SOKOL_ASSERT(_sg.mtl.in_pass);
  8289. _sg.mtl.in_pass = false;
  8290. _sg.mtl.pass_valid = false;
  8291. if (nil != _sg_mtl_cmd_encoder) {
  8292. [_sg_mtl_cmd_encoder endEncoding];
  8293. _sg_mtl_cmd_encoder = nil;
  8294. }
  8295. }
  8296. _SOKOL_PRIVATE void _sg_mtl_commit(void) {
  8297. SOKOL_ASSERT(!_sg.mtl.in_pass);
  8298. SOKOL_ASSERT(!_sg.mtl.pass_valid);
  8299. SOKOL_ASSERT(_sg.mtl.drawable_cb);
  8300. SOKOL_ASSERT(nil == _sg_mtl_cmd_encoder);
  8301. SOKOL_ASSERT(nil != _sg_mtl_cmd_buffer);
  8302. #if defined(_SG_TARGET_MACOS)
  8303. [_sg_mtl_uniform_buffers[_sg.mtl.cur_frame_rotate_index] didModifyRange:NSMakeRange(0, _sg.mtl.cur_ub_offset)];
  8304. #endif
  8305. /* present, commit and signal semaphore when done */
  8306. id<MTLDrawable> cur_drawable = (__bridge id<MTLDrawable>) _sg.mtl.drawable_cb();
  8307. [_sg_mtl_cmd_buffer presentDrawable:cur_drawable];
  8308. [_sg_mtl_cmd_buffer addCompletedHandler:^(id<MTLCommandBuffer> cmd_buffer) {
  8309. dispatch_semaphore_signal(_sg_mtl_sem);
  8310. }];
  8311. [_sg_mtl_cmd_buffer commit];
  8312. /* garbage-collect resources pending for release */
  8313. _sg_mtl_garbage_collect(_sg.mtl.frame_index);
  8314. /* rotate uniform buffer slot */
  8315. if (++_sg.mtl.cur_frame_rotate_index >= SG_NUM_INFLIGHT_FRAMES) {
  8316. _sg.mtl.cur_frame_rotate_index = 0;
  8317. }
  8318. _sg.mtl.frame_index++;
  8319. _sg.mtl.cur_ub_offset = 0;
  8320. _sg.mtl.cur_ub_base_ptr = 0;
  8321. _sg_mtl_cmd_buffer = nil;
  8322. }
  8323. _SOKOL_PRIVATE void _sg_mtl_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {
  8324. SOKOL_ASSERT(_sg.mtl.in_pass);
  8325. if (!_sg.mtl.pass_valid) {
  8326. return;
  8327. }
  8328. SOKOL_ASSERT(_sg_mtl_cmd_encoder);
  8329. MTLViewport vp;
  8330. vp.originX = (double) x;
  8331. vp.originY = (double) (origin_top_left ? y : (_sg.mtl.cur_height - (y + h)));
  8332. vp.width = (double) w;
  8333. vp.height = (double) h;
  8334. vp.znear = 0.0;
  8335. vp.zfar = 1.0;
  8336. [_sg_mtl_cmd_encoder setViewport:vp];
  8337. }
  8338. _SOKOL_PRIVATE void _sg_mtl_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {
  8339. SOKOL_ASSERT(_sg.mtl.in_pass);
  8340. if (!_sg.mtl.pass_valid) {
  8341. return;
  8342. }
  8343. SOKOL_ASSERT(_sg_mtl_cmd_encoder);
  8344. /* clip against framebuffer rect */
  8345. x = _sg_min(_sg_max(0, x), _sg.mtl.cur_width-1);
  8346. y = _sg_min(_sg_max(0, y), _sg.mtl.cur_height-1);
  8347. if ((x + w) > _sg.mtl.cur_width) {
  8348. w = _sg.mtl.cur_width - x;
  8349. }
  8350. if ((y + h) > _sg.mtl.cur_height) {
  8351. h = _sg.mtl.cur_height - y;
  8352. }
  8353. w = _sg_max(w, 1);
  8354. h = _sg_max(h, 1);
  8355. MTLScissorRect r;
  8356. r.x = x;
  8357. r.y = origin_top_left ? y : (_sg.mtl.cur_height - (y + h));
  8358. r.width = w;
  8359. r.height = h;
  8360. [_sg_mtl_cmd_encoder setScissorRect:r];
  8361. }
  8362. _SOKOL_PRIVATE void _sg_mtl_apply_pipeline(_sg_pipeline_t* pip) {
  8363. SOKOL_ASSERT(pip);
  8364. SOKOL_ASSERT(pip->shader);
  8365. SOKOL_ASSERT(_sg.mtl.in_pass);
  8366. if (!_sg.mtl.pass_valid) {
  8367. return;
  8368. }
  8369. SOKOL_ASSERT(_sg_mtl_cmd_encoder);
  8370. if ((_sg.mtl.state_cache.cur_pipeline != pip) || (_sg.mtl.state_cache.cur_pipeline_id.id != pip->slot.id)) {
  8371. _sg.mtl.state_cache.cur_pipeline = pip;
  8372. _sg.mtl.state_cache.cur_pipeline_id.id = pip->slot.id;
  8373. const float* c = pip->cmn.blend_color;
  8374. [_sg_mtl_cmd_encoder setBlendColorRed:c[0] green:c[1] blue:c[2] alpha:c[3]];
  8375. [_sg_mtl_cmd_encoder setCullMode:pip->mtl.cull_mode];
  8376. [_sg_mtl_cmd_encoder setFrontFacingWinding:pip->mtl.winding];
  8377. [_sg_mtl_cmd_encoder setStencilReferenceValue:pip->mtl.stencil_ref];
  8378. [_sg_mtl_cmd_encoder setDepthBias:pip->cmn.depth_bias slopeScale:pip->cmn.depth_bias_slope_scale clamp:pip->cmn.depth_bias_clamp];
  8379. SOKOL_ASSERT(pip->mtl.rps != _SG_MTL_INVALID_SLOT_INDEX);
  8380. [_sg_mtl_cmd_encoder setRenderPipelineState:_sg_mtl_idpool[pip->mtl.rps]];
  8381. SOKOL_ASSERT(pip->mtl.dss != _SG_MTL_INVALID_SLOT_INDEX);
  8382. [_sg_mtl_cmd_encoder setDepthStencilState:_sg_mtl_idpool[pip->mtl.dss]];
  8383. }
  8384. }
  8385. _SOKOL_PRIVATE void _sg_mtl_apply_bindings(
  8386. _sg_pipeline_t* pip,
  8387. _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs,
  8388. _sg_buffer_t* ib, int ib_offset,
  8389. _sg_image_t** vs_imgs, int num_vs_imgs,
  8390. _sg_image_t** fs_imgs, int num_fs_imgs)
  8391. {
  8392. SOKOL_ASSERT(_sg.mtl.in_pass);
  8393. if (!_sg.mtl.pass_valid) {
  8394. return;
  8395. }
  8396. SOKOL_ASSERT(_sg_mtl_cmd_encoder);
  8397. /* store index buffer binding, this will be needed later in sg_draw() */
  8398. _sg.mtl.state_cache.cur_indexbuffer = ib;
  8399. _sg.mtl.state_cache.cur_indexbuffer_offset = ib_offset;
  8400. if (ib) {
  8401. SOKOL_ASSERT(pip->cmn.index_type != SG_INDEXTYPE_NONE);
  8402. _sg.mtl.state_cache.cur_indexbuffer_id.id = ib->slot.id;
  8403. }
  8404. else {
  8405. SOKOL_ASSERT(pip->cmn.index_type == SG_INDEXTYPE_NONE);
  8406. _sg.mtl.state_cache.cur_indexbuffer_id.id = SG_INVALID_ID;
  8407. }
  8408. /* apply vertex buffers */
  8409. int slot;
  8410. for (slot = 0; slot < num_vbs; slot++) {
  8411. const _sg_buffer_t* vb = vbs[slot];
  8412. if ((_sg.mtl.state_cache.cur_vertexbuffers[slot] != vb) ||
  8413. (_sg.mtl.state_cache.cur_vertexbuffer_offsets[slot] != vb_offsets[slot]) ||
  8414. (_sg.mtl.state_cache.cur_vertexbuffer_ids[slot].id != vb->slot.id))
  8415. {
  8416. _sg.mtl.state_cache.cur_vertexbuffers[slot] = vb;
  8417. _sg.mtl.state_cache.cur_vertexbuffer_offsets[slot] = vb_offsets[slot];
  8418. _sg.mtl.state_cache.cur_vertexbuffer_ids[slot].id = vb->slot.id;
  8419. const NSUInteger mtl_slot = SG_MAX_SHADERSTAGE_UBS + slot;
  8420. SOKOL_ASSERT(vb->mtl.buf[vb->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);
  8421. [_sg_mtl_cmd_encoder setVertexBuffer:_sg_mtl_idpool[vb->mtl.buf[vb->cmn.active_slot]]
  8422. offset:vb_offsets[slot]
  8423. atIndex:mtl_slot];
  8424. }
  8425. }
  8426. /* apply vertex shader images */
  8427. for (slot = 0; slot < num_vs_imgs; slot++) {
  8428. const _sg_image_t* img = vs_imgs[slot];
  8429. if ((_sg.mtl.state_cache.cur_vs_images[slot] != img) || (_sg.mtl.state_cache.cur_vs_image_ids[slot].id != img->slot.id)) {
  8430. _sg.mtl.state_cache.cur_vs_images[slot] = img;
  8431. _sg.mtl.state_cache.cur_vs_image_ids[slot].id = img->slot.id;
  8432. SOKOL_ASSERT(img->mtl.tex[img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);
  8433. [_sg_mtl_cmd_encoder setVertexTexture:_sg_mtl_idpool[img->mtl.tex[img->cmn.active_slot]] atIndex:slot];
  8434. SOKOL_ASSERT(img->mtl.sampler_state != _SG_MTL_INVALID_SLOT_INDEX);
  8435. [_sg_mtl_cmd_encoder setVertexSamplerState:_sg_mtl_idpool[img->mtl.sampler_state] atIndex:slot];
  8436. }
  8437. }
  8438. /* apply fragment shader images */
  8439. for (slot = 0; slot < num_fs_imgs; slot++) {
  8440. const _sg_image_t* img = fs_imgs[slot];
  8441. if ((_sg.mtl.state_cache.cur_fs_images[slot] != img) || (_sg.mtl.state_cache.cur_fs_image_ids[slot].id != img->slot.id)) {
  8442. _sg.mtl.state_cache.cur_fs_images[slot] = img;
  8443. _sg.mtl.state_cache.cur_fs_image_ids[slot].id = img->slot.id;
  8444. SOKOL_ASSERT(img->mtl.tex[img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);
  8445. [_sg_mtl_cmd_encoder setFragmentTexture:_sg_mtl_idpool[img->mtl.tex[img->cmn.active_slot]] atIndex:slot];
  8446. SOKOL_ASSERT(img->mtl.sampler_state != _SG_MTL_INVALID_SLOT_INDEX);
  8447. [_sg_mtl_cmd_encoder setFragmentSamplerState:_sg_mtl_idpool[img->mtl.sampler_state] atIndex:slot];
  8448. }
  8449. }
  8450. }
  8451. #define _sg_mtl_roundup(val, round_to) (((val)+((round_to)-1))&~((round_to)-1))
  8452. _SOKOL_PRIVATE void _sg_mtl_apply_uniforms(sg_shader_stage stage_index, int ub_index, const void* data, int num_bytes) {
  8453. SOKOL_ASSERT(_sg.mtl.in_pass);
  8454. if (!_sg.mtl.pass_valid) {
  8455. return;
  8456. }
  8457. SOKOL_ASSERT(_sg_mtl_cmd_encoder);
  8458. SOKOL_ASSERT(data && (num_bytes > 0));
  8459. SOKOL_ASSERT((stage_index >= 0) && ((int)stage_index < SG_NUM_SHADER_STAGES));
  8460. SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS));
  8461. SOKOL_ASSERT((_sg.mtl.cur_ub_offset + num_bytes) <= _sg.mtl.ub_size);
  8462. SOKOL_ASSERT((_sg.mtl.cur_ub_offset & (_SG_MTL_UB_ALIGN-1)) == 0);
  8463. SOKOL_ASSERT(_sg.mtl.state_cache.cur_pipeline && _sg.mtl.state_cache.cur_pipeline->shader);
  8464. SOKOL_ASSERT(_sg.mtl.state_cache.cur_pipeline->slot.id == _sg.mtl.state_cache.cur_pipeline_id.id);
  8465. SOKOL_ASSERT(_sg.mtl.state_cache.cur_pipeline->shader->slot.id == _sg.mtl.state_cache.cur_pipeline->cmn.shader_id.id);
  8466. SOKOL_ASSERT(ub_index < _sg.mtl.state_cache.cur_pipeline->shader->cmn.stage[stage_index].num_uniform_blocks);
  8467. SOKOL_ASSERT(num_bytes <= _sg.mtl.state_cache.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size);
  8468. /* copy to global uniform buffer, record offset into cmd encoder, and advance offset */
  8469. uint8_t* dst = &_sg.mtl.cur_ub_base_ptr[_sg.mtl.cur_ub_offset];
  8470. memcpy(dst, data, num_bytes);
  8471. if (stage_index == SG_SHADERSTAGE_VS) {
  8472. [_sg_mtl_cmd_encoder setVertexBufferOffset:_sg.mtl.cur_ub_offset atIndex:ub_index];
  8473. }
  8474. else {
  8475. [_sg_mtl_cmd_encoder setFragmentBufferOffset:_sg.mtl.cur_ub_offset atIndex:ub_index];
  8476. }
  8477. _sg.mtl.cur_ub_offset = _sg_mtl_roundup(_sg.mtl.cur_ub_offset + num_bytes, _SG_MTL_UB_ALIGN);
  8478. }
  8479. _SOKOL_PRIVATE void _sg_mtl_draw(int base_element, int num_elements, int num_instances) {
  8480. SOKOL_ASSERT(_sg.mtl.in_pass);
  8481. if (!_sg.mtl.pass_valid) {
  8482. return;
  8483. }
  8484. SOKOL_ASSERT(_sg_mtl_cmd_encoder);
  8485. SOKOL_ASSERT(_sg.mtl.state_cache.cur_pipeline && (_sg.mtl.state_cache.cur_pipeline->slot.id == _sg.mtl.state_cache.cur_pipeline_id.id));
  8486. if (SG_INDEXTYPE_NONE != _sg.mtl.state_cache.cur_pipeline->cmn.index_type) {
  8487. /* indexed rendering */
  8488. SOKOL_ASSERT(_sg.mtl.state_cache.cur_indexbuffer && (_sg.mtl.state_cache.cur_indexbuffer->slot.id == _sg.mtl.state_cache.cur_indexbuffer_id.id));
  8489. const _sg_buffer_t* ib = _sg.mtl.state_cache.cur_indexbuffer;
  8490. SOKOL_ASSERT(ib->mtl.buf[ib->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);
  8491. const NSUInteger index_buffer_offset = _sg.mtl.state_cache.cur_indexbuffer_offset +
  8492. base_element * _sg.mtl.state_cache.cur_pipeline->mtl.index_size;
  8493. [_sg_mtl_cmd_encoder drawIndexedPrimitives:_sg.mtl.state_cache.cur_pipeline->mtl.prim_type
  8494. indexCount:num_elements
  8495. indexType:_sg.mtl.state_cache.cur_pipeline->mtl.index_type
  8496. indexBuffer:_sg_mtl_idpool[ib->mtl.buf[ib->cmn.active_slot]]
  8497. indexBufferOffset:index_buffer_offset
  8498. instanceCount:num_instances];
  8499. }
  8500. else {
  8501. /* non-indexed rendering */
  8502. [_sg_mtl_cmd_encoder drawPrimitives:_sg.mtl.state_cache.cur_pipeline->mtl.prim_type
  8503. vertexStart:base_element
  8504. vertexCount:num_elements
  8505. instanceCount:num_instances];
  8506. }
  8507. }
  8508. _SOKOL_PRIVATE void _sg_mtl_update_buffer(_sg_buffer_t* buf, const void* data, int data_size) {
  8509. SOKOL_ASSERT(buf && data && (data_size > 0));
  8510. if (++buf->cmn.active_slot >= buf->cmn.num_slots) {
  8511. buf->cmn.active_slot = 0;
  8512. }
  8513. __unsafe_unretained id<MTLBuffer> mtl_buf = _sg_mtl_idpool[buf->mtl.buf[buf->cmn.active_slot]];
  8514. void* dst_ptr = [mtl_buf contents];
  8515. memcpy(dst_ptr, data, data_size);
  8516. #if defined(_SG_TARGET_MACOS)
  8517. [mtl_buf didModifyRange:NSMakeRange(0, data_size)];
  8518. #endif
  8519. }
  8520. _SOKOL_PRIVATE void _sg_mtl_append_buffer(_sg_buffer_t* buf, const void* data, int data_size, bool new_frame) {
  8521. SOKOL_ASSERT(buf && data && (data_size > 0));
  8522. if (new_frame) {
  8523. if (++buf->cmn.active_slot >= buf->cmn.num_slots) {
  8524. buf->cmn.active_slot = 0;
  8525. }
  8526. }
  8527. __unsafe_unretained id<MTLBuffer> mtl_buf = _sg_mtl_idpool[buf->mtl.buf[buf->cmn.active_slot]];
  8528. uint8_t* dst_ptr = (uint8_t*) [mtl_buf contents];
  8529. dst_ptr += buf->cmn.append_pos;
  8530. memcpy(dst_ptr, data, data_size);
  8531. #if defined(_SG_TARGET_MACOS)
  8532. [mtl_buf didModifyRange:NSMakeRange(buf->cmn.append_pos, data_size)];
  8533. #endif
  8534. }
  8535. _SOKOL_PRIVATE void _sg_mtl_update_image(_sg_image_t* img, const sg_image_content* data) {
  8536. SOKOL_ASSERT(img && data);
  8537. if (++img->cmn.active_slot >= img->cmn.num_slots) {
  8538. img->cmn.active_slot = 0;
  8539. }
  8540. __unsafe_unretained id<MTLTexture> mtl_tex = _sg_mtl_idpool[img->mtl.tex[img->cmn.active_slot]];
  8541. _sg_mtl_copy_image_content(img, mtl_tex, data);
  8542. }
  8543. #endif
  8544. /*== BACKEND API WRAPPERS ====================================================*/
  8545. static inline void _sg_setup_backend(const sg_desc* desc) {
  8546. #if defined(_SOKOL_ANY_GL)
  8547. _sg_gl_setup_backend(desc);
  8548. #elif defined(SOKOL_METAL)
  8549. _sg_mtl_setup_backend(desc);
  8550. #elif defined(SOKOL_D3D11)
  8551. _sg_d3d11_setup_backend(desc);
  8552. #else
  8553. _sg_dummy_setup_backend(desc);
  8554. #endif
  8555. }
  8556. static inline void _sg_discard_backend(void) {
  8557. #if defined(_SOKOL_ANY_GL)
  8558. _sg_gl_discard_backend();
  8559. #elif defined(SOKOL_METAL)
  8560. _sg_mtl_discard_backend();
  8561. #elif defined(SOKOL_D3D11)
  8562. _sg_d3d11_discard_backend();
  8563. #else
  8564. _sg_dummy_discard_backend();
  8565. #endif
  8566. }
  8567. static inline void _sg_reset_state_cache(void) {
  8568. #if defined(_SOKOL_ANY_GL)
  8569. _sg_gl_reset_state_cache();
  8570. #elif defined(SOKOL_METAL)
  8571. _sg_mtl_reset_state_cache();
  8572. #elif defined(SOKOL_D3D11)
  8573. _sg_d3d11_reset_state_cache();
  8574. #else
  8575. _sg_dummy_reset_state_cache();
  8576. #endif
  8577. }
  8578. static inline void _sg_activate_context(_sg_context_t* ctx) {
  8579. #if defined(_SOKOL_ANY_GL)
  8580. _sg_gl_activate_context(ctx);
  8581. #elif defined(SOKOL_METAL)
  8582. _sg_mtl_activate_context(ctx);
  8583. #elif defined(SOKOL_D3D11)
  8584. _sg_d3d11_activate_context(ctx);
  8585. #else
  8586. _sg_dummy_activate_context(ctx);
  8587. #endif
  8588. }
  8589. static inline sg_resource_state _sg_create_context(_sg_context_t* ctx) {
  8590. #if defined(_SOKOL_ANY_GL)
  8591. return _sg_gl_create_context(ctx);
  8592. #elif defined(SOKOL_METAL)
  8593. return _sg_mtl_create_context(ctx);
  8594. #elif defined(SOKOL_D3D11)
  8595. return _sg_d3d11_create_context(ctx);
  8596. #else
  8597. return _sg_dummy_create_context(ctx);
  8598. #endif
  8599. }
  8600. static inline void _sg_destroy_context(_sg_context_t* ctx) {
  8601. #if defined(_SOKOL_ANY_GL)
  8602. _sg_gl_destroy_context(ctx);
  8603. #elif defined(SOKOL_METAL)
  8604. _sg_mtl_destroy_context(ctx);
  8605. #elif defined(SOKOL_D3D11)
  8606. _sg_d3d11_destroy_context(ctx);
  8607. #else
  8608. _sg_dummy_destroy_context(ctx);
  8609. #endif
  8610. }
  8611. static inline sg_resource_state _sg_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {
  8612. #if defined(_SOKOL_ANY_GL)
  8613. return _sg_gl_create_buffer(buf, desc);
  8614. #elif defined(SOKOL_METAL)
  8615. return _sg_mtl_create_buffer(buf, desc);
  8616. #elif defined(SOKOL_D3D11)
  8617. return _sg_d3d11_create_buffer(buf, desc);
  8618. #else
  8619. return _sg_dummy_create_buffer(buf, desc);
  8620. #endif
  8621. }
  8622. static inline void _sg_destroy_buffer(_sg_buffer_t* buf) {
  8623. #if defined(_SOKOL_ANY_GL)
  8624. _sg_gl_destroy_buffer(buf);
  8625. #elif defined(SOKOL_METAL)
  8626. _sg_mtl_destroy_buffer(buf);
  8627. #elif defined(SOKOL_D3D11)
  8628. _sg_d3d11_destroy_buffer(buf);
  8629. #else
  8630. _sg_dummy_destroy_buffer(buf);
  8631. #endif
  8632. }
  8633. static inline sg_resource_state _sg_create_image(_sg_image_t* img, const sg_image_desc* desc) {
  8634. #if defined(_SOKOL_ANY_GL)
  8635. return _sg_gl_create_image(img, desc);
  8636. #elif defined(SOKOL_METAL)
  8637. return _sg_mtl_create_image(img, desc);
  8638. #elif defined(SOKOL_D3D11)
  8639. return _sg_d3d11_create_image(img, desc);
  8640. #else
  8641. return _sg_dummy_create_image(img, desc);
  8642. #endif
  8643. }
  8644. static inline void _sg_destroy_image(_sg_image_t* img) {
  8645. #if defined(_SOKOL_ANY_GL)
  8646. _sg_gl_destroy_image(img);
  8647. #elif defined(SOKOL_METAL)
  8648. _sg_mtl_destroy_image(img);
  8649. #elif defined(SOKOL_D3D11)
  8650. _sg_d3d11_destroy_image(img);
  8651. #else
  8652. _sg_dummy_destroy_image(img);
  8653. #endif
  8654. }
  8655. static inline sg_resource_state _sg_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {
  8656. #if defined(_SOKOL_ANY_GL)
  8657. return _sg_gl_create_shader(shd, desc);
  8658. #elif defined(SOKOL_METAL)
  8659. return _sg_mtl_create_shader(shd, desc);
  8660. #elif defined(SOKOL_D3D11)
  8661. return _sg_d3d11_create_shader(shd, desc);
  8662. #else
  8663. return _sg_dummy_create_shader(shd, desc);
  8664. #endif
  8665. }
  8666. static inline void _sg_destroy_shader(_sg_shader_t* shd) {
  8667. #if defined(_SOKOL_ANY_GL)
  8668. _sg_gl_destroy_shader(shd);
  8669. #elif defined(SOKOL_METAL)
  8670. _sg_mtl_destroy_shader(shd);
  8671. #elif defined(SOKOL_D3D11)
  8672. _sg_d3d11_destroy_shader(shd);
  8673. #else
  8674. _sg_dummy_destroy_shader(shd);
  8675. #endif
  8676. }
  8677. static inline sg_resource_state _sg_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {
  8678. #if defined(_SOKOL_ANY_GL)
  8679. return _sg_gl_create_pipeline(pip, shd, desc);
  8680. #elif defined(SOKOL_METAL)
  8681. return _sg_mtl_create_pipeline(pip, shd, desc);
  8682. #elif defined(SOKOL_D3D11)
  8683. return _sg_d3d11_create_pipeline(pip, shd, desc);
  8684. #else
  8685. return _sg_dummy_create_pipeline(pip, shd, desc);
  8686. #endif
  8687. }
  8688. static inline void _sg_destroy_pipeline(_sg_pipeline_t* pip) {
  8689. #if defined(_SOKOL_ANY_GL)
  8690. _sg_gl_destroy_pipeline(pip);
  8691. #elif defined(SOKOL_METAL)
  8692. _sg_mtl_destroy_pipeline(pip);
  8693. #elif defined(SOKOL_D3D11)
  8694. _sg_d3d11_destroy_pipeline(pip);
  8695. #else
  8696. _sg_dummy_destroy_pipeline(pip);
  8697. #endif
  8698. }
  8699. static inline sg_resource_state _sg_create_pass(_sg_pass_t* pass, _sg_image_t** att_images, const sg_pass_desc* desc) {
  8700. #if defined(_SOKOL_ANY_GL)
  8701. return _sg_gl_create_pass(pass, att_images, desc);
  8702. #elif defined(SOKOL_METAL)
  8703. return _sg_mtl_create_pass(pass, att_images, desc);
  8704. #elif defined(SOKOL_D3D11)
  8705. return _sg_d3d11_create_pass(pass, att_images, desc);
  8706. #else
  8707. return _sg_dummy_create_pass(pass, att_images, desc);
  8708. #endif
  8709. }
  8710. static inline void _sg_destroy_pass(_sg_pass_t* pass) {
  8711. #if defined(_SOKOL_ANY_GL)
  8712. _sg_gl_destroy_pass(pass);
  8713. #elif defined(SOKOL_METAL)
  8714. _sg_mtl_destroy_pass(pass);
  8715. #elif defined(SOKOL_D3D11)
  8716. _sg_d3d11_destroy_pass(pass);
  8717. #else
  8718. _sg_dummy_destroy_pass(pass);
  8719. #endif
  8720. }
  8721. static inline _sg_image_t* _sg_pass_color_image(const _sg_pass_t* pass, int index) {
  8722. #if defined(_SOKOL_ANY_GL)
  8723. return _sg_gl_pass_color_image(pass, index);
  8724. #elif defined(SOKOL_METAL)
  8725. return _sg_mtl_pass_color_image(pass, index);
  8726. #elif defined(SOKOL_D3D11)
  8727. return _sg_d3d11_pass_color_image(pass, index);
  8728. #else
  8729. return _sg_dummy_pass_color_image(pass, index);
  8730. #endif
  8731. }
  8732. static inline _sg_image_t* _sg_pass_ds_image(const _sg_pass_t* pass) {
  8733. #if defined(_SOKOL_ANY_GL)
  8734. return _sg_gl_pass_ds_image(pass);
  8735. #elif defined(SOKOL_METAL)
  8736. return _sg_mtl_pass_ds_image(pass);
  8737. #elif defined(SOKOL_D3D11)
  8738. return _sg_d3d11_pass_ds_image(pass);
  8739. #else
  8740. return _sg_dummy_pass_ds_image(pass);
  8741. #endif
  8742. }
  8743. static inline void _sg_begin_pass(_sg_pass_t* pass, const sg_pass_action* action, int w, int h) {
  8744. #if defined(_SOKOL_ANY_GL)
  8745. _sg_gl_begin_pass(pass, action, w, h);
  8746. #elif defined(SOKOL_METAL)
  8747. _sg_mtl_begin_pass(pass, action, w, h);
  8748. #elif defined(SOKOL_D3D11)
  8749. _sg_d3d11_begin_pass(pass, action, w, h);
  8750. #else
  8751. _sg_dummy_begin_pass(pass, action, w, h);
  8752. #endif
  8753. }
  8754. static inline void _sg_end_pass(void) {
  8755. #if defined(_SOKOL_ANY_GL)
  8756. _sg_gl_end_pass();
  8757. #elif defined(SOKOL_METAL)
  8758. _sg_mtl_end_pass();
  8759. #elif defined(SOKOL_D3D11)
  8760. _sg_d3d11_end_pass();
  8761. #else
  8762. _sg_dummy_end_pass();
  8763. #endif
  8764. }
  8765. static inline void _sg_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {
  8766. #if defined(_SOKOL_ANY_GL)
  8767. _sg_gl_apply_viewport(x, y, w, h, origin_top_left);
  8768. #elif defined(SOKOL_METAL)
  8769. _sg_mtl_apply_viewport(x, y, w, h, origin_top_left);
  8770. #elif defined(SOKOL_D3D11)
  8771. _sg_d3d11_apply_viewport(x, y, w, h, origin_top_left);
  8772. #else
  8773. _sg_dummy_apply_viewport(x, y, w, h, origin_top_left);
  8774. #endif
  8775. }
  8776. static inline void _sg_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {
  8777. #if defined(_SOKOL_ANY_GL)
  8778. _sg_gl_apply_scissor_rect(x, y, w, h, origin_top_left);
  8779. #elif defined(SOKOL_METAL)
  8780. _sg_mtl_apply_scissor_rect(x, y, w, h, origin_top_left);
  8781. #elif defined(SOKOL_D3D11)
  8782. _sg_d3d11_apply_scissor_rect(x, y, w, h, origin_top_left);
  8783. #else
  8784. _sg_dummy_apply_scissor_rect(x, y, w, h, origin_top_left);
  8785. #endif
  8786. }
  8787. static inline void _sg_apply_pipeline(_sg_pipeline_t* pip) {
  8788. #if defined(_SOKOL_ANY_GL)
  8789. _sg_gl_apply_pipeline(pip);
  8790. #elif defined(SOKOL_METAL)
  8791. _sg_mtl_apply_pipeline(pip);
  8792. #elif defined(SOKOL_D3D11)
  8793. _sg_d3d11_apply_pipeline(pip);
  8794. #else
  8795. _sg_dummy_apply_pipeline(pip);
  8796. #endif
  8797. }
  8798. static inline void _sg_apply_bindings(
  8799. _sg_pipeline_t* pip,
  8800. _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs,
  8801. _sg_buffer_t* ib, int ib_offset,
  8802. _sg_image_t** vs_imgs, int num_vs_imgs,
  8803. _sg_image_t** fs_imgs, int num_fs_imgs)
  8804. {
  8805. #if defined(_SOKOL_ANY_GL)
  8806. _sg_gl_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs);
  8807. #elif defined(SOKOL_METAL)
  8808. _sg_mtl_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs);
  8809. #elif defined(SOKOL_D3D11)
  8810. _sg_d3d11_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs);
  8811. #else
  8812. _sg_dummy_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs);
  8813. #endif
  8814. }
  8815. static inline void _sg_apply_uniforms(sg_shader_stage stage_index, int ub_index, const void* data, int num_bytes) {
  8816. #if defined(_SOKOL_ANY_GL)
  8817. _sg_gl_apply_uniforms(stage_index, ub_index, data, num_bytes);
  8818. #elif defined(SOKOL_METAL)
  8819. _sg_mtl_apply_uniforms(stage_index, ub_index, data, num_bytes);
  8820. #elif defined(SOKOL_D3D11)
  8821. _sg_d3d11_apply_uniforms(stage_index, ub_index, data, num_bytes);
  8822. #else
  8823. _sg_dummy_apply_uniforms(stage_index, ub_index, data, num_bytes);
  8824. #endif
  8825. }
  8826. static inline void _sg_draw(int base_element, int num_elements, int num_instances) {
  8827. #if defined(_SOKOL_ANY_GL)
  8828. _sg_gl_draw(base_element, num_elements, num_instances);
  8829. #elif defined(SOKOL_METAL)
  8830. _sg_mtl_draw(base_element, num_elements, num_instances);
  8831. #elif defined(SOKOL_D3D11)
  8832. _sg_d3d11_draw(base_element, num_elements, num_instances);
  8833. #else
  8834. _sg_dummy_draw(base_element, num_elements, num_instances);
  8835. #endif
  8836. }
  8837. static inline void _sg_commit(void) {
  8838. #if defined(_SOKOL_ANY_GL)
  8839. _sg_gl_commit();
  8840. #elif defined(SOKOL_METAL)
  8841. _sg_mtl_commit();
  8842. #elif defined(SOKOL_D3D11)
  8843. _sg_d3d11_commit();
  8844. #else
  8845. _sg_dummy_commit();
  8846. #endif
  8847. }
  8848. static inline void _sg_update_buffer(_sg_buffer_t* buf, const void* data_ptr, int data_size) {
  8849. #if defined(_SOKOL_ANY_GL)
  8850. _sg_gl_update_buffer(buf, data_ptr, data_size);
  8851. #elif defined(SOKOL_METAL)
  8852. _sg_mtl_update_buffer(buf, data_ptr, data_size);
  8853. #elif defined(SOKOL_D3D11)
  8854. _sg_d3d11_update_buffer(buf, data_ptr, data_size);
  8855. #else
  8856. _sg_dummy_update_buffer(buf, data_ptr, data_size);
  8857. #endif
  8858. }
  8859. static inline void _sg_append_buffer(_sg_buffer_t* buf, const void* data_ptr, int data_size, bool new_frame) {
  8860. #if defined(_SOKOL_ANY_GL)
  8861. _sg_gl_append_buffer(buf, data_ptr, data_size, new_frame);
  8862. #elif defined(SOKOL_METAL)
  8863. _sg_mtl_append_buffer(buf, data_ptr, data_size, new_frame);
  8864. #elif defined(SOKOL_D3D11)
  8865. _sg_d3d11_append_buffer(buf, data_ptr, data_size, new_frame);
  8866. #else
  8867. _sg_dummy_append_buffer(buf, data_ptr, data_size, new_frame);
  8868. #endif
  8869. }
  8870. static inline void _sg_update_image(_sg_image_t* img, const sg_image_content* data) {
  8871. #if defined(_SOKOL_ANY_GL)
  8872. _sg_gl_update_image(img, data);
  8873. #elif defined(SOKOL_METAL)
  8874. _sg_mtl_update_image(img, data);
  8875. #elif defined(SOKOL_D3D11)
  8876. _sg_d3d11_update_image(img, data);
  8877. #else
  8878. _sg_dummy_update_image(img, data);
  8879. #endif
  8880. }
  8881. /*== RESOURCE POOLS ==========================================================*/
  8882. _SOKOL_PRIVATE void _sg_init_pool(_sg_pool_t* pool, int num) {
  8883. SOKOL_ASSERT(pool && (num >= 1));
  8884. /* slot 0 is reserved for the 'invalid id', so bump the pool size by 1 */
  8885. pool->size = num + 1;
  8886. pool->queue_top = 0;
  8887. /* generation counters indexable by pool slot index, slot 0 is reserved */
  8888. size_t gen_ctrs_size = sizeof(uint32_t) * pool->size;
  8889. pool->gen_ctrs = (uint32_t*) SOKOL_MALLOC(gen_ctrs_size);
  8890. SOKOL_ASSERT(pool->gen_ctrs);
  8891. memset(pool->gen_ctrs, 0, gen_ctrs_size);
  8892. /* it's not a bug to only reserve 'num' here */
  8893. pool->free_queue = (int*) SOKOL_MALLOC(sizeof(int)*num);
  8894. SOKOL_ASSERT(pool->free_queue);
  8895. /* never allocate the zero-th pool item since the invalid id is 0 */
  8896. for (int i = pool->size-1; i >= 1; i--) {
  8897. pool->free_queue[pool->queue_top++] = i;
  8898. }
  8899. }
  8900. _SOKOL_PRIVATE void _sg_discard_pool(_sg_pool_t* pool) {
  8901. SOKOL_ASSERT(pool);
  8902. SOKOL_ASSERT(pool->free_queue);
  8903. SOKOL_FREE(pool->free_queue);
  8904. pool->free_queue = 0;
  8905. SOKOL_ASSERT(pool->gen_ctrs);
  8906. SOKOL_FREE(pool->gen_ctrs);
  8907. pool->gen_ctrs = 0;
  8908. pool->size = 0;
  8909. pool->queue_top = 0;
  8910. }
  8911. _SOKOL_PRIVATE int _sg_pool_alloc_index(_sg_pool_t* pool) {
  8912. SOKOL_ASSERT(pool);
  8913. SOKOL_ASSERT(pool->free_queue);
  8914. if (pool->queue_top > 0) {
  8915. int slot_index = pool->free_queue[--pool->queue_top];
  8916. SOKOL_ASSERT((slot_index > 0) && (slot_index < pool->size));
  8917. return slot_index;
  8918. }
  8919. else {
  8920. /* pool exhausted */
  8921. return _SG_INVALID_SLOT_INDEX;
  8922. }
  8923. }
  8924. _SOKOL_PRIVATE void _sg_pool_free_index(_sg_pool_t* pool, int slot_index) {
  8925. SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < pool->size));
  8926. SOKOL_ASSERT(pool);
  8927. SOKOL_ASSERT(pool->free_queue);
  8928. SOKOL_ASSERT(pool->queue_top < pool->size);
  8929. #ifdef SOKOL_DEBUG
  8930. /* debug check against double-free */
  8931. for (int i = 0; i < pool->queue_top; i++) {
  8932. SOKOL_ASSERT(pool->free_queue[i] != slot_index);
  8933. }
  8934. #endif
  8935. pool->free_queue[pool->queue_top++] = slot_index;
  8936. SOKOL_ASSERT(pool->queue_top <= (pool->size-1));
  8937. }
  8938. _SOKOL_PRIVATE void _sg_reset_buffer(_sg_buffer_t* buf) {
  8939. SOKOL_ASSERT(buf);
  8940. memset(buf, 0, sizeof(_sg_buffer_t));
  8941. }
  8942. _SOKOL_PRIVATE void _sg_reset_image(_sg_image_t* img) {
  8943. SOKOL_ASSERT(img);
  8944. memset(img, 0, sizeof(_sg_image_t));
  8945. }
  8946. _SOKOL_PRIVATE void _sg_reset_shader(_sg_shader_t* shd) {
  8947. SOKOL_ASSERT(shd);
  8948. memset(shd, 0, sizeof(_sg_shader_t));
  8949. }
  8950. _SOKOL_PRIVATE void _sg_reset_pipeline(_sg_pipeline_t* pip) {
  8951. SOKOL_ASSERT(pip);
  8952. memset(pip, 0, sizeof(_sg_pipeline_t));
  8953. }
  8954. _SOKOL_PRIVATE void _sg_reset_pass(_sg_pass_t* pass) {
  8955. SOKOL_ASSERT(pass);
  8956. memset(pass, 0, sizeof(_sg_pass_t));
  8957. }
  8958. _SOKOL_PRIVATE void _sg_reset_context(_sg_context_t* ctx) {
  8959. SOKOL_ASSERT(ctx);
  8960. memset(ctx, 0, sizeof(_sg_context_t));
  8961. }
  8962. _SOKOL_PRIVATE void _sg_setup_pools(_sg_pools_t* p, const sg_desc* desc) {
  8963. SOKOL_ASSERT(p);
  8964. SOKOL_ASSERT(desc);
  8965. /* note: the pools here will have an additional item, since slot 0 is reserved */
  8966. SOKOL_ASSERT((desc->buffer_pool_size > 0) && (desc->buffer_pool_size < _SG_MAX_POOL_SIZE));
  8967. _sg_init_pool(&p->buffer_pool, desc->buffer_pool_size);
  8968. size_t buffer_pool_byte_size = sizeof(_sg_buffer_t) * p->buffer_pool.size;
  8969. p->buffers = (_sg_buffer_t*) SOKOL_MALLOC(buffer_pool_byte_size);
  8970. SOKOL_ASSERT(p->buffers);
  8971. memset(p->buffers, 0, buffer_pool_byte_size);
  8972. SOKOL_ASSERT((desc->image_pool_size > 0) && (desc->image_pool_size < _SG_MAX_POOL_SIZE));
  8973. _sg_init_pool(&p->image_pool, desc->image_pool_size);
  8974. size_t image_pool_byte_size = sizeof(_sg_image_t) * p->image_pool.size;
  8975. p->images = (_sg_image_t*) SOKOL_MALLOC(image_pool_byte_size);
  8976. SOKOL_ASSERT(p->images);
  8977. memset(p->images, 0, image_pool_byte_size);
  8978. SOKOL_ASSERT((desc->shader_pool_size > 0) && (desc->shader_pool_size < _SG_MAX_POOL_SIZE));
  8979. _sg_init_pool(&p->shader_pool, desc->shader_pool_size);
  8980. size_t shader_pool_byte_size = sizeof(_sg_shader_t) * p->shader_pool.size;
  8981. p->shaders = (_sg_shader_t*) SOKOL_MALLOC(shader_pool_byte_size);
  8982. SOKOL_ASSERT(p->shaders);
  8983. memset(p->shaders, 0, shader_pool_byte_size);
  8984. SOKOL_ASSERT((desc->pipeline_pool_size > 0) && (desc->pipeline_pool_size < _SG_MAX_POOL_SIZE));
  8985. _sg_init_pool(&p->pipeline_pool, desc->pipeline_pool_size);
  8986. size_t pipeline_pool_byte_size = sizeof(_sg_pipeline_t) * p->pipeline_pool.size;
  8987. p->pipelines = (_sg_pipeline_t*) SOKOL_MALLOC(pipeline_pool_byte_size);
  8988. SOKOL_ASSERT(p->pipelines);
  8989. memset(p->pipelines, 0, pipeline_pool_byte_size);
  8990. SOKOL_ASSERT((desc->pass_pool_size > 0) && (desc->pass_pool_size < _SG_MAX_POOL_SIZE));
  8991. _sg_init_pool(&p->pass_pool, desc->pass_pool_size);
  8992. size_t pass_pool_byte_size = sizeof(_sg_pass_t) * p->pass_pool.size;
  8993. p->passes = (_sg_pass_t*) SOKOL_MALLOC(pass_pool_byte_size);
  8994. SOKOL_ASSERT(p->passes);
  8995. memset(p->passes, 0, pass_pool_byte_size);
  8996. SOKOL_ASSERT((desc->context_pool_size > 0) && (desc->context_pool_size < _SG_MAX_POOL_SIZE));
  8997. _sg_init_pool(&p->context_pool, desc->context_pool_size);
  8998. size_t context_pool_byte_size = sizeof(_sg_context_t) * p->context_pool.size;
  8999. p->contexts = (_sg_context_t*) SOKOL_MALLOC(context_pool_byte_size);
  9000. SOKOL_ASSERT(p->contexts);
  9001. memset(p->contexts, 0, context_pool_byte_size);
  9002. }
  9003. _SOKOL_PRIVATE void _sg_discard_pools(_sg_pools_t* p) {
  9004. SOKOL_ASSERT(p);
  9005. SOKOL_FREE(p->contexts); p->contexts = 0;
  9006. SOKOL_FREE(p->passes); p->passes = 0;
  9007. SOKOL_FREE(p->pipelines); p->pipelines = 0;
  9008. SOKOL_FREE(p->shaders); p->shaders = 0;
  9009. SOKOL_FREE(p->images); p->images = 0;
  9010. SOKOL_FREE(p->buffers); p->buffers = 0;
  9011. _sg_discard_pool(&p->context_pool);
  9012. _sg_discard_pool(&p->pass_pool);
  9013. _sg_discard_pool(&p->pipeline_pool);
  9014. _sg_discard_pool(&p->shader_pool);
  9015. _sg_discard_pool(&p->image_pool);
  9016. _sg_discard_pool(&p->buffer_pool);
  9017. }
  9018. /* allocate the slot at slot_index:
  9019. - bump the slot's generation counter
  9020. - create a resource id from the generation counter and slot index
  9021. - set the slot's id to this id
  9022. - set the slot's state to ALLOC
  9023. - return the resource id
  9024. */
  9025. _SOKOL_PRIVATE uint32_t _sg_slot_alloc(_sg_pool_t* pool, _sg_slot_t* slot, int slot_index) {
  9026. /* FIXME: add handling for an overflowing generation counter,
  9027. for now, just overflow (another option is to disable
  9028. the slot)
  9029. */
  9030. SOKOL_ASSERT(pool && pool->gen_ctrs);
  9031. SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < pool->size));
  9032. SOKOL_ASSERT((slot->state == SG_RESOURCESTATE_INITIAL) && (slot->id == SG_INVALID_ID));
  9033. uint32_t ctr = ++pool->gen_ctrs[slot_index];
  9034. slot->id = (ctr<<_SG_SLOT_SHIFT)|(slot_index & _SG_SLOT_MASK);
  9035. slot->state = SG_RESOURCESTATE_ALLOC;
  9036. return slot->id;
  9037. }
  9038. /* extract slot index from id */
  9039. _SOKOL_PRIVATE int _sg_slot_index(uint32_t id) {
  9040. int slot_index = (int) (id & _SG_SLOT_MASK);
  9041. SOKOL_ASSERT(_SG_INVALID_SLOT_INDEX != slot_index);
  9042. return slot_index;
  9043. }
  9044. /* returns pointer to resource by id without matching id check */
  9045. _SOKOL_PRIVATE _sg_buffer_t* _sg_buffer_at(const _sg_pools_t* p, uint32_t buf_id) {
  9046. SOKOL_ASSERT(p && (SG_INVALID_ID != buf_id));
  9047. int slot_index = _sg_slot_index(buf_id);
  9048. SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->buffer_pool.size));
  9049. return &p->buffers[slot_index];
  9050. }
  9051. _SOKOL_PRIVATE _sg_image_t* _sg_image_at(const _sg_pools_t* p, uint32_t img_id) {
  9052. SOKOL_ASSERT(p && (SG_INVALID_ID != img_id));
  9053. int slot_index = _sg_slot_index(img_id);
  9054. SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->image_pool.size));
  9055. return &p->images[slot_index];
  9056. }
  9057. _SOKOL_PRIVATE _sg_shader_t* _sg_shader_at(const _sg_pools_t* p, uint32_t shd_id) {
  9058. SOKOL_ASSERT(p && (SG_INVALID_ID != shd_id));
  9059. int slot_index = _sg_slot_index(shd_id);
  9060. SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->shader_pool.size));
  9061. return &p->shaders[slot_index];
  9062. }
  9063. _SOKOL_PRIVATE _sg_pipeline_t* _sg_pipeline_at(const _sg_pools_t* p, uint32_t pip_id) {
  9064. SOKOL_ASSERT(p && (SG_INVALID_ID != pip_id));
  9065. int slot_index = _sg_slot_index(pip_id);
  9066. SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->pipeline_pool.size));
  9067. return &p->pipelines[slot_index];
  9068. }
  9069. _SOKOL_PRIVATE _sg_pass_t* _sg_pass_at(const _sg_pools_t* p, uint32_t pass_id) {
  9070. SOKOL_ASSERT(p && (SG_INVALID_ID != pass_id));
  9071. int slot_index = _sg_slot_index(pass_id);
  9072. SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->pass_pool.size));
  9073. return &p->passes[slot_index];
  9074. }
  9075. _SOKOL_PRIVATE _sg_context_t* _sg_context_at(const _sg_pools_t* p, uint32_t context_id) {
  9076. SOKOL_ASSERT(p && (SG_INVALID_ID != context_id));
  9077. int slot_index = _sg_slot_index(context_id);
  9078. SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->context_pool.size));
  9079. return &p->contexts[slot_index];
  9080. }
  9081. /* returns pointer to resource with matching id check, may return 0 */
  9082. _SOKOL_PRIVATE _sg_buffer_t* _sg_lookup_buffer(const _sg_pools_t* p, uint32_t buf_id) {
  9083. if (SG_INVALID_ID != buf_id) {
  9084. _sg_buffer_t* buf = _sg_buffer_at(p, buf_id);
  9085. if (buf->slot.id == buf_id) {
  9086. return buf;
  9087. }
  9088. }
  9089. return 0;
  9090. }
  9091. _SOKOL_PRIVATE _sg_image_t* _sg_lookup_image(const _sg_pools_t* p, uint32_t img_id) {
  9092. if (SG_INVALID_ID != img_id) {
  9093. _sg_image_t* img = _sg_image_at(p, img_id);
  9094. if (img->slot.id == img_id) {
  9095. return img;
  9096. }
  9097. }
  9098. return 0;
  9099. }
  9100. _SOKOL_PRIVATE _sg_shader_t* _sg_lookup_shader(const _sg_pools_t* p, uint32_t shd_id) {
  9101. SOKOL_ASSERT(p);
  9102. if (SG_INVALID_ID != shd_id) {
  9103. _sg_shader_t* shd = _sg_shader_at(p, shd_id);
  9104. if (shd->slot.id == shd_id) {
  9105. return shd;
  9106. }
  9107. }
  9108. return 0;
  9109. }
  9110. _SOKOL_PRIVATE _sg_pipeline_t* _sg_lookup_pipeline(const _sg_pools_t* p, uint32_t pip_id) {
  9111. SOKOL_ASSERT(p);
  9112. if (SG_INVALID_ID != pip_id) {
  9113. _sg_pipeline_t* pip = _sg_pipeline_at(p, pip_id);
  9114. if (pip->slot.id == pip_id) {
  9115. return pip;
  9116. }
  9117. }
  9118. return 0;
  9119. }
  9120. _SOKOL_PRIVATE _sg_pass_t* _sg_lookup_pass(const _sg_pools_t* p, uint32_t pass_id) {
  9121. SOKOL_ASSERT(p);
  9122. if (SG_INVALID_ID != pass_id) {
  9123. _sg_pass_t* pass = _sg_pass_at(p, pass_id);
  9124. if (pass->slot.id == pass_id) {
  9125. return pass;
  9126. }
  9127. }
  9128. return 0;
  9129. }
  9130. _SOKOL_PRIVATE _sg_context_t* _sg_lookup_context(const _sg_pools_t* p, uint32_t ctx_id) {
  9131. SOKOL_ASSERT(p);
  9132. if (SG_INVALID_ID != ctx_id) {
  9133. _sg_context_t* ctx = _sg_context_at(p, ctx_id);
  9134. if (ctx->slot.id == ctx_id) {
  9135. return ctx;
  9136. }
  9137. }
  9138. return 0;
  9139. }
  9140. _SOKOL_PRIVATE void _sg_destroy_all_resources(_sg_pools_t* p, uint32_t ctx_id) {
  9141. /* this is a bit dumb since it loops over all pool slots to
  9142. find the occupied slots, on the other hand it is only ever
  9143. executed at shutdown
  9144. NOTE: ONLY EXECUTE THIS AT SHUTDOWN
  9145. ...because the free queues will not be reset
  9146. and the resource slots not be cleared!
  9147. */
  9148. for (int i = 1; i < p->buffer_pool.size; i++) {
  9149. if (p->buffers[i].slot.ctx_id == ctx_id) {
  9150. sg_resource_state state = p->buffers[i].slot.state;
  9151. if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {
  9152. _sg_destroy_buffer(&p->buffers[i]);
  9153. }
  9154. }
  9155. }
  9156. for (int i = 1; i < p->image_pool.size; i++) {
  9157. if (p->images[i].slot.ctx_id == ctx_id) {
  9158. sg_resource_state state = p->images[i].slot.state;
  9159. if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {
  9160. _sg_destroy_image(&p->images[i]);
  9161. }
  9162. }
  9163. }
  9164. for (int i = 1; i < p->shader_pool.size; i++) {
  9165. if (p->shaders[i].slot.ctx_id == ctx_id) {
  9166. sg_resource_state state = p->shaders[i].slot.state;
  9167. if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {
  9168. _sg_destroy_shader(&p->shaders[i]);
  9169. }
  9170. }
  9171. }
  9172. for (int i = 1; i < p->pipeline_pool.size; i++) {
  9173. if (p->pipelines[i].slot.ctx_id == ctx_id) {
  9174. sg_resource_state state = p->pipelines[i].slot.state;
  9175. if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {
  9176. _sg_destroy_pipeline(&p->pipelines[i]);
  9177. }
  9178. }
  9179. }
  9180. for (int i = 1; i < p->pass_pool.size; i++) {
  9181. if (p->passes[i].slot.ctx_id == ctx_id) {
  9182. sg_resource_state state = p->passes[i].slot.state;
  9183. if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {
  9184. _sg_destroy_pass(&p->passes[i]);
  9185. }
  9186. }
  9187. }
  9188. }
  9189. /*== VALIDATION LAYER ========================================================*/
  9190. #if defined(SOKOL_DEBUG)
  9191. /* return a human readable string for an _sg_validate_error */
  9192. _SOKOL_PRIVATE const char* _sg_validate_string(_sg_validate_error_t err) {
  9193. switch (err) {
  9194. /* buffer creation validation errors */
  9195. case _SG_VALIDATE_BUFFERDESC_CANARY: return "sg_buffer_desc not initialized";
  9196. case _SG_VALIDATE_BUFFERDESC_SIZE: return "sg_buffer_desc.size cannot be 0";
  9197. case _SG_VALIDATE_BUFFERDESC_CONTENT: return "immutable buffers must be initialized with content (sg_buffer_desc.content)";
  9198. case _SG_VALIDATE_BUFFERDESC_NO_CONTENT: return "dynamic/stream usage buffers cannot be initialized with content";
  9199. /* image creation validation errros */
  9200. case _SG_VALIDATE_IMAGEDESC_CANARY: return "sg_image_desc not initialized";
  9201. case _SG_VALIDATE_IMAGEDESC_WIDTH: return "sg_image_desc.width must be > 0";
  9202. case _SG_VALIDATE_IMAGEDESC_HEIGHT: return "sg_image_desc.height must be > 0";
  9203. case _SG_VALIDATE_IMAGEDESC_RT_PIXELFORMAT: return "invalid pixel format for render-target image";
  9204. case _SG_VALIDATE_IMAGEDESC_NONRT_PIXELFORMAT: return "invalid pixel format for non-render-target image";
  9205. case _SG_VALIDATE_IMAGEDESC_MSAA_BUT_NO_RT: return "non-render-target images cannot be multisampled";
  9206. case _SG_VALIDATE_IMAGEDESC_NO_MSAA_RT_SUPPORT: return "MSAA not supported for this pixel format";
  9207. case _SG_VALIDATE_IMAGEDESC_RT_IMMUTABLE: return "render target images must be SG_USAGE_IMMUTABLE";
  9208. case _SG_VALIDATE_IMAGEDESC_RT_NO_CONTENT: return "render target images cannot be initialized with content";
  9209. case _SG_VALIDATE_IMAGEDESC_CONTENT: return "missing or invalid content for immutable image";
  9210. case _SG_VALIDATE_IMAGEDESC_NO_CONTENT: return "dynamic/stream usage images cannot be initialized with content";
  9211. /* shader creation */
  9212. case _SG_VALIDATE_SHADERDESC_CANARY: return "sg_shader_desc not initialized";
  9213. case _SG_VALIDATE_SHADERDESC_SOURCE: return "shader source code required";
  9214. case _SG_VALIDATE_SHADERDESC_BYTECODE: return "shader byte code required";
  9215. case _SG_VALIDATE_SHADERDESC_SOURCE_OR_BYTECODE: return "shader source or byte code required";
  9216. case _SG_VALIDATE_SHADERDESC_NO_BYTECODE_SIZE: return "shader byte code length (in bytes) required";
  9217. case _SG_VALIDATE_SHADERDESC_NO_CONT_UBS: return "shader uniform blocks must occupy continuous slots";
  9218. case _SG_VALIDATE_SHADERDESC_NO_CONT_UB_MEMBERS: return "uniform block members must occupy continuous slots";
  9219. case _SG_VALIDATE_SHADERDESC_NO_UB_MEMBERS: return "GL backend requires uniform block member declarations";
  9220. case _SG_VALIDATE_SHADERDESC_UB_MEMBER_NAME: return "uniform block member name missing";
  9221. case _SG_VALIDATE_SHADERDESC_UB_SIZE_MISMATCH: return "size of uniform block members doesn't match uniform block size";
  9222. case _SG_VALIDATE_SHADERDESC_NO_CONT_IMGS: return "shader images must occupy continuous slots";
  9223. case _SG_VALIDATE_SHADERDESC_IMG_NAME: return "GL backend requires uniform block member names";
  9224. case _SG_VALIDATE_SHADERDESC_ATTR_NAMES: return "GLES2 backend requires vertex attribute names";
  9225. case _SG_VALIDATE_SHADERDESC_ATTR_SEMANTICS: return "D3D11 backend requires vertex attribute semantics";
  9226. case _SG_VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG: return "vertex attribute name/semantic string too long (max len 16)";
  9227. /* pipeline creation */
  9228. case _SG_VALIDATE_PIPELINEDESC_CANARY: return "sg_pipeline_desc not initialized";
  9229. case _SG_VALIDATE_PIPELINEDESC_SHADER: return "sg_pipeline_desc.shader missing or invalid";
  9230. case _SG_VALIDATE_PIPELINEDESC_NO_ATTRS: return "sg_pipeline_desc.layout.attrs is empty or not continuous";
  9231. case _SG_VALIDATE_PIPELINEDESC_LAYOUT_STRIDE4: return "sg_pipeline_desc.layout.buffers[].stride must be multiple of 4";
  9232. case _SG_VALIDATE_PIPELINEDESC_ATTR_NAME: return "GLES2/WebGL missing vertex attribute name in shader";
  9233. case _SG_VALIDATE_PIPELINEDESC_ATTR_SEMANTICS: return "D3D11 missing vertex attribute semantics in shader";
  9234. /* pass creation */
  9235. case _SG_VALIDATE_PASSDESC_CANARY: return "sg_pass_desc not initialized";
  9236. case _SG_VALIDATE_PASSDESC_NO_COLOR_ATTS: return "sg_pass_desc.color_attachments[0] must be valid";
  9237. case _SG_VALIDATE_PASSDESC_NO_CONT_COLOR_ATTS: return "color attachments must occupy continuous slots";
  9238. case _SG_VALIDATE_PASSDESC_IMAGE: return "pass attachment image is not valid";
  9239. case _SG_VALIDATE_PASSDESC_MIPLEVEL: return "pass attachment mip level is bigger than image has mipmaps";
  9240. case _SG_VALIDATE_PASSDESC_FACE: return "pass attachment image is cubemap, but face index is too big";
  9241. case _SG_VALIDATE_PASSDESC_LAYER: return "pass attachment image is array texture, but layer index is too big";
  9242. case _SG_VALIDATE_PASSDESC_SLICE: return "pass attachment image is 3d texture, but slice value is too big";
  9243. case _SG_VALIDATE_PASSDESC_IMAGE_NO_RT: return "pass attachment image must be render targets";
  9244. case _SG_VALIDATE_PASSDESC_COLOR_PIXELFORMATS: return "all pass color attachment images must have the same pixel format";
  9245. case _SG_VALIDATE_PASSDESC_COLOR_INV_PIXELFORMAT: return "pass color-attachment images must have a renderable pixel format";
  9246. case _SG_VALIDATE_PASSDESC_DEPTH_INV_PIXELFORMAT: return "pass depth-attachment image must have depth pixel format";
  9247. case _SG_VALIDATE_PASSDESC_IMAGE_SIZES: return "all pass attachments must have the same size";
  9248. case _SG_VALIDATE_PASSDESC_IMAGE_SAMPLE_COUNTS: return "all pass attachments must have the same sample count";
  9249. /* sg_begin_pass */
  9250. case _SG_VALIDATE_BEGINPASS_PASS: return "sg_begin_pass: pass must be valid";
  9251. case _SG_VALIDATE_BEGINPASS_IMAGE: return "sg_begin_pass: one or more attachment images are not valid";
  9252. /* sg_apply_pipeline */
  9253. case _SG_VALIDATE_APIP_PIPELINE_VALID_ID: return "sg_apply_pipeline: invalid pipeline id provided";
  9254. case _SG_VALIDATE_APIP_PIPELINE_EXISTS: return "sg_apply_pipeline: pipeline object no longer alive";
  9255. case _SG_VALIDATE_APIP_PIPELINE_VALID: return "sg_apply_pipeline: pipeline object not in valid state";
  9256. case _SG_VALIDATE_APIP_SHADER_EXISTS: return "sg_apply_pipeline: shader object no longer alive";
  9257. case _SG_VALIDATE_APIP_SHADER_VALID: return "sg_apply_pipeline: shader object not in valid state";
  9258. case _SG_VALIDATE_APIP_ATT_COUNT: return "sg_apply_pipeline: color_attachment_count in pipeline doesn't match number of pass color attachments";
  9259. case _SG_VALIDATE_APIP_COLOR_FORMAT: return "sg_apply_pipeline: color_format in pipeline doesn't match pass color attachment pixel format";
  9260. case _SG_VALIDATE_APIP_DEPTH_FORMAT: return "sg_apply_pipeline: depth_format in pipeline doesn't match pass depth attachment pixel format";
  9261. case _SG_VALIDATE_APIP_SAMPLE_COUNT: return "sg_apply_pipeline: MSAA sample count in pipeline doesn't match render pass attachment sample count";
  9262. /* sg_apply_bindings */
  9263. case _SG_VALIDATE_ABND_PIPELINE: return "sg_apply_bindings: must be called after sg_apply_pipeline";
  9264. case _SG_VALIDATE_ABND_PIPELINE_EXISTS: return "sg_apply_bindings: currently applied pipeline object no longer alive";
  9265. case _SG_VALIDATE_ABND_PIPELINE_VALID: return "sg_apply_bindings: currently applied pipeline object not in valid state";
  9266. case _SG_VALIDATE_ABND_VBS: return "sg_apply_bindings: number of vertex buffers doesn't match number of pipeline vertex layouts";
  9267. case _SG_VALIDATE_ABND_VB_EXISTS: return "sg_apply_bindings: vertex buffer no longer alive";
  9268. case _SG_VALIDATE_ABND_VB_TYPE: return "sg_apply_bindings: buffer in vertex buffer slot is not a SG_BUFFERTYPE_VERTEXBUFFER";
  9269. case _SG_VALIDATE_ABND_VB_OVERFLOW: return "sg_apply_bindings: buffer in vertex buffer slot is overflown";
  9270. case _SG_VALIDATE_ABND_NO_IB: return "sg_apply_bindings: pipeline object defines indexed rendering, but no index buffer provided";
  9271. case _SG_VALIDATE_ABND_IB: return "sg_apply_bindings: pipeline object defines non-indexed rendering, but index buffer provided";
  9272. case _SG_VALIDATE_ABND_IB_EXISTS: return "sg_apply_bindings: index buffer no longer alive";
  9273. case _SG_VALIDATE_ABND_IB_TYPE: return "sg_apply_bindings: buffer in index buffer slot is not a SG_BUFFERTYPE_INDEXBUFFER";
  9274. case _SG_VALIDATE_ABND_IB_OVERFLOW: return "sg_apply_bindings: buffer in index buffer slot is overflown";
  9275. case _SG_VALIDATE_ABND_VS_IMGS: return "sg_apply_bindings: vertex shader image count doesn't match sg_shader_desc";
  9276. case _SG_VALIDATE_ABND_VS_IMG_EXISTS: return "sg_apply_bindings: vertex shader image no longer alive";
  9277. case _SG_VALIDATE_ABND_VS_IMG_TYPES: return "sg_apply_bindings: one or more vertex shader image types don't match sg_shader_desc";
  9278. case _SG_VALIDATE_ABND_FS_IMGS: return "sg_apply_bindings: fragment shader image count doesn't match sg_shader_desc";
  9279. case _SG_VALIDATE_ABND_FS_IMG_EXISTS: return "sg_apply_bindings: fragment shader image no longer alive";
  9280. case _SG_VALIDATE_ABND_FS_IMG_TYPES: return "sg_apply_bindings: one or more fragment shader image types don't match sg_shader_desc";
  9281. /* sg_apply_uniforms */
  9282. case _SG_VALIDATE_AUB_NO_PIPELINE: return "sg_apply_uniforms: must be called after sg_apply_pipeline()";
  9283. case _SG_VALIDATE_AUB_NO_UB_AT_SLOT: return "sg_apply_uniforms: no uniform block declaration at this shader stage UB slot";
  9284. case _SG_VALIDATE_AUB_SIZE: return "sg_apply_uniforms: data size exceeds declared uniform block size";
  9285. /* sg_update_buffer */
  9286. case _SG_VALIDATE_UPDATEBUF_USAGE: return "sg_update_buffer: cannot update immutable buffer";
  9287. case _SG_VALIDATE_UPDATEBUF_SIZE: return "sg_update_buffer: update size is bigger than buffer size";
  9288. case _SG_VALIDATE_UPDATEBUF_ONCE: return "sg_update_buffer: only one update allowed per buffer and frame";
  9289. case _SG_VALIDATE_UPDATEBUF_APPEND: return "sg_update_buffer: cannot call sg_update_buffer and sg_append_buffer in same frame";
  9290. /* sg_append_buffer */
  9291. case _SG_VALIDATE_APPENDBUF_USAGE: return "sg_append_buffer: cannot append to immutable buffer";
  9292. case _SG_VALIDATE_APPENDBUF_SIZE: return "sg_append_buffer: overall appended size is bigger than buffer size";
  9293. case _SG_VALIDATE_APPENDBUF_UPDATE: return "sg_append_buffer: cannot call sg_append_buffer and sg_update_buffer in same frame";
  9294. /* sg_update_image */
  9295. case _SG_VALIDATE_UPDIMG_USAGE: return "sg_update_image: cannot update immutable image";
  9296. case _SG_VALIDATE_UPDIMG_NOTENOUGHDATA: return "sg_update_image: not enough subimage data provided";
  9297. case _SG_VALIDATE_UPDIMG_SIZE: return "sg_update_image: provided subimage data size too big";
  9298. case _SG_VALIDATE_UPDIMG_COMPRESSED: return "sg_update_image: cannot update images with compressed format";
  9299. case _SG_VALIDATE_UPDIMG_ONCE: return "sg_update_image: only one update allowed per image and frame";
  9300. default: return "unknown validation error";
  9301. }
  9302. }
  9303. #endif /* defined(SOKOL_DEBUG) */
  9304. /*-- validation checks -------------------------------------------------------*/
  9305. #if defined(SOKOL_DEBUG)
  9306. _SOKOL_PRIVATE void _sg_validate_begin(void) {
  9307. _sg.validate_error = _SG_VALIDATE_SUCCESS;
  9308. }
  9309. _SOKOL_PRIVATE void _sg_validate(bool cond, _sg_validate_error_t err) {
  9310. if (!cond) {
  9311. _sg.validate_error = err;
  9312. SOKOL_LOG(_sg_validate_string(err));
  9313. }
  9314. }
  9315. _SOKOL_PRIVATE bool _sg_validate_end(void) {
  9316. if (_sg.validate_error != _SG_VALIDATE_SUCCESS) {
  9317. #if !defined(SOKOL_VALIDATE_NON_FATAL)
  9318. SOKOL_LOG("^^^^ VALIDATION FAILED, TERMINATING ^^^^");
  9319. SOKOL_ASSERT(false);
  9320. #endif
  9321. return false;
  9322. }
  9323. else {
  9324. return true;
  9325. }
  9326. }
  9327. #endif
  9328. _SOKOL_PRIVATE bool _sg_validate_buffer_desc(const sg_buffer_desc* desc) {
  9329. #if !defined(SOKOL_DEBUG)
  9330. _SOKOL_UNUSED(desc);
  9331. return true;
  9332. #else
  9333. SOKOL_ASSERT(desc);
  9334. SOKOL_VALIDATE_BEGIN();
  9335. SOKOL_VALIDATE(desc->_start_canary == 0, _SG_VALIDATE_BUFFERDESC_CANARY);
  9336. SOKOL_VALIDATE(desc->_end_canary == 0, _SG_VALIDATE_BUFFERDESC_CANARY);
  9337. SOKOL_VALIDATE(desc->size > 0, _SG_VALIDATE_BUFFERDESC_SIZE);
  9338. bool ext = (0 != desc->gl_buffers[0]) || (0 != desc->mtl_buffers[0]) || (0 != desc->d3d11_buffer);
  9339. if (!ext && (desc->usage == SG_USAGE_IMMUTABLE)) {
  9340. SOKOL_VALIDATE(0 != desc->content, _SG_VALIDATE_BUFFERDESC_CONTENT);
  9341. }
  9342. else {
  9343. SOKOL_VALIDATE(0 == desc->content, _SG_VALIDATE_BUFFERDESC_NO_CONTENT);
  9344. }
  9345. return SOKOL_VALIDATE_END();
  9346. #endif
  9347. }
  9348. _SOKOL_PRIVATE bool _sg_validate_image_desc(const sg_image_desc* desc) {
  9349. #if !defined(SOKOL_DEBUG)
  9350. _SOKOL_UNUSED(desc);
  9351. return true;
  9352. #else
  9353. SOKOL_ASSERT(desc);
  9354. SOKOL_VALIDATE_BEGIN();
  9355. SOKOL_VALIDATE(desc->_start_canary == 0, _SG_VALIDATE_IMAGEDESC_CANARY);
  9356. SOKOL_VALIDATE(desc->_end_canary == 0, _SG_VALIDATE_IMAGEDESC_CANARY);
  9357. SOKOL_VALIDATE(desc->width > 0, _SG_VALIDATE_IMAGEDESC_WIDTH);
  9358. SOKOL_VALIDATE(desc->height > 0, _SG_VALIDATE_IMAGEDESC_HEIGHT);
  9359. const sg_pixel_format fmt = desc->pixel_format;
  9360. const sg_usage usage = desc->usage;
  9361. const bool ext = (0 != desc->gl_textures[0]) || (0 != desc->mtl_textures[0]) || (0 != desc->d3d11_texture);
  9362. if (desc->render_target) {
  9363. SOKOL_ASSERT(((int)fmt >= 0) && ((int)fmt < _SG_PIXELFORMAT_NUM));
  9364. SOKOL_VALIDATE(_sg.formats[fmt].render, _SG_VALIDATE_IMAGEDESC_RT_PIXELFORMAT);
  9365. /* on GLES2, sample count for render targets is completely ignored */
  9366. #if defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
  9367. if (!_sg.gl.gles2) {
  9368. #endif
  9369. if (desc->sample_count > 1) {
  9370. SOKOL_VALIDATE(_sg.features.msaa_render_targets && _sg.formats[fmt].msaa, _SG_VALIDATE_IMAGEDESC_NO_MSAA_RT_SUPPORT);
  9371. }
  9372. #if defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
  9373. }
  9374. #endif
  9375. SOKOL_VALIDATE(usage == SG_USAGE_IMMUTABLE, _SG_VALIDATE_IMAGEDESC_RT_IMMUTABLE);
  9376. SOKOL_VALIDATE(desc->content.subimage[0][0].ptr==0, _SG_VALIDATE_IMAGEDESC_RT_NO_CONTENT);
  9377. }
  9378. else {
  9379. SOKOL_VALIDATE(desc->sample_count <= 1, _SG_VALIDATE_IMAGEDESC_MSAA_BUT_NO_RT);
  9380. const bool valid_nonrt_fmt = !_sg_is_valid_rendertarget_depth_format(fmt);
  9381. SOKOL_VALIDATE(valid_nonrt_fmt, _SG_VALIDATE_IMAGEDESC_NONRT_PIXELFORMAT);
  9382. /* FIXME: should use the same "expected size" computation as in _sg_validate_update_image() here */
  9383. if (!ext && (usage == SG_USAGE_IMMUTABLE)) {
  9384. const int num_faces = desc->type == SG_IMAGETYPE_CUBE ? 6:1;
  9385. const int num_mips = desc->num_mipmaps;
  9386. for (int face_index = 0; face_index < num_faces; face_index++) {
  9387. for (int mip_index = 0; mip_index < num_mips; mip_index++) {
  9388. const bool has_data = desc->content.subimage[face_index][mip_index].ptr != 0;
  9389. const bool has_size = desc->content.subimage[face_index][mip_index].size > 0;
  9390. SOKOL_VALIDATE(has_data && has_size, _SG_VALIDATE_IMAGEDESC_CONTENT);
  9391. }
  9392. }
  9393. }
  9394. else {
  9395. for (int face_index = 0; face_index < SG_CUBEFACE_NUM; face_index++) {
  9396. for (int mip_index = 0; mip_index < SG_MAX_MIPMAPS; mip_index++) {
  9397. const bool no_data = 0 == desc->content.subimage[face_index][mip_index].ptr;
  9398. const bool no_size = 0 == desc->content.subimage[face_index][mip_index].size;
  9399. SOKOL_VALIDATE(no_data && no_size, _SG_VALIDATE_IMAGEDESC_NO_CONTENT);
  9400. }
  9401. }
  9402. }
  9403. }
  9404. return SOKOL_VALIDATE_END();
  9405. #endif
  9406. }
  9407. _SOKOL_PRIVATE bool _sg_validate_shader_desc(const sg_shader_desc* desc) {
  9408. #if !defined(SOKOL_DEBUG)
  9409. _SOKOL_UNUSED(desc);
  9410. return true;
  9411. #else
  9412. SOKOL_ASSERT(desc);
  9413. SOKOL_VALIDATE_BEGIN();
  9414. SOKOL_VALIDATE(desc->_start_canary == 0, _SG_VALIDATE_SHADERDESC_CANARY);
  9415. SOKOL_VALIDATE(desc->_end_canary == 0, _SG_VALIDATE_SHADERDESC_CANARY);
  9416. #if defined(SOKOL_GLES2)
  9417. SOKOL_VALIDATE(0 != desc->attrs[0].name, _SG_VALIDATE_SHADERDESC_ATTR_NAMES);
  9418. #elif defined(SOKOL_D3D11)
  9419. SOKOL_VALIDATE(0 != desc->attrs[0].sem_name, _SG_VALIDATE_SHADERDESC_ATTR_SEMANTICS);
  9420. #endif
  9421. #if defined(SOKOL_GLCORE33) || defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
  9422. /* on GL, must provide shader source code */
  9423. SOKOL_VALIDATE(0 != desc->vs.source, _SG_VALIDATE_SHADERDESC_SOURCE);
  9424. SOKOL_VALIDATE(0 != desc->fs.source, _SG_VALIDATE_SHADERDESC_SOURCE);
  9425. #elif defined(SOKOL_METAL) || defined(SOKOL_D3D11)
  9426. /* on Metal or D3D11, must provide shader source code or byte code */
  9427. SOKOL_VALIDATE((0 != desc->vs.source)||(0 != desc->vs.byte_code), _SG_VALIDATE_SHADERDESC_SOURCE_OR_BYTECODE);
  9428. SOKOL_VALIDATE((0 != desc->fs.source)||(0 != desc->fs.byte_code), _SG_VALIDATE_SHADERDESC_SOURCE_OR_BYTECODE);
  9429. #else
  9430. /* Dummy Backend, don't require source or bytecode */
  9431. #endif
  9432. for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
  9433. if (desc->attrs[i].name) {
  9434. SOKOL_VALIDATE(strlen(desc->attrs[i].name) < _SG_STRING_SIZE, _SG_VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG);
  9435. }
  9436. if (desc->attrs[i].sem_name) {
  9437. SOKOL_VALIDATE(strlen(desc->attrs[i].sem_name) < _SG_STRING_SIZE, _SG_VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG);
  9438. }
  9439. }
  9440. /* if shader byte code, the size must also be provided */
  9441. if (0 != desc->vs.byte_code) {
  9442. SOKOL_VALIDATE(desc->vs.byte_code_size > 0, _SG_VALIDATE_SHADERDESC_NO_BYTECODE_SIZE);
  9443. }
  9444. if (0 != desc->fs.byte_code) {
  9445. SOKOL_VALIDATE(desc->fs.byte_code_size > 0, _SG_VALIDATE_SHADERDESC_NO_BYTECODE_SIZE);
  9446. }
  9447. for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {
  9448. const sg_shader_stage_desc* stage_desc = (stage_index == 0)? &desc->vs : &desc->fs;
  9449. bool uniform_blocks_continuous = true;
  9450. for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {
  9451. const sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_index];
  9452. if (ub_desc->size > 0) {
  9453. SOKOL_VALIDATE(uniform_blocks_continuous, _SG_VALIDATE_SHADERDESC_NO_CONT_UBS);
  9454. bool uniforms_continuous = true;
  9455. int uniform_offset = 0;
  9456. int num_uniforms = 0;
  9457. for (int u_index = 0; u_index < SG_MAX_UB_MEMBERS; u_index++) {
  9458. const sg_shader_uniform_desc* u_desc = &ub_desc->uniforms[u_index];
  9459. if (u_desc->type != SG_UNIFORMTYPE_INVALID) {
  9460. SOKOL_VALIDATE(uniforms_continuous, _SG_VALIDATE_SHADERDESC_NO_CONT_UB_MEMBERS);
  9461. #if defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
  9462. SOKOL_VALIDATE(u_desc->name, _SG_VALIDATE_SHADERDESC_UB_MEMBER_NAME);
  9463. #endif
  9464. const int array_count = u_desc->array_count;
  9465. uniform_offset += _sg_uniform_size(u_desc->type, array_count);
  9466. num_uniforms++;
  9467. }
  9468. else {
  9469. uniforms_continuous = false;
  9470. }
  9471. }
  9472. #if defined(SOKOL_GLCORE33) || defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
  9473. SOKOL_VALIDATE(uniform_offset == ub_desc->size, _SG_VALIDATE_SHADERDESC_UB_SIZE_MISMATCH);
  9474. SOKOL_VALIDATE(num_uniforms > 0, _SG_VALIDATE_SHADERDESC_NO_UB_MEMBERS);
  9475. #endif
  9476. }
  9477. else {
  9478. uniform_blocks_continuous = false;
  9479. }
  9480. }
  9481. bool images_continuous = true;
  9482. for (int img_index = 0; img_index < SG_MAX_SHADERSTAGE_IMAGES; img_index++) {
  9483. const sg_shader_image_desc* img_desc = &stage_desc->images[img_index];
  9484. if (img_desc->type != _SG_IMAGETYPE_DEFAULT) {
  9485. SOKOL_VALIDATE(images_continuous, _SG_VALIDATE_SHADERDESC_NO_CONT_IMGS);
  9486. #if defined(SOKOL_GLES2)
  9487. SOKOL_VALIDATE(img_desc->name, _SG_VALIDATE_SHADERDESC_IMG_NAME);
  9488. #endif
  9489. }
  9490. else {
  9491. images_continuous = false;
  9492. }
  9493. }
  9494. }
  9495. return SOKOL_VALIDATE_END();
  9496. #endif
  9497. }
  9498. _SOKOL_PRIVATE bool _sg_validate_pipeline_desc(const sg_pipeline_desc* desc) {
  9499. #if !defined(SOKOL_DEBUG)
  9500. _SOKOL_UNUSED(desc);
  9501. return true;
  9502. #else
  9503. SOKOL_ASSERT(desc);
  9504. SOKOL_VALIDATE_BEGIN();
  9505. SOKOL_VALIDATE(desc->_start_canary == 0, _SG_VALIDATE_PIPELINEDESC_CANARY);
  9506. SOKOL_VALIDATE(desc->_end_canary == 0, _SG_VALIDATE_PIPELINEDESC_CANARY);
  9507. SOKOL_VALIDATE(desc->shader.id != SG_INVALID_ID, _SG_VALIDATE_PIPELINEDESC_SHADER);
  9508. const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, desc->shader.id);
  9509. SOKOL_VALIDATE(shd && shd->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_PIPELINEDESC_SHADER);
  9510. for (int buf_index = 0; buf_index < SG_MAX_SHADERSTAGE_BUFFERS; buf_index++) {
  9511. const sg_buffer_layout_desc* l_desc = &desc->layout.buffers[buf_index];
  9512. if (l_desc->stride == 0) {
  9513. continue;
  9514. }
  9515. SOKOL_VALIDATE((l_desc->stride & 3) == 0, _SG_VALIDATE_PIPELINEDESC_LAYOUT_STRIDE4);
  9516. }
  9517. SOKOL_VALIDATE(desc->layout.attrs[0].format != SG_VERTEXFORMAT_INVALID, _SG_VALIDATE_PIPELINEDESC_NO_ATTRS);
  9518. bool attrs_cont = true;
  9519. for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
  9520. const sg_vertex_attr_desc* a_desc = &desc->layout.attrs[attr_index];
  9521. if (a_desc->format == SG_VERTEXFORMAT_INVALID) {
  9522. attrs_cont = false;
  9523. continue;
  9524. }
  9525. SOKOL_VALIDATE(attrs_cont, _SG_VALIDATE_PIPELINEDESC_NO_ATTRS);
  9526. SOKOL_ASSERT(a_desc->buffer_index < SG_MAX_SHADERSTAGE_BUFFERS);
  9527. #if defined(SOKOL_GLES2)
  9528. /* on GLES2, vertex attribute names must be provided */
  9529. SOKOL_VALIDATE(!_sg_strempty(&shd->gl.attrs[attr_index].name), _SG_VALIDATE_PIPELINEDESC_ATTR_NAME);
  9530. #elif defined(SOKOL_D3D11)
  9531. /* on D3D11, semantic names (and semantic indices) must be provided */
  9532. SOKOL_VALIDATE(!_sg_strempty(&shd->d3d11.attrs[attr_index].sem_name), _SG_VALIDATE_PIPELINEDESC_ATTR_SEMANTICS);
  9533. #endif
  9534. }
  9535. return SOKOL_VALIDATE_END();
  9536. #endif
  9537. }
  9538. _SOKOL_PRIVATE bool _sg_validate_pass_desc(const sg_pass_desc* desc) {
  9539. #if !defined(SOKOL_DEBUG)
  9540. _SOKOL_UNUSED(desc);
  9541. return true;
  9542. #else
  9543. SOKOL_ASSERT(desc);
  9544. SOKOL_VALIDATE_BEGIN();
  9545. SOKOL_VALIDATE(desc->_start_canary == 0, _SG_VALIDATE_PASSDESC_CANARY);
  9546. SOKOL_VALIDATE(desc->_end_canary == 0, _SG_VALIDATE_PASSDESC_CANARY);
  9547. bool atts_cont = true;
  9548. sg_pixel_format color_fmt = SG_PIXELFORMAT_NONE;
  9549. int width = -1, height = -1, sample_count = -1;
  9550. for (int att_index = 0; att_index < SG_MAX_COLOR_ATTACHMENTS; att_index++) {
  9551. const sg_attachment_desc* att = &desc->color_attachments[att_index];
  9552. if (att->image.id == SG_INVALID_ID) {
  9553. SOKOL_VALIDATE(att_index > 0, _SG_VALIDATE_PASSDESC_NO_COLOR_ATTS);
  9554. atts_cont = false;
  9555. continue;
  9556. }
  9557. SOKOL_VALIDATE(atts_cont, _SG_VALIDATE_PASSDESC_NO_CONT_COLOR_ATTS);
  9558. const _sg_image_t* img = _sg_lookup_image(&_sg.pools, att->image.id);
  9559. SOKOL_VALIDATE(img && img->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_PASSDESC_IMAGE);
  9560. SOKOL_VALIDATE(att->mip_level < img->cmn.num_mipmaps, _SG_VALIDATE_PASSDESC_MIPLEVEL);
  9561. if (img->cmn.type == SG_IMAGETYPE_CUBE) {
  9562. SOKOL_VALIDATE(att->face < 6, _SG_VALIDATE_PASSDESC_FACE);
  9563. }
  9564. else if (img->cmn.type == SG_IMAGETYPE_ARRAY) {
  9565. SOKOL_VALIDATE(att->layer < img->cmn.depth, _SG_VALIDATE_PASSDESC_LAYER);
  9566. }
  9567. else if (img->cmn.type == SG_IMAGETYPE_3D) {
  9568. SOKOL_VALIDATE(att->slice < img->cmn.depth, _SG_VALIDATE_PASSDESC_SLICE);
  9569. }
  9570. SOKOL_VALIDATE(img->cmn.render_target, _SG_VALIDATE_PASSDESC_IMAGE_NO_RT);
  9571. if (att_index == 0) {
  9572. color_fmt = img->cmn.pixel_format;
  9573. width = img->cmn.width >> att->mip_level;
  9574. height = img->cmn.height >> att->mip_level;
  9575. sample_count = img->cmn.sample_count;
  9576. }
  9577. else {
  9578. SOKOL_VALIDATE(img->cmn.pixel_format == color_fmt, _SG_VALIDATE_PASSDESC_COLOR_PIXELFORMATS);
  9579. SOKOL_VALIDATE(width == img->cmn.width >> att->mip_level, _SG_VALIDATE_PASSDESC_IMAGE_SIZES);
  9580. SOKOL_VALIDATE(height == img->cmn.height >> att->mip_level, _SG_VALIDATE_PASSDESC_IMAGE_SIZES);
  9581. SOKOL_VALIDATE(sample_count == img->cmn.sample_count, _SG_VALIDATE_PASSDESC_IMAGE_SAMPLE_COUNTS);
  9582. }
  9583. SOKOL_VALIDATE(_sg_is_valid_rendertarget_color_format(img->cmn.pixel_format), _SG_VALIDATE_PASSDESC_COLOR_INV_PIXELFORMAT);
  9584. }
  9585. if (desc->depth_stencil_attachment.image.id != SG_INVALID_ID) {
  9586. const sg_attachment_desc* att = &desc->depth_stencil_attachment;
  9587. const _sg_image_t* img = _sg_lookup_image(&_sg.pools, att->image.id);
  9588. SOKOL_VALIDATE(img && img->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_PASSDESC_IMAGE);
  9589. SOKOL_VALIDATE(att->mip_level < img->cmn.num_mipmaps, _SG_VALIDATE_PASSDESC_MIPLEVEL);
  9590. if (img->cmn.type == SG_IMAGETYPE_CUBE) {
  9591. SOKOL_VALIDATE(att->face < 6, _SG_VALIDATE_PASSDESC_FACE);
  9592. }
  9593. else if (img->cmn.type == SG_IMAGETYPE_ARRAY) {
  9594. SOKOL_VALIDATE(att->layer < img->cmn.depth, _SG_VALIDATE_PASSDESC_LAYER);
  9595. }
  9596. else if (img->cmn.type == SG_IMAGETYPE_3D) {
  9597. SOKOL_VALIDATE(att->slice < img->cmn.depth, _SG_VALIDATE_PASSDESC_SLICE);
  9598. }
  9599. SOKOL_VALIDATE(img->cmn.render_target, _SG_VALIDATE_PASSDESC_IMAGE_NO_RT);
  9600. SOKOL_VALIDATE(width == img->cmn.width >> att->mip_level, _SG_VALIDATE_PASSDESC_IMAGE_SIZES);
  9601. SOKOL_VALIDATE(height == img->cmn.height >> att->mip_level, _SG_VALIDATE_PASSDESC_IMAGE_SIZES);
  9602. SOKOL_VALIDATE(sample_count == img->cmn.sample_count, _SG_VALIDATE_PASSDESC_IMAGE_SAMPLE_COUNTS);
  9603. SOKOL_VALIDATE(_sg_is_valid_rendertarget_depth_format(img->cmn.pixel_format), _SG_VALIDATE_PASSDESC_DEPTH_INV_PIXELFORMAT);
  9604. }
  9605. return SOKOL_VALIDATE_END();
  9606. #endif
  9607. }
  9608. _SOKOL_PRIVATE bool _sg_validate_begin_pass(_sg_pass_t* pass) {
  9609. #if !defined(SOKOL_DEBUG)
  9610. _SOKOL_UNUSED(pass);
  9611. return true;
  9612. #else
  9613. SOKOL_VALIDATE_BEGIN();
  9614. SOKOL_VALIDATE(pass->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_BEGINPASS_PASS);
  9615. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  9616. const _sg_attachment_t* att = &pass->cmn.color_atts[i];
  9617. const _sg_image_t* img = _sg_pass_color_image(pass, i);
  9618. if (img) {
  9619. SOKOL_VALIDATE(img->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_BEGINPASS_IMAGE);
  9620. SOKOL_VALIDATE(img->slot.id == att->image_id.id, _SG_VALIDATE_BEGINPASS_IMAGE);
  9621. }
  9622. }
  9623. const _sg_image_t* ds_img = _sg_pass_ds_image(pass);
  9624. if (ds_img) {
  9625. const _sg_attachment_t* att = &pass->cmn.ds_att;
  9626. SOKOL_VALIDATE(ds_img->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_BEGINPASS_IMAGE);
  9627. SOKOL_VALIDATE(ds_img->slot.id == att->image_id.id, _SG_VALIDATE_BEGINPASS_IMAGE);
  9628. }
  9629. return SOKOL_VALIDATE_END();
  9630. #endif
  9631. }
  9632. _SOKOL_PRIVATE bool _sg_validate_apply_pipeline(sg_pipeline pip_id) {
  9633. #if !defined(SOKOL_DEBUG)
  9634. _SOKOL_UNUSED(pip_id);
  9635. return true;
  9636. #else
  9637. SOKOL_VALIDATE_BEGIN();
  9638. /* the pipeline object must be alive and valid */
  9639. SOKOL_VALIDATE(pip_id.id != SG_INVALID_ID, _SG_VALIDATE_APIP_PIPELINE_VALID_ID);
  9640. const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);
  9641. SOKOL_VALIDATE(pip != 0, _SG_VALIDATE_APIP_PIPELINE_EXISTS);
  9642. if (!pip) {
  9643. return SOKOL_VALIDATE_END();
  9644. }
  9645. SOKOL_VALIDATE(pip->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_APIP_PIPELINE_VALID);
  9646. /* the pipeline's shader must be alive and valid */
  9647. SOKOL_ASSERT(pip->shader);
  9648. SOKOL_VALIDATE(pip->shader->slot.id == pip->cmn.shader_id.id, _SG_VALIDATE_APIP_SHADER_EXISTS);
  9649. SOKOL_VALIDATE(pip->shader->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_APIP_SHADER_VALID);
  9650. /* check that pipeline attributes match current pass attributes */
  9651. const _sg_pass_t* pass = _sg_lookup_pass(&_sg.pools, _sg.cur_pass.id);
  9652. if (pass) {
  9653. /* an offscreen pass */
  9654. const _sg_image_t* att_img = _sg_pass_color_image(pass, 0);
  9655. SOKOL_VALIDATE(pip->cmn.color_attachment_count == pass->cmn.num_color_atts, _SG_VALIDATE_APIP_ATT_COUNT);
  9656. SOKOL_VALIDATE(pip->cmn.color_format == att_img->cmn.pixel_format, _SG_VALIDATE_APIP_COLOR_FORMAT);
  9657. SOKOL_VALIDATE(pip->cmn.sample_count == att_img->cmn.sample_count, _SG_VALIDATE_APIP_SAMPLE_COUNT);
  9658. const _sg_image_t* att_dsimg = _sg_pass_ds_image(pass);
  9659. if (att_dsimg) {
  9660. SOKOL_VALIDATE(pip->cmn.depth_format == att_dsimg->cmn.pixel_format, _SG_VALIDATE_APIP_DEPTH_FORMAT);
  9661. }
  9662. else {
  9663. SOKOL_VALIDATE(pip->cmn.depth_format == SG_PIXELFORMAT_NONE, _SG_VALIDATE_APIP_DEPTH_FORMAT);
  9664. }
  9665. }
  9666. else {
  9667. /* default pass */
  9668. SOKOL_VALIDATE(pip->cmn.color_attachment_count == 1, _SG_VALIDATE_APIP_ATT_COUNT);
  9669. SOKOL_VALIDATE(pip->cmn.color_format == _sg_default_rendertarget_colorformat(), _SG_VALIDATE_APIP_COLOR_FORMAT);
  9670. SOKOL_VALIDATE(pip->cmn.depth_format == _sg_default_rendertarget_depthformat(), _SG_VALIDATE_APIP_DEPTH_FORMAT);
  9671. /* FIXME: hmm, we don't know if the default framebuffer is multisampled here */
  9672. }
  9673. return SOKOL_VALIDATE_END();
  9674. #endif
  9675. }
  9676. _SOKOL_PRIVATE bool _sg_validate_apply_bindings(const sg_bindings* bindings) {
  9677. #if !defined(SOKOL_DEBUG)
  9678. _SOKOL_UNUSED(bindings);
  9679. return true;
  9680. #else
  9681. SOKOL_VALIDATE_BEGIN();
  9682. /* a pipeline object must have been applied */
  9683. SOKOL_VALIDATE(_sg.cur_pipeline.id != SG_INVALID_ID, _SG_VALIDATE_ABND_PIPELINE);
  9684. const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, _sg.cur_pipeline.id);
  9685. SOKOL_VALIDATE(pip != 0, _SG_VALIDATE_ABND_PIPELINE_EXISTS);
  9686. if (!pip) {
  9687. return SOKOL_VALIDATE_END();
  9688. }
  9689. SOKOL_VALIDATE(pip->slot.state == SG_RESOURCESTATE_VALID, _SG_VALIDATE_ABND_PIPELINE_VALID);
  9690. SOKOL_ASSERT(pip->shader);
  9691. /* has expected vertex buffers, and vertex buffers still exist */
  9692. for (int i = 0; i < SG_MAX_SHADERSTAGE_BUFFERS; i++) {
  9693. if (bindings->vertex_buffers[i].id != SG_INVALID_ID) {
  9694. SOKOL_VALIDATE(pip->cmn.vertex_layout_valid[i], _SG_VALIDATE_ABND_VBS);
  9695. /* buffers in vertex-buffer-slots must be of type SG_BUFFERTYPE_VERTEXBUFFER */
  9696. const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, bindings->vertex_buffers[i].id);
  9697. SOKOL_VALIDATE(buf != 0, _SG_VALIDATE_ABND_VB_EXISTS);
  9698. if (buf && buf->slot.state == SG_RESOURCESTATE_VALID) {
  9699. SOKOL_VALIDATE(SG_BUFFERTYPE_VERTEXBUFFER == buf->cmn.type, _SG_VALIDATE_ABND_VB_TYPE);
  9700. SOKOL_VALIDATE(!buf->cmn.append_overflow, _SG_VALIDATE_ABND_VB_OVERFLOW);
  9701. }
  9702. }
  9703. else {
  9704. /* vertex buffer provided in a slot which has no vertex layout in pipeline */
  9705. SOKOL_VALIDATE(!pip->cmn.vertex_layout_valid[i], _SG_VALIDATE_ABND_VBS);
  9706. }
  9707. }
  9708. /* index buffer expected or not, and index buffer still exists */
  9709. if (pip->cmn.index_type == SG_INDEXTYPE_NONE) {
  9710. /* pipeline defines non-indexed rendering, but index buffer provided */
  9711. SOKOL_VALIDATE(bindings->index_buffer.id == SG_INVALID_ID, _SG_VALIDATE_ABND_IB);
  9712. }
  9713. else {
  9714. /* pipeline defines indexed rendering, but no index buffer provided */
  9715. SOKOL_VALIDATE(bindings->index_buffer.id != SG_INVALID_ID, _SG_VALIDATE_ABND_NO_IB);
  9716. }
  9717. if (bindings->index_buffer.id != SG_INVALID_ID) {
  9718. /* buffer in index-buffer-slot must be of type SG_BUFFERTYPE_INDEXBUFFER */
  9719. const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, bindings->index_buffer.id);
  9720. SOKOL_VALIDATE(buf != 0, _SG_VALIDATE_ABND_IB_EXISTS);
  9721. if (buf && buf->slot.state == SG_RESOURCESTATE_VALID) {
  9722. SOKOL_VALIDATE(SG_BUFFERTYPE_INDEXBUFFER == buf->cmn.type, _SG_VALIDATE_ABND_IB_TYPE);
  9723. SOKOL_VALIDATE(!buf->cmn.append_overflow, _SG_VALIDATE_ABND_IB_OVERFLOW);
  9724. }
  9725. }
  9726. /* has expected vertex shader images */
  9727. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  9728. _sg_shader_stage_t* stage = &pip->shader->cmn.stage[SG_SHADERSTAGE_VS];
  9729. if (bindings->vs_images[i].id != SG_INVALID_ID) {
  9730. SOKOL_VALIDATE(i < stage->num_images, _SG_VALIDATE_ABND_VS_IMGS);
  9731. const _sg_image_t* img = _sg_lookup_image(&_sg.pools, bindings->vs_images[i].id);
  9732. SOKOL_VALIDATE(img != 0, _SG_VALIDATE_ABND_VS_IMG_EXISTS);
  9733. if (img && img->slot.state == SG_RESOURCESTATE_VALID) {
  9734. SOKOL_VALIDATE(img->cmn.type == stage->images[i].type, _SG_VALIDATE_ABND_VS_IMG_TYPES);
  9735. }
  9736. }
  9737. else {
  9738. SOKOL_VALIDATE(i >= stage->num_images, _SG_VALIDATE_ABND_VS_IMGS);
  9739. }
  9740. }
  9741. /* has expected fragment shader images */
  9742. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  9743. _sg_shader_stage_t* stage = &pip->shader->cmn.stage[SG_SHADERSTAGE_FS];
  9744. if (bindings->fs_images[i].id != SG_INVALID_ID) {
  9745. SOKOL_VALIDATE(i < stage->num_images, _SG_VALIDATE_ABND_FS_IMGS);
  9746. const _sg_image_t* img = _sg_lookup_image(&_sg.pools, bindings->fs_images[i].id);
  9747. SOKOL_VALIDATE(img != 0, _SG_VALIDATE_ABND_FS_IMG_EXISTS);
  9748. if (img && img->slot.state == SG_RESOURCESTATE_VALID) {
  9749. SOKOL_VALIDATE(img->cmn.type == stage->images[i].type, _SG_VALIDATE_ABND_FS_IMG_TYPES);
  9750. }
  9751. }
  9752. else {
  9753. SOKOL_VALIDATE(i >= stage->num_images, _SG_VALIDATE_ABND_FS_IMGS);
  9754. }
  9755. }
  9756. return SOKOL_VALIDATE_END();
  9757. #endif
  9758. }
  9759. _SOKOL_PRIVATE bool _sg_validate_apply_uniforms(sg_shader_stage stage_index, int ub_index, const void* data, int num_bytes) {
  9760. _SOKOL_UNUSED(data);
  9761. #if !defined(SOKOL_DEBUG)
  9762. _SOKOL_UNUSED(stage_index);
  9763. _SOKOL_UNUSED(ub_index);
  9764. _SOKOL_UNUSED(num_bytes);
  9765. return true;
  9766. #else
  9767. SOKOL_ASSERT((stage_index == SG_SHADERSTAGE_VS) || (stage_index == SG_SHADERSTAGE_FS));
  9768. SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS));
  9769. SOKOL_VALIDATE_BEGIN();
  9770. SOKOL_VALIDATE(_sg.cur_pipeline.id != SG_INVALID_ID, _SG_VALIDATE_AUB_NO_PIPELINE);
  9771. const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, _sg.cur_pipeline.id);
  9772. SOKOL_ASSERT(pip && (pip->slot.id == _sg.cur_pipeline.id));
  9773. SOKOL_ASSERT(pip->shader && (pip->shader->slot.id == pip->cmn.shader_id.id));
  9774. /* check that there is a uniform block at 'stage' and 'ub_index' */
  9775. const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[stage_index];
  9776. SOKOL_VALIDATE(ub_index < stage->num_uniform_blocks, _SG_VALIDATE_AUB_NO_UB_AT_SLOT);
  9777. /* check that the provided data size doesn't exceed the uniform block size */
  9778. SOKOL_VALIDATE(num_bytes <= stage->uniform_blocks[ub_index].size, _SG_VALIDATE_AUB_SIZE);
  9779. return SOKOL_VALIDATE_END();
  9780. #endif
  9781. }
  9782. _SOKOL_PRIVATE bool _sg_validate_update_buffer(const _sg_buffer_t* buf, const void* data, int size) {
  9783. #if !defined(SOKOL_DEBUG)
  9784. _SOKOL_UNUSED(buf);
  9785. _SOKOL_UNUSED(data);
  9786. _SOKOL_UNUSED(size);
  9787. return true;
  9788. #else
  9789. SOKOL_ASSERT(buf && data);
  9790. SOKOL_VALIDATE_BEGIN();
  9791. SOKOL_VALIDATE(buf->cmn.usage != SG_USAGE_IMMUTABLE, _SG_VALIDATE_UPDATEBUF_USAGE);
  9792. SOKOL_VALIDATE(buf->cmn.size >= size, _SG_VALIDATE_UPDATEBUF_SIZE);
  9793. SOKOL_VALIDATE(buf->cmn.update_frame_index != _sg.frame_index, _SG_VALIDATE_UPDATEBUF_ONCE);
  9794. SOKOL_VALIDATE(buf->cmn.append_frame_index != _sg.frame_index, _SG_VALIDATE_UPDATEBUF_APPEND);
  9795. return SOKOL_VALIDATE_END();
  9796. #endif
  9797. }
  9798. _SOKOL_PRIVATE bool _sg_validate_append_buffer(const _sg_buffer_t* buf, const void* data, int size) {
  9799. #if !defined(SOKOL_DEBUG)
  9800. _SOKOL_UNUSED(buf);
  9801. _SOKOL_UNUSED(data);
  9802. _SOKOL_UNUSED(size);
  9803. return true;
  9804. #else
  9805. SOKOL_ASSERT(buf && data);
  9806. SOKOL_VALIDATE_BEGIN();
  9807. SOKOL_VALIDATE(buf->cmn.usage != SG_USAGE_IMMUTABLE, _SG_VALIDATE_APPENDBUF_USAGE);
  9808. SOKOL_VALIDATE(buf->cmn.size >= (buf->cmn.append_pos+size), _SG_VALIDATE_APPENDBUF_SIZE);
  9809. SOKOL_VALIDATE(buf->cmn.update_frame_index != _sg.frame_index, _SG_VALIDATE_APPENDBUF_UPDATE);
  9810. return SOKOL_VALIDATE_END();
  9811. #endif
  9812. }
  9813. _SOKOL_PRIVATE bool _sg_validate_update_image(const _sg_image_t* img, const sg_image_content* data) {
  9814. #if !defined(SOKOL_DEBUG)
  9815. _SOKOL_UNUSED(img);
  9816. _SOKOL_UNUSED(data);
  9817. return true;
  9818. #else
  9819. SOKOL_ASSERT(img && data);
  9820. SOKOL_VALIDATE_BEGIN();
  9821. SOKOL_VALIDATE(img->cmn.usage != SG_USAGE_IMMUTABLE, _SG_VALIDATE_UPDIMG_USAGE);
  9822. SOKOL_VALIDATE(img->cmn.upd_frame_index != _sg.frame_index, _SG_VALIDATE_UPDIMG_ONCE);
  9823. SOKOL_VALIDATE(!_sg_is_compressed_pixel_format(img->cmn.pixel_format), _SG_VALIDATE_UPDIMG_COMPRESSED);
  9824. const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6 : 1;
  9825. const int num_mips = img->cmn.num_mipmaps;
  9826. for (int face_index = 0; face_index < num_faces; face_index++) {
  9827. for (int mip_index = 0; mip_index < num_mips; mip_index++) {
  9828. SOKOL_VALIDATE(0 != data->subimage[face_index][mip_index].ptr, _SG_VALIDATE_UPDIMG_NOTENOUGHDATA);
  9829. const int mip_width = _sg_max(img->cmn.width >> mip_index, 1);
  9830. const int mip_height = _sg_max(img->cmn.height >> mip_index, 1);
  9831. const int bytes_per_slice = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height);
  9832. const int expected_size = bytes_per_slice * img->cmn.depth;
  9833. SOKOL_VALIDATE(data->subimage[face_index][mip_index].size <= expected_size, _SG_VALIDATE_UPDIMG_SIZE);
  9834. }
  9835. }
  9836. return SOKOL_VALIDATE_END();
  9837. #endif
  9838. }
  9839. /*== fill in desc default values =============================================*/
  9840. _SOKOL_PRIVATE sg_buffer_desc _sg_buffer_desc_defaults(const sg_buffer_desc* desc) {
  9841. sg_buffer_desc def = *desc;
  9842. def.type = _sg_def(def.type, SG_BUFFERTYPE_VERTEXBUFFER);
  9843. def.usage = _sg_def(def.usage, SG_USAGE_IMMUTABLE);
  9844. return def;
  9845. }
  9846. _SOKOL_PRIVATE sg_image_desc _sg_image_desc_defaults(const sg_image_desc* desc) {
  9847. sg_image_desc def = *desc;
  9848. def.type = _sg_def(def.type, SG_IMAGETYPE_2D);
  9849. def.depth = _sg_def(def.depth, 1);
  9850. def.num_mipmaps = _sg_def(def.num_mipmaps, 1);
  9851. def.usage = _sg_def(def.usage, SG_USAGE_IMMUTABLE);
  9852. if (desc->render_target) {
  9853. def.pixel_format = _sg_def(def.pixel_format, _sg_default_rendertarget_colorformat());
  9854. }
  9855. else {
  9856. def.pixel_format = _sg_def(def.pixel_format, SG_PIXELFORMAT_RGBA8);
  9857. }
  9858. def.sample_count = _sg_def(def.sample_count, 1);
  9859. def.min_filter = _sg_def(def.min_filter, SG_FILTER_NEAREST);
  9860. def.mag_filter = _sg_def(def.mag_filter, SG_FILTER_NEAREST);
  9861. def.wrap_u = _sg_def(def.wrap_u, SG_WRAP_REPEAT);
  9862. def.wrap_v = _sg_def(def.wrap_v, SG_WRAP_REPEAT);
  9863. def.wrap_w = _sg_def(def.wrap_w, SG_WRAP_REPEAT);
  9864. def.border_color = _sg_def(def.border_color, SG_BORDERCOLOR_OPAQUE_BLACK);
  9865. def.max_anisotropy = _sg_def(def.max_anisotropy, 1);
  9866. def.max_lod = _sg_def_flt(def.max_lod, FLT_MAX);
  9867. return def;
  9868. }
  9869. _SOKOL_PRIVATE sg_shader_desc _sg_shader_desc_defaults(const sg_shader_desc* desc) {
  9870. sg_shader_desc def = *desc;
  9871. #if defined(SOKOL_METAL)
  9872. def.vs.entry = _sg_def(def.vs.entry, "_main");
  9873. def.fs.entry = _sg_def(def.fs.entry, "_main");
  9874. #else
  9875. def.vs.entry = _sg_def(def.vs.entry, "main");
  9876. def.fs.entry = _sg_def(def.fs.entry, "main");
  9877. #endif
  9878. for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {
  9879. sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS)? &def.vs : &def.fs;
  9880. for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {
  9881. sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_index];
  9882. if (0 == ub_desc->size) {
  9883. break;
  9884. }
  9885. for (int u_index = 0; u_index < SG_MAX_UB_MEMBERS; u_index++) {
  9886. sg_shader_uniform_desc* u_desc = &ub_desc->uniforms[u_index];
  9887. if (u_desc->type == SG_UNIFORMTYPE_INVALID) {
  9888. break;
  9889. }
  9890. u_desc->array_count = _sg_def(u_desc->array_count, 1);
  9891. }
  9892. }
  9893. }
  9894. return def;
  9895. }
  9896. _SOKOL_PRIVATE sg_pipeline_desc _sg_pipeline_desc_defaults(const sg_pipeline_desc* desc) {
  9897. sg_pipeline_desc def = *desc;
  9898. def.primitive_type = _sg_def(def.primitive_type, SG_PRIMITIVETYPE_TRIANGLES);
  9899. def.index_type = _sg_def(def.index_type, SG_INDEXTYPE_NONE);
  9900. def.depth_stencil.stencil_front.fail_op = _sg_def(def.depth_stencil.stencil_front.fail_op, SG_STENCILOP_KEEP);
  9901. def.depth_stencil.stencil_front.depth_fail_op = _sg_def(def.depth_stencil.stencil_front.depth_fail_op, SG_STENCILOP_KEEP);
  9902. def.depth_stencil.stencil_front.pass_op = _sg_def(def.depth_stencil.stencil_front.pass_op, SG_STENCILOP_KEEP);
  9903. def.depth_stencil.stencil_front.compare_func = _sg_def(def.depth_stencil.stencil_front.compare_func, SG_COMPAREFUNC_ALWAYS);
  9904. def.depth_stencil.stencil_back.fail_op = _sg_def(def.depth_stencil.stencil_back.fail_op, SG_STENCILOP_KEEP);
  9905. def.depth_stencil.stencil_back.depth_fail_op = _sg_def(def.depth_stencil.stencil_back.depth_fail_op, SG_STENCILOP_KEEP);
  9906. def.depth_stencil.stencil_back.pass_op = _sg_def(def.depth_stencil.stencil_back.pass_op, SG_STENCILOP_KEEP);
  9907. def.depth_stencil.stencil_back.compare_func = _sg_def(def.depth_stencil.stencil_back.compare_func, SG_COMPAREFUNC_ALWAYS);
  9908. def.depth_stencil.depth_compare_func = _sg_def(def.depth_stencil.depth_compare_func, SG_COMPAREFUNC_ALWAYS);
  9909. def.blend.src_factor_rgb = _sg_def(def.blend.src_factor_rgb, SG_BLENDFACTOR_ONE);
  9910. def.blend.dst_factor_rgb = _sg_def(def.blend.dst_factor_rgb, SG_BLENDFACTOR_ZERO);
  9911. def.blend.op_rgb = _sg_def(def.blend.op_rgb, SG_BLENDOP_ADD);
  9912. def.blend.src_factor_alpha = _sg_def(def.blend.src_factor_alpha, SG_BLENDFACTOR_ONE);
  9913. def.blend.dst_factor_alpha = _sg_def(def.blend.dst_factor_alpha, SG_BLENDFACTOR_ZERO);
  9914. def.blend.op_alpha = _sg_def(def.blend.op_alpha, SG_BLENDOP_ADD);
  9915. if (def.blend.color_write_mask == SG_COLORMASK_NONE) {
  9916. def.blend.color_write_mask = 0;
  9917. }
  9918. else {
  9919. def.blend.color_write_mask = (uint8_t) _sg_def((sg_color_mask)def.blend.color_write_mask, SG_COLORMASK_RGBA);
  9920. }
  9921. def.blend.color_attachment_count = _sg_def(def.blend.color_attachment_count, 1);
  9922. def.blend.color_format = _sg_def(def.blend.color_format, _sg_default_rendertarget_colorformat());
  9923. def.blend.depth_format = _sg_def(def.blend.depth_format, _sg_default_rendertarget_depthformat());
  9924. def.rasterizer.cull_mode = _sg_def(def.rasterizer.cull_mode, SG_CULLMODE_NONE);
  9925. def.rasterizer.face_winding = _sg_def(def.rasterizer.face_winding, SG_FACEWINDING_CW);
  9926. def.rasterizer.sample_count = _sg_def(def.rasterizer.sample_count, 1);
  9927. for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
  9928. sg_vertex_attr_desc* a_desc = &def.layout.attrs[attr_index];
  9929. if (a_desc->format == SG_VERTEXFORMAT_INVALID) {
  9930. break;
  9931. }
  9932. SOKOL_ASSERT((a_desc->buffer_index >= 0) && (a_desc->buffer_index < SG_MAX_SHADERSTAGE_BUFFERS));
  9933. sg_buffer_layout_desc* b_desc = &def.layout.buffers[a_desc->buffer_index];
  9934. b_desc->step_func = _sg_def(b_desc->step_func, SG_VERTEXSTEP_PER_VERTEX);
  9935. b_desc->step_rate = _sg_def(b_desc->step_rate, 1);
  9936. }
  9937. /* resolve vertex layout strides and offsets */
  9938. int auto_offset[SG_MAX_SHADERSTAGE_BUFFERS];
  9939. memset(auto_offset, 0, sizeof(auto_offset));
  9940. bool use_auto_offset = true;
  9941. for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
  9942. /* to use computed offsets, *all* attr offsets must be 0 */
  9943. if (def.layout.attrs[attr_index].offset != 0) {
  9944. use_auto_offset = false;
  9945. }
  9946. }
  9947. for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {
  9948. sg_vertex_attr_desc* a_desc = &def.layout.attrs[attr_index];
  9949. if (a_desc->format == SG_VERTEXFORMAT_INVALID) {
  9950. break;
  9951. }
  9952. SOKOL_ASSERT((a_desc->buffer_index >= 0) && (a_desc->buffer_index < SG_MAX_SHADERSTAGE_BUFFERS));
  9953. if (use_auto_offset) {
  9954. a_desc->offset = auto_offset[a_desc->buffer_index];
  9955. }
  9956. auto_offset[a_desc->buffer_index] += _sg_vertexformat_bytesize(a_desc->format);
  9957. }
  9958. /* compute vertex strides if needed */
  9959. for (int buf_index = 0; buf_index < SG_MAX_SHADERSTAGE_BUFFERS; buf_index++) {
  9960. sg_buffer_layout_desc* l_desc = &def.layout.buffers[buf_index];
  9961. if (l_desc->stride == 0) {
  9962. l_desc->stride = auto_offset[buf_index];
  9963. }
  9964. }
  9965. return def;
  9966. }
  9967. _SOKOL_PRIVATE sg_pass_desc _sg_pass_desc_defaults(const sg_pass_desc* desc) {
  9968. /* FIXME: no values to replace in sg_pass_desc? */
  9969. sg_pass_desc def = *desc;
  9970. return def;
  9971. }
  9972. /*== allocate/initialize resource private functions ==========================*/
  9973. _SOKOL_PRIVATE sg_buffer _sg_alloc_buffer(void) {
  9974. sg_buffer res;
  9975. int slot_index = _sg_pool_alloc_index(&_sg.pools.buffer_pool);
  9976. if (_SG_INVALID_SLOT_INDEX != slot_index) {
  9977. res.id = _sg_slot_alloc(&_sg.pools.buffer_pool, &_sg.pools.buffers[slot_index].slot, slot_index);
  9978. }
  9979. else {
  9980. /* pool is exhausted */
  9981. res.id = SG_INVALID_ID;
  9982. }
  9983. return res;
  9984. }
  9985. _SOKOL_PRIVATE sg_image _sg_alloc_image(void) {
  9986. sg_image res;
  9987. int slot_index = _sg_pool_alloc_index(&_sg.pools.image_pool);
  9988. if (_SG_INVALID_SLOT_INDEX != slot_index) {
  9989. res.id = _sg_slot_alloc(&_sg.pools.image_pool, &_sg.pools.images[slot_index].slot, slot_index);
  9990. }
  9991. else {
  9992. /* pool is exhausted */
  9993. res.id = SG_INVALID_ID;
  9994. }
  9995. return res;
  9996. }
  9997. _SOKOL_PRIVATE sg_shader _sg_alloc_shader(void) {
  9998. sg_shader res;
  9999. int slot_index = _sg_pool_alloc_index(&_sg.pools.shader_pool);
  10000. if (_SG_INVALID_SLOT_INDEX != slot_index) {
  10001. res.id = _sg_slot_alloc(&_sg.pools.shader_pool, &_sg.pools.shaders[slot_index].slot, slot_index);
  10002. }
  10003. else {
  10004. /* pool is exhausted */
  10005. res.id = SG_INVALID_ID;
  10006. }
  10007. return res;
  10008. }
  10009. _SOKOL_PRIVATE sg_pipeline _sg_alloc_pipeline(void) {
  10010. sg_pipeline res;
  10011. int slot_index = _sg_pool_alloc_index(&_sg.pools.pipeline_pool);
  10012. if (_SG_INVALID_SLOT_INDEX != slot_index) {
  10013. res.id =_sg_slot_alloc(&_sg.pools.pipeline_pool, &_sg.pools.pipelines[slot_index].slot, slot_index);
  10014. }
  10015. else {
  10016. /* pool is exhausted */
  10017. res.id = SG_INVALID_ID;
  10018. }
  10019. return res;
  10020. }
  10021. _SOKOL_PRIVATE sg_pass _sg_alloc_pass(void) {
  10022. sg_pass res;
  10023. int slot_index = _sg_pool_alloc_index(&_sg.pools.pass_pool);
  10024. if (_SG_INVALID_SLOT_INDEX != slot_index) {
  10025. res.id = _sg_slot_alloc(&_sg.pools.pass_pool, &_sg.pools.passes[slot_index].slot, slot_index);
  10026. }
  10027. else {
  10028. /* pool is exhausted */
  10029. res.id = SG_INVALID_ID;
  10030. }
  10031. return res;
  10032. }
  10033. _SOKOL_PRIVATE void _sg_init_buffer(sg_buffer buf_id, const sg_buffer_desc* desc) {
  10034. SOKOL_ASSERT(buf_id.id != SG_INVALID_ID && desc);
  10035. _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);
  10036. SOKOL_ASSERT(buf && buf->slot.state == SG_RESOURCESTATE_ALLOC);
  10037. buf->slot.ctx_id = _sg.active_context.id;
  10038. if (_sg_validate_buffer_desc(desc)) {
  10039. buf->slot.state = _sg_create_buffer(buf, desc);
  10040. }
  10041. else {
  10042. buf->slot.state = SG_RESOURCESTATE_FAILED;
  10043. }
  10044. SOKOL_ASSERT((buf->slot.state == SG_RESOURCESTATE_VALID)||(buf->slot.state == SG_RESOURCESTATE_FAILED));
  10045. }
  10046. _SOKOL_PRIVATE void _sg_init_image(sg_image img_id, const sg_image_desc* desc) {
  10047. SOKOL_ASSERT(img_id.id != SG_INVALID_ID && desc);
  10048. _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);
  10049. SOKOL_ASSERT(img && img->slot.state == SG_RESOURCESTATE_ALLOC);
  10050. img->slot.ctx_id = _sg.active_context.id;
  10051. if (_sg_validate_image_desc(desc)) {
  10052. img->slot.state = _sg_create_image(img, desc);
  10053. }
  10054. else {
  10055. img->slot.state = SG_RESOURCESTATE_FAILED;
  10056. }
  10057. SOKOL_ASSERT((img->slot.state == SG_RESOURCESTATE_VALID)||(img->slot.state == SG_RESOURCESTATE_FAILED));
  10058. }
  10059. _SOKOL_PRIVATE void _sg_init_shader(sg_shader shd_id, const sg_shader_desc* desc) {
  10060. SOKOL_ASSERT(shd_id.id != SG_INVALID_ID && desc);
  10061. _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);
  10062. SOKOL_ASSERT(shd && shd->slot.state == SG_RESOURCESTATE_ALLOC);
  10063. shd->slot.ctx_id = _sg.active_context.id;
  10064. if (_sg_validate_shader_desc(desc)) {
  10065. shd->slot.state = _sg_create_shader(shd, desc);
  10066. }
  10067. else {
  10068. shd->slot.state = SG_RESOURCESTATE_FAILED;
  10069. }
  10070. SOKOL_ASSERT((shd->slot.state == SG_RESOURCESTATE_VALID)||(shd->slot.state == SG_RESOURCESTATE_FAILED));
  10071. }
  10072. _SOKOL_PRIVATE void _sg_init_pipeline(sg_pipeline pip_id, const sg_pipeline_desc* desc) {
  10073. SOKOL_ASSERT(pip_id.id != SG_INVALID_ID && desc);
  10074. _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);
  10075. SOKOL_ASSERT(pip && pip->slot.state == SG_RESOURCESTATE_ALLOC);
  10076. pip->slot.ctx_id = _sg.active_context.id;
  10077. if (_sg_validate_pipeline_desc(desc)) {
  10078. _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, desc->shader.id);
  10079. SOKOL_ASSERT(shd && shd->slot.state == SG_RESOURCESTATE_VALID);
  10080. pip->slot.state = _sg_create_pipeline(pip, shd, desc);
  10081. }
  10082. else {
  10083. pip->slot.state = SG_RESOURCESTATE_FAILED;
  10084. }
  10085. SOKOL_ASSERT((pip->slot.state == SG_RESOURCESTATE_VALID)||(pip->slot.state == SG_RESOURCESTATE_FAILED));
  10086. }
  10087. _SOKOL_PRIVATE void _sg_init_pass(sg_pass pass_id, const sg_pass_desc* desc) {
  10088. SOKOL_ASSERT(pass_id.id != SG_INVALID_ID && desc);
  10089. _sg_pass_t* pass = _sg_lookup_pass(&_sg.pools, pass_id.id);
  10090. SOKOL_ASSERT(pass && pass->slot.state == SG_RESOURCESTATE_ALLOC);
  10091. pass->slot.ctx_id = _sg.active_context.id;
  10092. if (_sg_validate_pass_desc(desc)) {
  10093. /* lookup pass attachment image pointers */
  10094. _sg_image_t* att_imgs[SG_MAX_COLOR_ATTACHMENTS + 1];
  10095. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  10096. if (desc->color_attachments[i].image.id) {
  10097. att_imgs[i] = _sg_lookup_image(&_sg.pools, desc->color_attachments[i].image.id);
  10098. SOKOL_ASSERT(att_imgs[i] && att_imgs[i]->slot.state == SG_RESOURCESTATE_VALID);
  10099. }
  10100. else {
  10101. att_imgs[i] = 0;
  10102. }
  10103. }
  10104. const int ds_att_index = SG_MAX_COLOR_ATTACHMENTS;
  10105. if (desc->depth_stencil_attachment.image.id) {
  10106. att_imgs[ds_att_index] = _sg_lookup_image(&_sg.pools, desc->depth_stencil_attachment.image.id);
  10107. SOKOL_ASSERT(att_imgs[ds_att_index] && att_imgs[ds_att_index]->slot.state == SG_RESOURCESTATE_VALID);
  10108. }
  10109. else {
  10110. att_imgs[ds_att_index] = 0;
  10111. }
  10112. pass->slot.state = _sg_create_pass(pass, att_imgs, desc);
  10113. }
  10114. else {
  10115. pass->slot.state = SG_RESOURCESTATE_FAILED;
  10116. }
  10117. SOKOL_ASSERT((pass->slot.state == SG_RESOURCESTATE_VALID)||(pass->slot.state == SG_RESOURCESTATE_FAILED));
  10118. }
  10119. /*== PUBLIC API FUNCTIONS ====================================================*/
  10120. SOKOL_API_IMPL void sg_setup(const sg_desc* desc) {
  10121. SOKOL_ASSERT(desc);
  10122. SOKOL_ASSERT((desc->_start_canary == 0) && (desc->_end_canary == 0));
  10123. memset(&_sg, 0, sizeof(_sg));
  10124. _sg.desc = *desc;
  10125. /* replace zero-init items with their default values */
  10126. _sg.desc.buffer_pool_size = _sg_def(_sg.desc.buffer_pool_size, _SG_DEFAULT_BUFFER_POOL_SIZE);
  10127. _sg.desc.image_pool_size = _sg_def(_sg.desc.image_pool_size, _SG_DEFAULT_IMAGE_POOL_SIZE);
  10128. _sg.desc.shader_pool_size = _sg_def(_sg.desc.shader_pool_size, _SG_DEFAULT_SHADER_POOL_SIZE);
  10129. _sg.desc.pipeline_pool_size = _sg_def(_sg.desc.pipeline_pool_size, _SG_DEFAULT_PIPELINE_POOL_SIZE);
  10130. _sg.desc.pass_pool_size = _sg_def(_sg.desc.pass_pool_size, _SG_DEFAULT_PASS_POOL_SIZE);
  10131. _sg.desc.context_pool_size = _sg_def(_sg.desc.context_pool_size, _SG_DEFAULT_CONTEXT_POOL_SIZE);
  10132. _sg.desc.mtl_global_uniform_buffer_size = _sg_def(_sg.desc.mtl_global_uniform_buffer_size, _SG_MTL_DEFAULT_UB_SIZE);
  10133. _sg.desc.mtl_sampler_cache_size = _sg_def(_sg.desc.mtl_sampler_cache_size, _SG_MTL_DEFAULT_SAMPLER_CACHE_CAPACITY);
  10134. _sg_setup_pools(&_sg.pools, &_sg.desc);
  10135. _sg.frame_index = 1;
  10136. _sg_setup_backend(&_sg.desc);
  10137. _sg.valid = true;
  10138. sg_setup_context();
  10139. }
  10140. SOKOL_API_IMPL void sg_shutdown(void) {
  10141. /* can only delete resources for the currently set context here, if multiple
  10142. contexts are used, the app code must take care of properly releasing them
  10143. (since only the app code can switch between 3D-API contexts)
  10144. */
  10145. if (_sg.active_context.id != SG_INVALID_ID) {
  10146. _sg_context_t* ctx = _sg_lookup_context(&_sg.pools, _sg.active_context.id);
  10147. if (ctx) {
  10148. _sg_destroy_all_resources(&_sg.pools, _sg.active_context.id);
  10149. _sg_destroy_context(ctx);
  10150. }
  10151. }
  10152. _sg_discard_backend();
  10153. _sg_discard_pools(&_sg.pools);
  10154. _sg.valid = false;
  10155. }
  10156. SOKOL_API_IMPL bool sg_isvalid(void) {
  10157. return _sg.valid;
  10158. }
  10159. SOKOL_API_IMPL sg_desc sg_query_desc(void) {
  10160. SOKOL_ASSERT(_sg.valid);
  10161. return _sg.desc;
  10162. }
  10163. SOKOL_API_IMPL sg_backend sg_query_backend(void) {
  10164. SOKOL_ASSERT(_sg.valid);
  10165. return _sg.backend;
  10166. }
  10167. SOKOL_API_IMPL sg_features sg_query_features(void) {
  10168. SOKOL_ASSERT(_sg.valid);
  10169. return _sg.features;
  10170. }
  10171. SOKOL_API_IMPL sg_limits sg_query_limits(void) {
  10172. SOKOL_ASSERT(_sg.valid);
  10173. return _sg.limits;
  10174. }
  10175. SOKOL_API_IMPL sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt) {
  10176. SOKOL_ASSERT(_sg.valid);
  10177. int fmt_index = (int) fmt;
  10178. SOKOL_ASSERT((fmt_index > SG_PIXELFORMAT_NONE) && (fmt_index < _SG_PIXELFORMAT_NUM));
  10179. return _sg.formats[fmt_index];
  10180. }
  10181. SOKOL_API_IMPL sg_context sg_setup_context(void) {
  10182. SOKOL_ASSERT(_sg.valid);
  10183. sg_context res;
  10184. int slot_index = _sg_pool_alloc_index(&_sg.pools.context_pool);
  10185. if (_SG_INVALID_SLOT_INDEX != slot_index) {
  10186. res.id = _sg_slot_alloc(&_sg.pools.context_pool, &_sg.pools.contexts[slot_index].slot, slot_index);
  10187. _sg_context_t* ctx = _sg_context_at(&_sg.pools, res.id);
  10188. ctx->slot.state = _sg_create_context(ctx);
  10189. SOKOL_ASSERT(ctx->slot.state == SG_RESOURCESTATE_VALID);
  10190. _sg_activate_context(ctx);
  10191. }
  10192. else {
  10193. /* pool is exhausted */
  10194. res.id = SG_INVALID_ID;
  10195. }
  10196. _sg.active_context = res;
  10197. return res;
  10198. }
  10199. SOKOL_API_IMPL void sg_discard_context(sg_context ctx_id) {
  10200. SOKOL_ASSERT(_sg.valid);
  10201. _sg_destroy_all_resources(&_sg.pools, ctx_id.id);
  10202. _sg_context_t* ctx = _sg_lookup_context(&_sg.pools, ctx_id.id);
  10203. if (ctx) {
  10204. _sg_destroy_context(ctx);
  10205. _sg_reset_context(ctx);
  10206. _sg_pool_free_index(&_sg.pools.context_pool, _sg_slot_index(ctx_id.id));
  10207. }
  10208. _sg.active_context.id = SG_INVALID_ID;
  10209. _sg_activate_context(0);
  10210. }
  10211. SOKOL_API_IMPL void sg_activate_context(sg_context ctx_id) {
  10212. SOKOL_ASSERT(_sg.valid);
  10213. _sg.active_context = ctx_id;
  10214. _sg_context_t* ctx = _sg_lookup_context(&_sg.pools, ctx_id.id);
  10215. /* NOTE: ctx can be 0 here if the context is no longer valid */
  10216. _sg_activate_context(ctx);
  10217. }
  10218. SOKOL_API_IMPL sg_trace_hooks sg_install_trace_hooks(const sg_trace_hooks* trace_hooks) {
  10219. SOKOL_ASSERT(_sg.valid);
  10220. SOKOL_ASSERT(trace_hooks);
  10221. #if defined(SOKOL_TRACE_HOOKS)
  10222. sg_trace_hooks old_hooks = _sg.hooks;
  10223. _sg.hooks = *trace_hooks;
  10224. #else
  10225. static sg_trace_hooks old_hooks;
  10226. SOKOL_LOG("sg_install_trace_hooks() called, but SG_TRACE_HOOKS is not defined!");
  10227. #endif
  10228. return old_hooks;
  10229. }
  10230. SOKOL_API_IMPL sg_buffer sg_alloc_buffer(void) {
  10231. SOKOL_ASSERT(_sg.valid);
  10232. sg_buffer res = _sg_alloc_buffer();
  10233. _SG_TRACE_ARGS(alloc_buffer, res);
  10234. return res;
  10235. }
  10236. SOKOL_API_IMPL sg_image sg_alloc_image(void) {
  10237. SOKOL_ASSERT(_sg.valid);
  10238. sg_image res = _sg_alloc_image();
  10239. _SG_TRACE_ARGS(alloc_image, res);
  10240. return res;
  10241. }
  10242. SOKOL_API_IMPL sg_shader sg_alloc_shader(void) {
  10243. SOKOL_ASSERT(_sg.valid);
  10244. sg_shader res = _sg_alloc_shader();
  10245. _SG_TRACE_ARGS(alloc_shader, res);
  10246. return res;
  10247. }
  10248. SOKOL_API_IMPL sg_pipeline sg_alloc_pipeline(void) {
  10249. SOKOL_ASSERT(_sg.valid);
  10250. sg_pipeline res = _sg_alloc_pipeline();
  10251. _SG_TRACE_ARGS(alloc_pipeline, res);
  10252. return res;
  10253. }
  10254. SOKOL_API_IMPL sg_pass sg_alloc_pass(void) {
  10255. SOKOL_ASSERT(_sg.valid);
  10256. sg_pass res = _sg_alloc_pass();
  10257. _SG_TRACE_ARGS(alloc_pass, res);
  10258. return res;
  10259. }
  10260. SOKOL_API_IMPL void sg_init_buffer(sg_buffer buf_id, const sg_buffer_desc* desc) {
  10261. SOKOL_ASSERT(_sg.valid);
  10262. sg_buffer_desc desc_def = _sg_buffer_desc_defaults(desc);
  10263. _sg_init_buffer(buf_id, &desc_def);
  10264. _SG_TRACE_ARGS(init_buffer, buf_id, &desc_def);
  10265. }
  10266. SOKOL_API_IMPL void sg_init_image(sg_image img_id, const sg_image_desc* desc) {
  10267. SOKOL_ASSERT(_sg.valid);
  10268. sg_image_desc desc_def = _sg_image_desc_defaults(desc);
  10269. _sg_init_image(img_id, &desc_def);
  10270. _SG_TRACE_ARGS(init_image, img_id, &desc_def);
  10271. }
  10272. SOKOL_API_IMPL void sg_init_shader(sg_shader shd_id, const sg_shader_desc* desc) {
  10273. SOKOL_ASSERT(_sg.valid);
  10274. sg_shader_desc desc_def = _sg_shader_desc_defaults(desc);
  10275. _sg_init_shader(shd_id, &desc_def);
  10276. _SG_TRACE_ARGS(init_shader, shd_id, &desc_def);
  10277. }
  10278. SOKOL_API_IMPL void sg_init_pipeline(sg_pipeline pip_id, const sg_pipeline_desc* desc) {
  10279. SOKOL_ASSERT(_sg.valid);
  10280. sg_pipeline_desc desc_def = _sg_pipeline_desc_defaults(desc);
  10281. _sg_init_pipeline(pip_id, &desc_def);
  10282. _SG_TRACE_ARGS(init_pipeline, pip_id, &desc_def);
  10283. }
  10284. SOKOL_API_IMPL void sg_init_pass(sg_pass pass_id, const sg_pass_desc* desc) {
  10285. SOKOL_ASSERT(_sg.valid);
  10286. sg_pass_desc desc_def = _sg_pass_desc_defaults(desc);
  10287. _sg_init_pass(pass_id, &desc_def);
  10288. _SG_TRACE_ARGS(init_pass, pass_id, &desc_def);
  10289. }
  10290. /*-- set allocated resource to failed state ----------------------------------*/
  10291. SOKOL_API_IMPL void sg_fail_buffer(sg_buffer buf_id) {
  10292. SOKOL_ASSERT(_sg.valid);
  10293. SOKOL_ASSERT(buf_id.id != SG_INVALID_ID);
  10294. _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);
  10295. SOKOL_ASSERT(buf && buf->slot.state == SG_RESOURCESTATE_ALLOC);
  10296. buf->slot.ctx_id = _sg.active_context.id;
  10297. buf->slot.state = SG_RESOURCESTATE_FAILED;
  10298. _SG_TRACE_ARGS(fail_buffer, buf_id);
  10299. }
  10300. SOKOL_API_IMPL void sg_fail_image(sg_image img_id) {
  10301. SOKOL_ASSERT(_sg.valid);
  10302. SOKOL_ASSERT(img_id.id != SG_INVALID_ID);
  10303. _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);
  10304. SOKOL_ASSERT(img && img->slot.state == SG_RESOURCESTATE_ALLOC);
  10305. img->slot.ctx_id = _sg.active_context.id;
  10306. img->slot.state = SG_RESOURCESTATE_FAILED;
  10307. _SG_TRACE_ARGS(fail_image, img_id);
  10308. }
  10309. SOKOL_API_IMPL void sg_fail_shader(sg_shader shd_id) {
  10310. SOKOL_ASSERT(_sg.valid);
  10311. SOKOL_ASSERT(shd_id.id != SG_INVALID_ID);
  10312. _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);
  10313. SOKOL_ASSERT(shd && shd->slot.state == SG_RESOURCESTATE_ALLOC);
  10314. shd->slot.ctx_id = _sg.active_context.id;
  10315. shd->slot.state = SG_RESOURCESTATE_FAILED;
  10316. _SG_TRACE_ARGS(fail_shader, shd_id);
  10317. }
  10318. SOKOL_API_IMPL void sg_fail_pipeline(sg_pipeline pip_id) {
  10319. SOKOL_ASSERT(_sg.valid);
  10320. SOKOL_ASSERT(pip_id.id != SG_INVALID_ID);
  10321. _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);
  10322. SOKOL_ASSERT(pip && pip->slot.state == SG_RESOURCESTATE_ALLOC);
  10323. pip->slot.ctx_id = _sg.active_context.id;
  10324. pip->slot.state = SG_RESOURCESTATE_FAILED;
  10325. _SG_TRACE_ARGS(fail_pipeline, pip_id);
  10326. }
  10327. SOKOL_API_IMPL void sg_fail_pass(sg_pass pass_id) {
  10328. SOKOL_ASSERT(_sg.valid);
  10329. SOKOL_ASSERT(pass_id.id != SG_INVALID_ID);
  10330. _sg_pass_t* pass = _sg_lookup_pass(&_sg.pools, pass_id.id);
  10331. SOKOL_ASSERT(pass && pass->slot.state == SG_RESOURCESTATE_ALLOC);
  10332. pass->slot.ctx_id = _sg.active_context.id;
  10333. pass->slot.state = SG_RESOURCESTATE_FAILED;
  10334. _SG_TRACE_ARGS(fail_pass, pass_id);
  10335. }
  10336. /*-- get resource state */
  10337. SOKOL_API_IMPL sg_resource_state sg_query_buffer_state(sg_buffer buf_id) {
  10338. SOKOL_ASSERT(_sg.valid);
  10339. _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);
  10340. sg_resource_state res = buf ? buf->slot.state : SG_RESOURCESTATE_INVALID;
  10341. return res;
  10342. }
  10343. SOKOL_API_IMPL sg_resource_state sg_query_image_state(sg_image img_id) {
  10344. SOKOL_ASSERT(_sg.valid);
  10345. _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);
  10346. sg_resource_state res = img ? img->slot.state : SG_RESOURCESTATE_INVALID;
  10347. return res;
  10348. }
  10349. SOKOL_API_IMPL sg_resource_state sg_query_shader_state(sg_shader shd_id) {
  10350. SOKOL_ASSERT(_sg.valid);
  10351. _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);
  10352. sg_resource_state res = shd ? shd->slot.state : SG_RESOURCESTATE_INVALID;
  10353. return res;
  10354. }
  10355. SOKOL_API_IMPL sg_resource_state sg_query_pipeline_state(sg_pipeline pip_id) {
  10356. SOKOL_ASSERT(_sg.valid);
  10357. _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);
  10358. sg_resource_state res = pip ? pip->slot.state : SG_RESOURCESTATE_INVALID;
  10359. return res;
  10360. }
  10361. SOKOL_API_IMPL sg_resource_state sg_query_pass_state(sg_pass pass_id) {
  10362. SOKOL_ASSERT(_sg.valid);
  10363. _sg_pass_t* pass = _sg_lookup_pass(&_sg.pools, pass_id.id);
  10364. sg_resource_state res = pass ? pass->slot.state : SG_RESOURCESTATE_INVALID;
  10365. return res;
  10366. }
  10367. /*-- allocate and initialize resource ----------------------------------------*/
  10368. SOKOL_API_IMPL sg_buffer sg_make_buffer(const sg_buffer_desc* desc) {
  10369. SOKOL_ASSERT(_sg.valid);
  10370. SOKOL_ASSERT(desc);
  10371. sg_buffer_desc desc_def = _sg_buffer_desc_defaults(desc);
  10372. sg_buffer buf_id = _sg_alloc_buffer();
  10373. if (buf_id.id != SG_INVALID_ID) {
  10374. _sg_init_buffer(buf_id, &desc_def);
  10375. }
  10376. else {
  10377. SOKOL_LOG("buffer pool exhausted!");
  10378. _SG_TRACE_NOARGS(err_buffer_pool_exhausted);
  10379. }
  10380. _SG_TRACE_ARGS(make_buffer, &desc_def, buf_id);
  10381. return buf_id;
  10382. }
  10383. SOKOL_API_IMPL sg_image sg_make_image(const sg_image_desc* desc) {
  10384. SOKOL_ASSERT(_sg.valid);
  10385. SOKOL_ASSERT(desc);
  10386. sg_image_desc desc_def = _sg_image_desc_defaults(desc);
  10387. sg_image img_id = _sg_alloc_image();
  10388. if (img_id.id != SG_INVALID_ID) {
  10389. _sg_init_image(img_id, &desc_def);
  10390. }
  10391. else {
  10392. SOKOL_LOG("image pool exhausted!");
  10393. _SG_TRACE_NOARGS(err_image_pool_exhausted);
  10394. }
  10395. _SG_TRACE_ARGS(make_image, &desc_def, img_id);
  10396. return img_id;
  10397. }
  10398. SOKOL_API_IMPL sg_shader sg_make_shader(const sg_shader_desc* desc) {
  10399. SOKOL_ASSERT(_sg.valid);
  10400. SOKOL_ASSERT(desc);
  10401. sg_shader_desc desc_def = _sg_shader_desc_defaults(desc);
  10402. sg_shader shd_id = _sg_alloc_shader();
  10403. if (shd_id.id != SG_INVALID_ID) {
  10404. _sg_init_shader(shd_id, &desc_def);
  10405. }
  10406. else {
  10407. SOKOL_LOG("shader pool exhausted!");
  10408. _SG_TRACE_NOARGS(err_shader_pool_exhausted);
  10409. }
  10410. _SG_TRACE_ARGS(make_shader, &desc_def, shd_id);
  10411. return shd_id;
  10412. }
  10413. SOKOL_API_IMPL sg_pipeline sg_make_pipeline(const sg_pipeline_desc* desc) {
  10414. SOKOL_ASSERT(_sg.valid);
  10415. SOKOL_ASSERT(desc);
  10416. sg_pipeline_desc desc_def = _sg_pipeline_desc_defaults(desc);
  10417. sg_pipeline pip_id = _sg_alloc_pipeline();
  10418. if (pip_id.id != SG_INVALID_ID) {
  10419. _sg_init_pipeline(pip_id, &desc_def);
  10420. }
  10421. else {
  10422. SOKOL_LOG("pipeline pool exhausted!");
  10423. _SG_TRACE_NOARGS(err_pipeline_pool_exhausted);
  10424. }
  10425. _SG_TRACE_ARGS(make_pipeline, &desc_def, pip_id);
  10426. return pip_id;
  10427. }
  10428. SOKOL_API_IMPL sg_pass sg_make_pass(const sg_pass_desc* desc) {
  10429. SOKOL_ASSERT(_sg.valid);
  10430. SOKOL_ASSERT(desc);
  10431. sg_pass_desc desc_def = _sg_pass_desc_defaults(desc);
  10432. sg_pass pass_id = _sg_alloc_pass();
  10433. if (pass_id.id != SG_INVALID_ID) {
  10434. _sg_init_pass(pass_id, &desc_def);
  10435. }
  10436. else {
  10437. SOKOL_LOG("pass pool exhausted!");
  10438. _SG_TRACE_NOARGS(err_pass_pool_exhausted);
  10439. }
  10440. _SG_TRACE_ARGS(make_pass, &desc_def, pass_id);
  10441. return pass_id;
  10442. }
  10443. /*-- destroy resource --------------------------------------------------------*/
  10444. SOKOL_API_IMPL void sg_destroy_buffer(sg_buffer buf_id) {
  10445. SOKOL_ASSERT(_sg.valid);
  10446. _SG_TRACE_ARGS(destroy_buffer, buf_id);
  10447. _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);
  10448. if (buf) {
  10449. if (buf->slot.ctx_id == _sg.active_context.id) {
  10450. _sg_destroy_buffer(buf);
  10451. _sg_reset_buffer(buf);
  10452. _sg_pool_free_index(&_sg.pools.buffer_pool, _sg_slot_index(buf_id.id));
  10453. }
  10454. else {
  10455. SOKOL_LOG("sg_destroy_buffer: active context mismatch (must be same as for creation)");
  10456. _SG_TRACE_NOARGS(err_context_mismatch);
  10457. }
  10458. }
  10459. }
  10460. SOKOL_API_IMPL void sg_destroy_image(sg_image img_id) {
  10461. SOKOL_ASSERT(_sg.valid);
  10462. _SG_TRACE_ARGS(destroy_image, img_id);
  10463. _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);
  10464. if (img) {
  10465. if (img->slot.ctx_id == _sg.active_context.id) {
  10466. _sg_destroy_image(img);
  10467. _sg_reset_image(img);
  10468. _sg_pool_free_index(&_sg.pools.image_pool, _sg_slot_index(img_id.id));
  10469. }
  10470. else {
  10471. SOKOL_LOG("sg_destroy_image: active context mismatch (must be same as for creation)");
  10472. _SG_TRACE_NOARGS(err_context_mismatch);
  10473. }
  10474. }
  10475. }
  10476. SOKOL_API_IMPL void sg_destroy_shader(sg_shader shd_id) {
  10477. SOKOL_ASSERT(_sg.valid);
  10478. _SG_TRACE_ARGS(destroy_shader, shd_id);
  10479. _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);
  10480. if (shd) {
  10481. if (shd->slot.ctx_id == _sg.active_context.id) {
  10482. _sg_destroy_shader(shd);
  10483. _sg_reset_shader(shd);
  10484. _sg_pool_free_index(&_sg.pools.shader_pool, _sg_slot_index(shd_id.id));
  10485. }
  10486. else {
  10487. SOKOL_LOG("sg_destroy_shader: active context mismatch (must be same as for creation)");
  10488. _SG_TRACE_NOARGS(err_context_mismatch);
  10489. }
  10490. }
  10491. }
  10492. SOKOL_API_IMPL void sg_destroy_pipeline(sg_pipeline pip_id) {
  10493. SOKOL_ASSERT(_sg.valid);
  10494. _SG_TRACE_ARGS(destroy_pipeline, pip_id);
  10495. _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);
  10496. if (pip) {
  10497. if (pip->slot.ctx_id == _sg.active_context.id) {
  10498. _sg_destroy_pipeline(pip);
  10499. _sg_reset_pipeline(pip);
  10500. _sg_pool_free_index(&_sg.pools.pipeline_pool, _sg_slot_index(pip_id.id));
  10501. }
  10502. else {
  10503. SOKOL_LOG("sg_destroy_pipeline: active context mismatch (must be same as for creation)");
  10504. _SG_TRACE_NOARGS(err_context_mismatch);
  10505. }
  10506. }
  10507. }
  10508. SOKOL_API_IMPL void sg_destroy_pass(sg_pass pass_id) {
  10509. SOKOL_ASSERT(_sg.valid);
  10510. _SG_TRACE_ARGS(destroy_pass, pass_id);
  10511. _sg_pass_t* pass = _sg_lookup_pass(&_sg.pools, pass_id.id);
  10512. if (pass) {
  10513. if (pass->slot.ctx_id == _sg.active_context.id) {
  10514. _sg_destroy_pass(pass);
  10515. _sg_reset_pass(pass);
  10516. _sg_pool_free_index(&_sg.pools.pass_pool, _sg_slot_index(pass_id.id));
  10517. }
  10518. else {
  10519. SOKOL_LOG("sg_destroy_pass: active context mismatch (must be same as for creation)");
  10520. _SG_TRACE_NOARGS(err_context_mismatch);
  10521. }
  10522. }
  10523. }
  10524. SOKOL_API_IMPL void sg_begin_default_pass(const sg_pass_action* pass_action, int width, int height) {
  10525. SOKOL_ASSERT(_sg.valid);
  10526. SOKOL_ASSERT(pass_action);
  10527. SOKOL_ASSERT((pass_action->_start_canary == 0) && (pass_action->_end_canary == 0));
  10528. sg_pass_action pa;
  10529. _sg_resolve_default_pass_action(pass_action, &pa);
  10530. _sg.cur_pass.id = SG_INVALID_ID;
  10531. _sg.pass_valid = true;
  10532. _sg_begin_pass(0, &pa, width, height);
  10533. _SG_TRACE_ARGS(begin_default_pass, pass_action, width, height);
  10534. }
  10535. SOKOL_API_IMPL void sg_begin_pass(sg_pass pass_id, const sg_pass_action* pass_action) {
  10536. SOKOL_ASSERT(_sg.valid);
  10537. SOKOL_ASSERT(pass_action);
  10538. SOKOL_ASSERT((pass_action->_start_canary == 0) && (pass_action->_end_canary == 0));
  10539. _sg.cur_pass = pass_id;
  10540. _sg_pass_t* pass = _sg_lookup_pass(&_sg.pools, pass_id.id);
  10541. if (pass && _sg_validate_begin_pass(pass)) {
  10542. _sg.pass_valid = true;
  10543. sg_pass_action pa;
  10544. _sg_resolve_default_pass_action(pass_action, &pa);
  10545. const _sg_image_t* img = _sg_pass_color_image(pass, 0);
  10546. const int w = img->cmn.width;
  10547. const int h = img->cmn.height;
  10548. _sg_begin_pass(pass, &pa, w, h);
  10549. _SG_TRACE_ARGS(begin_pass, pass_id, pass_action);
  10550. }
  10551. else {
  10552. _sg.pass_valid = false;
  10553. _SG_TRACE_NOARGS(err_pass_invalid);
  10554. }
  10555. }
  10556. SOKOL_API_IMPL void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left) {
  10557. SOKOL_ASSERT(_sg.valid);
  10558. if (!_sg.pass_valid) {
  10559. _SG_TRACE_NOARGS(err_pass_invalid);
  10560. return;
  10561. }
  10562. _sg_apply_viewport(x, y, width, height, origin_top_left);
  10563. _SG_TRACE_ARGS(apply_viewport, x, y, width, height, origin_top_left);
  10564. }
  10565. SOKOL_API_IMPL void sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left) {
  10566. SOKOL_ASSERT(_sg.valid);
  10567. if (!_sg.pass_valid) {
  10568. _SG_TRACE_NOARGS(err_pass_invalid);
  10569. return;
  10570. }
  10571. _sg_apply_scissor_rect(x, y, width, height, origin_top_left);
  10572. _SG_TRACE_ARGS(apply_scissor_rect, x, y, width, height, origin_top_left);
  10573. }
  10574. SOKOL_API_IMPL void sg_apply_pipeline(sg_pipeline pip_id) {
  10575. SOKOL_ASSERT(_sg.valid);
  10576. _sg.bindings_valid = false;
  10577. if (!_sg_validate_apply_pipeline(pip_id)) {
  10578. _sg.next_draw_valid = false;
  10579. _SG_TRACE_NOARGS(err_draw_invalid);
  10580. return;
  10581. }
  10582. if (!_sg.pass_valid) {
  10583. _SG_TRACE_NOARGS(err_pass_invalid);
  10584. return;
  10585. }
  10586. _sg.cur_pipeline = pip_id;
  10587. _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);
  10588. SOKOL_ASSERT(pip);
  10589. _sg.next_draw_valid = (SG_RESOURCESTATE_VALID == pip->slot.state);
  10590. SOKOL_ASSERT(pip->shader && (pip->shader->slot.id == pip->cmn.shader_id.id));
  10591. _sg_apply_pipeline(pip);
  10592. _SG_TRACE_ARGS(apply_pipeline, pip_id);
  10593. }
  10594. SOKOL_API_IMPL void sg_apply_bindings(const sg_bindings* bindings) {
  10595. SOKOL_ASSERT(_sg.valid);
  10596. SOKOL_ASSERT(bindings);
  10597. SOKOL_ASSERT((bindings->_start_canary == 0) && (bindings->_end_canary==0));
  10598. if (!_sg_validate_apply_bindings(bindings)) {
  10599. _sg.next_draw_valid = false;
  10600. _SG_TRACE_NOARGS(err_draw_invalid);
  10601. return;
  10602. }
  10603. _sg.bindings_valid = true;
  10604. _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, _sg.cur_pipeline.id);
  10605. SOKOL_ASSERT(pip);
  10606. _sg_buffer_t* vbs[SG_MAX_SHADERSTAGE_BUFFERS] = { 0 };
  10607. int num_vbs = 0;
  10608. for (int i = 0; i < SG_MAX_SHADERSTAGE_BUFFERS; i++, num_vbs++) {
  10609. if (bindings->vertex_buffers[i].id) {
  10610. vbs[i] = _sg_lookup_buffer(&_sg.pools, bindings->vertex_buffers[i].id);
  10611. SOKOL_ASSERT(vbs[i]);
  10612. _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == vbs[i]->slot.state);
  10613. _sg.next_draw_valid &= !vbs[i]->cmn.append_overflow;
  10614. }
  10615. else {
  10616. break;
  10617. }
  10618. }
  10619. _sg_buffer_t* ib = 0;
  10620. if (bindings->index_buffer.id) {
  10621. ib = _sg_lookup_buffer(&_sg.pools, bindings->index_buffer.id);
  10622. SOKOL_ASSERT(ib);
  10623. _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == ib->slot.state);
  10624. _sg.next_draw_valid &= !ib->cmn.append_overflow;
  10625. }
  10626. _sg_image_t* vs_imgs[SG_MAX_SHADERSTAGE_IMAGES] = { 0 };
  10627. int num_vs_imgs = 0;
  10628. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++, num_vs_imgs++) {
  10629. if (bindings->vs_images[i].id) {
  10630. vs_imgs[i] = _sg_lookup_image(&_sg.pools, bindings->vs_images[i].id);
  10631. SOKOL_ASSERT(vs_imgs[i]);
  10632. _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == vs_imgs[i]->slot.state);
  10633. }
  10634. else {
  10635. break;
  10636. }
  10637. }
  10638. _sg_image_t* fs_imgs[SG_MAX_SHADERSTAGE_IMAGES] = { 0 };
  10639. int num_fs_imgs = 0;
  10640. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++, num_fs_imgs++) {
  10641. if (bindings->fs_images[i].id) {
  10642. fs_imgs[i] = _sg_lookup_image(&_sg.pools, bindings->fs_images[i].id);
  10643. SOKOL_ASSERT(fs_imgs[i]);
  10644. _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == fs_imgs[i]->slot.state);
  10645. }
  10646. else {
  10647. break;
  10648. }
  10649. }
  10650. if (_sg.next_draw_valid) {
  10651. const int* vb_offsets = bindings->vertex_buffer_offsets;
  10652. int ib_offset = bindings->index_buffer_offset;
  10653. _sg_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs);
  10654. _SG_TRACE_ARGS(apply_bindings, bindings);
  10655. }
  10656. else {
  10657. _SG_TRACE_NOARGS(err_draw_invalid);
  10658. }
  10659. }
  10660. SOKOL_API_IMPL void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const void* data, int num_bytes) {
  10661. SOKOL_ASSERT(_sg.valid);
  10662. SOKOL_ASSERT((stage == SG_SHADERSTAGE_VS) || (stage == SG_SHADERSTAGE_FS));
  10663. SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS));
  10664. SOKOL_ASSERT(data && (num_bytes > 0));
  10665. if (!_sg_validate_apply_uniforms(stage, ub_index, data, num_bytes)) {
  10666. _sg.next_draw_valid = false;
  10667. _SG_TRACE_NOARGS(err_draw_invalid);
  10668. return;
  10669. }
  10670. if (!_sg.pass_valid) {
  10671. _SG_TRACE_NOARGS(err_pass_invalid);
  10672. return;
  10673. }
  10674. if (!_sg.next_draw_valid) {
  10675. _SG_TRACE_NOARGS(err_draw_invalid);
  10676. }
  10677. _sg_apply_uniforms(stage, ub_index, data, num_bytes);
  10678. _SG_TRACE_ARGS(apply_uniforms, stage, ub_index, data, num_bytes);
  10679. }
  10680. SOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instances) {
  10681. SOKOL_ASSERT(_sg.valid);
  10682. #if defined(SOKOL_DEBUG)
  10683. if (!_sg.bindings_valid) {
  10684. SOKOL_LOG("attempting to draw without resource bindings");
  10685. }
  10686. #endif
  10687. if (!_sg.pass_valid) {
  10688. _SG_TRACE_NOARGS(err_pass_invalid);
  10689. return;
  10690. }
  10691. if (!_sg.next_draw_valid) {
  10692. _SG_TRACE_NOARGS(err_draw_invalid);
  10693. return;
  10694. }
  10695. if (!_sg.bindings_valid) {
  10696. _SG_TRACE_NOARGS(err_bindings_invalid);
  10697. return;
  10698. }
  10699. _sg_draw(base_element, num_elements, num_instances);
  10700. _SG_TRACE_ARGS(draw, base_element, num_elements, num_instances);
  10701. }
  10702. SOKOL_API_IMPL void sg_end_pass(void) {
  10703. SOKOL_ASSERT(_sg.valid);
  10704. if (!_sg.pass_valid) {
  10705. _SG_TRACE_NOARGS(err_pass_invalid);
  10706. return;
  10707. }
  10708. _sg_end_pass();
  10709. _sg.cur_pass.id = SG_INVALID_ID;
  10710. _sg.cur_pipeline.id = SG_INVALID_ID;
  10711. _sg.pass_valid = false;
  10712. _SG_TRACE_NOARGS(end_pass);
  10713. }
  10714. SOKOL_API_IMPL void sg_commit(void) {
  10715. SOKOL_ASSERT(_sg.valid);
  10716. _sg_commit();
  10717. _SG_TRACE_NOARGS(commit);
  10718. _sg.frame_index++;
  10719. }
  10720. SOKOL_API_IMPL void sg_reset_state_cache(void) {
  10721. SOKOL_ASSERT(_sg.valid);
  10722. _sg_reset_state_cache();
  10723. _SG_TRACE_NOARGS(reset_state_cache);
  10724. }
  10725. SOKOL_API_IMPL void sg_update_buffer(sg_buffer buf_id, const void* data, int num_bytes) {
  10726. SOKOL_ASSERT(_sg.valid);
  10727. _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);
  10728. if ((num_bytes > 0) && buf && (buf->slot.state == SG_RESOURCESTATE_VALID)) {
  10729. if (_sg_validate_update_buffer(buf, data, num_bytes)) {
  10730. SOKOL_ASSERT(num_bytes <= buf->cmn.size);
  10731. /* only one update allowed per buffer and frame */
  10732. SOKOL_ASSERT(buf->cmn.update_frame_index != _sg.frame_index);
  10733. /* update and append on same buffer in same frame not allowed */
  10734. SOKOL_ASSERT(buf->cmn.append_frame_index != _sg.frame_index);
  10735. _sg_update_buffer(buf, data, num_bytes);
  10736. buf->cmn.update_frame_index = _sg.frame_index;
  10737. }
  10738. }
  10739. _SG_TRACE_ARGS(update_buffer, buf_id, data, num_bytes);
  10740. }
  10741. SOKOL_API_IMPL int sg_append_buffer(sg_buffer buf_id, const void* data, int num_bytes) {
  10742. SOKOL_ASSERT(_sg.valid);
  10743. _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);
  10744. int result;
  10745. if (buf) {
  10746. /* rewind append cursor in a new frame */
  10747. if (buf->cmn.append_frame_index != _sg.frame_index) {
  10748. buf->cmn.append_pos = 0;
  10749. buf->cmn.append_overflow = false;
  10750. }
  10751. if ((buf->cmn.append_pos + num_bytes) > buf->cmn.size) {
  10752. buf->cmn.append_overflow = true;
  10753. }
  10754. const int start_pos = buf->cmn.append_pos;
  10755. if (buf->slot.state == SG_RESOURCESTATE_VALID) {
  10756. if (_sg_validate_append_buffer(buf, data, num_bytes)) {
  10757. if (!buf->cmn.append_overflow && (num_bytes > 0)) {
  10758. /* update and append on same buffer in same frame not allowed */
  10759. SOKOL_ASSERT(buf->cmn.update_frame_index != _sg.frame_index);
  10760. _sg_append_buffer(buf, data, num_bytes, buf->cmn.append_frame_index != _sg.frame_index);
  10761. buf->cmn.append_pos += num_bytes;
  10762. buf->cmn.append_frame_index = _sg.frame_index;
  10763. }
  10764. }
  10765. }
  10766. result = start_pos;
  10767. }
  10768. else {
  10769. /* FIXME: should we return -1 here? */
  10770. result = 0;
  10771. }
  10772. _SG_TRACE_ARGS(append_buffer, buf_id, data, num_bytes, result);
  10773. return result;
  10774. }
  10775. SOKOL_API_IMPL bool sg_query_buffer_overflow(sg_buffer buf_id) {
  10776. SOKOL_ASSERT(_sg.valid);
  10777. _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);
  10778. bool result = buf ? buf->cmn.append_overflow : false;
  10779. return result;
  10780. }
  10781. SOKOL_API_IMPL void sg_update_image(sg_image img_id, const sg_image_content* data) {
  10782. SOKOL_ASSERT(_sg.valid);
  10783. _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);
  10784. if (img && img->slot.state == SG_RESOURCESTATE_VALID) {
  10785. if (_sg_validate_update_image(img, data)) {
  10786. SOKOL_ASSERT(img->cmn.upd_frame_index != _sg.frame_index);
  10787. _sg_update_image(img, data);
  10788. img->cmn.upd_frame_index = _sg.frame_index;
  10789. }
  10790. }
  10791. _SG_TRACE_ARGS(update_image, img_id, data);
  10792. }
  10793. SOKOL_API_IMPL void sg_push_debug_group(const char* name) {
  10794. SOKOL_ASSERT(_sg.valid);
  10795. SOKOL_ASSERT(name);
  10796. _SG_TRACE_ARGS(push_debug_group, name);
  10797. }
  10798. SOKOL_API_IMPL void sg_pop_debug_group(void) {
  10799. SOKOL_ASSERT(_sg.valid);
  10800. _SG_TRACE_NOARGS(pop_debug_group);
  10801. }
  10802. SOKOL_API_IMPL sg_buffer_info sg_query_buffer_info(sg_buffer buf_id) {
  10803. SOKOL_ASSERT(_sg.valid);
  10804. sg_buffer_info info;
  10805. memset(&info, 0, sizeof(info));
  10806. const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);
  10807. if (buf) {
  10808. info.slot.state = buf->slot.state;
  10809. info.slot.res_id = buf->slot.id;
  10810. info.slot.ctx_id = buf->slot.ctx_id;
  10811. info.update_frame_index = buf->cmn.update_frame_index;
  10812. info.append_frame_index = buf->cmn.append_frame_index;
  10813. info.append_pos = buf->cmn.append_pos;
  10814. info.append_overflow = buf->cmn.append_overflow;
  10815. #if defined(SOKOL_D3D11)
  10816. info.num_slots = 1;
  10817. info.active_slot = 0;
  10818. #else
  10819. info.num_slots = buf->cmn.num_slots;
  10820. info.active_slot = buf->cmn.active_slot;
  10821. #endif
  10822. }
  10823. return info;
  10824. }
  10825. SOKOL_API_IMPL sg_image_info sg_query_image_info(sg_image img_id) {
  10826. SOKOL_ASSERT(_sg.valid);
  10827. sg_image_info info;
  10828. memset(&info, 0, sizeof(info));
  10829. const _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);
  10830. if (img) {
  10831. info.slot.state = img->slot.state;
  10832. info.slot.res_id = img->slot.id;
  10833. info.slot.ctx_id = img->slot.ctx_id;
  10834. #if defined(SOKOL_D3D11)
  10835. info.num_slots = 1;
  10836. info.active_slot = 0;
  10837. #else
  10838. info.num_slots = img->cmn.num_slots;
  10839. info.active_slot = img->cmn.active_slot;
  10840. #endif
  10841. }
  10842. return info;
  10843. }
  10844. SOKOL_API_IMPL sg_shader_info sg_query_shader_info(sg_shader shd_id) {
  10845. SOKOL_ASSERT(_sg.valid);
  10846. sg_shader_info info;
  10847. memset(&info, 0, sizeof(info));
  10848. const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);
  10849. if (shd) {
  10850. info.slot.state = shd->slot.state;
  10851. info.slot.res_id = shd->slot.id;
  10852. info.slot.ctx_id = shd->slot.ctx_id;
  10853. }
  10854. return info;
  10855. }
  10856. SOKOL_API_IMPL sg_pipeline_info sg_query_pipeline_info(sg_pipeline pip_id) {
  10857. SOKOL_ASSERT(_sg.valid);
  10858. sg_pipeline_info info;
  10859. memset(&info, 0, sizeof(info));
  10860. const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);
  10861. if (pip) {
  10862. info.slot.state = pip->slot.state;
  10863. info.slot.res_id = pip->slot.id;
  10864. info.slot.ctx_id = pip->slot.ctx_id;
  10865. }
  10866. return info;
  10867. }
  10868. SOKOL_API_IMPL sg_pass_info sg_query_pass_info(sg_pass pass_id) {
  10869. SOKOL_ASSERT(_sg.valid);
  10870. sg_pass_info info;
  10871. memset(&info, 0, sizeof(info));
  10872. const _sg_pass_t* pass = _sg_lookup_pass(&_sg.pools, pass_id.id);
  10873. if (pass) {
  10874. info.slot.state = pass->slot.state;
  10875. info.slot.res_id = pass->slot.id;
  10876. info.slot.ctx_id = pass->slot.ctx_id;
  10877. }
  10878. return info;
  10879. }
  10880. SOKOL_API_IMPL sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc* desc) {
  10881. SOKOL_ASSERT(_sg.valid && desc);
  10882. return _sg_buffer_desc_defaults(desc);
  10883. }
  10884. SOKOL_API_IMPL sg_image_desc sg_query_image_defaults(const sg_image_desc* desc) {
  10885. SOKOL_ASSERT(_sg.valid && desc);
  10886. return _sg_image_desc_defaults(desc);
  10887. }
  10888. SOKOL_API_IMPL sg_shader_desc sg_query_shader_defaults(const sg_shader_desc* desc) {
  10889. SOKOL_ASSERT(_sg.valid && desc);
  10890. return _sg_shader_desc_defaults(desc);
  10891. }
  10892. SOKOL_API_IMPL sg_pipeline_desc sg_query_pipeline_defaults(const sg_pipeline_desc* desc) {
  10893. SOKOL_ASSERT(_sg.valid && desc);
  10894. return _sg_pipeline_desc_defaults(desc);
  10895. }
  10896. SOKOL_API_IMPL sg_pass_desc sg_query_pass_defaults(const sg_pass_desc* desc) {
  10897. SOKOL_ASSERT(_sg.valid && desc);
  10898. return _sg_pass_desc_defaults(desc);
  10899. }
  10900. #ifdef _MSC_VER
  10901. #pragma warning(pop)
  10902. #endif
  10903. #endif /* SOKOL_IMPL */