| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468 |
- //-------------------------------------------------------------------------------------
- // BC6HBC7.cpp
- //
- // Block-compression (BC) functionality for BC6H and BC7 (DirectX 11 texture compression)
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- // PARTICULAR PURPOSE.
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //
- // http://go.microsoft.com/fwlink/?LinkId=248926
- //-------------------------------------------------------------------------------------
- //#include "directxtexp.h" ESENTHEL
- //#include "BC.h" ESENTHEL
- using namespace DirectX;
- using namespace DirectX::PackedVector;
- //-------------------------------------------------------------------------------------
- // Macros
- //-------------------------------------------------------------------------------------
- #define SIGN_EXTEND(x,nb) ((((x)&(1<<((nb)-1)))?((~0)<<(nb)):0)|(x))
- // Because these are used in SAL annotations, they need to remain macros rather than const values
- #define BC6H_MAX_REGIONS 2
- #define BC6H_MAX_INDICES 16
- #define BC7_MAX_REGIONS 3
- #define BC7_MAX_INDICES 16
- namespace
- {
- //-------------------------------------------------------------------------------------
- // Constants
- //-------------------------------------------------------------------------------------
- const uint16_t F16S_MASK = 0x8000; // f16 sign mask
- const uint16_t F16EM_MASK = 0x7fff; // f16 exp & mantissa mask
- const uint16_t F16MAX = 0x7bff; // MAXFLT bit pattern for XMHALF
- const size_t BC6H_NUM_CHANNELS = 3;
- const size_t BC6H_MAX_SHAPES = 32;
- const size_t BC7_NUM_CHANNELS = 4;
- const size_t BC7_MAX_SHAPES = 64;
- const int32_t BC67_WEIGHT_MAX = 64;
- const uint32_t BC67_WEIGHT_SHIFT = 6;
- const int32_t BC67_WEIGHT_ROUND = 32;
- const float fEpsilon = (0.25f / 64.0f) * (0.25f / 64.0f);
- const float pC3[] = { 2.0f / 2.0f, 1.0f / 2.0f, 0.0f / 2.0f };
- const float pD3[] = { 0.0f / 2.0f, 1.0f / 2.0f, 2.0f / 2.0f };
- const float pC4[] = { 3.0f / 3.0f, 2.0f / 3.0f, 1.0f / 3.0f, 0.0f / 3.0f };
- const float pD4[] = { 0.0f / 3.0f, 1.0f / 3.0f, 2.0f / 3.0f, 3.0f / 3.0f };
- // Partition, Shape, Pixel (index into 4x4 block)
- const uint8_t g_aPartitionTable[3][64][16] =
- {
- { // 1 Region case has no subsets (all 0)
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
- },
- { // BC6H/BC7 Partition Set for 2 Subsets
- { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, // Shape 0
- { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 }, // Shape 1
- { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }, // Shape 2
- { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 }, // Shape 3
- { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 }, // Shape 4
- { 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, // Shape 5
- { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, // Shape 6
- { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 }, // Shape 7
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 }, // Shape 8
- { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 9
- { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, // Shape 10
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 }, // Shape 11
- { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 12
- { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 13
- { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 14
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }, // Shape 15
- { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1 }, // Shape 16
- { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // Shape 17
- { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 }, // Shape 18
- { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 }, // Shape 19
- { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // Shape 20
- { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 }, // Shape 21
- { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 }, // Shape 22
- { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 }, // Shape 23
- { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 }, // Shape 24
- { 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 }, // Shape 25
- { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 }, // Shape 26
- { 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0 }, // Shape 27
- { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 }, // Shape 28
- { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // Shape 29
- { 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 }, // Shape 30
- { 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 }, // Shape 31
- // BC7 Partition Set for 2 Subsets (second-half)
- { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, // Shape 32
- { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 }, // Shape 33
- { 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0 }, // Shape 34
- { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 }, // Shape 35
- { 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 }, // Shape 36
- { 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 }, // Shape 37
- { 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 }, // Shape 38
- { 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 }, // Shape 39
- { 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0 }, // Shape 40
- { 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 }, // Shape 41
- { 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 }, // Shape 42
- { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0 }, // Shape 43
- { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }, // Shape 44
- { 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 }, // Shape 45
- { 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 }, // Shape 46
- { 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // Shape 47
- { 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, // Shape 48
- { 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 }, // Shape 49
- { 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0 }, // Shape 50
- { 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0 }, // Shape 51
- { 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 }, // Shape 52
- { 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1 }, // Shape 53
- { 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0 }, // Shape 54
- { 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0 }, // Shape 55
- { 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 }, // Shape 56
- { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1 }, // Shape 57
- { 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 }, // Shape 58
- { 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 }, // Shape 59
- { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }, // Shape 60
- { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // Shape 61
- { 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 }, // Shape 62
- { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1 } // Shape 63
- },
- { // BC7 Partition Set for 3 Subsets
- { 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2 }, // Shape 0
- { 0, 0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1 }, // Shape 1
- { 0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1 }, // Shape 2
- { 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1 }, // Shape 3
- { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2 }, // Shape 4
- { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2 }, // Shape 5
- { 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 }, // Shape 6
- { 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1 }, // Shape 7
- { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 }, // Shape 8
- { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2 }, // Shape 9
- { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2 }, // Shape 10
- { 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2 }, // Shape 11
- { 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2 }, // Shape 12
- { 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2 }, // Shape 13
- { 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2 }, // Shape 14
- { 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0 }, // Shape 15
- { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2 }, // Shape 16
- { 0, 1, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0 }, // Shape 17
- { 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2 }, // Shape 18
- { 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1 }, // Shape 19
- { 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2 }, // Shape 20
- { 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 2, 1 }, // Shape 21
- { 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2 }, // Shape 22
- { 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 1, 0, 2, 2, 1, 0 }, // Shape 23
- { 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0 }, // Shape 24
- { 0, 0, 1, 2, 0, 0, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2 }, // Shape 25
- { 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0 }, // Shape 26
- { 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1 }, // Shape 27
- { 0, 0, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 2, 2 }, // Shape 28
- { 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 2, 2, 2, 2 }, // Shape 29
- { 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1 }, // Shape 30
- { 0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1 }, // Shape 31
- { 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 2, 2, 2 }, // Shape 32
- { 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 0, 1, 1 }, // Shape 33
- { 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 2, 2, 2 }, // Shape 34
- { 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0 }, // Shape 35
- { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0 }, // Shape 36
- { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 }, // Shape 37
- { 0, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 0, 1, 2, 0 }, // Shape 38
- { 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1 }, // Shape 39
- { 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1 }, // Shape 40
- { 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2 }, // Shape 41
- { 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1 }, // Shape 42
- { 0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 2, 2 }, // Shape 43
- { 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1 }, // Shape 44
- { 0, 2, 2, 0, 1, 2, 2, 1, 0, 2, 2, 0, 1, 2, 2, 1 }, // Shape 45
- { 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1 }, // Shape 46
- { 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 }, // Shape 47
- { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2 }, // Shape 48
- { 0, 2, 2, 2, 0, 1, 1, 1, 0, 2, 2, 2, 0, 1, 1, 1 }, // Shape 49
- { 0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2 }, // Shape 50
- { 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2 }, // Shape 51
- { 0, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2 }, // Shape 52
- { 0, 0, 0, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2 }, // Shape 53
- { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2 }, // Shape 54
- { 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2 }, // Shape 55
- { 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2 }, // Shape 56
- { 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2 }, // Shape 57
- { 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2 }, // Shape 58
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2 }, // Shape 59
- { 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1 }, // Shape 60
- { 0, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2 }, // Shape 61
- { 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, // Shape 62
- { 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 2, 2, 2, 0 } // Shape 63
- }
- };
- // Partition, Shape, Fixup
- const uint8_t g_aFixUp[3][64][3] =
- {
- { // No fix-ups for 1st subset for BC6H or BC7
- { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },
- { 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },{ 0, 0, 0 },
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0},
- { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}
- },
- { // BC6H/BC7 Partition Set Fixups for 2 Subsets
- { 0,15, 0}, { 0,15, 0}, { 0,15, 0}, { 0,15, 0},
- { 0,15, 0}, { 0,15, 0}, { 0,15, 0}, { 0,15, 0},
- { 0,15, 0}, { 0,15, 0}, { 0,15, 0}, { 0,15, 0},
- { 0,15, 0}, { 0,15, 0}, { 0,15, 0}, { 0,15, 0},
- { 0,15, 0}, { 0, 2, 0}, { 0, 8, 0}, { 0, 2, 0},
- { 0, 2, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0,15, 0},
- { 0, 2, 0}, { 0, 8, 0}, { 0, 2, 0}, { 0, 2, 0},
- { 0, 8, 0}, { 0, 8, 0}, { 0, 2, 0}, { 0, 2, 0},
- // BC7 Partition Set Fixups for 2 Subsets (second-half)
- { 0,15, 0}, { 0,15, 0}, { 0, 6, 0}, { 0, 8, 0},
- { 0, 2, 0}, { 0, 8, 0}, { 0,15, 0}, { 0,15, 0},
- { 0, 2, 0}, { 0, 8, 0}, { 0, 2, 0}, { 0, 2, 0},
- { 0, 2, 0}, { 0,15, 0}, { 0,15, 0}, { 0, 6, 0},
- { 0, 6, 0}, { 0, 2, 0}, { 0, 6, 0}, { 0, 8, 0},
- { 0,15, 0}, { 0,15, 0}, { 0, 2, 0}, { 0, 2, 0},
- { 0,15, 0}, { 0,15, 0}, { 0,15, 0}, { 0,15, 0},
- { 0,15, 0}, { 0, 2, 0}, { 0, 2, 0}, { 0,15, 0}
- },
- { // BC7 Partition Set Fixups for 3 Subsets
- { 0, 3,15}, { 0, 3, 8}, { 0,15, 8}, { 0,15, 3},
- { 0, 8,15}, { 0, 3,15}, { 0,15, 3}, { 0,15, 8},
- { 0, 8,15}, { 0, 8,15}, { 0, 6,15}, { 0, 6,15},
- { 0, 6,15}, { 0, 5,15}, { 0, 3,15}, { 0, 3, 8},
- { 0, 3,15}, { 0, 3, 8}, { 0, 8,15}, { 0,15, 3},
- { 0, 3,15}, { 0, 3, 8}, { 0, 6,15}, { 0,10, 8},
- { 0, 5, 3}, { 0, 8,15}, { 0, 8, 6}, { 0, 6,10},
- { 0, 8,15}, { 0, 5,15}, { 0,15,10}, { 0,15, 8},
- { 0, 8,15}, { 0,15, 3}, { 0, 3,15}, { 0, 5,10},
- { 0, 6,10}, { 0,10, 8}, { 0, 8, 9}, { 0,15,10},
- { 0,15, 6}, { 0, 3,15}, { 0,15, 8}, { 0, 5,15},
- { 0,15, 3}, { 0,15, 6}, { 0,15, 6}, { 0,15, 8},
- { 0, 3,15}, { 0,15, 3}, { 0, 5,15}, { 0, 5,15},
- { 0, 5,15}, { 0, 8,15}, { 0, 5,15}, { 0,10,15},
- { 0, 5,15}, { 0,10,15}, { 0, 8,15}, { 0,13,15},
- { 0,15, 3}, { 0,12,15}, { 0, 3,15}, { 0, 3, 8}
- }
- };
- const int g_aWeights2[] = { 0, 21, 43, 64 };
- const int g_aWeights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 };
- const int g_aWeights4[] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
- }
- namespace DirectX
- {
- class LDRColorA
- {
- public:
- uint8_t r, g, b, a;
- LDRColorA() = default;
- LDRColorA(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) : r(_r), g(_g), b(_b), a(_a) {}
- const uint8_t& operator [] (_In_range_(0, 3) size_t uElement) const
- {
- switch (uElement)
- {
- case 0: return r;
- case 1: return g;
- case 2: return b;
- case 3: return a;
- default: assert(false); return r;
- }
- }
- uint8_t& operator [] (_In_range_(0, 3) size_t uElement)
- {
- switch (uElement)
- {
- case 0: return r;
- case 1: return g;
- case 2: return b;
- case 3: return a;
- default: assert(false); return r;
- }
- }
- LDRColorA operator = (_In_ const HDRColorA& c)
- {
- LDRColorA ret;
- HDRColorA tmp(c);
- tmp = tmp.Clamp(0.0f, 1.0f) * 255.0f;
- ret.r = uint8_t(tmp.r + 0.001f);
- ret.g = uint8_t(tmp.g + 0.001f);
- ret.b = uint8_t(tmp.b + 0.001f);
- ret.a = uint8_t(tmp.a + 0.001f);
- return ret;
- }
- static void InterpolateRGB(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ _In_range_(2, 4) size_t wcprec, _Out_ LDRColorA& out)
- {
- const int* aWeights = nullptr;
- switch (wcprec)
- {
- case 2: aWeights = g_aWeights2; assert(wc < 4); _Analysis_assume_(wc < 4); break;
- case 3: aWeights = g_aWeights3; assert(wc < 8); _Analysis_assume_(wc < 8); break;
- case 4: aWeights = g_aWeights4; assert(wc < 16); _Analysis_assume_(wc < 16); break;
- default: assert(false); out.r = out.g = out.b = 0; return;
- }
- out.r = uint8_t((uint32_t(c0.r) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.r) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
- out.g = uint8_t((uint32_t(c0.g) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.g) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
- out.b = uint8_t((uint32_t(c0.b) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.b) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
- }
- static void InterpolateA(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wa, _In_range_(2, 4) _In_ size_t waprec, _Out_ LDRColorA& out)
- {
- const int* aWeights = nullptr;
- switch (waprec)
- {
- case 2: aWeights = g_aWeights2; assert(wa < 4); _Analysis_assume_(wa < 4); break;
- case 3: aWeights = g_aWeights3; assert(wa < 8); _Analysis_assume_(wa < 8); break;
- case 4: aWeights = g_aWeights4; assert(wa < 16); _Analysis_assume_(wa < 16); break;
- default: assert(false); out.a = 0; return;
- }
- out.a = uint8_t((uint32_t(c0.a) * uint32_t(BC67_WEIGHT_MAX - aWeights[wa]) + uint32_t(c1.a) * uint32_t(aWeights[wa]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
- }
- static void Interpolate(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ size_t wa, _In_ _In_range_(2, 4) size_t wcprec, _In_ _In_range_(2, 4) size_t waprec, _Out_ LDRColorA& out)
- {
- InterpolateRGB(c0, c1, wc, wcprec, out);
- InterpolateA(c0, c1, wa, waprec, out);
- }
- };
- static_assert(sizeof(LDRColorA) == 4, "Unexpected packing");
- struct LDREndPntPair
- {
- LDRColorA A;
- LDRColorA B;
- };
- inline HDRColorA::HDRColorA(const LDRColorA& c)
- {
- r = float(c.r) * (1.0f / 255.0f);
- g = float(c.g) * (1.0f / 255.0f);
- b = float(c.b) * (1.0f / 255.0f);
- a = float(c.a) * (1.0f / 255.0f);
- }
- inline HDRColorA& HDRColorA::operator = (const LDRColorA& c)
- {
- r = (float)c.r;
- g = (float)c.g;
- b = (float)c.b;
- a = (float)c.a;
- return *this;
- }
- inline LDRColorA HDRColorA::ToLDRColorA() const
- {
- return LDRColorA((uint8_t)(r + 0.01f), (uint8_t)(g + 0.01f), (uint8_t)(b + 0.01f), (uint8_t)(a + 0.01f));
- }
- }
- namespace
- {
- class INTColor
- {
- public:
- int r, g, b;
- int pad;
- public:
- INTColor() = default;
- INTColor(int nr, int ng, int nb) { r = nr; g = ng; b = nb; }
- INTColor(const INTColor& c) { r = c.r; g = c.g; b = c.b; }
- INTColor operator - (_In_ const INTColor& c) const
- {
- return INTColor(r - c.r, g - c.g, b - c.b);
- }
- INTColor& operator += (_In_ const INTColor& c)
- {
- r += c.r;
- g += c.g;
- b += c.b;
- return *this;
- }
- INTColor& operator -= (_In_ const INTColor& c)
- {
- r -= c.r;
- g -= c.g;
- b -= c.b;
- return *this;
- }
- INTColor& operator &= (_In_ const INTColor& c)
- {
- r &= c.r;
- g &= c.g;
- b &= c.b;
- return *this;
- }
- int& operator [] (_In_ uint8_t i)
- {
- assert(i < sizeof(INTColor) / sizeof(int));
- _Analysis_assume_(i < sizeof(INTColor) / sizeof(int));
- return ((int*) this)[i];
- }
- void Set(_In_ const HDRColorA& c, _In_ bool bSigned)
- {
- PackedVector::XMHALF4 aF16;
- XMVECTOR v = XMLoadFloat4((const XMFLOAT4*)& c);
- XMStoreHalf4(&aF16, v);
- r = F16ToINT(aF16.x, bSigned);
- g = F16ToINT(aF16.y, bSigned);
- b = F16ToINT(aF16.z, bSigned);
- }
- INTColor& Clamp(_In_ int iMin, _In_ int iMax)
- {
- r = std::min<int>(iMax, std::max<int>(iMin, r));
- g = std::min<int>(iMax, std::max<int>(iMin, g));
- b = std::min<int>(iMax, std::max<int>(iMin, b));
- return *this;
- }
- INTColor& SignExtend(_In_ const LDRColorA& Prec)
- {
- r = SIGN_EXTEND(r, Prec.r);
- g = SIGN_EXTEND(g, Prec.g);
- b = SIGN_EXTEND(b, Prec.b);
- return *this;
- }
- void ToF16(_Out_writes_(3) PackedVector::HALF aF16[3], _In_ bool bSigned) const
- {
- aF16[0] = INT2F16(r, bSigned);
- aF16[1] = INT2F16(g, bSigned);
- aF16[2] = INT2F16(b, bSigned);
- }
- private:
- static int F16ToINT(_In_ const PackedVector::HALF& f, _In_ bool bSigned)
- {
- uint16_t input = *((const uint16_t*)&f);
- int out, s;
- if (bSigned)
- {
- s = input & F16S_MASK;
- input &= F16EM_MASK;
- if (input > F16MAX) out = F16MAX;
- else out = input;
- out = s ? -out : out;
- }
- else
- {
- if (input & F16S_MASK) out = 0;
- else out = input;
- }
- return out;
- }
- static PackedVector::HALF INT2F16(_In_ int input, _In_ bool bSigned)
- {
- PackedVector::HALF h;
- uint16_t out;
- if (bSigned)
- {
- int s = 0;
- if (input < 0)
- {
- s = F16S_MASK;
- input = -input;
- }
- out = uint16_t(s | input);
- }
- else
- {
- assert(input >= 0 && input <= F16MAX);
- out = (uint16_t)input;
- }
- *((uint16_t*)&h) = out;
- return h;
- }
- };
- static_assert(sizeof(INTColor) == 16, "Unexpected packing");
- struct INTEndPntPair
- {
- INTColor A;
- INTColor B;
- };
- template< size_t SizeInBytes >
- class CBits
- {
- public:
- uint8_t GetBit(_Inout_ size_t& uStartBit) const
- {
- assert(uStartBit < 128);
- _Analysis_assume_(uStartBit < 128);
- size_t uIndex = uStartBit >> 3;
- uint8_t ret = (m_uBits[uIndex] >> (uStartBit - (uIndex << 3))) & 0x01;
- uStartBit++;
- return ret;
- }
- uint8_t GetBits(_Inout_ size_t& uStartBit, _In_ size_t uNumBits) const
- {
- if (uNumBits == 0) return 0;
- assert(uStartBit + uNumBits <= 128 && uNumBits <= 8);
- _Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8);
- uint8_t ret;
- size_t uIndex = uStartBit >> 3;
- size_t uBase = uStartBit - (uIndex << 3);
- if (uBase + uNumBits > 8)
- {
- size_t uFirstIndexBits = 8 - uBase;
- size_t uNextIndexBits = uNumBits - uFirstIndexBits;
- ret = (m_uBits[uIndex] >> uBase) | ((m_uBits[uIndex + 1] & ((1 << uNextIndexBits) - 1)) << uFirstIndexBits);
- }
- else
- {
- ret = (m_uBits[uIndex] >> uBase) & ((1 << uNumBits) - 1);
- }
- assert(ret < (1 << uNumBits));
- uStartBit += uNumBits;
- return ret;
- }
- void SetBit(_Inout_ size_t& uStartBit, _In_ uint8_t uValue)
- {
- assert(uStartBit < 128 && uValue < 2);
- _Analysis_assume_(uStartBit < 128 && uValue < 2);
- size_t uIndex = uStartBit >> 3;
- size_t uBase = uStartBit - (uIndex << 3);
- m_uBits[uIndex] &= ~(1 << uBase);
- m_uBits[uIndex] |= uValue << uBase;
- uStartBit++;
- }
- void SetBits(_Inout_ size_t& uStartBit, _In_ size_t uNumBits, _In_ uint8_t uValue)
- {
- if (uNumBits == 0)
- return;
- assert(uStartBit + uNumBits <= 128 && uNumBits <= 8);
- _Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8);
- assert(uValue < (1 << uNumBits));
- size_t uIndex = uStartBit >> 3;
- size_t uBase = uStartBit - (uIndex << 3);
- if (uBase + uNumBits > 8)
- {
- size_t uFirstIndexBits = 8 - uBase;
- size_t uNextIndexBits = uNumBits - uFirstIndexBits;
- m_uBits[uIndex] &= ~(((1 << uFirstIndexBits) - 1) << uBase);
- m_uBits[uIndex] |= uValue << uBase;
- m_uBits[uIndex + 1] &= ~((1 << uNextIndexBits) - 1);
- m_uBits[uIndex + 1] |= uValue >> uFirstIndexBits;
- }
- else
- {
- m_uBits[uIndex] &= ~(((1 << uNumBits) - 1) << uBase);
- m_uBits[uIndex] |= uValue << uBase;
- }
- uStartBit += uNumBits;
- }
- private:
- uint8_t m_uBits[SizeInBytes];
- };
- // BC6H compression (16 bits per texel)
- class D3DX_BC6H : private CBits< 16 >
- {
- public:
- void Decode(_In_ bool bSigned, _Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) const;
- void Encode(_In_ bool bSigned, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn);
- private:
- #pragma warning(push)
- #pragma warning(disable : 4480)
- enum EField : uint8_t
- {
- NA, // N/A
- M, // Mode
- D, // Shape
- RW,
- RX,
- RY,
- RZ,
- GW,
- GX,
- GY,
- GZ,
- BW,
- BX,
- BY,
- BZ,
- };
- #pragma warning(pop)
- struct ModeDescriptor
- {
- EField m_eField;
- uint8_t m_uBit;
- };
- struct ModeInfo
- {
- uint8_t uMode;
- uint8_t uPartitions;
- bool bTransformed;
- uint8_t uIndexPrec;
- LDRColorA RGBAPrec[BC6H_MAX_REGIONS][2];
- };
- #pragma warning(push)
- #pragma warning(disable : 4512)
- struct EncodeParams
- {
- float fBestErr;
- const bool bSigned;
- uint8_t uMode;
- uint8_t uShape;
- const HDRColorA* const aHDRPixels;
- INTEndPntPair aUnqEndPts[BC6H_MAX_SHAPES][BC6H_MAX_REGIONS];
- INTColor aIPixels[NUM_PIXELS_PER_BLOCK];
- EncodeParams(const HDRColorA* const aOriginal, bool bSignedFormat) :
- fBestErr(FLT_MAX), bSigned(bSignedFormat), aHDRPixels(aOriginal)
- {
- for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- aIPixels[i].Set(aOriginal[i], bSigned);
- }
- }
- };
- #pragma warning(pop)
- static int Quantize(_In_ int iValue, _In_ int prec, _In_ bool bSigned);
- static int Unquantize(_In_ int comp, _In_ uint8_t uBitsPerComp, _In_ bool bSigned);
- static int FinishUnquantize(_In_ int comp, _In_ bool bSigned);
- static bool EndPointsFit(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[]);
- void GeneratePaletteQuantized(_In_ const EncodeParams* pEP, _In_ const INTEndPntPair& endPts,
- _Out_writes_(BC6H_MAX_INDICES) INTColor aPalette[]) const;
- float MapColorsQuantized(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ const INTEndPntPair &endPts) const;
- float PerturbOne(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ uint8_t ch,
- _In_ const INTEndPntPair& oldEndPts, _Out_ INTEndPntPair& newEndPts, _In_ float fOldErr, _In_ int do_b) const;
- void OptimizeOne(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ float aOrgErr,
- _In_ const INTEndPntPair &aOrgEndPts, _Out_ INTEndPntPair &aOptEndPts) const;
- void OptimizeEndPoints(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const float aOrgErr[],
- _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aOrgEndPts[],
- _Out_writes_all_(BC6H_MAX_REGIONS) INTEndPntPair aOptEndPts[]) const;
- static void SwapIndices(_In_ const EncodeParams* pEP, _Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[],
- _In_reads_(NUM_PIXELS_PER_BLOCK) size_t aIndices[]);
- void AssignIndices(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[],
- _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices[],
- _Out_writes_(BC6H_MAX_REGIONS) float aTotErr[]) const;
- void QuantizeEndPts(_In_ const EncodeParams* pEP, _Out_writes_(BC6H_MAX_REGIONS) INTEndPntPair* qQntEndPts) const;
- void EmitBlock(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[],
- _In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndices[]);
- void Refine(_Inout_ EncodeParams* pEP);
- static void GeneratePaletteUnquantized(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _Out_writes_(BC6H_MAX_INDICES) INTColor aPalette[]);
- float MapColors(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _In_ size_t np, _In_reads_(np) const size_t* auIndex) const;
- float RoughMSE(_Inout_ EncodeParams* pEP) const;
- private:
- const static ModeDescriptor ms_aDesc[][82];
- const static ModeInfo ms_aInfo[];
- const static int ms_aModeToInfo[];
- };
- // BC67 compression (16b bits per texel)
- class D3DX_BC7 : private CBits< 16 >
- {
- public:
- void Decode(Color (&pOut)[4][4]) const; // ESENTHEL CHANGED
- void Encode(DWORD flags, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn);
- private:
- struct ModeInfo
- {
- uint8_t uPartitions;
- uint8_t uPartitionBits;
- uint8_t uPBits;
- uint8_t uRotationBits;
- uint8_t uIndexModeBits;
- uint8_t uIndexPrec;
- uint8_t uIndexPrec2;
- LDRColorA RGBAPrec;
- LDRColorA RGBAPrecWithP;
- };
- #pragma warning(push)
- #pragma warning(disable : 4512)
- struct EncodeParams
- {
- uint8_t uMode;
- LDREndPntPair aEndPts[BC7_MAX_SHAPES][BC7_MAX_REGIONS];
- LDRColorA aLDRPixels[NUM_PIXELS_PER_BLOCK];
- const HDRColorA* const aHDRPixels;
- EncodeParams(const HDRColorA* const aOriginal) : aHDRPixels(aOriginal) {}
- };
- #pragma warning(pop)
- static uint8_t Quantize(_In_ uint8_t comp, _In_ uint8_t uPrec)
- {
- assert(0 < uPrec && uPrec <= 8);
- uint8_t rnd = (uint8_t)std::min<uint16_t>(255, uint16_t(comp) + (1 << (7 - uPrec)));
- return rnd >> (8 - uPrec);
- }
- static LDRColorA Quantize(_In_ const LDRColorA& c, _In_ const LDRColorA& RGBAPrec)
- {
- LDRColorA q;
- q.r = Quantize(c.r, RGBAPrec.r);
- q.g = Quantize(c.g, RGBAPrec.g);
- q.b = Quantize(c.b, RGBAPrec.b);
- if (RGBAPrec.a)
- q.a = Quantize(c.a, RGBAPrec.a);
- else
- q.a = 255;
- return q;
- }
- static uint8_t Unquantize(_In_ uint8_t comp, _In_ size_t uPrec)
- {
- assert(0 < uPrec && uPrec <= 8);
- comp = comp << (8 - uPrec);
- return comp | (comp >> uPrec);
- }
- static LDRColorA Unquantize(_In_ const LDRColorA& c, _In_ const LDRColorA& RGBAPrec)
- {
- LDRColorA q;
- q.r = Unquantize(c.r, RGBAPrec.r);
- q.g = Unquantize(c.g, RGBAPrec.g);
- q.b = Unquantize(c.b, RGBAPrec.b);
- q.a = RGBAPrec.a > 0 ? Unquantize(c.a, RGBAPrec.a) : 255;
- return q;
- }
- void GeneratePaletteQuantized(_In_ const EncodeParams* pEP, _In_ size_t uIndexMode, _In_ const LDREndPntPair& endpts,
- _Out_writes_(BC7_MAX_INDICES) LDRColorA aPalette[]) const;
- float PerturbOne(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode,
- _In_ size_t ch, _In_ const LDREndPntPair &old_endpts,
- _Out_ LDREndPntPair &new_endpts, _In_ float old_err, _In_ uint8_t do_b) const;
- void Exhaustive(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode,
- _In_ size_t ch, _Inout_ float& fOrgErr, _Inout_ LDREndPntPair& optEndPt) const;
- void OptimizeOne(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode,
- _In_ float orig_err, _In_ const LDREndPntPair &orig_endpts, _Out_ LDREndPntPair &opt_endpts) const;
- void OptimizeEndPoints(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode,
- _In_reads_(BC7_MAX_REGIONS) const float orig_err[],
- _In_reads_(BC7_MAX_REGIONS) const LDREndPntPair orig_endpts[],
- _Out_writes_(BC7_MAX_REGIONS) LDREndPntPair opt_endpts[]) const;
- void AssignIndices(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode,
- _In_reads_(BC7_MAX_REGIONS) LDREndPntPair endpts[],
- _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices[], _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices2[],
- _Out_writes_(BC7_MAX_REGIONS) float afTotErr[]) const;
- void EmitBlock(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uRotation, _In_ size_t uIndexMode,
- _In_reads_(BC7_MAX_REGIONS) const LDREndPntPair aEndPts[],
- _In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndex[],
- _In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndex2[]);
- float Refine(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uRotation, _In_ size_t uIndexMode);
- float MapColors(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode,
- _In_ const LDREndPntPair& endPts, _In_ float fMinErr) const;
- static float RoughMSE(_Inout_ EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode);
- private:
- const static ModeInfo ms_aInfo[];
- };
- }
- // BC6H Compression
- const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
- {
- { // Mode 1 (0x00) - 10 5 5 5
- { M, 0}, { M, 1}, {GY, 4}, {BY, 4}, {BZ, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4},
- {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 2 (0x01) - 7 6 6 6
- { M, 0}, { M, 1}, {GY, 5}, {GZ, 4}, {GZ, 5}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {BZ, 0}, {BZ, 1}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {BY, 5}, {BZ, 2}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BZ, 3}, {BZ, 5}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {RX, 5}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {GX, 5}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BX, 5}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4},
- {RY, 5}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {RZ, 5}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 3 (0x02) - 11 5 4 4
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {RW,10}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GW,10},
- {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BW,10},
- {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4},
- {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 4 (0x06) - 11 4 5 4
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RW,10},
- {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {GW,10}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BW,10},
- {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {BZ, 0},
- {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {GY, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 5 (0x0a) - 11 4 4 5
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RW,10},
- {BY, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GW,10},
- {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BW,10}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {BZ, 1},
- {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {BZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 6 (0x0e) - 9 5 5 5
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4},
- {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 7 (0x12) - 8 6 5 5
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {GZ, 4}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {BZ, 2}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BZ, 3}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {RX, 5}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4},
- {RY, 5}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {RZ, 5}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 8 (0x16) - 8 5 6 5
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {BZ, 0}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GY, 5}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {GZ, 5}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {GX, 5}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BZ, 1}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4},
- {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 9 (0x1a) - 8 5 5 6
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {BZ, 1}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {BY, 5}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BZ, 5}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {GZ, 4}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {BZ, 0}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BX, 5}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4},
- {BZ, 2}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {BZ, 3}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 10 (0x1e) - 6 6 6 6
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {GZ, 4}, {BZ, 0}, {BZ, 1}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GY, 5}, {BY, 5}, {BZ, 2}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {GZ, 5}, {BZ, 3}, {BZ, 5}, {BZ, 4}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {RX, 5}, {GY, 0}, {GY, 1}, {GY, 2}, {GY, 3}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {GX, 5}, {GZ, 0}, {GZ, 1}, {GZ, 2}, {GZ, 3}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BX, 5}, {BY, 0}, {BY, 1}, {BY, 2}, {BY, 3}, {RY, 0}, {RY, 1}, {RY, 2}, {RY, 3}, {RY, 4},
- {RY, 5}, {RZ, 0}, {RZ, 1}, {RZ, 2}, {RZ, 3}, {RZ, 4}, {RZ, 5}, { D, 0}, { D, 1}, { D, 2},
- { D, 3}, { D, 4},
- },
- { // Mode 11 (0x03) - 10 10
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {RX, 5}, {RX, 6}, {RX, 7}, {RX, 8}, {RX, 9}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {GX, 5}, {GX, 6}, {GX, 7}, {GX, 8}, {GX, 9}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BX, 5}, {BX, 6}, {BX, 7}, {BX, 8}, {BX, 9}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0},
- {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0},
- {NA, 0}, {NA, 0},
- },
- { // Mode 12 (0x07) - 11 9
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {RX, 5}, {RX, 6}, {RX, 7}, {RX, 8}, {RW,10}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {GX, 5}, {GX, 6}, {GX, 7}, {GX, 8}, {GW,10}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BX, 5}, {BX, 6}, {BX, 7}, {BX, 8}, {BW,10}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0},
- {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0},
- {NA, 0}, {NA, 0},
- },
- { // Mode 13 (0x0b) - 12 8
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RX, 4},
- {RX, 5}, {RX, 6}, {RX, 7}, {RW,11}, {RW,10}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GX, 4},
- {GX, 5}, {GX, 6}, {GX, 7}, {GW,11}, {GW,10}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BX, 4},
- {BX, 5}, {BX, 6}, {BX, 7}, {BW,11}, {BW,10}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0},
- {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0},
- {NA, 0}, {NA, 0},
- },
- { // Mode 14 (0x0f) - 16 4
- { M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
- {RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
- {GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
- {BW, 5}, {BW, 6}, {BW, 7}, {BW, 8}, {BW, 9}, {RX, 0}, {RX, 1}, {RX, 2}, {RX, 3}, {RW,15},
- {RW,14}, {RW,13}, {RW,12}, {RW,11}, {RW,10}, {GX, 0}, {GX, 1}, {GX, 2}, {GX, 3}, {GW,15},
- {GW,14}, {GW,13}, {GW,12}, {GW,11}, {GW,10}, {BX, 0}, {BX, 1}, {BX, 2}, {BX, 3}, {BW,15},
- {BW,14}, {BW,13}, {BW,12}, {BW,11}, {BW,10}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0},
- {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0}, {NA, 0},
- {NA, 0}, {NA, 0},
- },
- };
- // Mode, Partitions, Transformed, IndexPrec, RGBAPrec
- const D3DX_BC6H::ModeInfo D3DX_BC6H::ms_aInfo[] =
- {
- {0x00, 1, true, 3, LDRColorA(10,10,10,0), LDRColorA( 5, 5, 5,0), LDRColorA(5,5,5,0), LDRColorA(5,5,5,0)}, // Mode 1
- {0x01, 1, true, 3, LDRColorA( 7, 7, 7,0), LDRColorA( 6, 6, 6,0), LDRColorA(6,6,6,0), LDRColorA(6,6,6,0)}, // Mode 2
- {0x02, 1, true, 3, LDRColorA(11,11,11,0), LDRColorA( 5, 4, 4,0), LDRColorA(5,4,4,0), LDRColorA(5,4,4,0)}, // Mode 3
- {0x06, 1, true, 3, LDRColorA(11,11,11,0), LDRColorA( 4, 5, 4,0), LDRColorA(4,5,4,0), LDRColorA(4,5,4,0)}, // Mode 4
- {0x0a, 1, true, 3, LDRColorA(11,11,11,0), LDRColorA( 4, 4, 5,0), LDRColorA(4,4,5,0), LDRColorA(4,4,5,0)}, // Mode 5
- {0x0e, 1, true, 3, LDRColorA( 9, 9, 9,0), LDRColorA( 5, 5, 5,0), LDRColorA(5,5,5,0), LDRColorA(5,5,5,0)}, // Mode 6
- {0x12, 1, true, 3, LDRColorA( 8, 8, 8,0), LDRColorA( 6, 5, 5,0), LDRColorA(6,5,5,0), LDRColorA(6,5,5,0)}, // Mode 7
- {0x16, 1, true, 3, LDRColorA( 8, 8, 8,0), LDRColorA( 5, 6, 5,0), LDRColorA(5,6,5,0), LDRColorA(5,6,5,0)}, // Mode 8
- {0x1a, 1, true, 3, LDRColorA( 8, 8, 8,0), LDRColorA( 5, 5, 6,0), LDRColorA(5,5,6,0), LDRColorA(5,5,6,0)}, // Mode 9
- {0x1e, 1, false, 3, LDRColorA( 6, 6, 6,0), LDRColorA( 6, 6, 6,0), LDRColorA(6,6,6,0), LDRColorA(6,6,6,0)}, // Mode 10
- {0x03, 0, false, 4, LDRColorA(10,10,10,0), LDRColorA(10,10,10,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 11
- {0x07, 0, true, 4, LDRColorA(11,11,11,0), LDRColorA( 9, 9, 9,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 12
- {0x0b, 0, true, 4, LDRColorA(12,12,12,0), LDRColorA( 8, 8, 8,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 13
- {0x0f, 0, true, 4, LDRColorA(16,16,16,0), LDRColorA( 4, 4, 4,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 14
- };
- const int D3DX_BC6H::ms_aModeToInfo[] =
- {
- 0, // Mode 1 - 0x00
- 1, // Mode 2 - 0x01
- 2, // Mode 3 - 0x02
- 10, // Mode 11 - 0x03
- -1, // Invalid - 0x04
- -1, // Invalid - 0x05
- 3, // Mode 4 - 0x06
- 11, // Mode 12 - 0x07
- -1, // Invalid - 0x08
- -1, // Invalid - 0x09
- 4, // Mode 5 - 0x0a
- 12, // Mode 13 - 0x0b
- -1, // Invalid - 0x0c
- -1, // Invalid - 0x0d
- 5, // Mode 6 - 0x0e
- 13, // Mode 14 - 0x0f
- -1, // Invalid - 0x10
- -1, // Invalid - 0x11
- 6, // Mode 7 - 0x12
- -1, // Reserved - 0x13
- -1, // Invalid - 0x14
- -1, // Invalid - 0x15
- 7, // Mode 8 - 0x16
- -1, // Reserved - 0x17
- -1, // Invalid - 0x18
- -1, // Invalid - 0x19
- 8, // Mode 9 - 0x1a
- -1, // Reserved - 0x1b
- -1, // Invalid - 0x1c
- -1, // Invalid - 0x1d
- 9, // Mode 10 - 0x1e
- -1, // Resreved - 0x1f
- };
- // BC7 compression: uPartitions, uPartitionBits, uPBits, uRotationBits, uIndexModeBits, uIndexPrec, uIndexPrec2, RGBAPrec, RGBAPrecWithP
- const D3DX_BC7::ModeInfo D3DX_BC7::ms_aInfo[] =
- {
- {2, 4, 6, 0, 0, 3, 0, LDRColorA(4,4,4,0), LDRColorA(5,5,5,0)},
- // Mode 0: Color only, 3 Subsets, RGBP 4441 (unique P-bit), 3-bit indecies, 16 partitions
- {1, 6, 2, 0, 0, 3, 0, LDRColorA(6,6,6,0), LDRColorA(7,7,7,0)},
- // Mode 1: Color only, 2 Subsets, RGBP 6661 (shared P-bit), 3-bit indecies, 64 partitions
- {2, 6, 0, 0, 0, 2, 0, LDRColorA(5,5,5,0), LDRColorA(5,5,5,0)},
- // Mode 2: Color only, 3 Subsets, RGB 555, 2-bit indecies, 64 partitions
- {1, 6, 4, 0, 0, 2, 0, LDRColorA(7,7,7,0), LDRColorA(8,8,8,0)},
- // Mode 3: Color only, 2 Subsets, RGBP 7771 (unique P-bit), 2-bits indecies, 64 partitions
- {0, 0, 0, 2, 1, 2, 3, LDRColorA(5,5,5,6), LDRColorA(5,5,5,6)},
- // Mode 4: Color w/ Separate Alpha, 1 Subset, RGB 555, A6, 16x2/16x3-bit indices, 2-bit rotation, 1-bit index selector
- {0, 0, 0, 2, 0, 2, 2, LDRColorA(7,7,7,8), LDRColorA(7,7,7,8)},
- // Mode 5: Color w/ Separate Alpha, 1 Subset, RGB 777, A8, 16x2/16x2-bit indices, 2-bit rotation
- {0, 0, 2, 0, 0, 4, 0, LDRColorA(7,7,7,7), LDRColorA(8,8,8,8)},
- // Mode 6: Color+Alpha, 1 Subset, RGBAP 77771 (unique P-bit), 16x4-bit indecies
- {1, 6, 4, 0, 0, 2, 0, LDRColorA(5,5,5,5), LDRColorA(6,6,6,6)}
- // Mode 7: Color+Alpha, 2 Subsets, RGBAP 55551 (unique P-bit), 2-bit indices, 64 partitions
- };
- namespace
- {
- //-------------------------------------------------------------------------------------
- // Helper functions
- //-------------------------------------------------------------------------------------
- inline bool IsFixUpOffset(_In_range_(0, 2) size_t uPartitions, _In_range_(0, 63) size_t uShape, _In_range_(0, 15) size_t uOffset)
- {
- assert(uPartitions < 3 && uShape < 64 && uOffset < 16);
- _Analysis_assume_(uPartitions < 3 && uShape < 64 && uOffset < 16);
- for (size_t p = 0; p <= uPartitions; p++)
- {
- if (uOffset == g_aFixUp[uPartitions][uShape][p])
- {
- return true;
- }
- }
- return false;
- }
- inline void TransformForward(_Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[])
- {
- aEndPts[0].B -= aEndPts[0].A;
- aEndPts[1].A -= aEndPts[0].A;
- aEndPts[1].B -= aEndPts[0].A;
- }
- inline void TransformInverse(_Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[], _In_ const LDRColorA& Prec, _In_ bool bSigned)
- {
- INTColor WrapMask((1 << Prec.r) - 1, (1 << Prec.g) - 1, (1 << Prec.b) - 1);
- aEndPts[0].B += aEndPts[0].A; aEndPts[0].B &= WrapMask;
- aEndPts[1].A += aEndPts[0].A; aEndPts[1].A &= WrapMask;
- aEndPts[1].B += aEndPts[0].A; aEndPts[1].B &= WrapMask;
- if (bSigned)
- {
- aEndPts[0].B.SignExtend(Prec);
- aEndPts[1].A.SignExtend(Prec);
- aEndPts[1].B.SignExtend(Prec);
- }
- }
- inline float Norm(_In_ const INTColor& a, _In_ const INTColor& b)
- {
- float dr = float(a.r) - float(b.r);
- float dg = float(a.g) - float(b.g);
- float db = float(a.b) - float(b.b);
- return dr * dr + dg * dg + db * db;
- }
- // return # of bits needed to store n. handle signed or unsigned cases properly
- inline int NBits(_In_ int n, _In_ bool bIsSigned)
- {
- int nb;
- if (n == 0)
- {
- return 0; // no bits needed for 0, signed or not
- }
- else if(n > 0)
- {
- for(nb = 0; n; ++nb, n >>= 1);
- return nb + (bIsSigned ? 1 : 0);
- }
- else
- {
- assert(bIsSigned);
- for(nb = 0; n < -1; ++nb, n >>= 1) ;
- return nb + 1;
- }
- }
- //-------------------------------------------------------------------------------------
- float OptimizeRGB(
- _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pPoints,
- _Out_ HDRColorA* pX,
- _Out_ HDRColorA* pY,
- _In_range_(3, 4) size_t cSteps,
- size_t cPixels,
- _In_reads_(cPixels) const size_t* pIndex)
- {
- float fError = FLT_MAX;
- const float *pC = (3 == cSteps) ? pC3 : pC4;
- const float *pD = (3 == cSteps) ? pD3 : pD4;
- // Find Min and Max points, as starting point
- HDRColorA X(1.0f, 1.0f, 1.0f, 0.0f);
- HDRColorA Y(0.0f, 0.0f, 0.0f, 0.0f);
- for(size_t iPoint = 0; iPoint < cPixels; iPoint++)
- {
- if(pPoints[pIndex[iPoint]].r < X.r) X.r = pPoints[pIndex[iPoint]].r;
- if(pPoints[pIndex[iPoint]].g < X.g) X.g = pPoints[pIndex[iPoint]].g;
- if(pPoints[pIndex[iPoint]].b < X.b) X.b = pPoints[pIndex[iPoint]].b;
- if(pPoints[pIndex[iPoint]].r > Y.r) Y.r = pPoints[pIndex[iPoint]].r;
- if(pPoints[pIndex[iPoint]].g > Y.g) Y.g = pPoints[pIndex[iPoint]].g;
- if(pPoints[pIndex[iPoint]].b > Y.b) Y.b = pPoints[pIndex[iPoint]].b;
- }
- // Diagonal axis
- HDRColorA AB;
- AB.r = Y.r - X.r;
- AB.g = Y.g - X.g;
- AB.b = Y.b - X.b;
- float fAB = AB.r * AB.r + AB.g * AB.g + AB.b * AB.b;
- // Single color block.. no need to root-find
- if(fAB < FLT_MIN)
- {
- pX->r = X.r; pX->g = X.g; pX->b = X.b;
- pY->r = Y.r; pY->g = Y.g; pY->b = Y.b;
- return 0.0f;
- }
- // Try all four axis directions, to determine which diagonal best fits data
- float fABInv = 1.0f / fAB;
- HDRColorA Dir;
- Dir.r = AB.r * fABInv;
- Dir.g = AB.g * fABInv;
- Dir.b = AB.b * fABInv;
- HDRColorA Mid;
- Mid.r = (X.r + Y.r) * 0.5f;
- Mid.g = (X.g + Y.g) * 0.5f;
- Mid.b = (X.b + Y.b) * 0.5f;
- float fDir[4];
- fDir[0] = fDir[1] = fDir[2] = fDir[3] = 0.0f;
- for(size_t iPoint = 0; iPoint < cPixels; iPoint++)
- {
- HDRColorA Pt;
- Pt.r = (pPoints[pIndex[iPoint]].r - Mid.r) * Dir.r;
- Pt.g = (pPoints[pIndex[iPoint]].g - Mid.g) * Dir.g;
- Pt.b = (pPoints[pIndex[iPoint]].b - Mid.b) * Dir.b;
- float f;
- f = Pt.r + Pt.g + Pt.b; fDir[0] += f * f;
- f = Pt.r + Pt.g - Pt.b; fDir[1] += f * f;
- f = Pt.r - Pt.g + Pt.b; fDir[2] += f * f;
- f = Pt.r - Pt.g - Pt.b; fDir[3] += f * f;
- }
- float fDirMax = fDir[0];
- size_t iDirMax = 0;
- for(size_t iDir = 1; iDir < 4; iDir++)
- {
- if(fDir[iDir] > fDirMax)
- {
- fDirMax = fDir[iDir];
- iDirMax = iDir;
- }
- }
- if (iDirMax & 2) std::swap(X.g, Y.g);
- if (iDirMax & 1) std::swap(X.b, Y.b);
- // Two color block.. no need to root-find
- if (fAB < 1.0f / 4096.0f)
- {
- pX->r = X.r; pX->g = X.g; pX->b = X.b;
- pY->r = Y.r; pY->g = Y.g; pY->b = Y.b;
- return 0.0f;
- }
- // Use Newton's Method to find local minima of sum-of-squares error.
- float fSteps = (float) (cSteps - 1);
- for(size_t iIteration = 0; iIteration < 8; iIteration++)
- {
- // Calculate new steps
- HDRColorA pSteps[4] = {};
- for (size_t iStep = 0; iStep < cSteps; iStep++)
- {
- pSteps[iStep].r = X.r * pC[iStep] + Y.r * pD[iStep];
- pSteps[iStep].g = X.g * pC[iStep] + Y.g * pD[iStep];
- pSteps[iStep].b = X.b * pC[iStep] + Y.b * pD[iStep];
- }
- // Calculate color direction
- Dir.r = Y.r - X.r;
- Dir.g = Y.g - X.g;
- Dir.b = Y.b - X.b;
- float fLen = (Dir.r * Dir.r + Dir.g * Dir.g + Dir.b * Dir.b);
- if(fLen < (1.0f / 4096.0f))
- break;
- float fScale = fSteps / fLen;
- Dir.r *= fScale;
- Dir.g *= fScale;
- Dir.b *= fScale;
- // Evaluate function, and derivatives
- float d2X = 0.0f, d2Y = 0.0f;
- HDRColorA dX(0.0f, 0.0f, 0.0f, 0.0f), dY(0.0f, 0.0f, 0.0f, 0.0f);
- for(size_t iPoint = 0; iPoint < cPixels; iPoint++)
- {
- float fDot = (pPoints[pIndex[iPoint]].r - X.r) * Dir.r +
- (pPoints[pIndex[iPoint]].g - X.g) * Dir.g +
- (pPoints[pIndex[iPoint]].b - X.b) * Dir.b;
- size_t iStep;
- if(fDot <= 0.0f)
- iStep = 0;
- if(fDot >= fSteps)
- iStep = cSteps - 1;
- else
- iStep = size_t(fDot + 0.5f);
- HDRColorA Diff;
- Diff.r = pSteps[iStep].r - pPoints[pIndex[iPoint]].r;
- Diff.g = pSteps[iStep].g - pPoints[pIndex[iPoint]].g;
- Diff.b = pSteps[iStep].b - pPoints[pIndex[iPoint]].b;
- float fC = pC[iStep] * (1.0f / 8.0f);
- float fD = pD[iStep] * (1.0f / 8.0f);
- d2X += fC * pC[iStep];
- dX.r += fC * Diff.r;
- dX.g += fC * Diff.g;
- dX.b += fC * Diff.b;
- d2Y += fD * pD[iStep];
- dY.r += fD * Diff.r;
- dY.g += fD * Diff.g;
- dY.b += fD * Diff.b;
- }
- // Move endpoints
- if(d2X > 0.0f)
- {
- float f = -1.0f / d2X;
- X.r += dX.r * f;
- X.g += dX.g * f;
- X.b += dX.b * f;
- }
- if(d2Y > 0.0f)
- {
- float f = -1.0f / d2Y;
- Y.r += dY.r * f;
- Y.g += dY.g * f;
- Y.b += dY.b * f;
- }
- if((dX.r * dX.r < fEpsilon) && (dX.g * dX.g < fEpsilon) && (dX.b * dX.b < fEpsilon) &&
- (dY.r * dY.r < fEpsilon) && (dY.g * dY.g < fEpsilon) && (dY.b * dY.b < fEpsilon))
- {
- break;
- }
- }
- pX->r = X.r; pX->g = X.g; pX->b = X.b;
- pY->r = Y.r; pY->g = Y.g; pY->b = Y.b;
- return fError;
- }
- //-------------------------------------------------------------------------------------
- float OptimizeRGBA(
- _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pPoints,
- _Out_ HDRColorA* pX,
- _Out_ HDRColorA* pY,
- _In_range_(3, 4) size_t cSteps,
- size_t cPixels,
- _In_reads_(cPixels) const size_t* pIndex)
- {
- float fError = FLT_MAX;
- const float *pC = (3 == cSteps) ? pC3 : pC4;
- const float *pD = (3 == cSteps) ? pD3 : pD4;
- // Find Min and Max points, as starting point
- HDRColorA X(1.0f, 1.0f, 1.0f, 1.0f);
- HDRColorA Y(0.0f, 0.0f, 0.0f, 0.0f);
- for(size_t iPoint = 0; iPoint < cPixels; iPoint++)
- {
- if(pPoints[pIndex[iPoint]].r < X.r) X.r = pPoints[pIndex[iPoint]].r;
- if(pPoints[pIndex[iPoint]].g < X.g) X.g = pPoints[pIndex[iPoint]].g;
- if(pPoints[pIndex[iPoint]].b < X.b) X.b = pPoints[pIndex[iPoint]].b;
- if(pPoints[pIndex[iPoint]].a < X.a) X.a = pPoints[pIndex[iPoint]].a;
- if(pPoints[pIndex[iPoint]].r > Y.r) Y.r = pPoints[pIndex[iPoint]].r;
- if(pPoints[pIndex[iPoint]].g > Y.g) Y.g = pPoints[pIndex[iPoint]].g;
- if(pPoints[pIndex[iPoint]].b > Y.b) Y.b = pPoints[pIndex[iPoint]].b;
- if(pPoints[pIndex[iPoint]].a > Y.a) Y.a = pPoints[pIndex[iPoint]].a;
- }
- // Diagonal axis
- HDRColorA AB = Y - X;
- float fAB = AB * AB;
- // Single color block.. no need to root-find
- if(fAB < FLT_MIN)
- {
- *pX = X;
- *pY = Y;
- return 0.0f;
- }
- // Try all four axis directions, to determine which diagonal best fits data
- float fABInv = 1.0f / fAB;
- HDRColorA Dir = AB * fABInv;
- HDRColorA Mid = (X + Y) * 0.5f;
- float fDir[8];
- fDir[0] = fDir[1] = fDir[2] = fDir[3] = fDir[4] = fDir[5] = fDir[6] = fDir[7] = 0.0f;
- for(size_t iPoint = 0; iPoint < cPixels; iPoint++)
- {
- HDRColorA Pt;
- Pt.r = (pPoints[pIndex[iPoint]].r - Mid.r) * Dir.r;
- Pt.g = (pPoints[pIndex[iPoint]].g - Mid.g) * Dir.g;
- Pt.b = (pPoints[pIndex[iPoint]].b - Mid.b) * Dir.b;
- Pt.a = (pPoints[pIndex[iPoint]].a - Mid.a) * Dir.a;
- float f;
- f = Pt.r + Pt.g + Pt.b + Pt.a; fDir[0] += f * f;
- f = Pt.r + Pt.g + Pt.b - Pt.a; fDir[1] += f * f;
- f = Pt.r + Pt.g - Pt.b + Pt.a; fDir[2] += f * f;
- f = Pt.r + Pt.g - Pt.b - Pt.a; fDir[3] += f * f;
- f = Pt.r - Pt.g + Pt.b + Pt.a; fDir[4] += f * f;
- f = Pt.r - Pt.g + Pt.b - Pt.a; fDir[5] += f * f;
- f = Pt.r - Pt.g - Pt.b + Pt.a; fDir[6] += f * f;
- f = Pt.r - Pt.g - Pt.b - Pt.a; fDir[7] += f * f;
- }
- float fDirMax = fDir[0];
- size_t iDirMax = 0;
- for(size_t iDir = 1; iDir < 8; iDir++)
- {
- if(fDir[iDir] > fDirMax)
- {
- fDirMax = fDir[iDir];
- iDirMax = iDir;
- }
- }
- if (iDirMax & 4) std::swap(X.g, Y.g);
- if (iDirMax & 2) std::swap(X.b, Y.b);
- if (iDirMax & 1) std::swap(X.a, Y.a);
- // Two color block.. no need to root-find
- if(fAB < 1.0f / 4096.0f)
- {
- *pX = X;
- *pY = Y;
- return 0.0f;
- }
- // Use Newton's Method to find local minima of sum-of-squares error.
- float fSteps = (float) (cSteps - 1);
- for(size_t iIteration = 0; iIteration < 8 && fError > 0.0f; iIteration++)
- {
- // Calculate new steps
- HDRColorA pSteps[BC7_MAX_INDICES];
- LDRColorA lX, lY;
- lX = (X * 255.0f).ToLDRColorA();
- lY = (Y * 255.0f).ToLDRColorA();
- for(size_t iStep = 0; iStep < cSteps; iStep++)
- {
- pSteps[iStep] = X * pC[iStep] + Y * pD[iStep];
- //LDRColorA::Interpolate(lX, lY, i, i, wcprec, waprec, aSteps[i]);
- }
- // Calculate color direction
- Dir = Y - X;
- float fLen = Dir * Dir;
- if(fLen < (1.0f / 4096.0f))
- break;
- float fScale = fSteps / fLen;
- Dir *= fScale;
- // Evaluate function, and derivatives
- float d2X = 0.0f, d2Y = 0.0f;
- HDRColorA dX(0.0f, 0.0f, 0.0f, 0.0f), dY(0.0f, 0.0f, 0.0f, 0.0f);
- for(size_t iPoint = 0; iPoint < cPixels; ++iPoint)
- {
- float fDot = (pPoints[pIndex[iPoint]] - X) * Dir;
- size_t iStep;
- if(fDot <= 0.0f)
- iStep = 0;
- if(fDot >= fSteps)
- iStep = cSteps - 1;
- else
- iStep = size_t(fDot + 0.5f);
- HDRColorA Diff = pSteps[iStep] - pPoints[pIndex[iPoint]];
- float fC = pC[iStep] * (1.0f / 8.0f);
- float fD = pD[iStep] * (1.0f / 8.0f);
- d2X += fC * pC[iStep];
- dX += Diff * fC;
- d2Y += fD * pD[iStep];
- dY += Diff * fD;
- }
- // Move endpoints
- if(d2X > 0.0f)
- {
- float f = -1.0f / d2X;
- X += dX * f;
- }
- if(d2Y > 0.0f)
- {
- float f = -1.0f / d2Y;
- Y += dY * f;
- }
- if((dX * dX < fEpsilon) && (dY * dY < fEpsilon))
- break;
- }
- *pX = X;
- *pY = Y;
- return fError;
- }
- //-------------------------------------------------------------------------------------
- float ComputeError(
- _Inout_ const LDRColorA& pixel,
- _In_reads_(1 << uIndexPrec) const LDRColorA aPalette[],
- uint8_t uIndexPrec,
- uint8_t uIndexPrec2,
- _Out_opt_ size_t* pBestIndex = nullptr,
- _Out_opt_ size_t* pBestIndex2 = nullptr)
- {
- const size_t uNumIndices = size_t(1) << uIndexPrec;
- const size_t uNumIndices2 = size_t(1) << uIndexPrec2;
- float fTotalErr = 0;
- float fBestErr = FLT_MAX;
- if(pBestIndex)
- *pBestIndex = 0;
- if(pBestIndex2)
- *pBestIndex2 = 0;
- XMVECTOR vpixel = XMLoadUByte4( reinterpret_cast<const XMUBYTE4*>( &pixel ) );
- if(uIndexPrec2 == 0)
- {
- for(register size_t i = 0; i < uNumIndices && fBestErr > 0; i++)
- {
- XMVECTOR tpixel = XMLoadUByte4( reinterpret_cast<const XMUBYTE4*>( &aPalette[i] ) );
- // Compute ErrorMetric
- tpixel = XMVectorSubtract( vpixel, tpixel );
- float fErr = XMVectorGetX( XMVector4Dot( tpixel, tpixel ) );
- if(fErr > fBestErr) // error increased, so we're done searching
- break;
- if(fErr < fBestErr)
- {
- fBestErr = fErr;
- if(pBestIndex)
- *pBestIndex = i;
- }
- }
- fTotalErr += fBestErr;
- }
- else
- {
- for(register size_t i = 0; i < uNumIndices && fBestErr > 0; i++)
- {
- XMVECTOR tpixel = XMLoadUByte4( reinterpret_cast<const XMUBYTE4*>( &aPalette[i] ) );
- // Compute ErrorMetricRGB
- tpixel = XMVectorSubtract( vpixel, tpixel );
- float fErr = XMVectorGetX( XMVector3Dot( tpixel, tpixel ) );
- if(fErr > fBestErr) // error increased, so we're done searching
- break;
- if(fErr < fBestErr)
- {
- fBestErr = fErr;
- if(pBestIndex)
- *pBestIndex = i;
- }
- }
- fTotalErr += fBestErr;
- fBestErr = FLT_MAX;
- for(register size_t i = 0; i < uNumIndices2 && fBestErr > 0; i++)
- {
- // Compute ErrorMetricAlpha
- float ea = float(pixel.a) - float(aPalette[i].a);
- float fErr = ea*ea;
- if(fErr > fBestErr) // error increased, so we're done searching
- break;
- if(fErr < fBestErr)
- {
- fBestErr = fErr;
- if(pBestIndex2)
- *pBestIndex2 = i;
- }
- }
- fTotalErr += fBestErr;
- }
- return fTotalErr;
- }
- void FillWithErrorColors(Color (&color)[4][4]) // ESENTHEL ADDED
- {
- REP(16)color[0][i]=(SET_DEBUG ? PURPLE : BLACK);
- }
- void FillWithErrorColors(_Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut)
- {
- for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- #ifdef _DEBUG
- // Use Magenta in debug as a highly-visible error color
- pOut[i] = HDRColorA(1.0f, 0.0f, 1.0f, 1.0f);
- #else
- // In production use, default to black
- pOut[i] = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f);
- #endif
- }
- }
- }
- //-------------------------------------------------------------------------------------
- // BC6H Compression
- //-------------------------------------------------------------------------------------
- _Use_decl_annotations_
- void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const
- {
- assert(pOut );
- size_t uStartBit = 0;
- uint8_t uMode = GetBits(uStartBit, 2);
- if(uMode != 0x00 && uMode != 0x01)
- {
- uMode = (GetBits(uStartBit, 3) << 2) | uMode;
- }
- assert( uMode < 32 );
- _Analysis_assume_( uMode < 32 );
- if ( ms_aModeToInfo[uMode] >= 0 )
- {
- assert(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aInfo));
- _Analysis_assume_(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aInfo));
- const ModeDescriptor* desc = ms_aDesc[ms_aModeToInfo[uMode]];
- assert(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aDesc));
- _Analysis_assume_(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aDesc));
- const ModeInfo& info = ms_aInfo[ms_aModeToInfo[uMode]];
- INTEndPntPair aEndPts[BC6H_MAX_REGIONS];
- memset(aEndPts, 0, BC6H_MAX_REGIONS * 2 * sizeof(INTColor));
- uint32_t uShape = 0;
- // Read header
- const size_t uHeaderBits = info.uPartitions > 0 ? 82 : 65;
- while(uStartBit < uHeaderBits)
- {
- size_t uCurBit = uStartBit;
- if(GetBit(uStartBit))
- {
- switch(desc[uCurBit].m_eField)
- {
- case D: uShape |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case RW: aEndPts[0].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case RX: aEndPts[0].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case RY: aEndPts[1].A.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case RZ: aEndPts[1].B.r |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case GW: aEndPts[0].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case GX: aEndPts[0].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case GY: aEndPts[1].A.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case GZ: aEndPts[1].B.g |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case BW: aEndPts[0].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case BX: aEndPts[0].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case BY: aEndPts[1].A.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- case BZ: aEndPts[1].B.b |= 1 << uint32_t(desc[uCurBit].m_uBit); break;
- default:
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC6H: Invalid header bits encountered during decoding\n" );
- #endif
- FillWithErrorColors( pOut );
- return;
- }
- }
- }
- }
- assert( uShape < 64 );
- _Analysis_assume_( uShape < 64 );
- // Sign extend necessary end points
- if(bSigned)
- {
- aEndPts[0].A.SignExtend(info.RGBAPrec[0][0]);
- }
- if(bSigned || info.bTransformed)
- {
- assert( info.uPartitions < BC6H_MAX_REGIONS );
- _Analysis_assume_( info.uPartitions < BC6H_MAX_REGIONS );
- for(size_t p = 0; p <= info.uPartitions; ++p)
- {
- if(p != 0)
- {
- aEndPts[p].A.SignExtend(info.RGBAPrec[p][0]);
- }
- aEndPts[p].B.SignExtend(info.RGBAPrec[p][1]);
- }
- }
- // Inverse transform the end points
- if(info.bTransformed)
- {
- TransformInverse(aEndPts, info.RGBAPrec[0][0], bSigned);
- }
- // Read indices
- for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- size_t uNumBits = IsFixUpOffset(info.uPartitions, uShape, i) ? info.uIndexPrec-1 : info.uIndexPrec;
- if ( uStartBit + uNumBits > 128 )
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC6H: Invalid block encountered during decoding\n" );
- #endif
- FillWithErrorColors( pOut );
- return;
- }
- uint8_t uIndex = GetBits(uStartBit, uNumBits);
- if ( uIndex >= ((info.uPartitions > 0) ? 8 : 16) )
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC6H: Invalid index encountered during decoding\n" );
- #endif
- FillWithErrorColors( pOut );
- return;
- }
- size_t uRegion = g_aPartitionTable[info.uPartitions][uShape][i];
- assert( uRegion < BC6H_MAX_REGIONS );
- _Analysis_assume_( uRegion < BC6H_MAX_REGIONS );
- // Unquantize endpoints and interpolate
- int r1 = Unquantize(aEndPts[uRegion].A.r, info.RGBAPrec[0][0].r, bSigned);
- int g1 = Unquantize(aEndPts[uRegion].A.g, info.RGBAPrec[0][0].g, bSigned);
- int b1 = Unquantize(aEndPts[uRegion].A.b, info.RGBAPrec[0][0].b, bSigned);
- int r2 = Unquantize(aEndPts[uRegion].B.r, info.RGBAPrec[0][0].r, bSigned);
- int g2 = Unquantize(aEndPts[uRegion].B.g, info.RGBAPrec[0][0].g, bSigned);
- int b2 = Unquantize(aEndPts[uRegion].B.b, info.RGBAPrec[0][0].b, bSigned);
- const int* aWeights = info.uPartitions > 0 ? g_aWeights3 : g_aWeights4;
- INTColor fc;
- fc.r = FinishUnquantize((r1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + r2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned);
- fc.g = FinishUnquantize((g1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + g2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned);
- fc.b = FinishUnquantize((b1 * (BC67_WEIGHT_MAX - aWeights[uIndex]) + b2 * aWeights[uIndex] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT, bSigned);
- HALF rgb[3];
- fc.ToF16(rgb, bSigned);
- pOut[i].r = XMConvertHalfToFloat( rgb[0] );
- pOut[i].g = XMConvertHalfToFloat( rgb[1] );
- pOut[i].b = XMConvertHalfToFloat( rgb[2] );
- pOut[i].a = 1.0f;
- }
- }
- else
- {
- #ifdef _DEBUG
- const char* warnstr = "BC6H: Invalid mode encountered during decoding\n";
- switch( uMode )
- {
- case 0x13: warnstr = "BC6H: Reserved mode 10011 encountered during decoding\n"; break;
- case 0x17: warnstr = "BC6H: Reserved mode 10111 encountered during decoding\n"; break;
- case 0x1B: warnstr = "BC6H: Reserved mode 11011 encountered during decoding\n"; break;
- case 0x1F: warnstr = "BC6H: Reserved mode 11111 encountered during decoding\n"; break;
- }
- OutputDebugStringA( warnstr );
- #endif
- // Per the BC6H format spec, we must return opaque black
- for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- pOut[i] = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f);
- }
- }
- }
- _Use_decl_annotations_
- void D3DX_BC6H::Encode(bool bSigned, const HDRColorA* const pIn)
- {
- assert( pIn );
- EncodeParams EP(pIn, bSigned);
- for(EP.uMode = 0; EP.uMode < ARRAYSIZE(ms_aInfo) && EP.fBestErr > 0; ++EP.uMode)
- {
- const uint8_t uShapes = ms_aInfo[EP.uMode].uPartitions ? 32 : 1;
- // Number of rough cases to look at. reasonable values of this are 1, uShapes/4, and uShapes
- // uShapes/4 gets nearly all the cases; you can increase that a bit (say by 3 or 4) if you really want to squeeze the last bit out
- const size_t uItems = std::max<size_t>(1, uShapes >> 2);
- float afRoughMSE[BC6H_MAX_SHAPES];
- uint8_t auShape[BC6H_MAX_SHAPES];
- // pick the best uItems shapes and refine these.
- for(EP.uShape = 0; EP.uShape < uShapes; ++EP.uShape)
- {
- size_t uShape = EP.uShape;
- afRoughMSE[uShape] = RoughMSE(&EP);
- auShape[uShape] = static_cast<uint8_t>(uShape);
- }
- // Bubble up the first uItems items
- for(register size_t i = 0; i < uItems; i++)
- {
- for (register size_t j = i + 1; j < uShapes; j++)
- {
- if (afRoughMSE[i] > afRoughMSE[j])
- {
- std::swap(afRoughMSE[i], afRoughMSE[j]);
- std::swap(auShape[i], auShape[j]);
- }
- }
- }
- for(size_t i = 0; i < uItems && EP.fBestErr > 0; i++)
- {
- EP.uShape = auShape[i];
- Refine(&EP);
- }
- }
- }
- //-------------------------------------------------------------------------------------
- _Use_decl_annotations_
- int D3DX_BC6H::Quantize(int iValue, int prec, bool bSigned)
- {
- assert(prec > 1); // didn't bother to make it work for 1
- int q, s = 0;
- if(bSigned)
- {
- assert(iValue >= -F16MAX && iValue <= F16MAX);
- if(iValue < 0)
- {
- s = 1;
- iValue = -iValue;
- }
- q = (prec >= 16) ? iValue : (iValue << (prec-1)) / (F16MAX+1);
- if(s)
- q = -q;
- assert (q > -(1 << (prec-1)) && q < (1 << (prec-1)));
- }
- else
- {
- assert(iValue >= 0 && iValue <= F16MAX);
- q = (prec >= 15) ? iValue : (iValue << prec) / (F16MAX+1);
- assert (q >= 0 && q < (1 << prec));
- }
- return q;
- }
- _Use_decl_annotations_
- int D3DX_BC6H::Unquantize(int comp, uint8_t uBitsPerComp, bool bSigned)
- {
- int unq = 0, s = 0;
- if(bSigned)
- {
- if(uBitsPerComp >= 16)
- {
- unq = comp;
- }
- else
- {
- if(comp < 0)
- {
- s = 1;
- comp = -comp;
- }
- if(comp == 0) unq = 0;
- else if(comp >= ((1 << (uBitsPerComp - 1)) - 1)) unq = 0x7FFF;
- else unq = ((comp << 15) + 0x4000) >> (uBitsPerComp-1);
- if(s) unq = -unq;
- }
- }
- else
- {
- if(uBitsPerComp >= 15) unq = comp;
- else if(comp == 0) unq = 0;
- else if(comp == ((1 << uBitsPerComp) - 1)) unq = 0xFFFF;
- else unq = ((comp << 16) + 0x8000) >> uBitsPerComp;
- }
- return unq;
- }
- _Use_decl_annotations_
- int D3DX_BC6H::FinishUnquantize(int comp, bool bSigned)
- {
- if (bSigned)
- {
- return (comp < 0) ? -(((-comp) * 31) >> 5) : (comp * 31) >> 5; // scale the magnitude by 31/32
- }
- else
- {
- return (comp * 31) >> 6; // scale the magnitude by 31/64
- }
- }
- //-------------------------------------------------------------------------------------
- _Use_decl_annotations_
- bool D3DX_BC6H::EndPointsFit(const EncodeParams* pEP, const INTEndPntPair aEndPts[])
- {
- assert( pEP );
- const bool bTransformed = ms_aInfo[pEP->uMode].bTransformed;
- const bool bIsSigned = pEP->bSigned;
- const LDRColorA& Prec0 = ms_aInfo[pEP->uMode].RGBAPrec[0][0];
- const LDRColorA& Prec1 = ms_aInfo[pEP->uMode].RGBAPrec[0][1];
- const LDRColorA& Prec2 = ms_aInfo[pEP->uMode].RGBAPrec[1][0];
- const LDRColorA& Prec3 = ms_aInfo[pEP->uMode].RGBAPrec[1][1];
- INTColor aBits[4];
- aBits[0].r = NBits(aEndPts[0].A.r, bIsSigned);
- aBits[0].g = NBits(aEndPts[0].A.g, bIsSigned);
- aBits[0].b = NBits(aEndPts[0].A.b, bIsSigned);
- aBits[1].r = NBits(aEndPts[0].B.r, bTransformed || bIsSigned);
- aBits[1].g = NBits(aEndPts[0].B.g, bTransformed || bIsSigned);
- aBits[1].b = NBits(aEndPts[0].B.b, bTransformed || bIsSigned);
- if(aBits[0].r > Prec0.r || aBits[1].r > Prec1.r ||
- aBits[0].g > Prec0.g || aBits[1].g > Prec1.g ||
- aBits[0].b > Prec0.b || aBits[1].b > Prec1.b)
- return false;
- if(ms_aInfo[pEP->uMode].uPartitions)
- {
- aBits[2].r = NBits(aEndPts[1].A.r, bTransformed || bIsSigned);
- aBits[2].g = NBits(aEndPts[1].A.g, bTransformed || bIsSigned);
- aBits[2].b = NBits(aEndPts[1].A.b, bTransformed || bIsSigned);
- aBits[3].r = NBits(aEndPts[1].B.r, bTransformed || bIsSigned);
- aBits[3].g = NBits(aEndPts[1].B.g, bTransformed || bIsSigned);
- aBits[3].b = NBits(aEndPts[1].B.b, bTransformed || bIsSigned);
- if(aBits[2].r > Prec2.r || aBits[3].r > Prec3.r ||
- aBits[2].g > Prec2.g || aBits[3].g > Prec3.g ||
- aBits[2].b > Prec2.b || aBits[3].b > Prec3.b)
- return false;
- }
- return true;
- }
- _Use_decl_annotations_
- void D3DX_BC6H::GeneratePaletteQuantized(const EncodeParams* pEP, const INTEndPntPair& endPts, INTColor aPalette[]) const
- {
- assert( pEP );
- const size_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec;
- const size_t uNumIndices = size_t(1) << uIndexPrec;
- assert( uNumIndices > 0 );
- _Analysis_assume_( uNumIndices > 0 );
- const LDRColorA& Prec = ms_aInfo[pEP->uMode].RGBAPrec[0][0];
- // scale endpoints
- INTEndPntPair unqEndPts;
- unqEndPts.A.r = Unquantize(endPts.A.r, Prec.r, pEP->bSigned);
- unqEndPts.A.g = Unquantize(endPts.A.g, Prec.g, pEP->bSigned);
- unqEndPts.A.b = Unquantize(endPts.A.b, Prec.b, pEP->bSigned);
- unqEndPts.B.r = Unquantize(endPts.B.r, Prec.r, pEP->bSigned);
- unqEndPts.B.g = Unquantize(endPts.B.g, Prec.g, pEP->bSigned);
- unqEndPts.B.b = Unquantize(endPts.B.b, Prec.b, pEP->bSigned);
- // interpolate
- const int* aWeights = nullptr;
- switch(uIndexPrec)
- {
- case 3: aWeights = g_aWeights3; assert(uNumIndices <= 8); _Analysis_assume_(uNumIndices <= 8); break;
- case 4: aWeights = g_aWeights4; assert(uNumIndices <= 16); _Analysis_assume_(uNumIndices <= 16); break;
- default:
- assert(false);
- for(size_t i = 0; i < uNumIndices; ++i)
- {
- #pragma prefast(suppress:22102 22103, "writing blocks in two halves confuses tool")
- aPalette[i] = INTColor(0,0,0);
- }
- return;
- }
- for (size_t i = 0; i < uNumIndices; ++i)
- {
- aPalette[i].r = FinishUnquantize(
- (unqEndPts.A.r * (BC67_WEIGHT_MAX - aWeights[i]) + unqEndPts.B.r * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT,
- pEP->bSigned);
- aPalette[i].g = FinishUnquantize(
- (unqEndPts.A.g * (BC67_WEIGHT_MAX - aWeights[i]) + unqEndPts.B.g * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT,
- pEP->bSigned);
- aPalette[i].b = FinishUnquantize(
- (unqEndPts.A.b * (BC67_WEIGHT_MAX - aWeights[i]) + unqEndPts.B.b * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT,
- pEP->bSigned);
- }
- }
- // given a collection of colors and quantized endpoints, generate a palette, choose best entries, and return a single toterr
- _Use_decl_annotations_
- float D3DX_BC6H::MapColorsQuantized(const EncodeParams* pEP, const INTColor aColors[], size_t np, const INTEndPntPair &endPts) const
- {
- assert( pEP );
- const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec;
- const uint8_t uNumIndices = 1 << uIndexPrec;
- INTColor aPalette[BC6H_MAX_INDICES];
- GeneratePaletteQuantized(pEP, endPts, aPalette);
- float fTotErr = 0;
- for(size_t i = 0; i < np; ++i)
- {
- XMVECTOR vcolors = XMLoadSInt4( reinterpret_cast<const XMINT4*>( &aColors[i] ) );
- // Compute ErrorMetricRGB
- XMVECTOR tpal = XMLoadSInt4( reinterpret_cast<const XMINT4*>( &aPalette[0] ) );
- tpal = XMVectorSubtract( vcolors, tpal );
- float fBestErr = XMVectorGetX( XMVector3Dot( tpal, tpal ) );
- for(int j = 1; j < uNumIndices && fBestErr > 0; ++j)
- {
- // Compute ErrorMetricRGB
- tpal = XMLoadSInt4( reinterpret_cast<const XMINT4*>( &aPalette[j] ) );
- tpal = XMVectorSubtract( vcolors, tpal );
- float fErr = XMVectorGetX( XMVector3Dot( tpal, tpal ) );
- if(fErr > fBestErr) break; // error increased, so we're done searching
- if(fErr < fBestErr) fBestErr = fErr;
- }
- fTotErr += fBestErr;
- }
- return fTotErr;
- }
- _Use_decl_annotations_
- float D3DX_BC6H::PerturbOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, uint8_t ch,
- const INTEndPntPair& oldEndPts, INTEndPntPair& newEndPts, float fOldErr, int do_b) const
- {
- assert( pEP );
- uint8_t uPrec;
- switch(ch)
- {
- case 0: uPrec = ms_aInfo[pEP->uMode].RGBAPrec[0][0].r; break;
- case 1: uPrec = ms_aInfo[pEP->uMode].RGBAPrec[0][0].g; break;
- case 2: uPrec = ms_aInfo[pEP->uMode].RGBAPrec[0][0].b; break;
- default: assert(false); newEndPts = oldEndPts; return FLT_MAX;
- }
- INTEndPntPair tmpEndPts;
- float fMinErr = fOldErr;
- int beststep = 0;
- // copy real endpoints so we can perturb them
- tmpEndPts = newEndPts = oldEndPts;
- // do a logarithmic search for the best error for this endpoint (which)
- for(int step = 1 << (uPrec-1); step; step >>= 1)
- {
- bool bImproved = false;
- for(int sign = -1; sign <= 1; sign += 2)
- {
- if(do_b == 0)
- {
- tmpEndPts.A[ch] = newEndPts.A[ch] + sign * step;
- if(tmpEndPts.A[ch] < 0 || tmpEndPts.A[ch] >= (1 << uPrec))
- continue;
- }
- else
- {
- tmpEndPts.B[ch] = newEndPts.B[ch] + sign * step;
- if(tmpEndPts.B[ch] < 0 || tmpEndPts.B[ch] >= (1 << uPrec))
- continue;
- }
- float fErr = MapColorsQuantized(pEP, aColors, np, tmpEndPts);
- if(fErr < fMinErr)
- {
- bImproved = true;
- fMinErr = fErr;
- beststep = sign * step;
- }
- }
- // if this was an improvement, move the endpoint and continue search from there
- if(bImproved)
- {
- if(do_b == 0)
- newEndPts.A[ch] += beststep;
- else
- newEndPts.B[ch] += beststep;
- }
- }
- return fMinErr;
- }
- _Use_decl_annotations_
- void D3DX_BC6H::OptimizeOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, float aOrgErr,
- const INTEndPntPair &aOrgEndPts, INTEndPntPair &aOptEndPts) const
- {
- assert( pEP );
- float aOptErr = aOrgErr;
- aOptEndPts.A = aOrgEndPts.A;
- aOptEndPts.B = aOrgEndPts.B;
- INTEndPntPair new_a, new_b;
- INTEndPntPair newEndPts;
- int do_b;
- // now optimize each channel separately
- for(uint8_t ch = 0; ch < 3; ++ch)
- {
- // figure out which endpoint when perturbed gives the most improvement and start there
- // if we just alternate, we can easily end up in a local minima
- float fErr0 = PerturbOne(pEP, aColors, np, ch, aOptEndPts, new_a, aOptErr, 0); // perturb endpt A
- float fErr1 = PerturbOne(pEP, aColors, np, ch, aOptEndPts, new_b, aOptErr, 1); // perturb endpt B
- if(fErr0 < fErr1)
- {
- if(fErr0 >= aOptErr) continue;
- aOptEndPts.A[ch] = new_a.A[ch];
- aOptErr = fErr0;
- do_b = 1; // do B next
- }
- else
- {
- if(fErr1 >= aOptErr) continue;
- aOptEndPts.B[ch] = new_b.B[ch];
- aOptErr = fErr1;
- do_b = 0; // do A next
- }
- // now alternate endpoints and keep trying until there is no improvement
- for(;;)
- {
- float fErr = PerturbOne(pEP, aColors, np, ch, aOptEndPts, newEndPts, aOptErr, do_b);
- if(fErr >= aOptErr)
- break;
- if(do_b == 0)
- aOptEndPts.A[ch] = newEndPts.A[ch];
- else
- aOptEndPts.B[ch] = newEndPts.B[ch];
- aOptErr = fErr;
- do_b = 1 - do_b; // now move the other endpoint
- }
- }
- }
- _Use_decl_annotations_
- void D3DX_BC6H::OptimizeEndPoints(const EncodeParams* pEP, const float aOrgErr[], const INTEndPntPair aOrgEndPts[], INTEndPntPair aOptEndPts[]) const
- {
- assert( pEP );
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- assert( uPartitions < BC6H_MAX_REGIONS );
- _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS );
- INTColor aPixels[NUM_PIXELS_PER_BLOCK];
-
- for(size_t p = 0; p <= uPartitions; ++p)
- {
- // collect the pixels in the region
- size_t np = 0;
- for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- if(g_aPartitionTable[p][pEP->uShape][i] == p)
- {
- aPixels[np++] = pEP->aIPixels[i];
- }
- }
- OptimizeOne(pEP, aPixels, np, aOrgErr[p], aOrgEndPts[p], aOptEndPts[p]);
- }
- }
- // Swap endpoints as needed to ensure that the indices at fix up have a 0 high-order bit
- _Use_decl_annotations_
- void D3DX_BC6H::SwapIndices(const EncodeParams* pEP, INTEndPntPair aEndPts[], size_t aIndices[])
- {
- assert( pEP );
- const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- const size_t uNumIndices = size_t(1) << ms_aInfo[pEP->uMode].uIndexPrec;
- const size_t uHighIndexBit = uNumIndices >> 1;
- assert( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
- _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
- for(size_t p = 0; p <= uPartitions; ++p)
- {
- size_t i = g_aFixUp[uPartitions][pEP->uShape][p];
- assert(g_aPartitionTable[uPartitions][pEP->uShape][i] == p);
- if(aIndices[i] & uHighIndexBit)
- {
- // high bit is set, swap the aEndPts and indices for this region
- std::swap(aEndPts[p].A, aEndPts[p].B);
- for(size_t j = 0; j < NUM_PIXELS_PER_BLOCK; ++j)
- if(g_aPartitionTable[uPartitions][pEP->uShape][j] == p)
- aIndices[j] = uNumIndices - 1 - aIndices[j];
- }
- }
- }
- // assign indices given a tile, shape, and quantized endpoints, return toterr for each region
- _Use_decl_annotations_
- void D3DX_BC6H::AssignIndices(const EncodeParams* pEP, const INTEndPntPair aEndPts[], size_t aIndices[], float aTotErr[]) const
- {
- assert( pEP );
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- const uint8_t uNumIndices = 1 << ms_aInfo[pEP->uMode].uIndexPrec;
- assert( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
- _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
- // build list of possibles
- INTColor aPalette[BC6H_MAX_REGIONS][BC6H_MAX_INDICES];
- for(size_t p = 0; p <= uPartitions; ++p)
- {
- GeneratePaletteQuantized(pEP, aEndPts[p], aPalette[p]);
- aTotErr[p] = 0;
- }
- for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- const uint8_t uRegion = g_aPartitionTable[uPartitions][pEP->uShape][i];
- assert( uRegion < BC6H_MAX_REGIONS );
- _Analysis_assume_( uRegion < BC6H_MAX_REGIONS );
- float fBestErr = Norm(pEP->aIPixels[i], aPalette[uRegion][0]);
- aIndices[i] = 0;
- for(uint8_t j = 1; j < uNumIndices && fBestErr > 0; ++j)
- {
- float fErr = Norm(pEP->aIPixels[i], aPalette[uRegion][j]);
- if(fErr > fBestErr) break; // error increased, so we're done searching
- if(fErr < fBestErr)
- {
- fBestErr = fErr;
- aIndices[i] = j;
- }
- }
- aTotErr[uRegion] += fBestErr;
- }
- }
- _Use_decl_annotations_
- void D3DX_BC6H::QuantizeEndPts(const EncodeParams* pEP, INTEndPntPair* aQntEndPts) const
- {
- assert( pEP && aQntEndPts );
- const INTEndPntPair* aUnqEndPts = pEP->aUnqEndPts[pEP->uShape];
- const LDRColorA& Prec = ms_aInfo[pEP->uMode].RGBAPrec[0][0];
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- assert( uPartitions < BC6H_MAX_REGIONS );
- _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS );
- for(size_t p = 0; p <= uPartitions; ++p)
- {
- aQntEndPts[p].A.r = Quantize(aUnqEndPts[p].A.r, Prec.r, pEP->bSigned);
- aQntEndPts[p].A.g = Quantize(aUnqEndPts[p].A.g, Prec.g, pEP->bSigned);
- aQntEndPts[p].A.b = Quantize(aUnqEndPts[p].A.b, Prec.b, pEP->bSigned);
- aQntEndPts[p].B.r = Quantize(aUnqEndPts[p].B.r, Prec.r, pEP->bSigned);
- aQntEndPts[p].B.g = Quantize(aUnqEndPts[p].B.g, Prec.g, pEP->bSigned);
- aQntEndPts[p].B.b = Quantize(aUnqEndPts[p].B.b, Prec.b, pEP->bSigned);
- }
- }
- _Use_decl_annotations_
- void D3DX_BC6H::EmitBlock(const EncodeParams* pEP, const INTEndPntPair aEndPts[], const size_t aIndices[])
- {
- assert( pEP );
- const uint8_t uRealMode = ms_aInfo[pEP->uMode].uMode;
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec;
- const size_t uHeaderBits = uPartitions > 0 ? 82 : 65;
- const ModeDescriptor* desc = ms_aDesc[pEP->uMode];
- size_t uStartBit = 0;
- while(uStartBit < uHeaderBits)
- {
- switch(desc[uStartBit].m_eField)
- {
- case M: SetBit(uStartBit, uint8_t(uRealMode >> desc[uStartBit].m_uBit) & 0x01); break;
- case D: SetBit(uStartBit, uint8_t(pEP->uShape >> desc[uStartBit].m_uBit) & 0x01); break;
- case RW: SetBit(uStartBit, uint8_t(aEndPts[0].A.r >> desc[uStartBit].m_uBit) & 0x01); break;
- case RX: SetBit(uStartBit, uint8_t(aEndPts[0].B.r >> desc[uStartBit].m_uBit) & 0x01); break;
- case RY: SetBit(uStartBit, uint8_t(aEndPts[1].A.r >> desc[uStartBit].m_uBit) & 0x01); break;
- case RZ: SetBit(uStartBit, uint8_t(aEndPts[1].B.r >> desc[uStartBit].m_uBit) & 0x01); break;
- case GW: SetBit(uStartBit, uint8_t(aEndPts[0].A.g >> desc[uStartBit].m_uBit) & 0x01); break;
- case GX: SetBit(uStartBit, uint8_t(aEndPts[0].B.g >> desc[uStartBit].m_uBit) & 0x01); break;
- case GY: SetBit(uStartBit, uint8_t(aEndPts[1].A.g >> desc[uStartBit].m_uBit) & 0x01); break;
- case GZ: SetBit(uStartBit, uint8_t(aEndPts[1].B.g >> desc[uStartBit].m_uBit) & 0x01); break;
- case BW: SetBit(uStartBit, uint8_t(aEndPts[0].A.b >> desc[uStartBit].m_uBit) & 0x01); break;
- case BX: SetBit(uStartBit, uint8_t(aEndPts[0].B.b >> desc[uStartBit].m_uBit) & 0x01); break;
- case BY: SetBit(uStartBit, uint8_t(aEndPts[1].A.b >> desc[uStartBit].m_uBit) & 0x01); break;
- case BZ: SetBit(uStartBit, uint8_t(aEndPts[1].B.b >> desc[uStartBit].m_uBit) & 0x01); break;
- default: assert(false);
- }
- }
- for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- if(IsFixUpOffset(ms_aInfo[pEP->uMode].uPartitions, pEP->uShape, i))
- SetBits(uStartBit, uIndexPrec - 1, static_cast<uint8_t>( aIndices[i] ));
- else
- SetBits(uStartBit, uIndexPrec, static_cast<uint8_t>( aIndices[i] ));
- }
- assert(uStartBit == 128);
- }
- _Use_decl_annotations_
- void D3DX_BC6H::Refine(EncodeParams* pEP)
- {
- assert( pEP );
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- assert( uPartitions < BC6H_MAX_REGIONS );
- _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS );
- const bool bTransformed = ms_aInfo[pEP->uMode].bTransformed;
- float aOrgErr[BC6H_MAX_REGIONS], aOptErr[BC6H_MAX_REGIONS];
- INTEndPntPair aOrgEndPts[BC6H_MAX_REGIONS], aOptEndPts[BC6H_MAX_REGIONS];
- size_t aOrgIdx[NUM_PIXELS_PER_BLOCK], aOptIdx[NUM_PIXELS_PER_BLOCK];
- QuantizeEndPts(pEP, aOrgEndPts);
- AssignIndices(pEP, aOrgEndPts, aOrgIdx, aOrgErr);
- SwapIndices(pEP, aOrgEndPts, aOrgIdx);
- if(bTransformed) TransformForward(aOrgEndPts);
- if(EndPointsFit(pEP, aOrgEndPts))
- {
- if(bTransformed) TransformInverse(aOrgEndPts, ms_aInfo[pEP->uMode].RGBAPrec[0][0], pEP->bSigned);
- OptimizeEndPoints(pEP, aOrgErr, aOrgEndPts, aOptEndPts);
- AssignIndices(pEP, aOptEndPts, aOptIdx, aOptErr);
- SwapIndices(pEP, aOptEndPts, aOptIdx);
- float fOrgTotErr = 0.0f, fOptTotErr = 0.0f;
- for(size_t p = 0; p <= uPartitions; ++p)
- {
- fOrgTotErr += aOrgErr[p];
- fOptTotErr += aOptErr[p];
- }
- if(bTransformed) TransformForward(aOptEndPts);
- if(EndPointsFit(pEP, aOptEndPts) && fOptTotErr < fOrgTotErr && fOptTotErr < pEP->fBestErr)
- {
- pEP->fBestErr = fOptTotErr;
- EmitBlock(pEP, aOptEndPts, aOptIdx);
- }
- else if(fOrgTotErr < pEP->fBestErr)
- {
- // either it stopped fitting when we optimized it, or there was no improvement
- // so go back to the unoptimized endpoints which we know will fit
- if(bTransformed) TransformForward(aOrgEndPts);
- pEP->fBestErr = fOrgTotErr;
- EmitBlock(pEP, aOrgEndPts, aOrgIdx);
- }
- }
- }
- _Use_decl_annotations_
- void D3DX_BC6H::GeneratePaletteUnquantized(const EncodeParams* pEP, size_t uRegion, INTColor aPalette[])
- {
- assert( pEP );
- assert( uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
- _Analysis_assume_( uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
- const INTEndPntPair& endPts = pEP->aUnqEndPts[pEP->uShape][uRegion];
- const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec;
- const uint8_t uNumIndices = 1 << uIndexPrec;
- assert(uNumIndices > 0);
- _Analysis_assume_(uNumIndices > 0);
- const int* aWeights = nullptr;
- switch(uIndexPrec)
- {
- case 3: aWeights = g_aWeights3; assert(uNumIndices <= 8); _Analysis_assume_(uNumIndices <= 8); break;
- case 4: aWeights = g_aWeights4; assert(uNumIndices <= 16); _Analysis_assume_(uNumIndices <= 16); break;
- default:
- assert(false);
- for(size_t i = 0; i < uNumIndices; ++i)
- {
- #pragma prefast(suppress:22102 22103, "writing blocks in two halves confuses tool")
- aPalette[i] = INTColor(0,0,0);
- }
- return;
- }
- for(register size_t i = 0; i < uNumIndices; ++i)
- {
- aPalette[i].r = (endPts.A.r * (BC67_WEIGHT_MAX - aWeights[i]) + endPts.B.r * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT;
- aPalette[i].g = (endPts.A.g * (BC67_WEIGHT_MAX - aWeights[i]) + endPts.B.g * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT;
- aPalette[i].b = (endPts.A.b * (BC67_WEIGHT_MAX - aWeights[i]) + endPts.B.b * aWeights[i] + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT;
- }
- }
- _Use_decl_annotations_
- float D3DX_BC6H::MapColors(const EncodeParams* pEP, size_t uRegion, size_t np, const size_t* auIndex) const
- {
- assert( pEP );
- const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec;
- const uint8_t uNumIndices = 1 << uIndexPrec;
- INTColor aPalette[BC6H_MAX_INDICES];
- GeneratePaletteUnquantized(pEP, uRegion, aPalette);
- float fTotalErr = 0.0f;
- for(size_t i = 0; i < np; ++i)
- {
- float fBestErr = Norm(pEP->aIPixels[auIndex[i]], aPalette[0]);
- for(uint8_t j = 1; j < uNumIndices && fBestErr > 0.0f; ++j)
- {
- float fErr = Norm(pEP->aIPixels[auIndex[i]], aPalette[j]);
- if(fErr > fBestErr) break; // error increased, so we're done searching
- if(fErr < fBestErr) fBestErr = fErr;
- }
- fTotalErr += fBestErr;
- }
- return fTotalErr;
- }
- _Use_decl_annotations_
- float D3DX_BC6H::RoughMSE(EncodeParams* pEP) const
- {
- assert( pEP );
- assert( pEP->uShape < BC6H_MAX_SHAPES);
- _Analysis_assume_( pEP->uShape < BC6H_MAX_SHAPES);
- INTEndPntPair* aEndPts = pEP->aUnqEndPts[pEP->uShape];
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- assert( uPartitions < BC6H_MAX_REGIONS );
- _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS );
- size_t auPixIdx[NUM_PIXELS_PER_BLOCK];
- float fError = 0.0f;
- for(size_t p = 0; p <= uPartitions; ++p)
- {
- size_t np = 0;
- for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- if(g_aPartitionTable[uPartitions][pEP->uShape][i] == p)
- {
- auPixIdx[np++] = i;
- }
- }
- // handle simple cases
- assert(np > 0);
- if(np == 1)
- {
- aEndPts[p].A = pEP->aIPixels[auPixIdx[0]];
- aEndPts[p].B = pEP->aIPixels[auPixIdx[0]];
- continue;
- }
- else if(np == 2)
- {
- aEndPts[p].A = pEP->aIPixels[auPixIdx[0]];
- aEndPts[p].B = pEP->aIPixels[auPixIdx[1]];
- continue;
- }
- HDRColorA epA, epB;
- OptimizeRGB(pEP->aHDRPixels, &epA, &epB, 4, np, auPixIdx);
- aEndPts[p].A.Set(epA, pEP->bSigned);
- aEndPts[p].B.Set(epB, pEP->bSigned);
- if(pEP->bSigned)
- {
- aEndPts[p].A.Clamp(-F16MAX, F16MAX);
- aEndPts[p].B.Clamp(-F16MAX, F16MAX);
- }
- else
- {
- aEndPts[p].A.Clamp(0, F16MAX);
- aEndPts[p].B.Clamp(0, F16MAX);
- }
- fError += MapColors(pEP, p, np, auPixIdx);
- }
- return fError;
- }
- //-------------------------------------------------------------------------------------
- // BC7 Compression
- //-------------------------------------------------------------------------------------
- _Use_decl_annotations_
- void D3DX_BC7::Decode(Color (&pOut)[4][4]) const // !! this must be a reference because we're calling 'Zero' !!
- {
- size_t uFirst = 0;
- while(uFirst < 128 && !GetBit(uFirst)) {}
- uint8_t uMode = uint8_t(uFirst - 1);
- if(uMode < 8)
- {
- const uint8_t uPartitions = ms_aInfo[uMode].uPartitions;
- assert( uPartitions < BC7_MAX_REGIONS );
- _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
- const uint8_t uNumEndPts = (uPartitions + 1) << 1;
- const uint8_t uIndexPrec = ms_aInfo[uMode].uIndexPrec;
- const uint8_t uIndexPrec2 = ms_aInfo[uMode].uIndexPrec2;
- register size_t i;
- size_t uStartBit = uMode + 1;
- uint8_t P[6];
- uint8_t uShape = GetBits(uStartBit, ms_aInfo[uMode].uPartitionBits);
- assert( uShape < BC7_MAX_SHAPES );
- _Analysis_assume_( uShape < BC7_MAX_SHAPES );
- uint8_t uRotation = GetBits(uStartBit, ms_aInfo[uMode].uRotationBits);
- assert( uRotation < 4 );
- uint8_t uIndexMode = GetBits(uStartBit, ms_aInfo[uMode].uIndexModeBits);
- assert( uIndexMode < 2 );
- LDRColorA c[BC7_MAX_REGIONS << 1];
- const LDRColorA RGBAPrec = ms_aInfo[uMode].RGBAPrec;
- const LDRColorA RGBAPrecWithP = ms_aInfo[uMode].RGBAPrecWithP;
- assert( uNumEndPts <= (BC7_MAX_REGIONS << 1) );
- // Red channel
- for(i = 0; i < uNumEndPts; i++)
- {
- if ( uStartBit + RGBAPrec.r > 128 )
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC7: Invalid block encountered during decoding\n" );
- #endif
- FillWithErrorColors(pOut);
- return;
- }
- c[i].r = GetBits(uStartBit, RGBAPrec.r);
- }
- // Green channel
- for(i = 0; i < uNumEndPts; i++)
- {
- if ( uStartBit + RGBAPrec.g > 128 )
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC7: Invalid block encountered during decoding\n" );
- #endif
- FillWithErrorColors(pOut);
- return;
- }
- c[i].g = GetBits(uStartBit, RGBAPrec.g);
- }
- // Blue channel
- for(i = 0; i < uNumEndPts; i++)
- {
- if ( uStartBit + RGBAPrec.b > 128 )
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC7: Invalid block encountered during decoding\n" );
- #endif
- FillWithErrorColors(pOut);
- return;
- }
- c[i].b = GetBits(uStartBit, RGBAPrec.b);
- }
- // Alpha channel
- for(i = 0; i < uNumEndPts; i++)
- {
- if ( uStartBit + RGBAPrec.a > 128 )
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC7: Invalid block encountered during decoding\n" );
- #endif
- FillWithErrorColors(pOut);
- return;
- }
- c[i].a = RGBAPrec.a ? GetBits(uStartBit, RGBAPrec.a) : 255;
- }
- // P-bits
- assert( ms_aInfo[uMode].uPBits <= 6 );
- _Analysis_assume_( ms_aInfo[uMode].uPBits <= 6 );
- for(i = 0; i < ms_aInfo[uMode].uPBits; i++)
- {
- if ( uStartBit > 127 )
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC7: Invalid block encountered during decoding\n" );
- #endif
- FillWithErrorColors(pOut);
- return;
- }
- P[i] = GetBit(uStartBit);
- }
- if(ms_aInfo[uMode].uPBits)
- {
- for(i = 0; i < uNumEndPts; i++)
- {
- size_t pi = i * ms_aInfo[uMode].uPBits / uNumEndPts;
- for (register uint8_t ch = 0; ch < BC7_NUM_CHANNELS; ch++)
- {
- if(RGBAPrec[ch] != RGBAPrecWithP[ch])
- {
- c[i][ch] = (c[i][ch] << 1) | P[pi];
- }
- }
- }
- }
- for(i = 0; i < uNumEndPts; i++)
- {
- c[i] = Unquantize(c[i], RGBAPrecWithP);
- }
- uint8_t w1[NUM_PIXELS_PER_BLOCK], w2[NUM_PIXELS_PER_BLOCK];
- // read color indices
- for(i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- {
- size_t uNumBits = IsFixUpOffset(ms_aInfo[uMode].uPartitions, uShape, i) ? uIndexPrec - 1 : uIndexPrec;
- if ( uStartBit + uNumBits > 128 )
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC7: Invalid block encountered during decoding\n" );
- #endif
- FillWithErrorColors(pOut);
- return;
- }
- w1[i] = GetBits(uStartBit, uNumBits);
- }
- // read alpha indices
- if(uIndexPrec2)
- {
- for(i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- {
- size_t uNumBits = i ? uIndexPrec2 : uIndexPrec2 - 1;
- if ( uStartBit + uNumBits > 128 )
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC7: Invalid block encountered during decoding\n" );
- #endif
- FillWithErrorColors(pOut);
- return;
- }
- w2[i] = GetBits(uStartBit, uNumBits );
- }
- }
- for(i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- uint8_t uRegion = g_aPartitionTable[uPartitions][uShape][i];
- LDRColorA &outPixel = (LDRColorA&)pOut[0][i]; ASSERT(SIZE(LDRColorA)==SIZE(pOut[0][0])); // ESENTHEL CHANGED
- if(uIndexPrec2 == 0)
- {
- LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1[i], w1[i], uIndexPrec, uIndexPrec, outPixel);
- }
- else
- {
- if (uIndexMode == 0)
- {
- LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1[i], w2[i], uIndexPrec, uIndexPrec2, outPixel);
- }
- else
- {
- LDRColorA::Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w2[i], w1[i], uIndexPrec2, uIndexPrec, outPixel);
- }
- }
- switch (uRotation)
- {
- case 1: std::swap(outPixel.r, outPixel.a); break;
- case 2: std::swap(outPixel.g, outPixel.a); break;
- case 3: std::swap(outPixel.b, outPixel.a); break;
- }
- }
- }
- else
- {
- #ifdef _DEBUG
- OutputDebugStringA( "BC7: Reserved mode 8 encountered during decoding\n" );
- #endif
- // Per the BC7 format spec, we must return transparent black
- Zero(pOut); // ESENTHEL CHANGED
- }
- }
- _Use_decl_annotations_
- void D3DX_BC7::Encode(DWORD flags, const HDRColorA* const pIn)
- {
- assert(pIn);
- D3DX_BC7 final = *this;
- EncodeParams EP(pIn);
- float fMSEBest = FLT_MAX;
- for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- EP.aLDRPixels[i].r = uint8_t(std::max<float>(0.0f, std::min<float>(255.0f, pIn[i].r * 255.0f + 0.01f)));
- EP.aLDRPixels[i].g = uint8_t(std::max<float>(0.0f, std::min<float>(255.0f, pIn[i].g * 255.0f + 0.01f)));
- EP.aLDRPixels[i].b = uint8_t(std::max<float>(0.0f, std::min<float>(255.0f, pIn[i].b * 255.0f + 0.01f)));
- EP.aLDRPixels[i].a = uint8_t(std::max<float>(0.0f, std::min<float>(255.0f, pIn[i].a * 255.0f + 0.01f)));
- }
- for (EP.uMode = 0; EP.uMode < 8 && fMSEBest > 0; ++EP.uMode)
- {
- if (!(flags & BC_FLAGS_USE_3SUBSETS) && (EP.uMode == 0 || EP.uMode == 2))
- {
- // 3 subset modes tend to be used rarely and add significant compression time
- continue;
- }
- if ((flags & BC_FLAGS_FORCE_BC7_MODE6) && (EP.uMode != 6))
- {
- // Use only mode 6
- continue;
- }
- const size_t uShapes = size_t(1) << ms_aInfo[EP.uMode].uPartitionBits;
- assert(uShapes <= BC7_MAX_SHAPES);
- _Analysis_assume_(uShapes <= BC7_MAX_SHAPES);
- const size_t uNumRots = size_t(1) << ms_aInfo[EP.uMode].uRotationBits;
- const size_t uNumIdxMode = size_t(1) << ms_aInfo[EP.uMode].uIndexModeBits;
- // Number of rough cases to look at. reasonable values of this are 1, uShapes/4, and uShapes
- // uShapes/4 gets nearly all the cases; you can increase that a bit (say by 3 or 4) if you really want to squeeze the last bit out
- const size_t uItems = std::max<size_t>(1, uShapes >> 2);
- float afRoughMSE[BC7_MAX_SHAPES];
- size_t auShape[BC7_MAX_SHAPES];
- for (size_t r = 0; r < uNumRots && fMSEBest > 0; ++r)
- {
- switch (r)
- {
- case 1: for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].r, EP.aLDRPixels[i].a); break;
- case 2: for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].g, EP.aLDRPixels[i].a); break;
- case 3: for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].b, EP.aLDRPixels[i].a); break;
- }
- for (size_t im = 0; im < uNumIdxMode && fMSEBest > 0; ++im)
- {
- // pick the best uItems shapes and refine these.
- for (size_t s = 0; s < uShapes; s++)
- {
- afRoughMSE[s] = RoughMSE(&EP, s, im);
- auShape[s] = s;
- }
- // Bubble up the first uItems items
- for (size_t i = 0; i < uItems; i++)
- {
- for (size_t j = i + 1; j < uShapes; j++)
- {
- if (afRoughMSE[i] > afRoughMSE[j])
- {
- std::swap(afRoughMSE[i], afRoughMSE[j]);
- std::swap(auShape[i], auShape[j]);
- }
- }
- }
- for (size_t i = 0; i < uItems && fMSEBest > 0; i++)
- {
- float fMSE = Refine(&EP, auShape[i], r, im);
- if (fMSE < fMSEBest)
- {
- final = *this;
- fMSEBest = fMSE;
- }
- }
- }
- switch (r)
- {
- case 1: for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].r, EP.aLDRPixels[i].a); break;
- case 2: for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].g, EP.aLDRPixels[i].a); break;
- case 3: for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].b, EP.aLDRPixels[i].a); break;
- }
- }
- }
- *this = final;
- }
- //-------------------------------------------------------------------------------------
- _Use_decl_annotations_
- void D3DX_BC7::GeneratePaletteQuantized(const EncodeParams* pEP, size_t uIndexMode, const LDREndPntPair& endPts, LDRColorA aPalette[]) const
- {
- assert(pEP);
- const size_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec;
- const size_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2;
- const size_t uNumIndices = size_t(1) << uIndexPrec;
- const size_t uNumIndices2 = size_t(1) << uIndexPrec2;
- assert(uNumIndices > 0 && uNumIndices2 > 0);
- _Analysis_assume_(uNumIndices > 0 && uNumIndices2 > 0);
- assert((uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES));
- _Analysis_assume_((uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES));
- LDRColorA a = Unquantize(endPts.A, ms_aInfo[pEP->uMode].RGBAPrecWithP);
- LDRColorA b = Unquantize(endPts.B, ms_aInfo[pEP->uMode].RGBAPrecWithP);
- if(uIndexPrec2 == 0)
- {
- for(register size_t i = 0; i < uNumIndices; i++)
- LDRColorA::Interpolate(a, b, i, i, uIndexPrec, uIndexPrec, aPalette[i]);
- }
- else
- {
- for(register size_t i = 0; i < uNumIndices; i++)
- LDRColorA::InterpolateRGB(a, b, i, uIndexPrec, aPalette[i]);
- for(register size_t i = 0; i < uNumIndices2; i++)
- LDRColorA::InterpolateA(a, b, i, uIndexPrec2, aPalette[i]);
- }
- }
- _Use_decl_annotations_
- float D3DX_BC7::PerturbOne(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, size_t ch,
- const LDREndPntPair &oldEndPts, LDREndPntPair &newEndPts, float fOldErr, uint8_t do_b) const
- {
- assert( pEP );
- const int prec = ms_aInfo[pEP->uMode].RGBAPrecWithP[ch];
- LDREndPntPair tmp_endPts = newEndPts = oldEndPts;
- float fMinErr = fOldErr;
- uint8_t* pnew_c = (do_b ? &newEndPts.B[ch] : &newEndPts.A[ch]);
- uint8_t* ptmp_c = (do_b ? &tmp_endPts.B[ch] : &tmp_endPts.A[ch]);
- // do a logarithmic search for the best error for this endpoint (which)
- for(int step = 1 << (prec-1); step; step >>= 1)
- {
- bool bImproved = false;
- int beststep = 0;
- for(int sign = -1; sign <= 1; sign += 2)
- {
- int tmp = int(*pnew_c) + sign * step;
- if(tmp < 0 || tmp >= (1 << prec))
- continue;
- else
- *ptmp_c = (uint8_t) tmp;
- float fTotalErr = MapColors(pEP, aColors, np, uIndexMode, tmp_endPts, fMinErr);
- if(fTotalErr < fMinErr)
- {
- bImproved = true;
- fMinErr = fTotalErr;
- beststep = sign * step;
- }
- }
- // if this was an improvement, move the endpoint and continue search from there
- if(bImproved)
- *pnew_c = uint8_t(int(*pnew_c) + beststep);
- }
- return fMinErr;
- }
- // perturb the endpoints at least -3 to 3.
- // always ensure endpoint ordering is preserved (no need to overlap the scan)
- _Use_decl_annotations_
- void D3DX_BC7::Exhaustive(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, size_t ch,
- float& fOrgErr, LDREndPntPair& optEndPt) const
- {
- assert( pEP );
- const uint8_t uPrec = ms_aInfo[pEP->uMode].RGBAPrecWithP[ch];
- LDREndPntPair tmpEndPt;
- if(fOrgErr == 0)
- return;
- int delta = 5;
- // ok figure out the range of A and B
- tmpEndPt = optEndPt;
- int alow = std::max<int>(0, int(optEndPt.A[ch]) - delta);
- int ahigh = std::min<int>((1 << uPrec) - 1, int(optEndPt.A[ch]) + delta);
- int blow = std::max<int>(0, int(optEndPt.B[ch]) - delta);
- int bhigh = std::min<int>((1 << uPrec) - 1, int(optEndPt.B[ch]) + delta);
- int amin = 0;
- int bmin = 0;
- float fBestErr = fOrgErr;
- if (optEndPt.A[ch] <= optEndPt.B[ch])
- {
- // keep a <= b
- for (int a = alow; a <= ahigh; ++a)
- {
- for (int b = std::max<int>(a, blow); b < bhigh; ++b)
- {
- tmpEndPt.A[ch] = (uint8_t)a;
- tmpEndPt.B[ch] = (uint8_t)b;
- float fErr = MapColors(pEP, aColors, np, uIndexMode, tmpEndPt, fBestErr);
- if (fErr < fBestErr)
- {
- amin = a;
- bmin = b;
- fBestErr = fErr;
- }
- }
- }
- }
- else
- {
- // keep b <= a
- for (int b = blow; b < bhigh; ++b)
- {
- for (int a = std::max<int>(b, alow); a <= ahigh; ++a)
- {
- tmpEndPt.A[ch] = (uint8_t)a;
- tmpEndPt.B[ch] = (uint8_t)b;
- float fErr = MapColors(pEP, aColors, np, uIndexMode, tmpEndPt, fBestErr);
- if (fErr < fBestErr)
- {
- amin = a;
- bmin = b;
- fBestErr = fErr;
- }
- }
- }
- }
- if (fBestErr < fOrgErr)
- {
- optEndPt.A[ch] = (uint8_t)amin;
- optEndPt.B[ch] = (uint8_t)bmin;
- fOrgErr = fBestErr;
- }
- }
- _Use_decl_annotations_
- void D3DX_BC7::OptimizeOne(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode,
- float fOrgErr, const LDREndPntPair& org, LDREndPntPair& opt) const
- {
- assert(pEP);
- float fOptErr = fOrgErr;
- opt = org;
- LDREndPntPair new_a, new_b;
- LDREndPntPair newEndPts;
- uint8_t do_b;
- // now optimize each channel separately
- for (size_t ch = 0; ch < BC7_NUM_CHANNELS; ++ch)
- {
- if (ms_aInfo[pEP->uMode].RGBAPrecWithP[ch] == 0)
- continue;
- // figure out which endpoint when perturbed gives the most improvement and start there
- // if we just alternate, we can easily end up in a local minima
- float fErr0 = PerturbOne(pEP, aColors, np, uIndexMode, ch, opt, new_a, fOptErr, 0); // perturb endpt A
- float fErr1 = PerturbOne(pEP, aColors, np, uIndexMode, ch, opt, new_b, fOptErr, 1); // perturb endpt B
- uint8_t& copt_a = opt.A[ch];
- uint8_t& copt_b = opt.B[ch];
- uint8_t& cnew_a = new_a.A[ch];
- uint8_t& cnew_b = new_a.B[ch];
- if(fErr0 < fErr1)
- {
- if(fErr0 >= fOptErr)
- continue;
- copt_a = cnew_a;
- fOptErr = fErr0;
- do_b = 1; // do B next
- }
- else
- {
- if(fErr1 >= fOptErr)
- continue;
- copt_b = cnew_b;
- fOptErr = fErr1;
- do_b = 0; // do A next
- }
- // now alternate endpoints and keep trying until there is no improvement
- for( ; ; )
- {
- float fErr = PerturbOne(pEP, aColors, np, uIndexMode, ch, opt, newEndPts, fOptErr, do_b);
- if(fErr >= fOptErr)
- break;
- if(do_b == 0)
- copt_a = cnew_a;
- else
- copt_b = cnew_b;
- fOptErr = fErr;
- do_b = 1 - do_b; // now move the other endpoint
- }
- }
- // finally, do a small exhaustive search around what we think is the global minima to be sure
- for(size_t ch = 0; ch < BC7_NUM_CHANNELS; ch++)
- Exhaustive(pEP, aColors, np, uIndexMode, ch, fOptErr, opt);
- }
- _Use_decl_annotations_
- void D3DX_BC7::OptimizeEndPoints(const EncodeParams* pEP, size_t uShape, size_t uIndexMode, const float afOrgErr[],
- const LDREndPntPair aOrgEndPts[], LDREndPntPair aOptEndPts[]) const
- {
- assert( pEP );
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- assert( uPartitions < BC7_MAX_REGIONS && uShape < BC7_MAX_SHAPES );
- _Analysis_assume_( uPartitions < BC7_MAX_REGIONS && uShape < BC7_MAX_SHAPES );
- LDRColorA aPixels[NUM_PIXELS_PER_BLOCK];
- for(size_t p = 0; p <= uPartitions; ++p)
- {
- // collect the pixels in the region
- size_t np = 0;
- for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- if(g_aPartitionTable[uPartitions][uShape][i] == p)
- aPixels[np++] = pEP->aLDRPixels[i];
- OptimizeOne(pEP, aPixels, np, uIndexMode, afOrgErr[p], aOrgEndPts[p], aOptEndPts[p]);
- }
- }
- _Use_decl_annotations_
- void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uIndexMode, LDREndPntPair endPts[], size_t aIndices[], size_t aIndices2[],
- float afTotErr[]) const
- {
- assert( pEP );
- assert( uShape < BC7_MAX_SHAPES );
- _Analysis_assume_( uShape < BC7_MAX_SHAPES );
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- assert( uPartitions < BC7_MAX_REGIONS );
- _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
- const uint8_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec;
- const uint8_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2;
- const uint8_t uNumIndices = 1 << uIndexPrec;
- const uint8_t uNumIndices2 = 1 << uIndexPrec2;
- assert( (uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES) );
- _Analysis_assume_( (uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES) );
- const uint8_t uHighestIndexBit = uNumIndices >> 1;
- const uint8_t uHighestIndexBit2 = uNumIndices2 >> 1;
- LDRColorA aPalette[BC7_MAX_REGIONS][BC7_MAX_INDICES];
- // build list of possibles
- for(size_t p = 0; p <= uPartitions; p++)
- {
- GeneratePaletteQuantized(pEP, uIndexMode, endPts[p], aPalette[p]);
- afTotErr[p] = 0;
- }
- for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- {
- uint8_t uRegion = g_aPartitionTable[uPartitions][uShape][i];
- assert( uRegion < BC7_MAX_REGIONS );
- _Analysis_assume_( uRegion < BC7_MAX_REGIONS );
- afTotErr[uRegion] += ComputeError(pEP->aLDRPixels[i], aPalette[uRegion], uIndexPrec, uIndexPrec2, &(aIndices[i]), &(aIndices2[i]));
- }
- // swap endpoints as needed to ensure that the indices at index_positions have a 0 high-order bit
- if(uIndexPrec2 == 0)
- {
- for (register size_t p = 0; p <= uPartitions; p++)
- {
- if (aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit)
- {
- std::swap(endPts[p].A, endPts[p].B);
- for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- if (g_aPartitionTable[uPartitions][uShape][i] == p)
- aIndices[i] = uNumIndices - 1 - aIndices[i];
- }
- assert((aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit) == 0);
- }
- }
- else
- {
- for (register size_t p = 0; p <= uPartitions; p++)
- {
- if (aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit)
- {
- std::swap(endPts[p].A.r, endPts[p].B.r);
- std::swap(endPts[p].A.g, endPts[p].B.g);
- std::swap(endPts[p].A.b, endPts[p].B.b);
- for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- if(g_aPartitionTable[uPartitions][uShape][i] == p)
- aIndices[i] = uNumIndices - 1 - aIndices[i];
- }
- assert((aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit) == 0);
- if (aIndices2[0] & uHighestIndexBit2)
- {
- std::swap(endPts[p].A.a, endPts[p].B.a);
- for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- aIndices2[i] = uNumIndices2 - 1 - aIndices2[i];
- }
- assert((aIndices2[0] & uHighestIndexBit2) == 0);
- }
- }
- }
- _Use_decl_annotations_
- void D3DX_BC7::EmitBlock(const EncodeParams* pEP, size_t uShape, size_t uRotation, size_t uIndexMode, const LDREndPntPair aEndPts[], const size_t aIndex[], const size_t aIndex2[])
- {
- assert( pEP );
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- assert( uPartitions < BC7_MAX_REGIONS );
- _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
- const size_t uPBits = ms_aInfo[pEP->uMode].uPBits;
- const size_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec;
- const size_t uIndexPrec2 = ms_aInfo[pEP->uMode].uIndexPrec2;
- const LDRColorA RGBAPrec = ms_aInfo[pEP->uMode].RGBAPrec;
- const LDRColorA RGBAPrecWithP = ms_aInfo[pEP->uMode].RGBAPrecWithP;
- register size_t i;
- size_t uStartBit = 0;
- SetBits(uStartBit, pEP->uMode, 0);
- SetBits(uStartBit, 1, 1);
- SetBits(uStartBit, ms_aInfo[pEP->uMode].uRotationBits, static_cast<uint8_t>( uRotation ));
- SetBits(uStartBit, ms_aInfo[pEP->uMode].uIndexModeBits, static_cast<uint8_t>( uIndexMode ));
- SetBits(uStartBit, ms_aInfo[pEP->uMode].uPartitionBits, static_cast<uint8_t>( uShape ));
- if(uPBits)
- {
- const size_t uNumEP = size_t(1 + uPartitions) << 1;
- uint8_t aPVote[BC7_MAX_REGIONS << 1] = {0,0,0,0,0,0};
- uint8_t aCount[BC7_MAX_REGIONS << 1] = {0,0,0,0,0,0};
- for(uint8_t ch = 0; ch < BC7_NUM_CHANNELS; ch++)
- {
- uint8_t ep = 0;
- for(i = 0; i <= uPartitions; i++)
- {
- if(RGBAPrec[ch] == RGBAPrecWithP[ch])
- {
- SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].A[ch]);
- SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].B[ch]);
- }
- else
- {
- SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].A[ch] >> 1);
- SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].B[ch] >> 1);
- size_t idx = ep++ * uPBits / uNumEP;
- assert(idx < (BC7_MAX_REGIONS << 1));
- _Analysis_assume_(idx < (BC7_MAX_REGIONS << 1));
- aPVote[idx] += aEndPts[i].A[ch] & 0x01;
- aCount[idx]++;
- idx = ep++ * uPBits / uNumEP;
- assert(idx < (BC7_MAX_REGIONS << 1));
- _Analysis_assume_(idx < (BC7_MAX_REGIONS << 1));
- aPVote[idx] += aEndPts[i].B[ch] & 0x01;
- aCount[idx]++;
- }
- }
- }
- for(i = 0; i < uPBits; i++)
- {
- SetBits(uStartBit, 1, aPVote[i] > (aCount[i] >> 1) ? 1 : 0);
- }
- }
- else
- {
- for(size_t ch = 0; ch < BC7_NUM_CHANNELS; ch++)
- {
- for(i = 0; i <= uPartitions; i++)
- {
- SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].A[ch] );
- SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].B[ch] );
- }
- }
- }
- const size_t* aI1 = uIndexMode ? aIndex2 : aIndex;
- const size_t* aI2 = uIndexMode ? aIndex : aIndex2;
- for(i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- {
- if(IsFixUpOffset(ms_aInfo[pEP->uMode].uPartitions, uShape, i))
- SetBits(uStartBit, uIndexPrec - 1, static_cast<uint8_t>( aI1[i] ));
- else
- SetBits(uStartBit, uIndexPrec, static_cast<uint8_t>( aI1[i] ));
- }
- if(uIndexPrec2)
- for(i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- SetBits(uStartBit, i ? uIndexPrec2 : uIndexPrec2 - 1, static_cast<uint8_t>( aI2[i] ));
- assert(uStartBit == 128);
- }
- _Use_decl_annotations_
- float D3DX_BC7::Refine(const EncodeParams* pEP, size_t uShape, size_t uRotation, size_t uIndexMode)
- {
- assert( pEP );
- assert( uShape < BC7_MAX_SHAPES );
- _Analysis_assume_( uShape < BC7_MAX_SHAPES );
- const LDREndPntPair* aEndPts = pEP->aEndPts[uShape];
- const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- assert( uPartitions < BC7_MAX_REGIONS );
- _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
- LDREndPntPair aOrgEndPts[BC7_MAX_REGIONS];
- LDREndPntPair aOptEndPts[BC7_MAX_REGIONS];
- size_t aOrgIdx[NUM_PIXELS_PER_BLOCK];
- size_t aOrgIdx2[NUM_PIXELS_PER_BLOCK];
- size_t aOptIdx[NUM_PIXELS_PER_BLOCK];
- size_t aOptIdx2[NUM_PIXELS_PER_BLOCK];
- float aOrgErr[BC7_MAX_REGIONS];
- float aOptErr[BC7_MAX_REGIONS];
- for(register size_t p = 0; p <= uPartitions; p++)
- {
- aOrgEndPts[p].A = Quantize(aEndPts[p].A, ms_aInfo[pEP->uMode].RGBAPrecWithP);
- aOrgEndPts[p].B = Quantize(aEndPts[p].B, ms_aInfo[pEP->uMode].RGBAPrecWithP);
- }
- AssignIndices(pEP, uShape, uIndexMode, aOrgEndPts, aOrgIdx, aOrgIdx2, aOrgErr);
- OptimizeEndPoints(pEP, uShape, uIndexMode, aOrgErr, aOrgEndPts, aOptEndPts);
- AssignIndices(pEP, uShape, uIndexMode, aOptEndPts, aOptIdx, aOptIdx2, aOptErr);
- float fOrgTotErr = 0, fOptTotErr = 0;
- for(register size_t p = 0; p <= uPartitions; p++)
- {
- fOrgTotErr += aOrgErr[p];
- fOptTotErr += aOptErr[p];
- }
- if(fOptTotErr < fOrgTotErr)
- {
- EmitBlock(pEP, uShape, uRotation, uIndexMode, aOptEndPts, aOptIdx, aOptIdx2);
- return fOptTotErr;
- }
- else
- {
- EmitBlock(pEP, uShape, uRotation, uIndexMode, aOrgEndPts, aOrgIdx, aOrgIdx2);
- return fOrgTotErr;
- }
- }
- _Use_decl_annotations_
- float D3DX_BC7::MapColors(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, const LDREndPntPair& endPts, float fMinErr) const
- {
- assert( pEP );
- const uint8_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec;
- const uint8_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2;
- LDRColorA aPalette[BC7_MAX_INDICES];
- float fTotalErr = 0;
- GeneratePaletteQuantized(pEP, uIndexMode, endPts, aPalette);
- for(register size_t i = 0; i < np; ++i)
- {
- fTotalErr += ComputeError(aColors[i], aPalette, uIndexPrec, uIndexPrec2);
- if(fTotalErr > fMinErr) // check for early exit
- {
- fTotalErr = FLT_MAX;
- break;
- }
- }
- return fTotalErr;
- }
- _Use_decl_annotations_
- float D3DX_BC7::RoughMSE(EncodeParams* pEP, size_t uShape, size_t uIndexMode)
- {
- assert( pEP );
- assert( uShape < BC7_MAX_SHAPES );
- _Analysis_assume_( uShape < BC7_MAX_SHAPES );
- LDREndPntPair* aEndPts = pEP->aEndPts[uShape];
- const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- assert( uPartitions < BC7_MAX_REGIONS );
- _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
- const uint8_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec;
- const uint8_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2;
- const uint8_t uNumIndices = 1 << uIndexPrec;
- const uint8_t uNumIndices2 = 1 << uIndexPrec2;
- size_t auPixIdx[NUM_PIXELS_PER_BLOCK];
- LDRColorA aPalette[BC7_MAX_REGIONS][BC7_MAX_INDICES];
- for(size_t p = 0; p <= uPartitions; p++)
- {
- size_t np = 0;
- for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- {
- if (g_aPartitionTable[uPartitions][uShape][i] == p)
- {
- auPixIdx[np++] = i;
- }
- }
- // handle simple cases
- assert(np > 0);
- if(np == 1)
- {
- aEndPts[p].A = pEP->aLDRPixels[auPixIdx[0]];
- aEndPts[p].B = pEP->aLDRPixels[auPixIdx[0]];
- continue;
- }
- else if(np == 2)
- {
- aEndPts[p].A = pEP->aLDRPixels[auPixIdx[0]];
- aEndPts[p].B = pEP->aLDRPixels[auPixIdx[1]];
- continue;
- }
- if(uIndexPrec2 == 0)
- {
- HDRColorA epA, epB;
- OptimizeRGBA(pEP->aHDRPixels, &epA, &epB, 4, np, auPixIdx);
- epA.Clamp(0.0f, 1.0f);
- epB.Clamp(0.0f, 1.0f);
- epA *= 255.0f;
- epB *= 255.0f;
- aEndPts[p].A = epA.ToLDRColorA();
- aEndPts[p].B = epB.ToLDRColorA();
- }
- else
- {
- uint8_t uMinAlpha = 255, uMaxAlpha = 0;
- for (register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
- {
- uMinAlpha = std::min<uint8_t>(uMinAlpha, pEP->aLDRPixels[auPixIdx[i]].a);
- uMaxAlpha = std::max<uint8_t>(uMaxAlpha, pEP->aLDRPixels[auPixIdx[i]].a);
- }
- HDRColorA epA, epB;
- OptimizeRGB(pEP->aHDRPixels, &epA, &epB, 4, np, auPixIdx);
- epA.Clamp(0.0f, 1.0f);
- epB.Clamp(0.0f, 1.0f);
- epA *= 255.0f;
- epB *= 255.0f;
- aEndPts[p].A = epA.ToLDRColorA();
- aEndPts[p].B = epB.ToLDRColorA();
- aEndPts[p].A.a = uMinAlpha;
- aEndPts[p].B.a = uMaxAlpha;
- }
- }
- if(uIndexPrec2 == 0)
- {
- for(size_t p = 0; p <= uPartitions; p++)
- for(register size_t i = 0; i < uNumIndices; i++)
- LDRColorA::Interpolate(aEndPts[p].A, aEndPts[p].B, i, i, uIndexPrec, uIndexPrec, aPalette[p][i]);
- }
- else
- {
- for(size_t p = 0; p <= uPartitions; p++)
- {
- for(register size_t i = 0; i < uNumIndices; i++)
- LDRColorA::InterpolateRGB(aEndPts[p].A, aEndPts[p].B, i, uIndexPrec, aPalette[p][i]);
- for(register size_t i = 0; i < uNumIndices2; i++)
- LDRColorA::InterpolateA(aEndPts[p].A, aEndPts[p].B, i, uIndexPrec2, aPalette[p][i]);
- }
- }
- float fTotalErr = 0;
- for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
- {
- uint8_t uRegion = g_aPartitionTable[uPartitions][uShape][i];
- fTotalErr += ComputeError(pEP->aLDRPixels[i], aPalette[uRegion], uIndexPrec, uIndexPrec2);
- }
- return fTotalErr;
- }
- //=====================================================================================
- // Entry points
- //=====================================================================================
- //-------------------------------------------------------------------------------------
- // BC6H Compression
- //-------------------------------------------------------------------------------------
- _Use_decl_annotations_
- void DirectX::D3DXDecodeBC6HU(XMVECTOR *pColor, const uint8_t *pBC)
- {
- assert(pColor && pBC);
- static_assert(sizeof(D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes");
- reinterpret_cast<const D3DX_BC6H*>(pBC)->Decode(false, reinterpret_cast<HDRColorA*>(pColor));
- }
- _Use_decl_annotations_
- void DirectX::D3DXDecodeBC6HS(XMVECTOR *pColor, const uint8_t *pBC)
- {
- assert( pColor && pBC );
- static_assert( sizeof(D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes" );
- reinterpret_cast< const D3DX_BC6H* >( pBC )->Decode(true, reinterpret_cast<HDRColorA*>(pColor));
- }
- _Use_decl_annotations_
- void DirectX::D3DXEncodeBC6HU(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
- {
- UNREFERENCED_PARAMETER(flags);
- assert(pBC && pColor);
- static_assert(sizeof(D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes");
- reinterpret_cast<D3DX_BC6H*>(pBC)->Encode(false, reinterpret_cast<const HDRColorA*>(pColor));
- }
- _Use_decl_annotations_
- void DirectX::D3DXEncodeBC6HS(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
- {
- UNREFERENCED_PARAMETER(flags);
- assert(pBC && pColor);
- static_assert(sizeof(D3DX_BC6H) == 16, "D3DX_BC6H should be 16 bytes");
- reinterpret_cast<D3DX_BC6H*>(pBC)->Encode(true, reinterpret_cast<const HDRColorA*>(pColor));
- }
- //-------------------------------------------------------------------------------------
- // BC7 Compression
- //-------------------------------------------------------------------------------------
- _Use_decl_annotations_
- void DirectX::D3DXDecodeBC7(Color (&color)[4][4], const uint8_t *pBC) // ESENTHEL CHANGED
- {
- static_assert( sizeof(D3DX_BC7) == 16, "D3DX_BC7 should be 16 bytes" );
- reinterpret_cast< const D3DX_BC7* >( pBC )->Decode(color); // ESENTHEL CHANGED
- }
- _Use_decl_annotations_
- void DirectX::D3DXEncodeBC7(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
- {
- assert(pBC && pColor);
- static_assert(sizeof(D3DX_BC7) == 16, "D3DX_BC7 should be 16 bytes");
- reinterpret_cast<D3DX_BC7*>(pBC)->Encode(flags, reinterpret_cast<const HDRColorA*>(pColor));
- }
|