| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733 |
- /*==============================================================================================================
- * Copyright (c) 2020 John Jackson
- * gs_gfxt: Graphics Extension Util for Gunslinger
- * File: gs_gfxt.h
- * Github: https://github.com/MrFrenik/gunslinger
- * All Rights Reserved
- * MIT License
- * May all those that this source may reach be blessed by the LORD and find peace and joy in life.
- * Everyone who drinks of this water will be thirsty again; but whoever drinks of the water
- * that I will give him shall never thirst; John 4:13-14
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- * The above copyright, blessing, biblical verse, notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE WARRANTIES OF MECHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
-
- =================================================================================================================*/
- #ifndef GS_GFXT_H
- #define GS_GFXT_H
- /*
- USAGE: (IMPORTANT)
- =================================================================================================================
- Before including, define the gunslinger graphics extension implementation like this:
- #define GS_GFXT_IMPL
- in EXACTLY ONE C or C++ file that includes this header, BEFORE the
- include, like this:
- #define GS_GFXT_IMPL
- #include "gs_gfxt.h"
- All other files should just #include "gs_gfxt.h" without the #define.
- MUST include "gs.h" and declare GS_IMPL BEFORE this file, since this file relies on gunslinger core:
- #define GS_IMPL
- #include "gs.h"
- #define GS_GFXT_IMPL
- #include "gs_gfxt.h"
- GS_GFXT_HNDL:
- Internally, gfxt uses handles to retrieve raw data for shared types, like materials, meshes, pipelines, etc.
- This keeps memory consumption low allowing for trivial copying of references and handles without having to copy raw data.
- This handle, by default, is defined to a void* for pointers for raw data storage. This can be defined by the user to whatever
- handle type he'd like to use, such as a uint32_t handle to a slot array id. Additionally, all description objects that
- operate on shared data pass around a function pointer descriptor for how to retrieve that data - all of which can be user defined.
- ================================================================================================================
- */
- /*==== Interface ====*/
- /** @defgroup gs_graphics_extension_util Graphics Extension Util
- * Gunslinger Graphics Extension Util
- * @{
- */
- //=== Raw data retrieval/Handles ===//
- #ifndef GS_GFXT_HNDL
- #define GS_GFXT_HNDL void* // Default handle will just be a pointer to the data itself
- #endif
- // Config
- #ifndef GS_GFXT_TEX_COORD_MAX
- #define GS_GFXT_TEX_COORD_MAX 4
- #endif
- #ifndef GS_GFXT_COLOR_MAX
- #define GS_GFXT_COLOR_MAX 4
- #endif
- #ifndef GS_GFXT_JOINT_MAX
- #define GS_GFXT_JOINT_MAX 4
- #endif
- #ifndef GS_GFXT_WEIGHT_MAX
- #define GS_GFXT_WEIGHT_MAX 4
- #endif
- // Custom UINT field
- #ifndef GS_GFXT_CUSTOM_UINT_MAX
- #define GS_GFXT_CUSTOM_UINT_MAX 4
- #endif
- #ifndef GS_GFXT_INCLUDE_DIR_MAX
- #define GS_GFXT_INCLUDE_DIR_MAX 8
- #endif
- #ifndef GS_GFXT_UNIFORM_VIEW_MATRIX
- #define GS_GFXT_UNIFORM_VIEW_MATRIX "U_VIEW_MTX"
- #endif
- #ifndef GS_GFXT_UNIFORM_PROJECTION_MATRIX
- #define GS_GFXT_UNIFORM_PROJECTION_MATRIX "U_PROJECTION_MTX"
- #endif
- #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX
- #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX "U_VIEW_PROJECTION_MTX"
- #endif
- #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0
- #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0 "U_VIEW_PROJECTION_MTX_0"
- #endif
- #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1
- #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1 "U_VIEW_PROJECTION_MTX_1"
- #endif
- #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2
- #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2 "U_VIEW_PROJECTION_MTX_2"
- #endif
- #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3
- #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3 "U_VIEW_PROJECTION_MTX_3"
- #endif
- #ifndef GS_GFXT_UNIFORM_MODEL_MATRIX
- #define GS_GFXT_UNIFORM_MODEL_MATRIX "U_MODEL_MTX"
- #endif
- #ifndef GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX
- #define GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX "U_INVERSE_MODEL_MTX"
- #endif
- #ifndef GS_GFXT_UNIFORM_VIEW_WORLD_POSITION
- #define GS_GFXT_UNIFORM_VIEW_WORLD_POSITION "U_VIEW_WORLD_POSITION"
- #endif
- #ifndef GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX
- #define GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX "U_MVP_MTX"
- #endif
- #ifndef GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0
- #define GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0 "U_MVP_MTX_0"
- #endif
- #ifndef GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1
- #define GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1 "U_MVP_MTX_1"
- #endif
- #ifndef GS_GFXT_UNIFORM_TIME
- #define GS_GFXT_UNIFORM_TIME "U_TIME"
- #endif
- typedef void* (*gs_gfxt_raw_data_func)(GS_GFXT_HNDL hndl, void* user_data);
- #define GS_GFXT_RAW_DATA(FUNC_DESC, T)\
- ((T*)(FUNC_DESC)->func((FUNC_DESC)->hndl, (FUNC_DESC)->user_data))
- typedef struct gs_gfxt_raw_data_func_desc_t {
- GS_GFXT_HNDL hndl; // Handle used for retrieving data.
- gs_gfxt_raw_data_func func; // User defined function for pipeline data retrieval
- void* user_data; // Optional user data for function
- } gs_gfxt_raw_data_func_desc_t;
- //=== Uniforms/Uniform blocks ===//
- typedef struct gs_gfxt_uniform_desc_t {
- char name[64]; // Name of uniform (for binding to shader)
- gs_graphics_uniform_type type; // Type of uniform: GS_GRAPHICS_UNIFORM_VEC2, GS_GRAPHICS_UNIFORM_VEC3, etc.
- uint32_t binding; // Binding for this uniform in shader
- gs_graphics_shader_stage_type stage; // Shader stage for this uniform
- gs_graphics_access_type access_type; // Access type for this uniform (compute only)
- } gs_gfxt_uniform_desc_t;
- typedef struct gs_gfxt_uniform_t {
- gs_handle(gs_graphics_uniform_t) hndl; // Graphics handle resource for actual uniform
- uint32_t offset; // Individual offset for this uniform in material byte buffer data
- uint32_t binding; // Binding for this uniform
- size_t size; // Size of this uniform data in bytes
- gs_graphics_uniform_type type; // Type of this uniform
- gs_graphics_access_type access_type; // Access type of uniform (compute only)
- } gs_gfxt_uniform_t;
- typedef struct gs_gfxt_uniform_block_desc_t {
- gs_gfxt_uniform_desc_t* layout; // Layout for all uniform data for this block to hold
- size_t size; // Size of layout in bytes
- } gs_gfxt_uniform_block_desc_t;
- typedef struct gs_gfxt_uniform_block_lookup_key_t {
- char name[64];
- } gs_gfxt_uniform_block_lookup_key_t;
- typedef struct gs_gfxt_uniform_block_t {
- gs_dyn_array(gs_gfxt_uniform_t) uniforms; // Raw uniform handle array
- gs_hash_table(uint64_t, uint32_t) lookup; // Index lookup table (used for byte buffer offsets in material uni. data)
- size_t size; // Total size of material data for entire block
- } gs_gfxt_uniform_block_t;
- //=== Texture ===//
- typedef gs_handle(gs_graphics_texture_t) gs_gfxt_texture_t;
- //=== Mesh ===//
- typedef gs_asset_mesh_attribute_type gs_gfxt_mesh_attribute_type;
- typedef gs_asset_mesh_layout_t gs_gfxt_mesh_layout_t;
- /*
- typedef struct
- {
- union
- {
- void* interleave;
- struct
- {
- void* positions;
- void* normals;
- void* tangents;
- void* tex_coords[TEX_COORD_MAX];
- void* joints[JOINT_MAX];
- void* weights[WEIGHT_MAX];
- } non_interleave;
- } vertex;
- size_t vertex_size;
- void* indices;
- } gs_gfxt_mesh_primitive_data_t;
- */
- typedef struct
- {
- void* data;
- size_t size;
- } gs_gfxt_mesh_vertex_attribute_t;
- typedef struct
- {
- gs_gfxt_mesh_vertex_attribute_t positions; // All position data
- gs_gfxt_mesh_vertex_attribute_t normals;
- gs_gfxt_mesh_vertex_attribute_t tangents;
- gs_gfxt_mesh_vertex_attribute_t tex_coords[GS_GFXT_TEX_COORD_MAX];
- gs_gfxt_mesh_vertex_attribute_t colors[GS_GFXT_COLOR_MAX];
- gs_gfxt_mesh_vertex_attribute_t joints[GS_GFXT_JOINT_MAX];
- gs_gfxt_mesh_vertex_attribute_t weights[GS_GFXT_WEIGHT_MAX];
- gs_gfxt_mesh_vertex_attribute_t custom_uint[GS_GFXT_CUSTOM_UINT_MAX];
- gs_gfxt_mesh_vertex_attribute_t indices;
- uint32_t count; // Total count of indices
- } gs_gfxt_mesh_vertex_data_t;
- // Structured/packed raw mesh data
- // TODO(john): Make the primitives array static to avoid heap alloc
- typedef struct gs_gfxt_mesh_raw_data_t {
- gs_dyn_array(gs_gfxt_mesh_vertex_data_t) primitives; // All primitive data
- } gs_gfxt_mesh_raw_data_t;
- typedef struct gs_gfxt_mesh_import_options_t {
- gs_gfxt_mesh_layout_t* layout; // Mesh attribute layout array
- size_t size; // Size of mesh attribute layout array in bytes
- size_t index_buffer_element_size; // Size of index data size in bytes
- } gs_gfxt_mesh_import_options_t;
- GS_API_DECL void gs_gfxt_mesh_import_options_free(gs_gfxt_mesh_import_options_t* opt);
- typedef struct gs_gfxt_mesh_desc_s {
- gs_gfxt_mesh_raw_data_t* meshes; // Mesh data array
- size_t size; // Size of mesh data array in bytes
- bool32 keep_data; // Whether or not to free data after use
- } gs_gfxt_mesh_desc_t;
- typedef struct gs_gfxt_vertex_stream_s
- {
- gs_handle(gs_graphics_vertex_buffer_t) positions;
- gs_handle(gs_graphics_vertex_buffer_t) normals;
- gs_handle(gs_graphics_vertex_buffer_t) tangents;
- gs_handle(gs_graphics_vertex_buffer_t) colors[GS_GFXT_COLOR_MAX];
- gs_handle(gs_graphics_vertex_buffer_t) tex_coords[GS_GFXT_TEX_COORD_MAX];
- gs_handle(gs_graphics_vertex_buffer_t) joints[GS_GFXT_JOINT_MAX];
- gs_handle(gs_graphics_vertex_buffer_t) weights[GS_GFXT_WEIGHT_MAX];
- gs_handle(gs_graphics_vertex_buffer_t) custom_uint[GS_GFXT_CUSTOM_UINT_MAX];
- } gs_gfxt_vertex_stream_t;
- typedef struct gs_gfxt_mesh_primitive_s {
- gs_gfxt_vertex_stream_t stream; // All vertex data streams
- gs_handle(gs_graphics_index_buffer_t) indices; // Index buffer
- uint32_t count; // Total number of vertices
- } gs_gfxt_mesh_primitive_t;
- typedef struct gs_gfxt_mesh_s {
- gs_dyn_array(gs_gfxt_mesh_primitive_t) primitives;
- gs_gfxt_mesh_desc_t desc;
- } gs_gfxt_mesh_t;
- //=== Pipeline ===//
- typedef struct gs_gfxt_pipeline_desc_s {
- gs_graphics_pipeline_desc_t pip_desc; // Description for constructing pipeline object
- gs_gfxt_uniform_block_desc_t ublock_desc; // Description for constructing uniform block object
- } gs_gfxt_pipeline_desc_t;
- typedef struct gs_gfxt_pipeline_s {
- gs_handle(gs_graphics_pipeline_t) hndl; // Graphics handle resource for actual pipeline
- gs_gfxt_uniform_block_t ublock; // Uniform block for holding all uniform data
- gs_dyn_array(gs_gfxt_mesh_layout_t) mesh_layout;
- gs_graphics_pipeline_desc_t desc;
- } gs_gfxt_pipeline_t;
- //=== Material ===//
- typedef struct gs_gfxt_material_desc_s {
- gs_gfxt_raw_data_func_desc_t pip_func; // Description for retrieving raw pipeline pointer data from handle.
- } gs_gfxt_material_desc_t;
- typedef struct gs_gfxt_material_s {
- gs_gfxt_material_desc_t desc; // Material description object
- gs_byte_buffer_t uniform_data; // Byte buffer of actual uniform data to send to GPU
- gs_byte_buffer_t image_buffer_data; // Image buffer data
- } gs_gfxt_material_t;
- //=== Renderable ===//
- typedef struct gs_gfxt_renderable_desc_s {
- gs_gfxt_raw_data_func_desc_t mesh; // Description for retrieving raw mesh pointer data from handle.
- gs_gfxt_raw_data_func_desc_t material; // Description for retrieving raw material pointer data from handle.
- } gs_gfxt_renderable_desc_t;
- typedef struct gs_gfxt_renderable_s {
- gs_gfxt_renderable_desc_t desc; // Renderable description object
- gs_mat4 model_matrix; // Model matrix for renderable
- } gs_gfxt_renderable_t;
- //=== Graphics scene ===//
- typedef struct gs_gfxt_scene_s {
- gs_slot_array(gs_gfxt_renderable_t) renderables;
- } gs_gfxt_scene_t;
- //==== API =====//
- //=== Creation ===//
- GS_API_DECL gs_gfxt_pipeline_t gs_gfxt_pipeline_create(const gs_gfxt_pipeline_desc_t* desc);
- GS_API_DECL gs_gfxt_material_t gs_gfxt_material_create(gs_gfxt_material_desc_t* desc);
- GS_API_DECL gs_gfxt_mesh_t gs_gfxt_mesh_create(const gs_gfxt_mesh_desc_t* desc);
- GS_API_DECL void gs_gfxt_mesh_update_or_create(gs_gfxt_mesh_t* mesh, const gs_gfxt_mesh_desc_t* desc);
- GS_API_DECL gs_gfxt_renderable_t gs_gfxt_renderable_create(const gs_gfxt_renderable_desc_t* desc);
- GS_API_DECL gs_gfxt_uniform_block_t gs_gfxt_uniform_block_create(const gs_gfxt_uniform_block_desc_t* desc);
- GS_API_DECL gs_gfxt_texture_t gs_gfxt_texture_create(gs_graphics_texture_desc_t* desc);
- //=== Destruction ===//
- GS_API_DECL void gs_gfxt_texture_destroy(gs_gfxt_texture_t* texture);
- GS_API_DECL void gs_gfxt_material_destroy(gs_gfxt_material_t* material);
- GS_API_DECL void gs_gfxt_mesh_destroy(gs_gfxt_mesh_t* mesh);
- GS_API_DECL void gs_gfxt_uniform_block_destroy(gs_gfxt_uniform_block_t* ub);
- GS_API_DECL void gs_gfxt_pipeline_destroy(gs_gfxt_pipeline_t* pipeline);
- //=== Resource Loading ===//
- GS_API_DECL gs_gfxt_pipeline_t gs_gfxt_pipeline_load_from_file(const char* path);
- GS_API_DECL gs_gfxt_pipeline_t gs_gfxt_pipeline_load_from_memory(const char* data, size_t sz);
- GS_API_DECL gs_gfxt_pipeline_t gs_gfxt_pipeline_load_from_memory_ext(const char* data, size_t sz, const char* file_dir);
- GS_API_DECL gs_gfxt_texture_t gs_gfxt_texture_load_from_file(const char* path, gs_graphics_texture_desc_t* desc, bool flip, bool keep_data);
- GS_API_DECL gs_gfxt_texture_t gs_gfxt_texture_load_from_memory(const char* data, size_t sz, gs_graphics_texture_desc_t* desc, bool flip, bool keep_data);
- //=== Copy ===//
- GS_API_DECL gs_gfxt_material_t gs_gfxt_material_deep_copy(gs_gfxt_material_t* src);
- //=== Pipeline API ===//
- GS_API_DECL gs_gfxt_uniform_t* gs_gfxt_pipeline_get_uniform(gs_gfxt_pipeline_t* pip, const char* name);
- //=== Material API ===//
- GS_API_DECL void gs_gfxt_material_set_uniform(gs_gfxt_material_t* mat, const char* name, const void* data);
- GS_API_DECL void gs_gfxt_material_bind(gs_command_buffer_t* cb, gs_gfxt_material_t* mat);
- GS_API_DECL void gs_gfxt_material_bind_pipeline(gs_command_buffer_t* cb, gs_gfxt_material_t* mat);
- GS_API_DECL void gs_gfxt_material_bind_uniforms(gs_command_buffer_t* cb, gs_gfxt_material_t* mat);
- GS_API_DECL gs_gfxt_pipeline_t* gs_gfxt_material_get_pipeline(gs_gfxt_material_t* mat);
- //=== Mesh API ===//
- GS_API_DECL void gs_gfxt_mesh_draw_pipeline(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_pipeline_t* pip);
- GS_API_DECL void gs_gfxt_mesh_draw_material(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_material_t* mat);
- GS_API_DECL void gs_gfxt_mesh_draw_materials(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_material_t** mats, size_t mats_size);
- GS_API_DECL void gs_gfxt_mesh_draw_layout(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_mesh_layout_t* layout, size_t layout_size);
- GS_API_DECL gs_gfxt_mesh_t gs_gfxt_mesh_load_from_file(const char* file, gs_gfxt_mesh_import_options_t* options);
- GS_API_DECL bool gs_gfxt_load_gltf_data_from_file(const char* path, gs_gfxt_mesh_import_options_t* options, gs_gfxt_mesh_raw_data_t** out, uint32_t* mesh_count);
- // Util API
- GS_API_DECL void* gs_gfxt_raw_data_default_impl(GS_GFXT_HNDL hndl, void* user_data);
- // Mesh Generation API
- GS_API_DECL gs_gfxt_mesh_t gs_gfxt_mesh_unit_quad_generate(gs_gfxt_mesh_import_options_t* options);
- gs_handle(gs_graphics_texture_t) gs_gfxt_texture_generate_default();
- /** @} */ // end of gs_graphics_extension_util
- #ifdef GS_GFXT_IMPL
- /*==== Implementation ====*/
- // Creation/Destruction
- GS_API_DECL gs_gfxt_pipeline_t
- gs_gfxt_pipeline_create(const gs_gfxt_pipeline_desc_t* desc)
- {
- gs_gfxt_pipeline_t pip = gs_default_val();
- if (!desc) {
- gs_assert(false);
- return pip;
- }
- pip.hndl = gs_graphics_pipeline_create(&desc->pip_desc);
- pip.ublock = gs_gfxt_uniform_block_create(&desc->ublock_desc);
- pip.desc = desc->pip_desc;
- pip.desc.layout.attrs = gs_malloc(desc->pip_desc.layout.size);
- memcpy(pip.desc.layout.attrs, desc->pip_desc.layout.attrs, desc->pip_desc.layout.size);
- return pip;
- }
- GS_API_DECL gs_gfxt_uniform_block_t
- gs_gfxt_uniform_block_create(const gs_gfxt_uniform_block_desc_t* desc)
- {
- gs_gfxt_uniform_block_t block = gs_default_val();
- if (!desc) return block;
- // Iterate through layout, construct uniforms, place them into hash table
- uint32_t offset = 0;
- uint32_t image2D_offset = 0;
- uint32_t ct = desc->size / sizeof(gs_gfxt_uniform_desc_t);
- for (uint32_t i = 0; i < ct; ++i)
- {
- gs_gfxt_uniform_desc_t* ud = &desc->layout[i];
- gs_gfxt_uniform_t u = gs_default_val();
- gs_graphics_uniform_desc_t u_desc = gs_default_val();
- gs_graphics_uniform_layout_desc_t u_layout = gs_default_val();
- u_layout.type = ud->type;
- memcpy(u_desc.name, ud->name, 64);
- u_desc.layout = &u_layout;
- u.binding = ud->binding;
- u.type = ud->type;
- // Determine offset/hndl
- switch (ud->type)
- {
- case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
- {
- u.offset = image2D_offset;
- } break;
- default:
- {
- u.hndl = gs_graphics_uniform_create(&u_desc);
- u.offset = offset;
- } break;
- }
- // Add to data offset based on type
- switch (ud->type) {
- default:
- case GS_GRAPHICS_UNIFORM_FLOAT: offset += sizeof(float); break;
- case GS_GRAPHICS_UNIFORM_INT: offset += sizeof(int32_t); break;
- case GS_GRAPHICS_UNIFORM_VEC2: offset += sizeof(gs_vec2); break;
- case GS_GRAPHICS_UNIFORM_VEC3: offset += sizeof(gs_vec3); break;
- case GS_GRAPHICS_UNIFORM_VEC4: offset += sizeof(gs_vec4); break;
- case GS_GRAPHICS_UNIFORM_MAT4: offset += sizeof(gs_mat4); break;
- case GS_GRAPHICS_UNIFORM_SAMPLER2D: offset += sizeof(gs_handle(gs_graphics_texture_t)); break;
- case GS_GRAPHICS_UNIFORM_USAMPLER2D: offset += sizeof(gs_handle(gs_graphics_texture_t)); break;
- case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
- {
- image2D_offset += sizeof(gs_handle(gs_graphics_texture_t));
- } break;
- }
- // Add uniform to block with name as key
- uint64_t key = gs_hash_str64(ud->name);
- gs_dyn_array_push(block.uniforms, u);
- gs_hash_table_insert(block.lookup, key, gs_dyn_array_size(block.uniforms) - 1);
- }
- block.size = offset;
- return block;
- }
- GS_API_DECL gs_gfxt_texture_t
- gs_gfxt_texture_create(gs_graphics_texture_desc_t* desc)
- {
- return gs_graphics_texture_create(desc);
- }
- GS_API_DECL gs_gfxt_material_t
- gs_gfxt_material_create(gs_gfxt_material_desc_t* desc)
- {
- gs_gfxt_material_t mat = gs_default_val();
- if (!desc) {
- gs_assert(false);
- return mat;
- }
- // Set desc information to defaults if not provided.
- if (!desc->pip_func.func) desc->pip_func.func = gs_gfxt_raw_data_default_impl;
- gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&desc->pip_func, gs_gfxt_pipeline_t);
- gs_assert(pip);
- mat.desc = *desc;
- mat.uniform_data = gs_byte_buffer_new();
- mat.image_buffer_data = gs_byte_buffer_new();
- gs_byte_buffer_resize(&mat.uniform_data, pip->ublock.size);
- gs_byte_buffer_memset(&mat.uniform_data, 0);
- return mat;
- }
- GS_API_DECL gs_gfxt_mesh_t
- gs_gfxt_mesh_create(const gs_gfxt_mesh_desc_t* desc)
- {
- gs_gfxt_mesh_t mesh = gs_default_val();
- if (!desc) {
- return mesh;
- }
- const uint32_t mesh_count = desc->size / sizeof(gs_gfxt_mesh_raw_data_t);
- // Process all mesh data, add meshes
- for (uint32_t i = 0; i < mesh_count; ++i)
- {
- gs_gfxt_mesh_raw_data_t* m = &desc->meshes[i];
- for (uint32_t p = 0; p < gs_dyn_array_size(m->primitives); ++p)
- {
- // Get raw vertex data
- gs_gfxt_mesh_vertex_data_t* vdata = &m->primitives[p];
- // Construct primitive
- gs_gfxt_mesh_primitive_t prim = gs_default_val();
- prim.count = vdata->count;
- // Positions
- if (vdata->positions.data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->positions.data;
- vdesc.size = vdata->positions.size;
- prim.stream.positions = gs_graphics_vertex_buffer_create(&vdesc);
- if (!desc->keep_data)
- {
- gs_free(vdata->positions.data);
- }
- }
- // Normals
- if (vdata->normals.data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->normals.data;
- vdesc.size = vdata->normals.size;
- prim.stream.normals = gs_graphics_vertex_buffer_create(&vdesc);
- if (!desc->keep_data)
- {
- gs_free(vdata->normals.data);
- }
- }
- // Tangents
- if (vdata->tangents.data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->tangents.data;
- vdesc.size = vdata->tangents.size;
- prim.stream.tangents = gs_graphics_vertex_buffer_create(&vdesc);
- if (!desc->keep_data)
- {
- gs_free(vdata->tangents.data);
- }
- }
- // Texcoords
- for (uint32_t j = 0; j < GS_GFXT_TEX_COORD_MAX; ++j)
- {
- if (vdata->tex_coords[j].data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->tex_coords[j].data;
- vdesc.size = vdata->tex_coords[j].size;
- prim.stream.tex_coords[j] = gs_graphics_vertex_buffer_create(&vdesc);
- if (!desc->keep_data)
- {
- gs_free(vdata->tex_coords[j].data);
- }
- }
- }
- // Colors
- for (uint32_t j = 0; j < GS_GFXT_COLOR_MAX; ++j)
- {
- if (vdata->colors[j].data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->colors[j].data;
- vdesc.size = vdata->colors[j].size;
- prim.stream.colors[j] = gs_graphics_vertex_buffer_create(&vdesc);
- if (!desc->keep_data)
- {
- gs_free(vdata->colors[j].data);
- }
- }
- }
- // Joints
- for (uint32_t j = 0; j < GS_GFXT_JOINT_MAX; ++j)
- {
- if (vdata->joints[j].data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->joints[j].data;
- vdesc.size = vdata->joints[j].size;
- prim.stream.joints[j] = gs_graphics_vertex_buffer_create(&vdesc);
- if (!desc->keep_data)
- {
- gs_free(vdata->joints[j].data);
- }
- }
- }
- // Weights
- for (uint32_t j = 0; j < GS_GFXT_WEIGHT_MAX; ++j)
- {
- if (vdata->weights[j].data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->weights[j].data;
- vdesc.size = vdata->weights[j].size;
- prim.stream.weights[j] = gs_graphics_vertex_buffer_create(&vdesc);
- if (!desc->keep_data)
- {
- gs_free(vdata->weights[j].data);
- }
- }
- }
- // Index buffer decl
- gs_graphics_index_buffer_desc_t idesc = gs_default_val();
- idesc.data = vdata->indices.data;
- idesc.size = vdata->indices.size;
- // Construct index buffer for primitive
- prim.indices = gs_graphics_index_buffer_create(&idesc);
- if (!desc->keep_data)
- {
- gs_free(vdata->indices.data);
- }
- // Add primitive to mesh
- gs_dyn_array_push(mesh.primitives, prim);
- }
- if (!desc->keep_data)
- {
- gs_dyn_array_free(m->primitives);
- }
- }
- if (!desc->keep_data)
- {
- gs_free(desc->meshes);
- }
- return mesh;
- }
- GS_API_DECL void
- gs_gfxt_mesh_update_or_create(gs_gfxt_mesh_t* mesh, const gs_gfxt_mesh_desc_t* desc)
- {
- if (!desc || !mesh) {
- return;
- }
- /*
- // Need to create mesh if not already done
- if (gs_dyn_array_empty(mesh->primitives)) {
- *mesh = gs_gfxt_mesh_create(desc);
- return;
- }
- */
- const uint32_t mesh_count = desc->size / sizeof(gs_gfxt_mesh_raw_data_t);
- // Process all mesh data, add meshes
- for (uint32_t i = 0; i < mesh_count; ++i)
- {
- gs_gfxt_mesh_raw_data_t* m = &desc->meshes[i];
- for (uint32_t p = 0; p < gs_dyn_array_size(m->primitives); ++p)
- {
- // Get raw vertex data
- gs_gfxt_mesh_vertex_data_t* vdata = &m->primitives[p];
- // Construct or retrieve mesh primitive
- gs_gfxt_mesh_primitive_t* prim = NULL;
- if (gs_dyn_array_empty(mesh->primitives) || gs_dyn_array_size(mesh->primitives) < p)
- {
- gs_gfxt_mesh_primitive_t dprim = gs_default_val();
- gs_dyn_array_push(mesh->primitives, dprim);
- }
- prim = &mesh->primitives[p];
- // Set prim count
- prim->count = vdata->count;
- // Positions
- if (vdata->positions.data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->positions.data;
- vdesc.size = vdata->positions.size;
- // Update
- if (prim->stream.positions.id)
- {
- gs_graphics_vertex_buffer_update(prim->stream.positions, &vdesc);
- }
- // Create
- else
- {
- prim->stream.positions = gs_graphics_vertex_buffer_create(&vdesc);
- }
- if (!desc->keep_data)
- {
- gs_free(vdata->positions.data);
- }
- }
- // Normals
- if (vdata->normals.data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->normals.data;
- vdesc.size = vdata->normals.size;
- // Update
- if (prim->stream.normals.id)
- {
- gs_graphics_vertex_buffer_update(prim->stream.normals, &vdesc);
- }
- else
- {
- prim->stream.normals = gs_graphics_vertex_buffer_create(&vdesc);
- }
- if (!desc->keep_data)
- {
- gs_free(vdata->normals.data);
- }
- }
- // Tangents
- if (vdata->tangents.data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->tangents.data;
- vdesc.size = vdata->tangents.size;
- if (prim->stream.tangents.id)
- {
- gs_graphics_vertex_buffer_update(prim->stream.tangents, &vdesc);
- }
- else
- {
- prim->stream.tangents = gs_graphics_vertex_buffer_create(&vdesc);
- }
- if (!desc->keep_data)
- {
- gs_free(vdata->tangents.data);
- }
- }
- // Texcoords
- for (uint32_t j = 0; j < GS_GFXT_TEX_COORD_MAX; ++j)
- {
- if (vdata->tex_coords[j].data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->tex_coords[j].data;
- vdesc.size = vdata->tex_coords[j].size;
- if (prim->stream.tex_coords[j].id)
- {
- gs_graphics_vertex_buffer_update(prim->stream.tex_coords[j], &vdesc);
- }
- else
- {
- prim->stream.tex_coords[j] = gs_graphics_vertex_buffer_create(&vdesc);
- }
- if (!desc->keep_data)
- {
- gs_free(vdata->tex_coords[j].data);
- }
- }
- }
- // Colors
- for (uint32_t j = 0; j < GS_GFXT_COLOR_MAX; ++j)
- {
- if (vdata->colors[j].data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->colors[j].data;
- vdesc.size = vdata->colors[j].size;
-
- if (prim->stream.colors[j].id)
- {
- gs_graphics_vertex_buffer_update(prim->stream.colors[j], &vdesc);
- }
- else
- {
- prim->stream.colors[j] = gs_graphics_vertex_buffer_create(&vdesc);
- }
- if (!desc->keep_data)
- {
- gs_free(vdata->colors[j].data);
- }
- }
- }
- // Joints
- for (uint32_t j = 0; j < GS_GFXT_JOINT_MAX; ++j)
- {
- if (vdata->joints[j].data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->joints[j].data;
- vdesc.size = vdata->joints[j].size;
- if (prim->stream.joints[j].id)
- {
- gs_graphics_vertex_buffer_update(prim->stream.joints[j], &vdesc);
- }
- else
- {
- prim->stream.joints[j] = gs_graphics_vertex_buffer_create(&vdesc);
- }
- if (!desc->keep_data)
- {
- gs_free(vdata->joints[j].data);
- }
- }
- }
- // Weights
- for (uint32_t j = 0; j < GS_GFXT_WEIGHT_MAX; ++j)
- {
- if (vdata->weights[j].data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->weights[j].data;
- vdesc.size = vdata->weights[j].size;
- if (prim->stream.weights[j].id)
- {
- gs_graphics_vertex_buffer_update(prim->stream.weights[j], &vdesc);
- }
- else
- {
- prim->stream.weights[j] = gs_graphics_vertex_buffer_create(&vdesc);
- }
- if (!desc->keep_data)
- {
- gs_free(vdata->weights[j].data);
- }
- }
- }
- // Custom uint
- for (uint32_t j = 0; j < GS_GFXT_CUSTOM_UINT_MAX; ++j)
- {
- if (vdata->custom_uint[j].data)
- {
- gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
- vdesc.data = vdata->custom_uint[j].data;
- vdesc.size = vdata->custom_uint[j].size;
- if (prim->stream.custom_uint[j].id)
- {
- gs_graphics_vertex_buffer_update(prim->stream.custom_uint[j], &vdesc);
- }
- else
- {
- prim->stream.custom_uint[j] = gs_graphics_vertex_buffer_create(&vdesc);
- }
- if (!desc->keep_data)
- {
- gs_free(vdata->custom_uint[j].data);
- }
- }
- }
- // Index buffer decl
- gs_graphics_index_buffer_desc_t idesc = gs_default_val();
- idesc.data = vdata->indices.data;
- idesc.size = vdata->indices.size;
- // Construct index buffer for primitive
- if (prim->indices.id)
- {
- gs_graphics_index_buffer_update(prim->indices, &idesc);
- }
- else
- {
- prim->indices = gs_graphics_index_buffer_create(&idesc);
- }
- if (!desc->keep_data)
- {
- gs_free(vdata->indices.data);
- }
- }
- if (!desc->keep_data)
- {
- gs_dyn_array_free(m->primitives);
- }
- }
- if (!desc->keep_data)
- {
- gs_free(desc->meshes);
- }
- }
- GS_API_DECL gs_gfxt_renderable_t
- gs_gfxt_renderable_create(const gs_gfxt_renderable_desc_t* desc)
- {
- gs_gfxt_renderable_t rend = gs_default_val();
- if (!desc) {
- return rend;
- }
- rend.model_matrix = gs_mat4_identity();
- rend.desc = *desc;
- return rend;
- }
- //=== Destruction ===//
- GS_API_DECL void
- gs_gfxt_texture_destroy(gs_gfxt_texture_t* texture)
- {
- gs_graphics_texture_destroy(*texture);
- }
- GS_API_DECL void
- gs_gfxt_material_destroy(gs_gfxt_material_t* material)
- {
- // Destroy all material data
- gs_byte_buffer_free(&material->uniform_data);
- gs_byte_buffer_free(&material->image_buffer_data);
- }
- GS_API_DECL void
- gs_gfxt_mesh_destroy(gs_gfxt_mesh_t* mesh)
- {
- // Iterate through all primitives, destroy all vertex and index buffers
- for (uint32_t p = 0; p < gs_dyn_array_size(mesh->primitives); ++p)
- {
- gs_gfxt_mesh_primitive_t* prim = &mesh->primitives[p];
- // Free index buffer
- if (prim->indices.id) gs_graphics_index_buffer_destroy(prim->indices);
- // Free vertex stream
- if (prim->stream.positions.id) gs_graphics_vertex_buffer_destroy(prim->stream.positions);
- if (prim->stream.normals.id) gs_graphics_vertex_buffer_destroy(prim->stream.normals);
- if (prim->stream.tangents.id) gs_graphics_vertex_buffer_destroy(prim->stream.tangents);
- for (uint32_t i = 0; i < GS_GFXT_COLOR_MAX; ++i)
- {
- if (prim->stream.colors[i].id) gs_graphics_vertex_buffer_destroy(prim->stream.colors[i]);
- }
- for (uint32_t i = 0; i < GS_GFXT_TEX_COORD_MAX; ++i)
- {
- if (prim->stream.tex_coords[i].id) gs_graphics_vertex_buffer_destroy(prim->stream.tex_coords[i]);
- }
- for (uint32_t i = 0; i < GS_GFXT_JOINT_MAX; ++i)
- {
- if (prim->stream.joints[i].id) gs_graphics_vertex_buffer_destroy(prim->stream.joints[i]);
- }
- for ( uint32_t i = 0; i < GS_GFXT_WEIGHT_MAX; ++i )
- {
- if (prim->stream.weights[i].id) gs_graphics_vertex_buffer_destroy(prim->stream.weights[i]);
- }
- }
- }
- GS_API_DECL void
- gs_gfxt_uniform_block_destroy(gs_gfxt_uniform_block_t* ub)
- {
- for (uint32_t i = 0; i < gs_dyn_array_size(ub->uniforms); ++i)
- {
- gs_gfxt_uniform_t* u = &ub->uniforms[i];
- gs_graphics_uniform_destroy(u->hndl);
- }
- gs_dyn_array_free(ub->uniforms);
- gs_hash_table_free(ub->lookup);
- }
- GS_API_DECL void
- gs_gfxt_pipeline_destroy(gs_gfxt_pipeline_t* pipeline)
- {
- // Destroy uniform block for pipeline
- gs_gfxt_uniform_block_destroy(&pipeline->ublock);
- // Free shaders (if responsible for them)
- gs_graphics_shader_destroy(pipeline->desc.raster.shader);
-
- // Destroy pipeline
- if (pipeline->desc.layout.attrs) gs_free(pipeline->desc.layout.attrs);
- if (pipeline->mesh_layout) gs_dyn_array_free(pipeline->mesh_layout);
- gs_graphics_pipeline_destroy(pipeline->hndl);
- }
- //=== Copy API ===//
- GS_API_DECL gs_gfxt_material_t gs_gfxt_material_deep_copy(gs_gfxt_material_t* src)
- {
- gs_gfxt_material_t mat = gs_gfxt_material_create(&src->desc);
- gs_byte_buffer_copy_contents(&mat.uniform_data, &src->uniform_data);
- return mat;
- }
- //=== Pipeline API ===//
- GS_API_DECL gs_gfxt_uniform_t*
- gs_gfxt_pipeline_get_uniform(gs_gfxt_pipeline_t* pip, const char* name)
- {
- uint64_t key = gs_hash_str64(name);
- if (!gs_hash_table_exists(pip->ublock.lookup, key)) {
- return NULL;
- }
- // Based on name, need to get uniform
- uint32_t uidx = gs_hash_table_get(pip->ublock.lookup, key);
- return &pip->ublock.uniforms[uidx];
- }
- //=== Material API ===//
- GS_API_DECL
- void gs_gfxt_material_set_uniform(gs_gfxt_material_t* mat, const char* name, const void* data)
- {
- if (!mat || !name || !data) return;
- gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&mat->desc.pip_func, gs_gfxt_pipeline_t);
- gs_assert(pip);
- // Get key for name lookup
- uint64_t key = gs_hash_str64(name);
- if (!gs_hash_table_exists(pip->ublock.lookup, key)) {
- gs_timed_action(60, {
- gs_log_warning("Unable to find uniform: %s", name);
- });
- return;
- }
- // Based on name, need to get uniform
- uint32_t uidx = gs_hash_table_get(pip->ublock.lookup, key);
- gs_gfxt_uniform_t* u = &pip->ublock.uniforms[uidx];
- // Seek to beginning of data
- gs_byte_buffer_seek_to_beg(&mat->uniform_data);
- gs_byte_buffer_seek_to_beg(&mat->image_buffer_data);
- // Advance by offset
- switch (u->type)
- {
- case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F: gs_byte_buffer_advance_position(&mat->image_buffer_data, u->offset); break;
- default: gs_byte_buffer_advance_position(&mat->uniform_data, u->offset); break;
- }
- switch (u->type)
- {
- case GS_GRAPHICS_UNIFORM_FLOAT: gs_byte_buffer_write(&mat->uniform_data, float, *(float*)data); break;
- case GS_GRAPHICS_UNIFORM_INT: gs_byte_buffer_write(&mat->uniform_data, int32_t, *(int32_t*)data); break;
- case GS_GRAPHICS_UNIFORM_VEC2: gs_byte_buffer_write(&mat->uniform_data, gs_vec2, *(gs_vec2*)data); break;
- case GS_GRAPHICS_UNIFORM_VEC3: gs_byte_buffer_write(&mat->uniform_data, gs_vec3, *(gs_vec3*)data); break;
- case GS_GRAPHICS_UNIFORM_VEC4: gs_byte_buffer_write(&mat->uniform_data, gs_vec4, *(gs_vec4*)data); break;
- case GS_GRAPHICS_UNIFORM_MAT4: gs_byte_buffer_write(&mat->uniform_data, gs_mat4, *(gs_mat4*)data); break;
- case GS_GRAPHICS_UNIFORM_SAMPLERCUBE:
- case GS_GRAPHICS_UNIFORM_SAMPLER2D:
- case GS_GRAPHICS_UNIFORM_USAMPLER2D:
- {
- gs_byte_buffer_write(&mat->uniform_data, gs_handle(gs_graphics_texture_t), *(gs_handle(gs_graphics_texture_t)*)data);
- } break;
- case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F: {
- gs_byte_buffer_write(&mat->image_buffer_data, gs_handle(gs_graphics_texture_t), *(gs_handle(gs_graphics_texture_t)*)data);
- } break;
- }
- }
- GS_API_DECL gs_gfxt_pipeline_t* gs_gfxt_material_get_pipeline(gs_gfxt_material_t* mat)
- {
- gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&mat->desc.pip_func, gs_gfxt_pipeline_t);
- return pip;
- }
- GS_API_DECL
- void gs_gfxt_material_bind(gs_command_buffer_t* cb, gs_gfxt_material_t* mat)
- {
- gs_gfxt_material_bind_pipeline(cb, mat);
- gs_gfxt_material_bind_uniforms(cb, mat);
- }
- GS_API_DECL
- void gs_gfxt_material_bind_pipeline(gs_command_buffer_t* cb, gs_gfxt_material_t* mat)
- {
- // Binds the pipeline
- gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&mat->desc.pip_func, gs_gfxt_pipeline_t);
- gs_assert(pip);
- gs_graphics_pipeline_bind(cb, pip->hndl);
- }
- GS_API_DECL
- void gs_gfxt_material_bind_uniforms(gs_command_buffer_t* cb, gs_gfxt_material_t* mat)
- {
- if (!mat) return;
- gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&mat->desc.pip_func, gs_gfxt_pipeline_t);
- gs_assert(pip);
- // Grab uniform layout from pipeline
- for (uint32_t i = 0; i < gs_dyn_array_size(pip->ublock.uniforms); ++i)
- {
- gs_gfxt_uniform_t* u = &pip->ublock.uniforms[i];
- gs_graphics_bind_desc_t bind = gs_default_val();
- // Need to buffer these up so it's a single call...
- switch (u->type)
- {
- case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
- {
- gs_graphics_bind_image_buffer_desc_t ibuffer[1];
- ibuffer[0].tex = *(gs_handle(gs_graphics_texture_t)*)(mat->image_buffer_data.data + u->offset);
- ibuffer[0].binding = u->binding;
- ibuffer[0].access = GS_GRAPHICS_ACCESS_WRITE_ONLY;
- bind.image_buffers.desc = ibuffer;
- bind.image_buffers.size = sizeof(ibuffer);
- gs_graphics_apply_bindings(cb, &bind);
- } break;
- default:
- {
- gs_graphics_bind_uniform_desc_t uniforms[1];
- uniforms[0].uniform = u->hndl;
- uniforms[0].data = (mat->uniform_data.data + u->offset);
- uniforms[0].binding = u->binding;
- bind.uniforms.desc = uniforms;
- bind.uniforms.size = sizeof(uniforms);
- gs_graphics_apply_bindings(cb, &bind);
- } break;
- }
- }
- }
- // Mesh API
- GS_API_DECL void
- gs_gfxt_mesh_draw(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mp)
- {
- /*
- // For each primitive in mesh
- for (uint32_t i = 0; i < gs_dyn_array_size(mp->primitives); ++i)
- {
- gs_gfxt_mesh_primitive_t* prim = &mp->primitives[i];
- // Bindings for all buffers: vertex, index, uniform, sampler
- gs_graphics_bind_desc_t binds = gs_default_val();
- gs_graphics_bind_vertex_buffer_desc_t vdesc = gs_default_val();
- gs_graphics_bind_index_buffer_desc_t idesc = gs_default_val();
- vdesc.buffer = prim->vbo;
- idesc.buffer = prim->indices;
- binds.vertex_buffers.desc = &vdesc;
- binds.index_buffers.desc = &idesc;
- gs_graphics_draw_desc_t ddesc = gs_default_val();
- ddesc.start = 0;
- ddesc.count = prim->count;
- gs_graphics_apply_bindings(cb, &binds);
- gs_graphics_draw(cb, &ddesc);
- }
- */
- }
- GS_API_DECL void
- gs_gfxt_mesh_primitive_draw_layout(gs_command_buffer_t* cb, gs_gfxt_mesh_primitive_t* prim, gs_gfxt_mesh_layout_t* layout, size_t layout_size, uint32_t instance_count)
- {
- if (!layout || !layout_size || !prim || !cb)
- {
- return;
- }
- gs_graphics_bind_vertex_buffer_desc_t vbos[8] = {0}; // Make this a define
- uint32_t l = 0;
- const uint32_t ct = layout_size / sizeof(gs_gfxt_mesh_layout_t);
- for (uint32_t a = 0; a < ct; ++a)
- {
- vbos[l].data_type = GS_GRAPHICS_VERTEX_DATA_NONINTERLEAVED;
- switch (layout[a].type)
- {
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION: {if (!prim->stream.positions.id) continue; vbos[l].buffer = prim->stream.positions;} break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL: {if (!prim->stream.normals.id) continue; vbos[l].buffer = prim->stream.normals;} break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT: {if (!prim->stream.tangents.id) continue; vbos[l].buffer = prim->stream.tangents;} break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_JOINT: {if (!prim->stream.joints[0].id) continue; vbos[l].buffer = prim->stream.joints[0];} break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_WEIGHT: {if (!prim->stream.weights[0].id) continue; vbos[l].buffer = prim->stream.weights[0];} break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD: {if (!prim->stream.tex_coords[0].id) continue; vbos[l].buffer = prim->stream.tex_coords[0];} break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR: {if (!prim->stream.colors[0].id) continue; vbos[l].buffer = prim->stream.colors[0];} break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_UINT: {if (!prim->stream.custom_uint[0].id) continue; vbos[l].buffer = prim->stream.custom_uint[0];} break;
- }
- ++l;
- }
- gs_graphics_bind_index_buffer_desc_t ibos = gs_default_val();
- ibos.buffer = prim->indices;
- // Bindings for all buffers: vertex, index, uniform, sampler
- gs_graphics_bind_desc_t binds = gs_default_val();
- // .vertex_buffers = {.desc = vbos, .size = sizeof(vbos)},
- binds.vertex_buffers.desc = vbos;
- binds.vertex_buffers.size = l * sizeof(gs_graphics_bind_vertex_buffer_desc_t);
- binds.index_buffers.desc = &ibos;
- gs_graphics_draw_desc_t ddesc = gs_default_val();
- ddesc.start = 0;
- ddesc.count = prim->count;
- ddesc.instances = instance_count;
- gs_graphics_apply_bindings(cb, &binds);
- gs_graphics_draw(cb, &ddesc);
- }
- GS_API_DECL void
- gs_gfxt_mesh_draw_layout(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_mesh_layout_t* layout, size_t layout_size)
- {
- if (!layout || !mesh || !cb)
- {
- return;
- }
- uint32_t ct = layout_size / sizeof(gs_gfxt_mesh_layout_t);
- // For each primitive in mesh
- for (uint32_t i = 0; i < gs_dyn_array_size(mesh->primitives); ++i)
- {
- gs_gfxt_mesh_primitive_t* prim = &mesh->primitives[i];
- gs_gfxt_mesh_primitive_draw_layout(cb, prim, layout, layout_size, 1);
- }
- }
- GS_API_DECL void
- gs_gfxt_mesh_draw_materials(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_material_t** mats, size_t mats_size)
- {
- // Iterate through primitives, draw each primitive with assigned mat
- if (!mats || !mats_size || !cb || !mesh)
- {
- return;
- }
- const uint32_t ct = mats_size / sizeof(gs_gfxt_material_t*);
- gs_gfxt_material_t* mat = NULL;
- // For each primitive in mesh
- for (uint32_t i = 0; i < gs_dyn_array_size(mesh->primitives); ++i)
- {
- gs_gfxt_mesh_primitive_t* prim = &mesh->primitives[i];
- // Get corresponding material, if available
- uint32_t mat_idx = i < ct ? i : ct - 1;
- mat = mats[mat_idx] ? mats[mat_idx] : mat;
- // Can't draw without a valid material present
- if (!mat) continue;
- // Bind material pipeline and uniforms
- gs_gfxt_material_bind(cb, mat);
- // Get pipeline
- gs_gfxt_pipeline_t* pip = gs_gfxt_material_get_pipeline(mat);
- gs_gfxt_mesh_primitive_draw_layout(cb, prim, pip->mesh_layout, gs_dyn_array_size(pip->mesh_layout) * sizeof(gs_gfxt_mesh_layout_t), 1);
- }
- }
- GS_API_DECL void
- gs_gfxt_mesh_draw_material(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_material_t* mat)
- {
- if (!mat || !mesh || !cb)
- {
- return;
- }
- gs_gfxt_pipeline_t* pip = gs_gfxt_material_get_pipeline(mat);
- gs_gfxt_mesh_draw_layout(cb, mesh, pip->mesh_layout, gs_dyn_array_size(pip->mesh_layout) * sizeof(gs_gfxt_mesh_layout_t));
- }
- GS_API_DECL void
- gs_gfxt_mesh_draw_pipeline(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_pipeline_t* pip)
- {
- if (!pip || !mesh || !cb)
- {
- return;
- }
- gs_gfxt_mesh_draw_layout(cb, mesh, pip->mesh_layout, gs_dyn_array_size(pip->mesh_layout) * sizeof(gs_gfxt_mesh_layout_t));
- }
- // Util API
- GS_API_DECL
- void* gs_gfxt_raw_data_default_impl(GS_GFXT_HNDL hndl, void* user_data)
- {
- return hndl;
- }
- GS_API_DECL void gs_gfxt_mesh_import_options_free(gs_gfxt_mesh_import_options_t* opt)
- {
- if (opt->layout)
- {
- gs_dyn_array_free(opt->layout);
- }
- }
- GS_API_DECL
- gs_gfxt_mesh_t gs_gfxt_mesh_load_from_file(const char* path, gs_gfxt_mesh_import_options_t* options)
- {
- gs_gfxt_mesh_t mesh = gs_default_val();
- if (!gs_platform_file_exists(path)) {
- gs_println("Warning:GFXT:MeshLoadFromFile:File does not exist: %s", path);
- return mesh;
- }
- // Mesh data to fill out
- uint32_t mesh_count = 0;
- gs_gfxt_mesh_raw_data_t* meshes = NULL;
- // Get file extension from path
- gs_transient_buffer(file_ext, 32);
- gs_platform_file_extension(file_ext, 32, path);
- // GLTF
- if (gs_string_compare_equal(file_ext, "gltf")) {
- gs_gfxt_load_gltf_data_from_file(path, options, &meshes, &mesh_count);
- }
- // GLB
- else if (gs_string_compare_equal(file_ext, "glb")) {
- gs_gfxt_load_gltf_data_from_file(path, options, &meshes, &mesh_count);
- }
- else {
- gs_println("Warning:GFXT:MeshLoadFromFile:File extension not supported: %s, file: %s", file_ext, path);
- return mesh;
- }
- gs_gfxt_mesh_desc_t mdesc = gs_default_val();
- mdesc.meshes = meshes;
- mdesc.size = mesh_count * sizeof(gs_gfxt_mesh_raw_data_t);
- mesh = gs_gfxt_mesh_create(&mdesc);
- mesh.desc = mdesc;
- return mesh;
- }
- GS_API_DECL bool
- gs_gfxt_load_gltf_data_from_file(const char* path, gs_gfxt_mesh_import_options_t* options,
- gs_gfxt_mesh_raw_data_t** out, uint32_t* mesh_count)
- {
- // Use cgltf like a boss
- cgltf_options cgltf_options = gs_default_val();
- size_t len = 0;
- char* file_data = NULL;
- // Get file extension from path
- gs_transient_buffer(file_ext, 32);
- gs_platform_file_extension(file_ext, 32, path);
- // GLTF
- if (gs_string_compare_equal(file_ext, "gltf")) {
- file_data = gs_platform_read_file_contents(path, "rb", &len);
- gs_println("GFXT:Loading GLTF: %s", path);
- }
- // GLB
- else if (gs_string_compare_equal(file_ext, "glb")) {
- file_data = gs_platform_read_file_contents(path, "rb", &len);
- gs_println("GFXT:Loading GLTF: %s", path);
- }
- else {
- gs_println("Warning:GFXT:LoadGLTFDataFromFile:File extension not supported: %s, file: %s", file_ext, path);
- return false;
- }
- cgltf_data* data = NULL;
- cgltf_result result = cgltf_parse(&cgltf_options, file_data, (cgltf_size)len, &data);
- gs_free(file_data);
- if (result != cgltf_result_success) {
- gs_println("GFXT:Mesh:LoadFromFile:Failed load gltf");
- cgltf_free(data);
- return false;
- }
- // Load buffers as well
- result = cgltf_load_buffers(&cgltf_options, data, path);
- if (result != cgltf_result_success) {
- cgltf_free(data);
- gs_println("GFXT:Mesh:LoadFromFile:Failed to load buffers");
- return false;
- }
- // Type of index data
- size_t index_element_size = options ? options->index_buffer_element_size : 0;
- // Temporary structures
- gs_dyn_array(gs_vec3) positions = NULL;
- gs_dyn_array(gs_vec3) normals = NULL;
- gs_dyn_array(gs_vec3) tangents = NULL;
- gs_dyn_array(gs_color_t) colors[GS_GFXT_COLOR_MAX] = gs_default_val();
- gs_dyn_array(gs_vec2) uvs[GS_GFXT_TEX_COORD_MAX] = gs_default_val();
- gs_dyn_array(float) weights[GS_GFXT_WEIGHT_MAX] = gs_default_val();
- gs_dyn_array(float) joints[GS_GFXT_JOINT_MAX] = gs_default_val();
- gs_dyn_array(gs_gfxt_mesh_layout_t) layouts = gs_default_val();
- gs_byte_buffer_t v_data = gs_byte_buffer_new();
- gs_byte_buffer_t i_data = gs_byte_buffer_new();
- gs_mat4 world_mat = gs_mat4_identity();
- // Allocate memory for buffers
- *mesh_count = data->meshes_count;
- *out = (gs_gfxt_mesh_raw_data_t*)gs_malloc(data->meshes_count * sizeof(gs_gfxt_mesh_raw_data_t));
- memset(*out, 0, sizeof(gs_gfxt_mesh_raw_data_t) * data->meshes_count);
- // For each node, for each mesh
- uint32_t i = 0;
- for (uint32_t _n = 0; _n < data->nodes_count; ++_n)
- {
- cgltf_node* node = &data->nodes[_n];
- if (node->mesh == NULL) continue;
- gs_println("Load mesh from node: %s", node->name);
- // Reset matrix
- world_mat = gs_mat4_identity();
- // gs_println("i: %zu, r: %zu, t: %zu, s: %zu, m: %zu", i, node->has_rotation, node->has_translation, node->has_scale, node->has_matrix);
- // Not sure what "local transform" does, since world gives me the actual world result...probably for animation
- if (node->has_rotation || node->has_translation || node->has_scale)
- {
- cgltf_node_transform_world(node, (float*)&world_mat);
- }
- // if (node->has_matrix)
- // {
- // // Multiply local by world
- // gs_mat4 tmp = gs_default_val();
- // cgltf_node_transform_world(node, (float*)&tmp);
- // world_mat = gs_mat4_mul(world_mat, tmp);
- // }
-
- // Do node mesh data
- cgltf_mesh* cmesh = node->mesh;
- {
- // Initialize mesh data
- gs_gfxt_mesh_raw_data_t* mesh = &((*out)[i]);
- bool warnings[gs_enum_count(gs_asset_mesh_attribute_type)] = gs_default_val();
- bool printed = false;
- // For each primitive in mesh
- for (uint32_t p = 0; p < cmesh->primitives_count; ++p)
- {
- cgltf_primitive* prim = &cmesh->primitives[p];
- // Mesh primitive to fill out
- gs_gfxt_mesh_vertex_data_t primitive = gs_default_val();
- // Clear temp data from previous use
- gs_dyn_array_clear(positions);
- gs_dyn_array_clear(normals);
- gs_dyn_array_clear(tangents);
- for (uint32_t ci = 0; ci < GS_GFXT_COLOR_MAX; ++ci) gs_dyn_array_clear(colors[ci]);
- for (uint32_t tci = 0; tci < GS_GFXT_TEX_COORD_MAX; ++tci) gs_dyn_array_clear(uvs[tci]);
- for (uint32_t wi = 0; wi < GS_GFXT_WEIGHT_MAX; ++wi) gs_dyn_array_clear(weights[wi]);
- for (uint32_t ji = 0; ji < GS_GFXT_JOINT_MAX; ++ji) gs_dyn_array_clear(joints[ji]);
- gs_dyn_array_clear(layouts);
- gs_byte_buffer_clear(&v_data);
- gs_byte_buffer_clear(&i_data);
- // Collect all provided attribute data for each vertex that's available in gltf data
- #define __GFXT_GLTF_PUSH_ATTR(ATTR, TYPE, COUNT, ARR, ARR_TYPE, LAYOUTS, LAYOUT_TYPE)\
- do {\
- int32_t N = 0;\
- TYPE* BUF = (TYPE*)ATTR->buffer_view->buffer->data + ATTR->buffer_view->offset/sizeof(TYPE) + ATTR->offset/sizeof(TYPE);\
- gs_assert(BUF);\
- TYPE V[COUNT] = gs_default_val();\
- /* For each vertex */\
- for (uint32_t k = 0; k < ATTR->count; k++)\
- {\
- /* For each element */\
- for (int l = 0; l < COUNT; l++) {\
- V[l] = BUF[N + l];\
- }\
- N += (int32_t)(ATTR->stride/sizeof(TYPE));\
- /* Add to temp data array */\
- ARR_TYPE ELEM = gs_default_val();\
- memcpy((void*)&ELEM, (void*)V, sizeof(ARR_TYPE));\
- gs_dyn_array_push(ARR, ELEM);\
- }\
- /* Push into layout */\
- gs_gfxt_mesh_layout_t LAYOUT = gs_default_val();\
- LAYOUT.type = LAYOUT_TYPE;\
- gs_dyn_array_push(LAYOUTS, LAYOUT);\
- } while (0)
- // For each attribute in primitive
- for (uint32_t a = 0; a < prim->attributes_count; ++a)
- {
- // Accessor for attribute data
- cgltf_accessor* attr = prim->attributes[a].data;
- // Index for data
- int32_t aidx = prim->attributes[a].index;
- // Switch on type for reading data
- switch (prim->attributes[a].type)
- {
- case cgltf_attribute_type_position: {
- int32_t N = 0;
- float* BUF = (float*)attr->buffer_view->buffer->data + attr->buffer_view->offset/sizeof(float) + attr->offset/sizeof(float);
- gs_assert(BUF);
- float V[3] = gs_default_val();
- /* For each vertex */
- for (uint32_t k = 0; k < attr->count; k++)
- {
- /* For each element */
- for (int l = 0; l < 3; l++) {
- V[l] = BUF[N + l];
- }
- N += (int32_t)(attr->stride/sizeof(float));
- /* Add to temp data array */
- gs_vec3 ELEM = gs_default_val();
- memcpy((void*)&ELEM, (void*)V, sizeof(gs_vec3));
- // Transform into world space
- ELEM = gs_mat4_mul_vec3(world_mat, ELEM);
- gs_dyn_array_push(positions, ELEM);
- }
- /* Push into layout */
- gs_gfxt_mesh_layout_t LAYOUT = gs_default_val();
- LAYOUT.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION;
- gs_dyn_array_push(layouts, LAYOUT);
- } break;
- case cgltf_attribute_type_normal: {
- __GFXT_GLTF_PUSH_ATTR(attr, float, 3, normals, gs_vec3, layouts, GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL);
- } break;
- case cgltf_attribute_type_tangent: {
- __GFXT_GLTF_PUSH_ATTR(attr, float, 3, tangents, gs_vec3, layouts, GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT);
- } break;
- case cgltf_attribute_type_texcoord: {
- __GFXT_GLTF_PUSH_ATTR(attr, float, 2, uvs[aidx], gs_vec2, layouts, GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD);
- } break;
- case cgltf_attribute_type_color: {
- // Need to parse color as sRGB then convert to gs_color_t
- int32_t N = 0;
- float* BUF = (float*)attr->buffer_view->buffer->data + attr->buffer_view->offset/sizeof(float) + attr->offset/sizeof(float);
- gs_assert(BUF);
- float V[3] = gs_default_val();
- /* For each vertex */\
- for (uint32_t k = 0; k < attr->count; k++)
- {
- /* For each element */
- for (int l = 0; l < 3; l++) {
- V[l] = BUF[N + l];
- }
- N += (int32_t)(attr->stride/sizeof(float));
- /* Add to temp data array */
- gs_color_t ELEM = gs_default_val();
- // Need to convert over now
- ELEM.r = (uint8_t)(V[0] * 255.f);
- ELEM.g = (uint8_t)(V[1] * 255.f);
- ELEM.b = (uint8_t)(V[2] * 255.f);
- ELEM.a = 255;
- gs_dyn_array_push(colors[aidx], ELEM);
- }
- /* Push into layout */
- gs_gfxt_mesh_layout_t LAYOUT = gs_default_val();
- LAYOUT.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR;
- gs_dyn_array_push(layouts, LAYOUT);
- } break;
- // Not sure what to do with these for now
- case cgltf_attribute_type_joints:
- {
- // Push into layout
- gs_gfxt_mesh_layout_t layout = gs_default_val();
- layout.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_JOINT;
- gs_dyn_array_push(layouts, layout);
- } break;
- case cgltf_attribute_type_weights:
- {
- // Push into layout
- gs_gfxt_mesh_layout_t layout = gs_default_val();
- layout.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_WEIGHT;
- gs_dyn_array_push(layouts, layout);
- } break;
- // Shouldn't hit here...
- default: {
- } break;
- }
- }
- // Indices for primitive
- cgltf_accessor* acc = prim->indices;
- #define __GFXT_GLTF_PUSH_IDX(BB, ACC, TYPE)\
- do {\
- int32_t n = 0;\
- TYPE* buf = (TYPE*)acc->buffer_view->buffer->data + acc->buffer_view->offset/sizeof(TYPE) + acc->offset/sizeof(TYPE);\
- gs_assert(buf);\
- TYPE v = 0;\
- /* For each index */\
- for (uint32_t k = 0; k < acc->count; k++) {\
- /* For each element */\
- for (int l = 0; l < 1; l++) {\
- v = buf[n + l];\
- }\
- n += (int32_t)(acc->stride/sizeof(TYPE));\
- /* Add to temp positions array */\
- switch (index_element_size) {\
- case 0: gs_byte_buffer_write(BB, uint16_t, (uint16_t)v); break;\
- case 2: gs_byte_buffer_write(BB, uint16_t, (uint16_t)v); break;\
- case 4: gs_byte_buffer_write(BB, uint32_t, (uint32_t)v); break;\
- }\
- }\
- } while (0)
- // If indices are available
- if (acc)
- {
- switch (acc->component_type)
- {
- case cgltf_component_type_r_8: __GFXT_GLTF_PUSH_IDX(&i_data, acc, int8_t); break;
- case cgltf_component_type_r_8u: __GFXT_GLTF_PUSH_IDX(&i_data, acc, uint8_t); break;
- case cgltf_component_type_r_16: __GFXT_GLTF_PUSH_IDX(&i_data, acc, int16_t); break;
- case cgltf_component_type_r_16u: __GFXT_GLTF_PUSH_IDX(&i_data, acc, uint16_t); break;
- case cgltf_component_type_r_32u: __GFXT_GLTF_PUSH_IDX(&i_data, acc, uint32_t); break;
- case cgltf_component_type_r_32f: __GFXT_GLTF_PUSH_IDX(&i_data, acc, float); break;
- // Shouldn't hit here
- default: {
- } break;
- }
- }
- else
- {
- // Iterate over positions size, then just push back indices
- for (uint32_t i = 0; i < gs_dyn_array_size(positions); ++i)
- {
- switch (index_element_size)
- {
- default:
- case 0: gs_byte_buffer_write(&i_data, uint16_t, (uint16_t)i); break;
- case 2: gs_byte_buffer_write(&i_data, uint16_t, (uint16_t)i); break;
- case 4: gs_byte_buffer_write(&i_data, uint32_t, (uint32_t)i); break;
- }
- }
- }
- // Grab mesh layout pointer to use
- /*
- gs_gfxt_mesh_layout_t* layoutp = options ? options->layout : layouts;
- uint32_t layout_ct = options ? options->size / sizeof(gs_gfxt_mesh_layout_t) : gs_dyn_array_size(layouts);
- // Iterate layout to fill data buffers according to provided layout
- {
- uint32_t vct = 0;
- vct = gs_max(vct, gs_dyn_array_size(positions));
- vct = gs_max(vct, gs_dyn_array_size(colors));
- vct = gs_max(vct, gs_dyn_array_size(uvs));
- vct = gs_max(vct, gs_dyn_array_size(normals));
- vct = gs_max(vct, gs_dyn_array_size(tangents));
- #define __GLTF_WRITE_DATA(IT, VDATA, ARR, ARR_TYPE, ARR_DEF_VAL, LAYOUT_TYPE)\
- do {\
- if (IT < gs_dyn_array_size(ARR)) {\
- gs_byte_buffer_write(&(VDATA), ARR_TYPE, ARR[IT]);\
- }\
- else {\
- gs_byte_buffer_write(&(VDATA), ARR_TYPE, ARR_DEF_VAL);\
- if (!warnings[LAYOUT_TYPE]) {\
- warnings[LAYOUT_TYPE] = true;\
- }\
- }\
- } while (0)
- for (uint32_t it = 0; it < vct; ++it)
- {
- // For each attribute in layout
- for (uint32_t l = 0; l < layout_ct; ++l)
- {
- switch (layoutp[l].type)
- {
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION: {
- __GLTF_WRITE_DATA(it, v_data, positions, gs_vec3, gs_v3(0.f, 0.f, 0.f), GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION);
- } break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD: {
- __GLTF_WRITE_DATA(it, v_data, uvs, gs_vec2, gs_v2(0.f, 0.f), GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD);
- } break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR: {
- __GLTF_WRITE_DATA(it, v_data, colors, gs_color_t, GS_COLOR_WHITE, GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR);
- } break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL: {
- __GLTF_WRITE_DATA(it, v_data, normals, gs_vec3, gs_v3(0.f, 0.f, 1.f), GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL);
- } break;
- case GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT: {
- __GLTF_WRITE_DATA(it, v_data, tangents, gs_vec3, gs_v3(0.f, 1.f, 0.f), GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT);
- } break;
- default:
- {
- } break;
- }
- }
- }
- }
- // Add to out data
- mesh->vertices[p] = gs_malloc(v_data.size);
- mesh->indices[p] = gs_malloc(i_data.size);
- mesh->vertex_sizes[p] = v_data.size;
- mesh->index_sizes[p] = i_data.size;
- // Copy data
- memcpy(mesh->vertices[p], v_data.data, v_data.size);
- memcpy(mesh->indices[p], i_data.data, i_data.size);
- */
- /*
- typedef struct
- {
- void* data;
- size_t size;
- } gs_gfxt_mesh_vertex_attribute_t;
- typedef struct
- {
- gs_gfxt_mesh_vertex_attribute_t positions; // All position data
- gs_gfxt_mesh_vertex_attribute_t normals;
- gs_gfxt_mesh_vertex_attribute_t tangents;
- gs_gfxt_mesh_vertex_attribute_t tex_coords[GS_GFXT_TEX_COORD_MAX];
- gs_gfxt_mesh_vertex_attribute_t joints[GS_GFXT_JOINT_MAX];
- gs_gfxt_mesh_vertex_attribute_t weights[GS_GFXT_WEIGHT_MAX];
- gs_gfxt_mesh_vertex_attribute_t indices;
- } gs_gfxt_mesh_vertex_data_t;
- // Structured/packed raw mesh data
- typedef struct gs_gfxt_mesh_raw_data_t {
- uint16_t prim_count;
- size_t* vertex_sizes;
- size_t* index_sizes;
- void** vertices;
- void** indices;
- gs_dyn_array(gs_gfxt_mesh_vertex_data_t) primitives; // All primitive data
- } gs_gfxt_mesh_raw_data_t;
- */
- // Count
- primitive.count = prim->indices->count;
- // Indices
- primitive.indices.size = i_data.size;
- primitive.indices.data = gs_malloc(i_data.size);
- memcpy(primitive.indices.data, i_data.data, i_data.size);
- // Positions
- if (!gs_dyn_array_empty(positions))
- {
- primitive.positions.size = gs_dyn_array_size(positions) * sizeof(gs_vec3);
- primitive.positions.data = gs_malloc(primitive.positions.size);
- memcpy(primitive.positions.data, positions, primitive.positions.size);
- }
- // Normals
- if (!gs_dyn_array_empty(normals))
- {
- primitive.normals.size = gs_dyn_array_size(normals) * sizeof(gs_vec3);
- primitive.normals.data = gs_malloc(primitive.normals.size);
- memcpy(primitive.normals.data, normals, primitive.normals.size);
- }
- // Tangents
- if (!gs_dyn_array_empty(tangents))
- {
- primitive.tangents.size = gs_dyn_array_size(tangents) * sizeof(gs_vec3);
- primitive.tangents.data = gs_malloc(primitive.tangents.size);
- memcpy(primitive.tangents.data, tangents, primitive.tangents.size);
- }
- // Texcoords
- for (uint32_t tci = 0; tci < GS_GFXT_TEX_COORD_MAX; ++tci)
- {
- if (!gs_dyn_array_empty(uvs[tci]))
- {
- primitive.tex_coords[tci].size = gs_dyn_array_size(uvs[tci]) * sizeof(gs_vec2);
- primitive.tex_coords[tci].data = gs_malloc(primitive.tex_coords[tci].size);
- memcpy(primitive.tex_coords[tci].data, uvs[tci], primitive.tex_coords[tci].size);
- }
- else
- {
- break;
- }
- }
- // Colors
- for (uint32_t ci = 0; ci < GS_GFXT_COLOR_MAX; ++ci)
- {
- if (!gs_dyn_array_empty(colors[ci]))
- {
- primitive.colors[ci].size = gs_dyn_array_size(colors[ci]) * sizeof(gs_color_t);
- primitive.colors[ci].data = gs_malloc(primitive.colors[ci].size);
- memcpy(primitive.colors[ci].data, colors[ci], primitive.colors[ci].size);
- }
- else
- {
- break;
- }
- }
- // Joints
- for (uint32_t ji = 0; ji < GS_GFXT_JOINT_MAX; ++ji)
- {
- if (!gs_dyn_array_empty(joints[ji]))
- {
- primitive.joints[ji].size = gs_dyn_array_size(joints[ji]) * sizeof(float);
- primitive.joints[ji].data = gs_malloc(primitive.joints[ji].size);
- memcpy(primitive.joints[ji].data, joints[ji], primitive.joints[ji].size);
- }
- else
- {
- break;
- }
- }
- // Weights
- for (uint32_t wi = 0; wi < GS_GFXT_WEIGHT_MAX; ++wi)
- {
- if (!gs_dyn_array_empty(weights[wi]))
- {
- primitive.weights[wi].size = gs_dyn_array_size(weights[wi]) * sizeof(float);
- primitive.weights[wi].data = gs_malloc(primitive.weights[wi].size);
- memcpy(primitive.weights[wi].data, weights[wi], primitive.weights[wi].size);
- }
- else
- {
- break;
- }
- }
- // Add primitive to mesh
- gs_dyn_array_push(mesh->primitives, primitive);
- }
- if (!printed)
- {
- printed = true;
- if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION]){
- gs_log_warning("Mesh attribute: POSITION not found. Resorting to default.");
- }
- if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD]) {
- gs_log_warning("Mesh attribute: TEXCOORD not found. Resorting to default.");
- }
- if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR]) {
- gs_log_warning("Mesh attribute: COLOR not found. Resorting to default.");
- }
- if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL]) {
- gs_log_warning("Mesh attribute: NORMAL not found. Resorting to default.");
- }
- if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT]) {
- gs_log_warning("Mesh attribute: WEIGHTS not found. Resorting to default.");
- }
- }
- }
- // Increment i if successful
- i++;
- }
- gs_println("Finished loading mesh.");
- // Free all data at the end
- cgltf_free(data);
- gs_dyn_array_free(positions);
- gs_dyn_array_free(normals);
- gs_dyn_array_free(tangents);
- for (uint32_t ci = 0; ci < GS_GFXT_COLOR_MAX; ++ci) gs_dyn_array_free(colors[ci]);
- for (uint32_t tci = 0; tci < GS_GFXT_TEX_COORD_MAX; ++tci) gs_dyn_array_free(uvs[tci]);
- for (uint32_t wi = 0; wi < GS_GFXT_WEIGHT_MAX; ++wi) gs_dyn_array_free(weights[wi]);
- for (uint32_t ji = 0; ji < GS_GFXT_JOINT_MAX; ++ji) gs_dyn_array_free(joints[ji]);
- gs_dyn_array_free(layouts);
- gs_byte_buffer_free(&v_data);
- gs_byte_buffer_free(&i_data);
- return true;
- }
- GS_API_DECL
- gs_gfxt_mesh_t gs_gfxt_mesh_unit_quad_generate(gs_gfxt_mesh_import_options_t* options)
- {
- gs_gfxt_mesh_t mesh = gs_default_val();
- gs_vec3 v_pos[] = {
- gs_v3(-1.0f, -1.0f, 0.f), // Top Left
- gs_v3(+1.0f, -1.0f, 0.f), // Top Right
- gs_v3(-1.0f, +1.0f, 0.f), // Bottom Left
- gs_v3(+1.0f, +1.0f, 0.f) // Bottom Right
- };
- // Vertex data for quad
- gs_vec2 v_uvs[] = {
- gs_v2(0.0f, 0.0f), // Top Left
- gs_v2(1.0f, 0.0f), // Top Right
- gs_v2(0.0f, 1.0f), // Bottom Left
- gs_v2(1.0f, 1.0f) // Bottom Right
- };
- gs_vec3 v_norm[] = {
- gs_v3(0.f, 0.f, 1.f),
- gs_v3(0.f, 0.f, 1.f),
- gs_v3(0.f, 0.f, 1.f),
- gs_v3(0.f, 0.f, 1.f)
- };
- gs_vec3 v_tan[] = {
- gs_v3(1.f, 0.f, 0.f),
- gs_v3(1.f, 0.f, 0.f),
- gs_v3(1.f, 0.f, 0.f),
- gs_v3(1.f, 0.f, 0.f)
- };
- gs_color_t v_color[] = {
- GS_COLOR_WHITE,
- GS_COLOR_WHITE,
- GS_COLOR_WHITE,
- GS_COLOR_WHITE
- };
- // Index data for quad
- uint16_t i_data[] = {
- 0, 3, 2, // First Triangle
- 0, 1, 3 // Second Triangle
- };
- // Mesh data
- gs_gfxt_mesh_raw_data_t mesh_data = gs_default_val();
- // Primitive to upload
- gs_gfxt_mesh_vertex_data_t vert_data = gs_default_val();
- vert_data.positions.data = v_pos; vert_data.positions.size = sizeof(v_pos);
- vert_data.normals.data = v_norm; vert_data.normals.size = sizeof(v_norm);
- vert_data.tangents.data = v_tan; vert_data.tangents.size = sizeof(v_tan);
- vert_data.colors[0].data = v_color; vert_data.colors[0].size = sizeof(v_color);
- vert_data.tex_coords[0].data = v_uvs; vert_data.tex_coords[0].size = sizeof(v_uvs);
- vert_data.indices.data = i_data; vert_data.indices.size = sizeof(i_data);
- vert_data.count = 6;
- // Push into primitives
- gs_dyn_array_push(mesh_data.primitives, vert_data);
- // If no decl, then just use default layout
- /*
- gs_gfxt_mesh_import_options_t* moptions = options ? options : &def_options;
- uint32_t ct = moptions->size / sizeof(gs_asset_mesh_layout_t);
- */
- gs_gfxt_mesh_desc_t mdesc = gs_default_val();
- mdesc.meshes = &mesh_data;
- mdesc.size = 1 * sizeof(gs_gfxt_mesh_raw_data_t);
- mdesc.keep_data = true;
- mesh = gs_gfxt_mesh_create(&mdesc);
- mesh.desc = mdesc;
- // Free data
- if (mesh_data.primitives) gs_dyn_array_free(mesh_data.primitives);
- return mesh;
- }
- GS_API_DECL gs_handle(gs_graphics_texture_t)
- gs_gfxt_texture_generate_default()
- {
- // Generate procedural texture data (checkered texture)
- #define GS_GFXT_ROW_COL_CT 5
- gs_color_t c0 = GS_COLOR_WHITE;
- gs_color_t c1 = gs_color(20, 50, 150, 255);
- gs_color_t pixels[GS_GFXT_ROW_COL_CT * GS_GFXT_ROW_COL_CT] = gs_default_val();
- for (uint32_t r = 0; r < GS_GFXT_ROW_COL_CT; ++r) {
- for (uint32_t c = 0; c < GS_GFXT_ROW_COL_CT; ++c) {
- const bool re = (r % 2) == 0;
- const bool ce = (c % 2) == 0;
- uint32_t idx = r * GS_GFXT_ROW_COL_CT + c;
- pixels[idx] = (re && ce) ? c0 : (re) ? c1 : (ce) ? c1 : c0;
- }
- }
- gs_graphics_texture_desc_t desc = gs_default_val();
- desc.width = GS_GFXT_ROW_COL_CT;
- desc.height = GS_GFXT_ROW_COL_CT;
- desc.format = GS_GRAPHICS_TEXTURE_FORMAT_RGBA8;
- desc.min_filter = GS_GRAPHICS_TEXTURE_FILTER_NEAREST;
- desc.mag_filter = GS_GRAPHICS_TEXTURE_FILTER_NEAREST;
- desc.wrap_s = GS_GRAPHICS_TEXTURE_WRAP_REPEAT;
- desc.wrap_t = GS_GRAPHICS_TEXTURE_WRAP_REPEAT;
- *desc.data = pixels;
- // Create dynamic texture
- return gs_graphics_texture_create(&desc);
- }
- //=== Resource Loading ===//
- typedef struct tmp_buffer_t
- {
- char txt[1024];
- } tmp_buffer_t;
- typedef struct gs_shader_io_data_t
- {
- char type[64];
- char name[64];
- } gs_shader_io_data_t;
- typedef struct gs_pipeline_parse_data_t
- {
- gs_dyn_array(gs_shader_io_data_t) io_list[3];
- gs_dyn_array(gs_gfxt_mesh_layout_t) mesh_layout;
- gs_dyn_array(gs_graphics_vertex_attribute_type) vertex_layout;
- char* code[3];
- char dir[256];
- } gs_ppd_t;
- #define gs_parse_warning(TXT, ...)\
- do {\
- gs_printf("WARNING::");\
- gs_printf(TXT, ##__VA_ARGS__);\
- gs_println("");\
- } while (0)
- #define gs_parse_error(TXT, ASSERT, ...)\
- do {\
- gs_printf("ERROR::");\
- gs_printf(TXT, ##__VA_ARGS__);\
- gs_println("");\
- if (ASSERT) gs_assert(false);\
- } while (0)
- #define gs_parse_block(NAME, ...)\
- do {\
- gs_println("gs_pipeline_load_from_file::parsing::%s", #NAME);\
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))\
- {\
- gs_println("error::gs_pipeline_load_from_file::error parsing raster from .sf resource");\
- gs_assert(false);\
- }\
- \
- uint32_t bc = 1;\
- while (gs_lexer_can_lex(lex) && bc)\
- {\
- gs_token_t token = gs_lexer_next_token(lex);\
- switch (token.type)\
- {\
- case GS_TOKEN_LBRACE: {bc++;} break;\
- case GS_TOKEN_RBRACE: {bc--;} break;\
- \
- case GS_TOKEN_IDENTIFIER:\
- {\
- __VA_ARGS__\
- }\
- }\
- }\
- } while (0)
- const char* gs_get_vertex_attribute_string(gs_graphics_vertex_attribute_type type)
- {
- switch (type)
- {
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT: return "float"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT2: return "vec2"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT3: return "vec3"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT4: return "vec4"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT: return "int"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT2: return "vec2"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT3: return "vec3"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT4: return "vec4"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE: return "float"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE2: return "vec2"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE3: return "vec3"; break;
- case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE4: return "vec4"; break;
- default: return "UNKNOWN"; break;
- }
- }
- gs_graphics_vertex_attribute_type gs_get_vertex_attribute_from_token(const gs_token_t* t)
- {
- if (gs_token_compare_text(t, "float")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT;
- else if (gs_token_compare_text(t, "float2")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT2;
- else if (gs_token_compare_text(t, "float3")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT3;
- else if (gs_token_compare_text(t, "float4")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT4;
- else if (gs_token_compare_text(t, "uint4")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT4;
- else if (gs_token_compare_text(t, "uint3")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT3;
- else if (gs_token_compare_text(t, "uint2")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT2;
- else if (gs_token_compare_text(t, "uint")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT;
- else if (gs_token_compare_text(t, "byte4")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE4;
- else if (gs_token_compare_text(t, "byte3")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE3;
- else if (gs_token_compare_text(t, "byte2")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE2;
- else if (gs_token_compare_text(t, "byte")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE;
- return (gs_graphics_vertex_attribute_type)0x00;
- }
- gs_graphics_uniform_type gs_uniform_type_from_token(const gs_token_t* t)
- {
- if (gs_token_compare_text(t, "float")) return GS_GRAPHICS_UNIFORM_FLOAT;
- else if (gs_token_compare_text(t, "int")) return GS_GRAPHICS_UNIFORM_INT;
- else if (gs_token_compare_text(t, "vec2")) return GS_GRAPHICS_UNIFORM_VEC2;
- else if (gs_token_compare_text(t, "vec3")) return GS_GRAPHICS_UNIFORM_VEC3;
- else if (gs_token_compare_text(t, "vec4")) return GS_GRAPHICS_UNIFORM_VEC4;
- else if (gs_token_compare_text(t, "mat4")) return GS_GRAPHICS_UNIFORM_MAT4;
- else if (gs_token_compare_text(t, "sampler2D")) return GS_GRAPHICS_UNIFORM_SAMPLER2D;
- else if (gs_token_compare_text(t, "sampler2DShadow"))return GS_GRAPHICS_UNIFORM_SAMPLER2DSHADOW;
- else if (gs_token_compare_text(t, "usampler2D")) return GS_GRAPHICS_UNIFORM_USAMPLER2D;
- else if (gs_token_compare_text(t, "samplerCube")) return GS_GRAPHICS_UNIFORM_SAMPLERCUBE;
- else if (gs_token_compare_text(t, "img2D_rgba32f")) return GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F;
- return (gs_graphics_uniform_type)0x00;
- }
- const char* gs_uniform_string_from_type(gs_graphics_uniform_type type)
- {
- switch (type)
- {
- case GS_GRAPHICS_UNIFORM_FLOAT: return "float"; break;
- case GS_GRAPHICS_UNIFORM_INT: return "int"; break;
- case GS_GRAPHICS_UNIFORM_VEC2: return "vec2"; break;
- case GS_GRAPHICS_UNIFORM_VEC3: return "vec3"; break;
- case GS_GRAPHICS_UNIFORM_VEC4: return "vec4"; break;
- case GS_GRAPHICS_UNIFORM_MAT4: return "mat4"; break;
- case GS_GRAPHICS_UNIFORM_SAMPLER2D: return "sampler2D"; break;
- case GS_GRAPHICS_UNIFORM_SAMPLER2DSHADOW: return "sampler2DShadow"; break;
- case GS_GRAPHICS_UNIFORM_USAMPLER2D: return "usampler2D"; break;
- case GS_GRAPHICS_UNIFORM_SAMPLERCUBE: return "samplerCube"; break;
- case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F: return "image2D"; break;
- default: return "UNKNOWN"; break;
- }
- return (char*)0x00;
- }
- // Make this an extern function that can be bubbled up to the app
- bool gs_parse_uniform_special_keyword(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd, gs_graphics_shader_stage_type stage, gs_gfxt_uniform_desc_t* uniform)
- {
- gs_token_t token = lex->current_token;
- // Determine if uniform is one of special key defines
- if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX, sizeof(GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0, sizeof(GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1, sizeof(GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_MODEL_MATRIX")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_MODEL_MATRIX, sizeof(GS_GFXT_UNIFORM_MODEL_MATRIX));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX, sizeof(GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_PROJECTION_MATRIX")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_PROJECTION_MATRIX, sizeof(GS_GFXT_UNIFORM_PROJECTION_MATRIX));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_MATRIX")) {
- uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
- memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_MATRIX, sizeof(GS_GFXT_UNIFORM_VIEW_MATRIX));
- return true;
- }
- else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_TIME")) {
- uniform->type = GS_GRAPHICS_UNIFORM_FLOAT;
- memcpy(uniform->name, GS_GFXT_UNIFORM_TIME, sizeof(GS_GFXT_UNIFORM_TIME));
- return true;
- }
- return false;
- }
- bool gs_parse_uniforms(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd, gs_graphics_shader_stage_type stage)
- {
- uint32_t image_binding = 0;
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
- {
- gs_log_warning("Unable to parsing uniforms from .sf resource");
- return false;
- }
- uint32_t bc = 1;\
- while (gs_lexer_can_lex(lex) && bc)
- {
- gs_token_t token = gs_lexer_next_token(lex);
- switch (token.type)
- {
- case GS_TOKEN_LBRACE: {bc++;} break;
- case GS_TOKEN_RBRACE: {bc--;} break;
- case GS_TOKEN_IDENTIFIER:
- {
- gs_gfxt_uniform_desc_t uniform = {0};
- uniform.stage = stage;
- bool special = gs_parse_uniform_special_keyword(lex, desc, ppd, stage, &uniform);
- // Determine if uniform is one of special key defines
- if (!special)
- {
- uniform.type = gs_uniform_type_from_token(&token);
- switch (uniform.type)
- {
- default: break;
- case GS_GRAPHICS_UNIFORM_SAMPLER2D:
- case GS_GRAPHICS_UNIFORM_USAMPLER2D:
- case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
- {
- uniform.binding = image_binding++;
- } break;
- }
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Unidentified token (Expected identifier)");
- gs_token_debug_print(&lex->current_token);
- return false;
- }
- token = lex->current_token;
- memcpy(uniform.name, token.text, token.len);
- }
- // Add uniform to ublock descriptor
- gs_dyn_array_push(desc->ublock_desc.layout, uniform);
- } break;
- }
- }
- return true;
- }
- bool gs_parse_io(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd, gs_graphics_shader_stage_type type)
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
- {
- gs_log_warning("Expected opening left brace. Unable to parse io from .sf resource");\
- return false;
- }
- uint32_t bc = 1;
- while (gs_lexer_can_lex(lex) && bc)
- {
- gs_token_t token = gs_lexer_next_token(lex);
- switch (token.type)
- {
- case GS_TOKEN_LBRACE: {bc++;} break;
- case GS_TOKEN_RBRACE: {bc--;} break;
- case GS_TOKEN_IDENTIFIER:
- {
- gs_shader_io_data_t io = {0};
- memcpy(io.type, token.text, token.len);
- switch (type)
- {
- case GS_GRAPHICS_SHADER_STAGE_VERTEX:
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("IO expected identifier name after type, shader stage vertex.");
- gs_token_debug_print(&lex->current_token);
- return false;
- }
- token = lex->current_token;
- memcpy(io.name, token.text, token.len);
- gs_dyn_array_push(ppd->io_list[0], io);
- } break;
- case GS_GRAPHICS_SHADER_STAGE_FRAGMENT:
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("IO expected identifier name after type, shader stage fragment.");
- gs_token_debug_print(&lex->current_token);
- return false;
- }
- token = lex->current_token;
- memcpy(io.name, token.text, token.len);
- gs_dyn_array_push(ppd->io_list[1], io);
- } break;
- case GS_GRAPHICS_SHADER_STAGE_COMPUTE:
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_NUMBER))
- {
- gs_log_warning("IO expected number after type, shader stage compute.");
- gs_token_debug_print(&lex->current_token);
- return false;
- }
- token = lex->current_token;
- memcpy(io.name, token.text, token.len);
- gs_dyn_array_push(ppd->io_list[2], io);
- } break;
- }
- } break;
- }
- }
- return true;
- }
- bool gs_parse_code(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd, gs_graphics_shader_stage_type stage)
- {
- if (!gs_lexer_require_token_type(lex, GS_TOKEN_LBRACE))
- {
- gs_log_warning("Expected opening left brace");
- return false;
- }
- // Something is broken up here...
- uint32_t bc = 1;
- gs_token_t cur = gs_lexer_peek(lex);
- gs_token_t token = lex->current_token;
- while (gs_lexer_can_lex(lex) && bc)
- {
- token = lex->next_token(lex);
- switch (token.type)
- {
- case GS_TOKEN_LBRACE: {bc++;} break;
- case GS_TOKEN_RBRACE: {bc--;} break;
- }
- }
- // Allocate size for code
- const size_t sz = (size_t)(token.text - cur.text);
- char* code = (char*)gs_malloc(sz);
- memset(code, 0, sz);
- memcpy(code, cur.text, sz - 1);
- gs_byte_buffer_t cbuffer = gs_byte_buffer_new();
- // List of include directories to gather
- uint32_t iidx = 0;
- typedef struct {
- char path[GS_GFXT_INCLUDE_DIR_MAX];
- char* start;
- char* end;
- } include_t;
- include_t includes[256] = {0};
- // Need to parse through code and replace keywords with appropriate mappings
- gs_lexer_t clex = gs_lexer_c_ctor(code);
- clex.skip_white_space = false;
- while (clex.can_lex(&clex))
- {
- gs_token_t tkn = clex.next_token(&clex);
- // Push back tkn text + len. Don't skip whitespace in this lexer.
- switch (tkn.type)
- {
- default: {
- gs_byte_buffer_write_bulk(&cbuffer, tkn.text, tkn.len);
- } break;
- case GS_TOKEN_IDENTIFIER: {
- // evil replace a const char*
- if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_MODEL_MATRIX")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_MODEL_MATRIX, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_MATRIX")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_MATRIX, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_PROJECTION_MATRIX")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_PROJECTION_MATRIX, (char)32);
- }
- else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_TIME")) {
- gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_TIME, (char)32);
- }
- gs_byte_buffer_write_bulk(&cbuffer, tkn.text, tkn.len);
- } break;
- case GS_TOKEN_HASH: {
- gs_token_t htoken = tkn;
- tkn = clex.next_token(&clex);
- switch (tkn.type) {
- case GS_TOKEN_IDENTIFIER: {
- // Parse include
- if (gs_token_compare_text(&tkn, "include") && iidx < GS_GFXT_INCLUDE_DIR_MAX) {
- // Length of include string
- size_t ilen = 8;
- // Grab next token, expect string
- // Don't grab next token - advance to string
- // tkn = clex.next_token(&clex);
- if (gs_lexer_find_next_token_type(&clex, GS_TOKEN_STRING)) {
- // if (tkn.type == GS_TOKEN_STRING) {
- tkn = clex.current_token;
- // Just fucking replace it here, on the spot. Then fix up the lexer. Done.
- memcpy(includes[iidx].path, tkn.text + 1, tkn.len - 2);
- // evil replace a const char*
- // Store token text pointer, use that later for concat
- gs_util_string_replace((char*)tkn.text - ilen - 1, tkn.len + ilen + 1,
- " ", (char)32);
- // Need to collect other uniforms from these includes (parse code)
- gs_snprintfc(FINAL_PATH, 256, "%s/%s", ppd->dir, includes[iidx].path);
- // Load include using final path and relative path from include
- size_t len = 0;
- char* inc_src = gs_platform_read_file_contents(FINAL_PATH, "rb", &len);
- gs_byte_buffer_write_bulk(&cbuffer, inc_src, len);
- // includes[iidx].start = tkn.text;
- // includes[iidx].end = tkn.text + ilen + tkn.len;
- // size_t total_len = len + (start - code);
- // char* cat0 = gs_util_string_concat(start, inc_src);
- // char* cat1 = gs_util_string_concat(cat0, includes[iidx].end);
- // // Concat, replace text, free include src
- // // gs_free(cat0);
- // // gs_free(code);
- // code = cat1;
- // start = code;
- // end = code + total_len;
- // // Need to find where to place the token...ehhh...
- // clex = gs_lexer_c_ctor(code);
- // clex.at = code + total_len;
- iidx++;
- }
- }
- else {
- gs_byte_buffer_write(&cbuffer, char, '#');
- clex.current_token = tkn;
- clex.at = tkn.text;
- }
- // else if (gs_token_compare_text(&tkn, "define")) {
- // Push back # and identifier into buffer
- // gs_println("Writing: %*.s", tkn.len + 1, tkn.text - tkn.len - 1);
- // gs_snprintfc(TMP, 8, "#define");
- // gs_byte_buffer_write_bulk(&cbuffer, TMP, sizeof(TMP));
- // gs_byte_buffer_write_str(&cbuffer, "#define");
- // }
- } break;
- // default: {
- // // Push back # and identifier into buffer
- // gs_println("Writing: %*.s", tkn.len + 1, tkn.text - tkn.len - 1);
- // gs_byte_buffer_write_bulk(&cbuffer, tkn.text - tkn.len - 1, tkn.len + 1);
- // } break;
- }
- } break;
- }
- }
- // Allocate a new buffer as copy of original code. Use original for pointer references to where to cat.
- // size_t ilen = 0;
- // for (uint32_t i = 0; i < GS_GFXT_INCLUDE_DIR_MAX; ++i)
- // {
- // if (!includes[i].path[0]) continue;
- // // Need to collect other uniforms from these includes (parse code)
- // gs_snprintfc(FINAL_PATH, 256, "%s/%s", ppd->dir, includes[i].path);
- // // gs_println("INC_DIR: %s", FINAL_PATH);
- // // Load include using final path and relative path from include
- // size_t len = 0;
- // char* inc_src = gs_platform_read_file_contents(FINAL_PATH, "rb", &len);
- // gs_assert(inc_src);
- // // Concat, starting at a particular location.
- // const char* src_start_slice = includes[i].start + ilen;
- // const char* src_end_slice = includes[i].end + ilen;
- // char* cat = gs_util_string_concat(src_start_slice, inc_src);
- // char* cat2 = gs_util_string_concat(cat, src_end_slice);
- // // Concat with (cat) src starting at workable range
- // // Realloc previous code to greater size, shift contents around
- // char* cat = gs_util_string_concat(inc_src, code);
- // gs_free(code);
- // code = cat;
- // }
- // Add a final EOF character
- gs_byte_buffer_write(&cbuffer, char, '\0');
- gs_free(code);
- switch (stage)
- {
- // case GS_GRAPHICS_SHADER_STAGE_VERTEX: ppd->code[0] = code; break;
- // case GS_GRAPHICS_SHADER_STAGE_FRAGMENT: ppd->code[1] = code; break;
- // case GS_GRAPHICS_SHADER_STAGE_COMPUTE: ppd->code[2] = code; break;
- case GS_GRAPHICS_SHADER_STAGE_VERTEX: ppd->code[0] = cbuffer.data; break;
- case GS_GRAPHICS_SHADER_STAGE_FRAGMENT: ppd->code[1] = cbuffer.data; break;
- case GS_GRAPHICS_SHADER_STAGE_COMPUTE: ppd->code[2] = cbuffer.data; break;
- }
- return true;
- }
- gs_gfxt_mesh_attribute_type gs_mesh_attribute_type_from_token(const gs_token_t* token)
- {
- if (gs_token_compare_text(token, "POSITION")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION;
- else if (gs_token_compare_text(token, "NORMAL")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL;
- else if (gs_token_compare_text(token, "COLOR")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR;
- else if (gs_token_compare_text(token, "TANGENT")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT;
- else if (gs_token_compare_text(token, "TEXCOORD0")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD1")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD2")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD3")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD4")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD5")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD6")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD7")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD8")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD9")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD10")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD11")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "TEXCOORD12")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
- else if (gs_token_compare_text(token, "UINT")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_UINT;
- // Default
- return (gs_gfxt_mesh_attribute_type)0x00;
- }
- bool gs_parse_vertex_mesh_attributes(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
- {
- gs_assert(false);
- }
- uint32_t bc = 1;
- while (gs_lexer_can_lex(lex) && bc)
- {
- gs_token_t token = gs_lexer_next_token(lex);
- // gs_token_debug_print(&token);
- switch (token.type)
- {
- case GS_TOKEN_LBRACE: {bc++;} break;
- case GS_TOKEN_RBRACE: {bc--;} break;
-
- case GS_TOKEN_IDENTIFIER:
- {
- // Get attribute name
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_assert(false);
- }
- gs_token_t token_name = lex->current_token;
- // gs_token_debug_print(&token_name);
- #define PUSH_ATTR(MESH_ATTR, VERT_ATTR)\
- do {\
- gs_gfxt_mesh_layout_t layout = gs_default_val();\
- layout.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_##MESH_ATTR;\
- gs_dyn_array_push(ppd->mesh_layout, layout);\
- gs_graphics_vertex_attribute_desc_t attr = gs_default_val();\
- memcpy(attr.name, token_name.text, token_name.len);\
- attr.format = GS_GRAPHICS_VERTEX_ATTRIBUTE_##VERT_ATTR;\
- gs_dyn_array_push(desc->pip_desc.layout.attrs, attr);\
- /*gs_println("%s: %s", #MESH_ATTR, #VERT_ATTR);*/\
- } while (0)
- if (gs_token_compare_text(&token, "POSITION")) PUSH_ATTR(POSITION, FLOAT3);
- else if (gs_token_compare_text(&token, "NORMAL")) PUSH_ATTR(NORMAL, FLOAT3);
- else if (gs_token_compare_text(&token, "COLOR")) PUSH_ATTR(COLOR, BYTE4);
- else if (gs_token_compare_text(&token, "TANGENT")) PUSH_ATTR(TANGENT, FLOAT3);
- else if (gs_token_compare_text(&token, "TEXCOORD")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD0")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD1")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD2")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD3")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD4")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD5")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD6")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD8")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD9")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD10")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD11")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "TEXCOORD12")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "FLOAT")) PUSH_ATTR(WEIGHT, FLOAT4);
- else if (gs_token_compare_text(&token, "FLOAT2")) PUSH_ATTR(TEXCOORD, FLOAT2);
- else if (gs_token_compare_text(&token, "FLOAT3")) PUSH_ATTR(POSITION, FLOAT3);
- else if (gs_token_compare_text(&token, "UINT")) PUSH_ATTR(UINT, UINT);
- // else if (gs_token_compare_text(&token, "FLOAT4")) PUSH_ATTR(TANGENT, FLOAT4);
- else
- {
- gs_log_warning("Unidentified vertex attribute: %.*s: %.*s",
- token.len, token.text, token_name.len, token_name.text);
- return false;
- }
- }
- }
- }
- return true;
- }
- bool gs_parse_vertex_attributes(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
- {
- return gs_parse_vertex_mesh_attributes(lex, desc, ppd);
- }
- bool gs_parse_shader_stage(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd, gs_graphics_shader_stage_type stage)
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
- {
- gs_println("error::gs_pipeline_load_from_file::error parsing raster from .sf resource");
- gs_assert(false);
- }
- uint32_t bc = 1;
- while (gs_lexer_can_lex(lex) && bc)
- {
- gs_token_t token = gs_lexer_next_token(lex);
- switch (token.type)
- {
- case GS_TOKEN_LBRACE: {bc++;} break;
- case GS_TOKEN_RBRACE: {bc--;} break;
- case GS_TOKEN_IDENTIFIER:
- {
- if (stage == GS_GRAPHICS_SHADER_STAGE_VERTEX &&
- gs_token_compare_text(&token, "attributes"))
- {
- gs_println("parsing attributes...");
- if (!gs_parse_vertex_attributes(lex, desc, ppd))
- {
- gs_log_warning("Unable to parse vertex attributes.");
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "uniforms"))
- {
- gs_println("parsing uniforms...");
- if (!gs_parse_uniforms(lex, desc, ppd, stage))
- {
- gs_log_warning("Unable to parse 'uniforms' for stage: %zu.", (u32)stage);
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "out"))
- {
- gs_println("parsing out...");
- if (!gs_parse_io(lex, desc, ppd, stage))
- {
- gs_log_warning("Unable to parse 'out' for stage: %zu.", (u32)stage);
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "in"))
- {
- gs_println("parsing in...");
- if (!gs_parse_io(lex, desc, ppd, stage))
- {
- gs_log_warning("Unable to parse 'in' for stage: %zu.", (u32)stage);
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "code"))
- {
- gs_println("parsing code...");
- if (!gs_parse_code(lex, desc, ppd, stage))
- {
- gs_log_warning("Unable to parse 'code' for stage: %zu.", (u32)stage);
- return false;
- }
- }
- } break;
- }
- }
- return true;
- }
- bool gs_parse_compute_shader_stage(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
- {
- gs_parse_block(
- PIPELINE::COMPUTE_SHADER_STAGE,
- {
- if (gs_token_compare_text(&token, "uniforms"))
- {
- if (!gs_parse_uniforms(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE))
- {
- gs_log_warning("Unable to parse 'uniforms' for compute shader");
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "in"))
- {
- if (!gs_parse_io(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE))
- {
- gs_log_warning("Unable to parse 'in' for compute shader");
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "code"))
- {
- if (!gs_parse_code(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE))
- {
- gs_log_warning("Unable to parse 'code' for compute shader");
- return false;
- }
- }
- });
- return true;
- }
- bool gs_parse_shader(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
- {
- gs_log_warning("Unable to parse shader from .sf resource. Expected opening left brace.");
- return false;
- }
- // Braces
- uint32_t bc = 1;
- while (gs_lexer_can_lex(lex) && bc)
- {
- gs_token_t token = lex->next_token(lex);
- switch (token.type)
- {
- case GS_TOKEN_LBRACE: {bc++;} break;
- case GS_TOKEN_RBRACE: {bc--;} break;
- case GS_TOKEN_IDENTIFIER:
- {
- // Vertex shader
- if (gs_token_compare_text(&token, "vertex"))
- {
- gs_println("parsing vertex shader");
- if (!gs_parse_shader_stage(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_VERTEX))
- {
- gs_log_warning("Unable to parse shader stage: Vertex");
- return false;
- }
- }
- // Fragment shader
- else if (gs_token_compare_text(&token, "fragment"))
- {
- gs_println("parsing fragment shader");
- if (!gs_parse_shader_stage(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_FRAGMENT))
- {
- gs_log_warning("Unable to parse shader stage: Fragment");
- return false;
- }
- }
- // Compute shader
- else if (gs_token_compare_text(&token, "compute"))
- {
- gs_println("parsing compute shader");
- if (!gs_parse_shader_stage(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE))
- {
- gs_log_warning("Unable to parse shader stage: Compute");
- return false;
- }
- }
- } break;
- }
- }
- return true;
- }
- bool gs_parse_depth(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd)
- {
- gs_parse_block(
- PIPELINE::DEPTH,
- {
- // Depth function
- if (gs_token_compare_text(&token, "func"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- token = lex->current_token;
- gs_log_warning("Depth func type not found after function decl: %.*s", token.len, token.text);
- return false;
- }
- token = lex->current_token;
-
- if (gs_token_compare_text(&token, "LESS")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_LESS;
- else if (gs_token_compare_text(&token, "EQUAL")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_EQUAL;
- else if (gs_token_compare_text(&token, "LEQUAL")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_LEQUAL;
- else if (gs_token_compare_text(&token, "GREATER")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_GREATER;
- else if (gs_token_compare_text(&token, "NOTEQUAL")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_NOTEQUAL;
- else if (gs_token_compare_text(&token, "GEQUAL")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_GEQUAL;
- else if (gs_token_compare_text(&token, "ALWAYS")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_ALWAYS;
- else if (gs_token_compare_text(&token, "NEVER")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_NEVER;
- else
- {
- token = lex->current_token;
- gs_log_warning("Func type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- if (gs_token_compare_text(&token, "mask"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- token = lex->current_token;
- gs_log_warning("Depth mask type not found after function decl: %.*s", token.len, token.text);
- return false;
- }
- token = lex->current_token;
-
- if (gs_token_compare_text(&token, "ENABLED")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_ENABLED;
- else if (gs_token_compare_text(&token, "TRUE")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_ENABLED;
- else if (gs_token_compare_text(&token, "true")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_ENABLED;
- else if (gs_token_compare_text(&token, "DISABLED")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_DISABLED;
- else if (gs_token_compare_text(&token, "FALSE")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_DISABLED;
- else if (gs_token_compare_text(&token, "false")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_DISABLED;
- else
- {
- token = lex->current_token;
- gs_log_warning("Mask type %.*s not valid.", token.len, token.text);
- return false;
- }
- gs_println("MASK: %zu", (uint32_t)pdesc->pip_desc.depth.mask);
- }
- });
- return true;
- }
- bool gs_parse_blend(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd)
- {
- gs_parse_block(
- PIPELINE::BLEND,
- {
- // Blend function
- if (gs_token_compare_text(&token, "func"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Blend func type not found after function decl.");
- return false;
- }
- token = lex->current_token;
-
- if (gs_token_compare_text(&token, "ADD")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_ADD;
- else if (gs_token_compare_text(&token, "SUBTRACT")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_SUBTRACT;
- else if (gs_token_compare_text(&token, "REVERSE_SUBTRACT")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_REVERSE_SUBTRACT;
- else if (gs_token_compare_text(&token, "MIN")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_MIN;
- else if (gs_token_compare_text(&token, "MAX")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_MAX;
- else
- {
- gs_log_warning("Blend func type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- // Source blend
- else if (gs_token_compare_text(&token, "src"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Blend src type not found after decl.");
- return false;
- }
- token = lex->current_token;
-
- if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ZERO;
- else if (gs_token_compare_text(&token, "ONE")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE;
- else if (gs_token_compare_text(&token, "SRC_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_SRC_COLOR;
- else if (gs_token_compare_text(&token, "ONE_MINUS_SRC_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_COLOR;
- else if (gs_token_compare_text(&token, "DST_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_DST_COLOR;
- else if (gs_token_compare_text(&token, "ONE_MINUS_DST_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_COLOR;
- else if (gs_token_compare_text(&token, "SRC_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_SRC_ALPHA;
- else if (gs_token_compare_text(&token, "ONE_MINUS_SRC_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_ALPHA;
- else if (gs_token_compare_text(&token, "DST_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_DST_ALPHA;
- else if (gs_token_compare_text(&token, "ONE_MINUS_DST_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_ALPHA;
- else if (gs_token_compare_text(&token, "CONSTANT_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_CONSTANT_COLOR;
- else if (gs_token_compare_text(&token, "ONE_MINUS_CONSTANT_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_ALPHA;
- else if (gs_token_compare_text(&token, "CONSTANT_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_CONSTANT_ALPHA;
- else if (gs_token_compare_text(&token, "ONE_MINUS_CONSTANT_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_ALPHA;
- else
- {
- gs_log_warning("Blend src type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- // Dest blend
- else if (gs_token_compare_text(&token, "dst"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Blend dst type not found after decl.");
- return false;
- }
- token = lex->current_token;
-
- if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ZERO;
- else if (gs_token_compare_text(&token, "ONE")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE;
- else if (gs_token_compare_text(&token, "SRC_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_SRC_COLOR;
- else if (gs_token_compare_text(&token, "ONE_MINUS_SRC_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_COLOR;
- else if (gs_token_compare_text(&token, "DST_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_DST_COLOR;
- else if (gs_token_compare_text(&token, "ONE_MINUS_DST_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_COLOR;
- else if (gs_token_compare_text(&token, "SRC_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_SRC_ALPHA;
- else if (gs_token_compare_text(&token, "ONE_MINUS_SRC_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_ALPHA;
- else if (gs_token_compare_text(&token, "DST_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_DST_ALPHA;
- else if (gs_token_compare_text(&token, "ONE_MINUS_DST_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_ALPHA;
- else if (gs_token_compare_text(&token, "CONSTANT_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_CONSTANT_COLOR;
- else if (gs_token_compare_text(&token, "ONE_MINUS_CONSTANT_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_ALPHA;
- else if (gs_token_compare_text(&token, "CONSTANT_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_CONSTANT_ALPHA;
- else if (gs_token_compare_text(&token, "ONE_MINUS_CONSTANT_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_ALPHA;
- else
- {
- gs_log_warning("Blend dst type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- });
- return true;
- }
- bool gs_parse_stencil(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd)
- {
- gs_parse_block(
- PIPELINE::STENCIL,
- {
- // Function
- if (gs_token_compare_text(&token, "func"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Stencil func type not found after decl.");
- return false;
- }
- else
- {
- token = lex->current_token;
-
- if (gs_token_compare_text(&token, "LESS")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_LESS;
- else if (gs_token_compare_text(&token, "EQUAL")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_EQUAL;
- else if (gs_token_compare_text(&token, "LEQUAL")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_LEQUAL;
- else if (gs_token_compare_text(&token, "GREATER")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_GREATER;
- else if (gs_token_compare_text(&token, "NOTEQUAL")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_NOTEQUAL;
- else if (gs_token_compare_text(&token, "GEQUAL")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_GEQUAL;
- else if (gs_token_compare_text(&token, "ALWAYS")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_ALWAYS;
- else if (gs_token_compare_text(&token, "NEVER")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_NEVER;
- else
- {
- gs_log_warning("Stencil func type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- }
- // Reference value
- else if (gs_token_compare_text(&token, "ref"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_NUMBER))
- {
- gs_log_warning("Stencil reference value not found after decl.");
- return false;
- }
- else
- {
- token = lex->current_token;
- gs_snprintfc(TMP, 16, "%.*s", token.len, token.text);
- pdesc->pip_desc.stencil.ref = atoi(TMP);
- }
- }
- // Component mask
- else if (gs_token_compare_text(&token, "comp_mask"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_NUMBER))
- {
- gs_log_warning("Stencil component mask value not found after decl.");
- return false;
- }
- else
- {
- token = lex->current_token;
- gs_snprintfc(TMP, 16, "%.*s", token.len, token.text);
- pdesc->pip_desc.stencil.comp_mask = atoi(TMP);
- }
- }
- // Write mask
- else if (gs_token_compare_text(&token, "write_mask"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_NUMBER))
- {
- gs_log_warning("Stencil write mask value not found after decl.");
- return false;
- }
- else
- {
- token = lex->current_token;
- gs_snprintfc(TMP, 16, "%.*s", token.len, token.text);
- pdesc->pip_desc.stencil.write_mask = atoi(TMP);
- }
- }
- // Stencil test failure
- else if (gs_token_compare_text(&token, "sfail"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Stencil sfail value not found after decl.");
- return false;
- }
- else
- {
- token = lex->current_token;
- if (gs_token_compare_text(&token, "KEEP")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_KEEP;
- else if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_ZERO;
- else if (gs_token_compare_text(&token, "REPLACE")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_REPLACE;
- else if (gs_token_compare_text(&token, "INCR")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_INCR;
- else if (gs_token_compare_text(&token, "INCR_WRAP")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_INCR_WRAP;
- else if (gs_token_compare_text(&token, "DECR")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_DECR;
- else if (gs_token_compare_text(&token, "DECR_WRAP")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_DECR_WRAP;
- else if (gs_token_compare_text(&token, "INVERT")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_INVERT;
- else
- {
- gs_log_warning("Stencil sfail type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- }
- // Stencil test pass, Depth fail
- else if (gs_token_compare_text(&token, "dpfail"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Stencil dpfail value not found after decl.");
- return false;
- }
- else
- {
- token = lex->current_token;
- if (gs_token_compare_text(&token, "KEEP")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_KEEP;
- else if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_ZERO;
- else if (gs_token_compare_text(&token, "REPLACE")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_REPLACE;
- else if (gs_token_compare_text(&token, "INCR")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_INCR;
- else if (gs_token_compare_text(&token, "INCR_WRAP")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_INCR_WRAP;
- else if (gs_token_compare_text(&token, "DECR")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_DECR;
- else if (gs_token_compare_text(&token, "DECR_WRAP")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_DECR_WRAP;
- else if (gs_token_compare_text(&token, "INVERT")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_INVERT;
- else
- {
- gs_log_warning("Stencil dpfail type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- }
- // Stencil test pass, Depth pass
- else if (gs_token_compare_text(&token, "dppass"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Stencil dppass value not found after decl.");
- return false;
- }
- else
- {
- token = lex->current_token;
- if (gs_token_compare_text(&token, "KEEP")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_KEEP;
- else if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_ZERO;
- else if (gs_token_compare_text(&token, "REPLACE")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_REPLACE;
- else if (gs_token_compare_text(&token, "INCR")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_INCR;
- else if (gs_token_compare_text(&token, "INCR_WRAP")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_INCR_WRAP;
- else if (gs_token_compare_text(&token, "DECR")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_DECR;
- else if (gs_token_compare_text(&token, "DECR_WRAP")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_DECR_WRAP;
- else if (gs_token_compare_text(&token, "INVERT")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_INVERT;
- else
- {
- gs_log_warning("Stencil dppass type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- }
- });
- return true;
- }
- bool gs_parse_raster(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd)
- {
- gs_parse_block(
- PIPELINE::RASTER,
- {
- // Index Buffer Element Size
- if (gs_token_compare_text(&token, "index_buffer_element_size"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Raster index buffer element size not found.", token.len, token.text);
- }
-
- token = lex->current_token;
- if (gs_token_compare_text(&token, "UINT32") || gs_token_compare_text(&token, "uint32_t") || gs_token_compare_text(&token, "u32"))
- {
- pdesc->pip_desc.raster.index_buffer_element_size = sizeof(uint32_t);
- }
- else if (gs_token_compare_text(&token, "UINT16") || gs_token_compare_text(&token, "uint16_t") || gs_token_compare_text(&token, "u16"))
- {
- pdesc->pip_desc.raster.index_buffer_element_size = sizeof(uint16_t);
- }
-
- // Default
- else
- {
- pdesc->pip_desc.raster.index_buffer_element_size = sizeof(uint32_t);
- }
- }
- // Face culling
- if (gs_token_compare_text(&token, "face_culling"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Raster face culling type not found.");
- return false;
- }
-
- token = lex->current_token;
- if (gs_token_compare_text(&token, "FRONT")) pdesc->pip_desc.raster.face_culling = GS_GRAPHICS_FACE_CULLING_FRONT;
- else if (gs_token_compare_text(&token, "BACK")) pdesc->pip_desc.raster.face_culling = GS_GRAPHICS_FACE_CULLING_BACK;
- else if (gs_token_compare_text(&token, "FRONT_AND_BACK")) pdesc->pip_desc.raster.face_culling = GS_GRAPHICS_FACE_CULLING_FRONT_AND_BACK;
- else
- {
- gs_log_warning("Raster face culling type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- // Winding order
- if (gs_token_compare_text(&token, "winding_order"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Raster winding order type not found.");
- return false;
- }
-
- token = lex->current_token;
- if (gs_token_compare_text(&token, "CW")) pdesc->pip_desc.raster.winding_order = GS_GRAPHICS_WINDING_ORDER_CW;
- else if (gs_token_compare_text(&token, "CCW")) pdesc->pip_desc.raster.winding_order = GS_GRAPHICS_WINDING_ORDER_CCW;
- else
- {
- gs_log_warning("Raster winding order type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- // Primtive
- if (gs_token_compare_text(&token, "primitive"))
- {
- if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
- {
- gs_log_warning("Raster primitive type not found.");
- return false;
- }
-
- token = lex->current_token;
- if (gs_token_compare_text(&token, "LINES")) pdesc->pip_desc.raster.primitive = GS_GRAPHICS_PRIMITIVE_LINES;
- else if (gs_token_compare_text(&token, "TRIANGLES")) pdesc->pip_desc.raster.primitive = GS_GRAPHICS_PRIMITIVE_TRIANGLES;
- else if (gs_token_compare_text(&token, "QUADS")) pdesc->pip_desc.raster.primitive = GS_GRAPHICS_PRIMITIVE_QUADS;
- else
- {
- gs_log_warning("Raster primitive type %.*s not valid.", token.len, token.text);
- return false;
- }
- }
- });
- return true;
- }
- bool gs_parse_pipeline(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
- {
- // Get next identifier
- while (lex->can_lex(lex))
- {
- gs_token_t token = lex->next_token(lex);
- switch (token.type)
- {
- case GS_TOKEN_IDENTIFIER:
- {
- if (gs_token_compare_text(&token, "shader"))
- {
- gs_println("parsing shader");
- if (!gs_parse_shader(lex, desc, ppd))
- {
- gs_log_warning("Unable to parse shader descriptor");
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "raster"))
- {
- if (!gs_parse_raster(lex, desc, ppd))
- {
- gs_log_warning("Unable to parse raster descriptor");
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "depth"))
- {
- if (!gs_parse_depth(lex, desc, ppd))
- {
- gs_log_warning("Unable to parse depth descriptor");
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "stencil"))
- {
- if (!gs_parse_stencil(lex, desc, ppd))
- {
- gs_log_warning("Unable to parse stencil descriptor");
- return false;
- }
- }
- else if (gs_token_compare_text(&token, "blend"))
- {
- if (!gs_parse_blend(lex, desc, ppd))
- {
- gs_log_warning("Unable to parse blend descriptor");
- return false;
- }
- }
- } break;
- }
- }
- return true;
- }
- char* gs_pipeline_generate_shader_code(gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd, gs_graphics_shader_stage_type stage)
- {
- gs_println("GENERATING CODE...");
- // Get major/minor version of shader
- gs_graphics_info_t* ginfo = gs_graphics_info();
- gs_snprintfc(MAJMINSTR, 128, "#version %zu%zu0\n", ginfo->major_version, ginfo->minor_version);
- // Shaders
- #ifdef GS_PLATFORM_WEB
- #define _GS_VERSION_STR "#version 300 es\n"
- #else
- #define _GS_VERSION_STR "#version 430\n"
- #endif
- // Source code
- char* src = NULL;
- uint32_t sidx = 0;
- // Set sidx
- switch (stage)
- {
- case GS_GRAPHICS_SHADER_STAGE_VERTEX: sidx = 0; break;
- case GS_GRAPHICS_SHADER_STAGE_FRAGMENT: sidx = 1; break;
- case GS_GRAPHICS_SHADER_STAGE_COMPUTE: sidx = 2; break;
- }
- // Early out for now...
- if (!ppd->code[sidx])
- {
- return src;
- }
- // Shader header
- gs_snprintfc(shader_header, 512, "%s precision mediump float;\n", stage == GS_GRAPHICS_SHADER_STAGE_COMPUTE ? "#version 430\n" : _GS_VERSION_STR);
- // Generate shader code
- if (ppd->code[sidx])
- {
- const size_t header_sz = (size_t)gs_string_length(shader_header);
- size_t total_sz = gs_string_length(ppd->code[sidx]) + header_sz + 2048;
- src = (char*)gs_malloc(total_sz);
- memset(src, 0, total_sz);
- strncat(src, shader_header, header_sz);
-
- // Attributes
- if (stage == GS_GRAPHICS_SHADER_STAGE_VERTEX)
- {
- for (uint32_t i = 0; i < gs_dyn_array_size(pdesc->pip_desc.layout.attrs); ++i)
- {
- const char* aname = pdesc->pip_desc.layout.attrs[i].name;
- const char* atype = gs_get_vertex_attribute_string(pdesc->pip_desc.layout.attrs[i].format);
- gs_snprintfc(ATTR, 64, "layout(location = %zu) in %s %s;\n", i, atype, aname);
- const size_t sz = gs_string_length(ATTR);
- strncat(src, ATTR, sz);
- }
- }
- // Compute shader image buffer binding
- uint32_t img_binding = 0;
- // Uniforms
- for (uint32_t i = 0; i < gs_dyn_array_size(pdesc->ublock_desc.layout); ++i)
- {
- gs_gfxt_uniform_desc_t* udesc = &pdesc->ublock_desc.layout[i];
- if (udesc->stage != stage) continue;
- switch (stage)
- {
- case GS_GRAPHICS_SHADER_STAGE_COMPUTE:
- {
- // Need to go from uniform type to string
- const char* utype = gs_uniform_string_from_type(udesc->type);
- const char* uname = udesc->name;
- switch (udesc->type)
- {
- default:
- {
- gs_snprintfc(TMP, 64, "uniform %s %s;\n", utype, uname);
- const size_t sz = gs_string_length(TMP);
- strncat(src, TMP, sz);
- } break;
- case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
- {
- gs_snprintfc(TMP, 64, "layout (rgba32f, binding = %zu) uniform image2D %s;\n", img_binding++, uname);
- const size_t sz = gs_string_length(TMP);
- strncat(src, TMP, sz);
- } break;
- }
- } break;
- default:
- {
- // Need to go from uniform type to string
- const char* utype = gs_uniform_string_from_type(udesc->type);
- const char* uname = udesc->name;
- gs_snprintfc(TMP, 64, "uniform %s %s;\n", utype, uname);
- const size_t sz = gs_string_length(TMP);
- strncat(src, TMP, sz);
- } break;
- }
- }
- // Out
- switch (stage)
- {
- case GS_GRAPHICS_SHADER_STAGE_FRAGMENT:
- case GS_GRAPHICS_SHADER_STAGE_VERTEX:
- {
- for (uint32_t i = 0; i < gs_dyn_array_size(ppd->io_list[sidx]); ++i)
- {
- gs_shader_io_data_t* out = &ppd->io_list[sidx][i];
- const char* otype = out->type;
- const char* oname = out->name;
- gs_transient_buffer(TMP, 64);
- if (stage == GS_GRAPHICS_SHADER_STAGE_FRAGMENT)
- {
- gs_snprintf(TMP, 64, "layout(location = %zu) out %s %s;\n", i, otype, oname);
- }
- else
- {
- gs_snprintf(TMP, 64, "out %s %s;\n", otype, oname);
- }
- const size_t sz = gs_string_length(TMP);
- strncat(src, TMP, sz);
- }
- } break;
- default: break;
- }
- // In
- switch (stage)
- {
- case GS_GRAPHICS_SHADER_STAGE_FRAGMENT:
- {
- for (uint32_t i = 0; i < gs_dyn_array_size(ppd->io_list[0]); ++i)
- {
- gs_shader_io_data_t* out = &ppd->io_list[0][i];
- const char* otype = out->type;
- const char* oname = out->name;
- gs_snprintfc(TMP, 64, "in %s %s;\n", otype, oname);
- const size_t sz = gs_string_length(TMP);
- strncat(src, TMP, sz);
- }
- } break;
- case GS_GRAPHICS_SHADER_STAGE_COMPUTE:
- {
- /*
- gs_snprintfc(TMP, 64, "layout(");
- strncat(src, "layout(", 7);
- for (uint32_t i = 0; i < gs_dyn_array_size(ppd->io_list[2]); ++i)
- {
- gs_shader_io_data_t* out = &ppd->io_list[2][i];
- const char* otype = out->type;
- const char* oname = out->name;
- gs_snprintfc(TMP, 64, "%s = %s%s", otype, oname, i == gs_dyn_array_size(ppd->io_list[2]) - 1 ? "" : ", ");
- const size_t sz = gs_string_length(TMP);
- strncat(src, TMP, sz);
- }
- strncat(src, ") in;\n", 7);
- */
- } break;
- default: break;
- }
- // Code
- {
- const size_t sz = gs_string_length(ppd->code[sidx]);
- strncat(src, ppd->code[sidx], sz);
- }
- }
- return src;
- }
- GS_API_DECL gs_gfxt_pipeline_t
- gs_gfxt_pipeline_load_from_file(const char* path)
- {
- // Load file, generate lexer off of file data, parse contents for pipeline information
- size_t len = 0;
- char* file_data = gs_platform_read_file_contents(path, "rb", &len);
- gs_assert(file_data);
- gs_log_success("Parsing pipeline: %s", path);
- gs_gfxt_pipeline_t pip = gs_gfxt_pipeline_load_from_memory_ext(file_data, len, path);
- gs_free(file_data);
- return pip;
- }
- GS_API_DECL gs_gfxt_pipeline_t
- gs_gfxt_pipeline_load_from_memory(const char* file_data, size_t sz)
- {
- return gs_gfxt_pipeline_load_from_memory_ext(file_data, sz, ".");
- }
- GS_API_DECL gs_gfxt_pipeline_t
- gs_gfxt_pipeline_load_from_memory_ext(const char* file_data, size_t sz, const char* file_path)
- {
- // Cast to pip
- gs_gfxt_pipeline_t pip = gs_default_val();
- gs_ppd_t ppd = gs_default_val();
- gs_gfxt_pipeline_desc_t pdesc = gs_default_val();
- pdesc.pip_desc.raster.index_buffer_element_size = sizeof(uint32_t);
- // Determine original file directory from path
- if (file_path)
- {
- gs_lexer_t lex = gs_lexer_c_ctor(file_path);
- gs_token_t tparen = {0};
- while (lex.can_lex(&lex))
- {
- gs_token_t token = lex.next_token(&lex);
- // Look for last paren + identifier combo
- switch (token.type)
- {
- case GS_TOKEN_FSLASH:
- case GS_TOKEN_BSLASH:
- {
- tparen = token;
- } break;
- }
- }
- // Now save dir
- gs_println("HERE: %zu", tparen.text - file_path);
- memcpy(ppd.dir, file_path, tparen.text - file_path);
- gs_println("PPD_DIR: %s", ppd.dir);
- }
- gs_lexer_t lex = gs_lexer_c_ctor(file_data);
- while (lex.can_lex(&lex))
- {
- gs_token_t token = lex.next_token(&lex);
- switch (token.type)
- {
- case GS_TOKEN_IDENTIFIER:
- {
- if (gs_token_compare_text(&token, "pipeline"))
- {
- if (!gs_parse_pipeline(&lex, &pdesc, &ppd))
- {
- gs_log_warning("Unable to parse pipeline");
- return pip;
- }
- }
- } break;
- }
- }
- // Generate vertex shader code
- char* v_src = gs_pipeline_generate_shader_code(&pdesc, &ppd, GS_GRAPHICS_SHADER_STAGE_VERTEX);
- // gs_println("%s", v_src);
- // Generate fragment shader code
- char* f_src = gs_pipeline_generate_shader_code(&pdesc, &ppd, GS_GRAPHICS_SHADER_STAGE_FRAGMENT);
- // gs_println("%s", f_src);
-
- // Generate compute shader code (need to check for this first)
- char* c_src = gs_pipeline_generate_shader_code(&pdesc, &ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE);
- // gs_println("%s", c_src);
- // Construct compute shader
- if (c_src)
- {
- gs_graphics_shader_desc_t sdesc = gs_default_val();
- gs_graphics_shader_source_desc_t source_desc[1] = gs_default_val();
- source_desc[0].type = GS_GRAPHICS_SHADER_STAGE_COMPUTE;
- source_desc[0].source = c_src;
- sdesc.sources = source_desc;
- sdesc.size = 1 * sizeof(gs_graphics_shader_source_desc_t);
- pdesc.pip_desc.compute.shader = gs_graphics_shader_create(&sdesc);
- }
- // Construct raster shader
- else
- {
- gs_graphics_shader_desc_t sdesc = gs_default_val();
- gs_graphics_shader_source_desc_t source_desc[2] = gs_default_val();
- source_desc[0].type = GS_GRAPHICS_SHADER_STAGE_VERTEX;
- source_desc[0].source = v_src;
- source_desc[1].type = GS_GRAPHICS_SHADER_STAGE_FRAGMENT;
- source_desc[1].source = f_src;
- sdesc.sources = source_desc;
- sdesc.size = 2 * sizeof(gs_graphics_shader_source_desc_t);
- pdesc.pip_desc.raster.shader = gs_graphics_shader_create(&sdesc);
- }
- // Set up layout
- pdesc.pip_desc.layout.size = gs_dyn_array_size(pdesc.pip_desc.layout.attrs) * sizeof(gs_graphics_vertex_attribute_desc_t);
- // Set up ublock
- pdesc.ublock_desc.size = gs_dyn_array_size(pdesc.ublock_desc.layout) * sizeof(gs_gfxt_uniform_desc_t);
- // Create pipeline
- pip = gs_gfxt_pipeline_create(&pdesc);
- // Create mesh layout
- if (ppd.mesh_layout)
- {
- for (uint32_t i = 0; i < gs_dyn_array_size(ppd.mesh_layout); ++i)
- {
- gs_dyn_array_push(pip.mesh_layout, ppd.mesh_layout[i]);
- }
- }
- // Free all malloc'd data
- if (v_src) gs_free(v_src);
- if (f_src) gs_free(f_src);
- if (c_src) gs_free(c_src);
- gs_dyn_array_free(pdesc.ublock_desc.layout);
- gs_dyn_array_free(pdesc.pip_desc.layout.attrs);
- gs_dyn_array_free(ppd.mesh_layout);
- gs_dyn_array_free(ppd.vertex_layout);
-
- for (uint32_t i = 0; i < 3; ++i)
- {
- if (ppd.code[i]) gs_free(ppd.code[i]);
- gs_dyn_array_free(ppd.io_list[i]);
- }
- return pip;
- }
- GS_API_DECL gs_gfxt_texture_t
- gs_gfxt_texture_load_from_file(const char* path, gs_graphics_texture_desc_t* desc, bool flip, bool keep_data)
- {
- gs_asset_texture_t tex = gs_default_val();
- gs_asset_texture_load_from_file(path, &tex, desc, flip, keep_data);
- if (desc) {
- *desc = tex.desc;
- }
- return tex.hndl;
- }
- GS_API_DECL gs_gfxt_texture_t gs_gfxt_texture_load_from_memory(const char* data, size_t sz, gs_graphics_texture_desc_t* desc, bool flip, bool keep_data)
- {
- gs_asset_texture_t tex = gs_default_val();
- gs_asset_texture_load_from_memory(data, sz, &tex, desc, flip, keep_data);
- if (desc) {
- *desc = tex.desc;
- }
- return tex.hndl;
- }
- #endif // GS_GFXT_IMPL
- #endif // GS_GFXT_H
- /*
- */
|