gs_gfxt.h 151 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733
  1. /*==============================================================================================================
  2. * Copyright (c) 2020 John Jackson
  3. * gs_gfxt: Graphics Extension Util for Gunslinger
  4. * File: gs_gfxt.h
  5. * Github: https://github.com/MrFrenik/gunslinger
  6. * All Rights Reserved
  7. * MIT License
  8. * May all those that this source may reach be blessed by the LORD and find peace and joy in life.
  9. * Everyone who drinks of this water will be thirsty again; but whoever drinks of the water
  10. * that I will give him shall never thirst; John 4:13-14
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  12. * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
  13. * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
  14. * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  15. * The above copyright, blessing, biblical verse, notice and this permission notice shall be included in all
  16. * copies or substantial portions of the Software.
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  18. * TO THE WARRANTIES OF MECHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  20. * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. * IN THE SOFTWARE.
  22. =================================================================================================================*/
  23. #ifndef GS_GFXT_H
  24. #define GS_GFXT_H
  25. /*
  26. USAGE: (IMPORTANT)
  27. =================================================================================================================
  28. Before including, define the gunslinger graphics extension implementation like this:
  29. #define GS_GFXT_IMPL
  30. in EXACTLY ONE C or C++ file that includes this header, BEFORE the
  31. include, like this:
  32. #define GS_GFXT_IMPL
  33. #include "gs_gfxt.h"
  34. All other files should just #include "gs_gfxt.h" without the #define.
  35. MUST include "gs.h" and declare GS_IMPL BEFORE this file, since this file relies on gunslinger core:
  36. #define GS_IMPL
  37. #include "gs.h"
  38. #define GS_GFXT_IMPL
  39. #include "gs_gfxt.h"
  40. GS_GFXT_HNDL:
  41. Internally, gfxt uses handles to retrieve raw data for shared types, like materials, meshes, pipelines, etc.
  42. This keeps memory consumption low allowing for trivial copying of references and handles without having to copy raw data.
  43. This handle, by default, is defined to a void* for pointers for raw data storage. This can be defined by the user to whatever
  44. handle type he'd like to use, such as a uint32_t handle to a slot array id. Additionally, all description objects that
  45. operate on shared data pass around a function pointer descriptor for how to retrieve that data - all of which can be user defined.
  46. ================================================================================================================
  47. */
  48. /*==== Interface ====*/
  49. /** @defgroup gs_graphics_extension_util Graphics Extension Util
  50. * Gunslinger Graphics Extension Util
  51. * @{
  52. */
  53. //=== Raw data retrieval/Handles ===//
  54. #ifndef GS_GFXT_HNDL
  55. #define GS_GFXT_HNDL void* // Default handle will just be a pointer to the data itself
  56. #endif
  57. // Config
  58. #ifndef GS_GFXT_TEX_COORD_MAX
  59. #define GS_GFXT_TEX_COORD_MAX 4
  60. #endif
  61. #ifndef GS_GFXT_COLOR_MAX
  62. #define GS_GFXT_COLOR_MAX 4
  63. #endif
  64. #ifndef GS_GFXT_JOINT_MAX
  65. #define GS_GFXT_JOINT_MAX 4
  66. #endif
  67. #ifndef GS_GFXT_WEIGHT_MAX
  68. #define GS_GFXT_WEIGHT_MAX 4
  69. #endif
  70. // Custom UINT field
  71. #ifndef GS_GFXT_CUSTOM_UINT_MAX
  72. #define GS_GFXT_CUSTOM_UINT_MAX 4
  73. #endif
  74. #ifndef GS_GFXT_INCLUDE_DIR_MAX
  75. #define GS_GFXT_INCLUDE_DIR_MAX 8
  76. #endif
  77. #ifndef GS_GFXT_UNIFORM_VIEW_MATRIX
  78. #define GS_GFXT_UNIFORM_VIEW_MATRIX "U_VIEW_MTX"
  79. #endif
  80. #ifndef GS_GFXT_UNIFORM_PROJECTION_MATRIX
  81. #define GS_GFXT_UNIFORM_PROJECTION_MATRIX "U_PROJECTION_MTX"
  82. #endif
  83. #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX
  84. #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX "U_VIEW_PROJECTION_MTX"
  85. #endif
  86. #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0
  87. #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0 "U_VIEW_PROJECTION_MTX_0"
  88. #endif
  89. #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1
  90. #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1 "U_VIEW_PROJECTION_MTX_1"
  91. #endif
  92. #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2
  93. #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2 "U_VIEW_PROJECTION_MTX_2"
  94. #endif
  95. #ifndef GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3
  96. #define GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3 "U_VIEW_PROJECTION_MTX_3"
  97. #endif
  98. #ifndef GS_GFXT_UNIFORM_MODEL_MATRIX
  99. #define GS_GFXT_UNIFORM_MODEL_MATRIX "U_MODEL_MTX"
  100. #endif
  101. #ifndef GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX
  102. #define GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX "U_INVERSE_MODEL_MTX"
  103. #endif
  104. #ifndef GS_GFXT_UNIFORM_VIEW_WORLD_POSITION
  105. #define GS_GFXT_UNIFORM_VIEW_WORLD_POSITION "U_VIEW_WORLD_POSITION"
  106. #endif
  107. #ifndef GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX
  108. #define GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX "U_MVP_MTX"
  109. #endif
  110. #ifndef GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0
  111. #define GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0 "U_MVP_MTX_0"
  112. #endif
  113. #ifndef GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1
  114. #define GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1 "U_MVP_MTX_1"
  115. #endif
  116. #ifndef GS_GFXT_UNIFORM_TIME
  117. #define GS_GFXT_UNIFORM_TIME "U_TIME"
  118. #endif
  119. typedef void* (*gs_gfxt_raw_data_func)(GS_GFXT_HNDL hndl, void* user_data);
  120. #define GS_GFXT_RAW_DATA(FUNC_DESC, T)\
  121. ((T*)(FUNC_DESC)->func((FUNC_DESC)->hndl, (FUNC_DESC)->user_data))
  122. typedef struct gs_gfxt_raw_data_func_desc_t {
  123. GS_GFXT_HNDL hndl; // Handle used for retrieving data.
  124. gs_gfxt_raw_data_func func; // User defined function for pipeline data retrieval
  125. void* user_data; // Optional user data for function
  126. } gs_gfxt_raw_data_func_desc_t;
  127. //=== Uniforms/Uniform blocks ===//
  128. typedef struct gs_gfxt_uniform_desc_t {
  129. char name[64]; // Name of uniform (for binding to shader)
  130. gs_graphics_uniform_type type; // Type of uniform: GS_GRAPHICS_UNIFORM_VEC2, GS_GRAPHICS_UNIFORM_VEC3, etc.
  131. uint32_t binding; // Binding for this uniform in shader
  132. gs_graphics_shader_stage_type stage; // Shader stage for this uniform
  133. gs_graphics_access_type access_type; // Access type for this uniform (compute only)
  134. } gs_gfxt_uniform_desc_t;
  135. typedef struct gs_gfxt_uniform_t {
  136. gs_handle(gs_graphics_uniform_t) hndl; // Graphics handle resource for actual uniform
  137. uint32_t offset; // Individual offset for this uniform in material byte buffer data
  138. uint32_t binding; // Binding for this uniform
  139. size_t size; // Size of this uniform data in bytes
  140. gs_graphics_uniform_type type; // Type of this uniform
  141. gs_graphics_access_type access_type; // Access type of uniform (compute only)
  142. } gs_gfxt_uniform_t;
  143. typedef struct gs_gfxt_uniform_block_desc_t {
  144. gs_gfxt_uniform_desc_t* layout; // Layout for all uniform data for this block to hold
  145. size_t size; // Size of layout in bytes
  146. } gs_gfxt_uniform_block_desc_t;
  147. typedef struct gs_gfxt_uniform_block_lookup_key_t {
  148. char name[64];
  149. } gs_gfxt_uniform_block_lookup_key_t;
  150. typedef struct gs_gfxt_uniform_block_t {
  151. gs_dyn_array(gs_gfxt_uniform_t) uniforms; // Raw uniform handle array
  152. gs_hash_table(uint64_t, uint32_t) lookup; // Index lookup table (used for byte buffer offsets in material uni. data)
  153. size_t size; // Total size of material data for entire block
  154. } gs_gfxt_uniform_block_t;
  155. //=== Texture ===//
  156. typedef gs_handle(gs_graphics_texture_t) gs_gfxt_texture_t;
  157. //=== Mesh ===//
  158. typedef gs_asset_mesh_attribute_type gs_gfxt_mesh_attribute_type;
  159. typedef gs_asset_mesh_layout_t gs_gfxt_mesh_layout_t;
  160. /*
  161. typedef struct
  162. {
  163. union
  164. {
  165. void* interleave;
  166. struct
  167. {
  168. void* positions;
  169. void* normals;
  170. void* tangents;
  171. void* tex_coords[TEX_COORD_MAX];
  172. void* joints[JOINT_MAX];
  173. void* weights[WEIGHT_MAX];
  174. } non_interleave;
  175. } vertex;
  176. size_t vertex_size;
  177. void* indices;
  178. } gs_gfxt_mesh_primitive_data_t;
  179. */
  180. typedef struct
  181. {
  182. void* data;
  183. size_t size;
  184. } gs_gfxt_mesh_vertex_attribute_t;
  185. typedef struct
  186. {
  187. gs_gfxt_mesh_vertex_attribute_t positions; // All position data
  188. gs_gfxt_mesh_vertex_attribute_t normals;
  189. gs_gfxt_mesh_vertex_attribute_t tangents;
  190. gs_gfxt_mesh_vertex_attribute_t tex_coords[GS_GFXT_TEX_COORD_MAX];
  191. gs_gfxt_mesh_vertex_attribute_t colors[GS_GFXT_COLOR_MAX];
  192. gs_gfxt_mesh_vertex_attribute_t joints[GS_GFXT_JOINT_MAX];
  193. gs_gfxt_mesh_vertex_attribute_t weights[GS_GFXT_WEIGHT_MAX];
  194. gs_gfxt_mesh_vertex_attribute_t custom_uint[GS_GFXT_CUSTOM_UINT_MAX];
  195. gs_gfxt_mesh_vertex_attribute_t indices;
  196. uint32_t count; // Total count of indices
  197. } gs_gfxt_mesh_vertex_data_t;
  198. // Structured/packed raw mesh data
  199. // TODO(john): Make the primitives array static to avoid heap alloc
  200. typedef struct gs_gfxt_mesh_raw_data_t {
  201. gs_dyn_array(gs_gfxt_mesh_vertex_data_t) primitives; // All primitive data
  202. } gs_gfxt_mesh_raw_data_t;
  203. typedef struct gs_gfxt_mesh_import_options_t {
  204. gs_gfxt_mesh_layout_t* layout; // Mesh attribute layout array
  205. size_t size; // Size of mesh attribute layout array in bytes
  206. size_t index_buffer_element_size; // Size of index data size in bytes
  207. } gs_gfxt_mesh_import_options_t;
  208. GS_API_DECL void gs_gfxt_mesh_import_options_free(gs_gfxt_mesh_import_options_t* opt);
  209. typedef struct gs_gfxt_mesh_desc_s {
  210. gs_gfxt_mesh_raw_data_t* meshes; // Mesh data array
  211. size_t size; // Size of mesh data array in bytes
  212. bool32 keep_data; // Whether or not to free data after use
  213. } gs_gfxt_mesh_desc_t;
  214. typedef struct gs_gfxt_vertex_stream_s
  215. {
  216. gs_handle(gs_graphics_vertex_buffer_t) positions;
  217. gs_handle(gs_graphics_vertex_buffer_t) normals;
  218. gs_handle(gs_graphics_vertex_buffer_t) tangents;
  219. gs_handle(gs_graphics_vertex_buffer_t) colors[GS_GFXT_COLOR_MAX];
  220. gs_handle(gs_graphics_vertex_buffer_t) tex_coords[GS_GFXT_TEX_COORD_MAX];
  221. gs_handle(gs_graphics_vertex_buffer_t) joints[GS_GFXT_JOINT_MAX];
  222. gs_handle(gs_graphics_vertex_buffer_t) weights[GS_GFXT_WEIGHT_MAX];
  223. gs_handle(gs_graphics_vertex_buffer_t) custom_uint[GS_GFXT_CUSTOM_UINT_MAX];
  224. } gs_gfxt_vertex_stream_t;
  225. typedef struct gs_gfxt_mesh_primitive_s {
  226. gs_gfxt_vertex_stream_t stream; // All vertex data streams
  227. gs_handle(gs_graphics_index_buffer_t) indices; // Index buffer
  228. uint32_t count; // Total number of vertices
  229. } gs_gfxt_mesh_primitive_t;
  230. typedef struct gs_gfxt_mesh_s {
  231. gs_dyn_array(gs_gfxt_mesh_primitive_t) primitives;
  232. gs_gfxt_mesh_desc_t desc;
  233. } gs_gfxt_mesh_t;
  234. //=== Pipeline ===//
  235. typedef struct gs_gfxt_pipeline_desc_s {
  236. gs_graphics_pipeline_desc_t pip_desc; // Description for constructing pipeline object
  237. gs_gfxt_uniform_block_desc_t ublock_desc; // Description for constructing uniform block object
  238. } gs_gfxt_pipeline_desc_t;
  239. typedef struct gs_gfxt_pipeline_s {
  240. gs_handle(gs_graphics_pipeline_t) hndl; // Graphics handle resource for actual pipeline
  241. gs_gfxt_uniform_block_t ublock; // Uniform block for holding all uniform data
  242. gs_dyn_array(gs_gfxt_mesh_layout_t) mesh_layout;
  243. gs_graphics_pipeline_desc_t desc;
  244. } gs_gfxt_pipeline_t;
  245. //=== Material ===//
  246. typedef struct gs_gfxt_material_desc_s {
  247. gs_gfxt_raw_data_func_desc_t pip_func; // Description for retrieving raw pipeline pointer data from handle.
  248. } gs_gfxt_material_desc_t;
  249. typedef struct gs_gfxt_material_s {
  250. gs_gfxt_material_desc_t desc; // Material description object
  251. gs_byte_buffer_t uniform_data; // Byte buffer of actual uniform data to send to GPU
  252. gs_byte_buffer_t image_buffer_data; // Image buffer data
  253. } gs_gfxt_material_t;
  254. //=== Renderable ===//
  255. typedef struct gs_gfxt_renderable_desc_s {
  256. gs_gfxt_raw_data_func_desc_t mesh; // Description for retrieving raw mesh pointer data from handle.
  257. gs_gfxt_raw_data_func_desc_t material; // Description for retrieving raw material pointer data from handle.
  258. } gs_gfxt_renderable_desc_t;
  259. typedef struct gs_gfxt_renderable_s {
  260. gs_gfxt_renderable_desc_t desc; // Renderable description object
  261. gs_mat4 model_matrix; // Model matrix for renderable
  262. } gs_gfxt_renderable_t;
  263. //=== Graphics scene ===//
  264. typedef struct gs_gfxt_scene_s {
  265. gs_slot_array(gs_gfxt_renderable_t) renderables;
  266. } gs_gfxt_scene_t;
  267. //==== API =====//
  268. //=== Creation ===//
  269. GS_API_DECL gs_gfxt_pipeline_t gs_gfxt_pipeline_create(const gs_gfxt_pipeline_desc_t* desc);
  270. GS_API_DECL gs_gfxt_material_t gs_gfxt_material_create(gs_gfxt_material_desc_t* desc);
  271. GS_API_DECL gs_gfxt_mesh_t gs_gfxt_mesh_create(const gs_gfxt_mesh_desc_t* desc);
  272. GS_API_DECL void gs_gfxt_mesh_update_or_create(gs_gfxt_mesh_t* mesh, const gs_gfxt_mesh_desc_t* desc);
  273. GS_API_DECL gs_gfxt_renderable_t gs_gfxt_renderable_create(const gs_gfxt_renderable_desc_t* desc);
  274. GS_API_DECL gs_gfxt_uniform_block_t gs_gfxt_uniform_block_create(const gs_gfxt_uniform_block_desc_t* desc);
  275. GS_API_DECL gs_gfxt_texture_t gs_gfxt_texture_create(gs_graphics_texture_desc_t* desc);
  276. //=== Destruction ===//
  277. GS_API_DECL void gs_gfxt_texture_destroy(gs_gfxt_texture_t* texture);
  278. GS_API_DECL void gs_gfxt_material_destroy(gs_gfxt_material_t* material);
  279. GS_API_DECL void gs_gfxt_mesh_destroy(gs_gfxt_mesh_t* mesh);
  280. GS_API_DECL void gs_gfxt_uniform_block_destroy(gs_gfxt_uniform_block_t* ub);
  281. GS_API_DECL void gs_gfxt_pipeline_destroy(gs_gfxt_pipeline_t* pipeline);
  282. //=== Resource Loading ===//
  283. GS_API_DECL gs_gfxt_pipeline_t gs_gfxt_pipeline_load_from_file(const char* path);
  284. GS_API_DECL gs_gfxt_pipeline_t gs_gfxt_pipeline_load_from_memory(const char* data, size_t sz);
  285. GS_API_DECL gs_gfxt_pipeline_t gs_gfxt_pipeline_load_from_memory_ext(const char* data, size_t sz, const char* file_dir);
  286. 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);
  287. 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);
  288. //=== Copy ===//
  289. GS_API_DECL gs_gfxt_material_t gs_gfxt_material_deep_copy(gs_gfxt_material_t* src);
  290. //=== Pipeline API ===//
  291. GS_API_DECL gs_gfxt_uniform_t* gs_gfxt_pipeline_get_uniform(gs_gfxt_pipeline_t* pip, const char* name);
  292. //=== Material API ===//
  293. GS_API_DECL void gs_gfxt_material_set_uniform(gs_gfxt_material_t* mat, const char* name, const void* data);
  294. GS_API_DECL void gs_gfxt_material_bind(gs_command_buffer_t* cb, gs_gfxt_material_t* mat);
  295. GS_API_DECL void gs_gfxt_material_bind_pipeline(gs_command_buffer_t* cb, gs_gfxt_material_t* mat);
  296. GS_API_DECL void gs_gfxt_material_bind_uniforms(gs_command_buffer_t* cb, gs_gfxt_material_t* mat);
  297. GS_API_DECL gs_gfxt_pipeline_t* gs_gfxt_material_get_pipeline(gs_gfxt_material_t* mat);
  298. //=== Mesh API ===//
  299. GS_API_DECL void gs_gfxt_mesh_draw_pipeline(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_pipeline_t* pip);
  300. GS_API_DECL void gs_gfxt_mesh_draw_material(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_material_t* mat);
  301. 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);
  302. 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);
  303. GS_API_DECL gs_gfxt_mesh_t gs_gfxt_mesh_load_from_file(const char* file, gs_gfxt_mesh_import_options_t* options);
  304. 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);
  305. // Util API
  306. GS_API_DECL void* gs_gfxt_raw_data_default_impl(GS_GFXT_HNDL hndl, void* user_data);
  307. // Mesh Generation API
  308. GS_API_DECL gs_gfxt_mesh_t gs_gfxt_mesh_unit_quad_generate(gs_gfxt_mesh_import_options_t* options);
  309. gs_handle(gs_graphics_texture_t) gs_gfxt_texture_generate_default();
  310. /** @} */ // end of gs_graphics_extension_util
  311. #ifdef GS_GFXT_IMPL
  312. /*==== Implementation ====*/
  313. // Creation/Destruction
  314. GS_API_DECL gs_gfxt_pipeline_t
  315. gs_gfxt_pipeline_create(const gs_gfxt_pipeline_desc_t* desc)
  316. {
  317. gs_gfxt_pipeline_t pip = gs_default_val();
  318. if (!desc) {
  319. gs_assert(false);
  320. return pip;
  321. }
  322. pip.hndl = gs_graphics_pipeline_create(&desc->pip_desc);
  323. pip.ublock = gs_gfxt_uniform_block_create(&desc->ublock_desc);
  324. pip.desc = desc->pip_desc;
  325. pip.desc.layout.attrs = gs_malloc(desc->pip_desc.layout.size);
  326. memcpy(pip.desc.layout.attrs, desc->pip_desc.layout.attrs, desc->pip_desc.layout.size);
  327. return pip;
  328. }
  329. GS_API_DECL gs_gfxt_uniform_block_t
  330. gs_gfxt_uniform_block_create(const gs_gfxt_uniform_block_desc_t* desc)
  331. {
  332. gs_gfxt_uniform_block_t block = gs_default_val();
  333. if (!desc) return block;
  334. // Iterate through layout, construct uniforms, place them into hash table
  335. uint32_t offset = 0;
  336. uint32_t image2D_offset = 0;
  337. uint32_t ct = desc->size / sizeof(gs_gfxt_uniform_desc_t);
  338. for (uint32_t i = 0; i < ct; ++i)
  339. {
  340. gs_gfxt_uniform_desc_t* ud = &desc->layout[i];
  341. gs_gfxt_uniform_t u = gs_default_val();
  342. gs_graphics_uniform_desc_t u_desc = gs_default_val();
  343. gs_graphics_uniform_layout_desc_t u_layout = gs_default_val();
  344. u_layout.type = ud->type;
  345. memcpy(u_desc.name, ud->name, 64);
  346. u_desc.layout = &u_layout;
  347. u.binding = ud->binding;
  348. u.type = ud->type;
  349. // Determine offset/hndl
  350. switch (ud->type)
  351. {
  352. case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
  353. {
  354. u.offset = image2D_offset;
  355. } break;
  356. default:
  357. {
  358. u.hndl = gs_graphics_uniform_create(&u_desc);
  359. u.offset = offset;
  360. } break;
  361. }
  362. // Add to data offset based on type
  363. switch (ud->type) {
  364. default:
  365. case GS_GRAPHICS_UNIFORM_FLOAT: offset += sizeof(float); break;
  366. case GS_GRAPHICS_UNIFORM_INT: offset += sizeof(int32_t); break;
  367. case GS_GRAPHICS_UNIFORM_VEC2: offset += sizeof(gs_vec2); break;
  368. case GS_GRAPHICS_UNIFORM_VEC3: offset += sizeof(gs_vec3); break;
  369. case GS_GRAPHICS_UNIFORM_VEC4: offset += sizeof(gs_vec4); break;
  370. case GS_GRAPHICS_UNIFORM_MAT4: offset += sizeof(gs_mat4); break;
  371. case GS_GRAPHICS_UNIFORM_SAMPLER2D: offset += sizeof(gs_handle(gs_graphics_texture_t)); break;
  372. case GS_GRAPHICS_UNIFORM_USAMPLER2D: offset += sizeof(gs_handle(gs_graphics_texture_t)); break;
  373. case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
  374. {
  375. image2D_offset += sizeof(gs_handle(gs_graphics_texture_t));
  376. } break;
  377. }
  378. // Add uniform to block with name as key
  379. uint64_t key = gs_hash_str64(ud->name);
  380. gs_dyn_array_push(block.uniforms, u);
  381. gs_hash_table_insert(block.lookup, key, gs_dyn_array_size(block.uniforms) - 1);
  382. }
  383. block.size = offset;
  384. return block;
  385. }
  386. GS_API_DECL gs_gfxt_texture_t
  387. gs_gfxt_texture_create(gs_graphics_texture_desc_t* desc)
  388. {
  389. return gs_graphics_texture_create(desc);
  390. }
  391. GS_API_DECL gs_gfxt_material_t
  392. gs_gfxt_material_create(gs_gfxt_material_desc_t* desc)
  393. {
  394. gs_gfxt_material_t mat = gs_default_val();
  395. if (!desc) {
  396. gs_assert(false);
  397. return mat;
  398. }
  399. // Set desc information to defaults if not provided.
  400. if (!desc->pip_func.func) desc->pip_func.func = gs_gfxt_raw_data_default_impl;
  401. gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&desc->pip_func, gs_gfxt_pipeline_t);
  402. gs_assert(pip);
  403. mat.desc = *desc;
  404. mat.uniform_data = gs_byte_buffer_new();
  405. mat.image_buffer_data = gs_byte_buffer_new();
  406. gs_byte_buffer_resize(&mat.uniform_data, pip->ublock.size);
  407. gs_byte_buffer_memset(&mat.uniform_data, 0);
  408. return mat;
  409. }
  410. GS_API_DECL gs_gfxt_mesh_t
  411. gs_gfxt_mesh_create(const gs_gfxt_mesh_desc_t* desc)
  412. {
  413. gs_gfxt_mesh_t mesh = gs_default_val();
  414. if (!desc) {
  415. return mesh;
  416. }
  417. const uint32_t mesh_count = desc->size / sizeof(gs_gfxt_mesh_raw_data_t);
  418. // Process all mesh data, add meshes
  419. for (uint32_t i = 0; i < mesh_count; ++i)
  420. {
  421. gs_gfxt_mesh_raw_data_t* m = &desc->meshes[i];
  422. for (uint32_t p = 0; p < gs_dyn_array_size(m->primitives); ++p)
  423. {
  424. // Get raw vertex data
  425. gs_gfxt_mesh_vertex_data_t* vdata = &m->primitives[p];
  426. // Construct primitive
  427. gs_gfxt_mesh_primitive_t prim = gs_default_val();
  428. prim.count = vdata->count;
  429. // Positions
  430. if (vdata->positions.data)
  431. {
  432. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  433. vdesc.data = vdata->positions.data;
  434. vdesc.size = vdata->positions.size;
  435. prim.stream.positions = gs_graphics_vertex_buffer_create(&vdesc);
  436. if (!desc->keep_data)
  437. {
  438. gs_free(vdata->positions.data);
  439. }
  440. }
  441. // Normals
  442. if (vdata->normals.data)
  443. {
  444. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  445. vdesc.data = vdata->normals.data;
  446. vdesc.size = vdata->normals.size;
  447. prim.stream.normals = gs_graphics_vertex_buffer_create(&vdesc);
  448. if (!desc->keep_data)
  449. {
  450. gs_free(vdata->normals.data);
  451. }
  452. }
  453. // Tangents
  454. if (vdata->tangents.data)
  455. {
  456. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  457. vdesc.data = vdata->tangents.data;
  458. vdesc.size = vdata->tangents.size;
  459. prim.stream.tangents = gs_graphics_vertex_buffer_create(&vdesc);
  460. if (!desc->keep_data)
  461. {
  462. gs_free(vdata->tangents.data);
  463. }
  464. }
  465. // Texcoords
  466. for (uint32_t j = 0; j < GS_GFXT_TEX_COORD_MAX; ++j)
  467. {
  468. if (vdata->tex_coords[j].data)
  469. {
  470. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  471. vdesc.data = vdata->tex_coords[j].data;
  472. vdesc.size = vdata->tex_coords[j].size;
  473. prim.stream.tex_coords[j] = gs_graphics_vertex_buffer_create(&vdesc);
  474. if (!desc->keep_data)
  475. {
  476. gs_free(vdata->tex_coords[j].data);
  477. }
  478. }
  479. }
  480. // Colors
  481. for (uint32_t j = 0; j < GS_GFXT_COLOR_MAX; ++j)
  482. {
  483. if (vdata->colors[j].data)
  484. {
  485. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  486. vdesc.data = vdata->colors[j].data;
  487. vdesc.size = vdata->colors[j].size;
  488. prim.stream.colors[j] = gs_graphics_vertex_buffer_create(&vdesc);
  489. if (!desc->keep_data)
  490. {
  491. gs_free(vdata->colors[j].data);
  492. }
  493. }
  494. }
  495. // Joints
  496. for (uint32_t j = 0; j < GS_GFXT_JOINT_MAX; ++j)
  497. {
  498. if (vdata->joints[j].data)
  499. {
  500. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  501. vdesc.data = vdata->joints[j].data;
  502. vdesc.size = vdata->joints[j].size;
  503. prim.stream.joints[j] = gs_graphics_vertex_buffer_create(&vdesc);
  504. if (!desc->keep_data)
  505. {
  506. gs_free(vdata->joints[j].data);
  507. }
  508. }
  509. }
  510. // Weights
  511. for (uint32_t j = 0; j < GS_GFXT_WEIGHT_MAX; ++j)
  512. {
  513. if (vdata->weights[j].data)
  514. {
  515. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  516. vdesc.data = vdata->weights[j].data;
  517. vdesc.size = vdata->weights[j].size;
  518. prim.stream.weights[j] = gs_graphics_vertex_buffer_create(&vdesc);
  519. if (!desc->keep_data)
  520. {
  521. gs_free(vdata->weights[j].data);
  522. }
  523. }
  524. }
  525. // Index buffer decl
  526. gs_graphics_index_buffer_desc_t idesc = gs_default_val();
  527. idesc.data = vdata->indices.data;
  528. idesc.size = vdata->indices.size;
  529. // Construct index buffer for primitive
  530. prim.indices = gs_graphics_index_buffer_create(&idesc);
  531. if (!desc->keep_data)
  532. {
  533. gs_free(vdata->indices.data);
  534. }
  535. // Add primitive to mesh
  536. gs_dyn_array_push(mesh.primitives, prim);
  537. }
  538. if (!desc->keep_data)
  539. {
  540. gs_dyn_array_free(m->primitives);
  541. }
  542. }
  543. if (!desc->keep_data)
  544. {
  545. gs_free(desc->meshes);
  546. }
  547. return mesh;
  548. }
  549. GS_API_DECL void
  550. gs_gfxt_mesh_update_or_create(gs_gfxt_mesh_t* mesh, const gs_gfxt_mesh_desc_t* desc)
  551. {
  552. if (!desc || !mesh) {
  553. return;
  554. }
  555. /*
  556. // Need to create mesh if not already done
  557. if (gs_dyn_array_empty(mesh->primitives)) {
  558. *mesh = gs_gfxt_mesh_create(desc);
  559. return;
  560. }
  561. */
  562. const uint32_t mesh_count = desc->size / sizeof(gs_gfxt_mesh_raw_data_t);
  563. // Process all mesh data, add meshes
  564. for (uint32_t i = 0; i < mesh_count; ++i)
  565. {
  566. gs_gfxt_mesh_raw_data_t* m = &desc->meshes[i];
  567. for (uint32_t p = 0; p < gs_dyn_array_size(m->primitives); ++p)
  568. {
  569. // Get raw vertex data
  570. gs_gfxt_mesh_vertex_data_t* vdata = &m->primitives[p];
  571. // Construct or retrieve mesh primitive
  572. gs_gfxt_mesh_primitive_t* prim = NULL;
  573. if (gs_dyn_array_empty(mesh->primitives) || gs_dyn_array_size(mesh->primitives) < p)
  574. {
  575. gs_gfxt_mesh_primitive_t dprim = gs_default_val();
  576. gs_dyn_array_push(mesh->primitives, dprim);
  577. }
  578. prim = &mesh->primitives[p];
  579. // Set prim count
  580. prim->count = vdata->count;
  581. // Positions
  582. if (vdata->positions.data)
  583. {
  584. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  585. vdesc.data = vdata->positions.data;
  586. vdesc.size = vdata->positions.size;
  587. // Update
  588. if (prim->stream.positions.id)
  589. {
  590. gs_graphics_vertex_buffer_update(prim->stream.positions, &vdesc);
  591. }
  592. // Create
  593. else
  594. {
  595. prim->stream.positions = gs_graphics_vertex_buffer_create(&vdesc);
  596. }
  597. if (!desc->keep_data)
  598. {
  599. gs_free(vdata->positions.data);
  600. }
  601. }
  602. // Normals
  603. if (vdata->normals.data)
  604. {
  605. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  606. vdesc.data = vdata->normals.data;
  607. vdesc.size = vdata->normals.size;
  608. // Update
  609. if (prim->stream.normals.id)
  610. {
  611. gs_graphics_vertex_buffer_update(prim->stream.normals, &vdesc);
  612. }
  613. else
  614. {
  615. prim->stream.normals = gs_graphics_vertex_buffer_create(&vdesc);
  616. }
  617. if (!desc->keep_data)
  618. {
  619. gs_free(vdata->normals.data);
  620. }
  621. }
  622. // Tangents
  623. if (vdata->tangents.data)
  624. {
  625. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  626. vdesc.data = vdata->tangents.data;
  627. vdesc.size = vdata->tangents.size;
  628. if (prim->stream.tangents.id)
  629. {
  630. gs_graphics_vertex_buffer_update(prim->stream.tangents, &vdesc);
  631. }
  632. else
  633. {
  634. prim->stream.tangents = gs_graphics_vertex_buffer_create(&vdesc);
  635. }
  636. if (!desc->keep_data)
  637. {
  638. gs_free(vdata->tangents.data);
  639. }
  640. }
  641. // Texcoords
  642. for (uint32_t j = 0; j < GS_GFXT_TEX_COORD_MAX; ++j)
  643. {
  644. if (vdata->tex_coords[j].data)
  645. {
  646. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  647. vdesc.data = vdata->tex_coords[j].data;
  648. vdesc.size = vdata->tex_coords[j].size;
  649. if (prim->stream.tex_coords[j].id)
  650. {
  651. gs_graphics_vertex_buffer_update(prim->stream.tex_coords[j], &vdesc);
  652. }
  653. else
  654. {
  655. prim->stream.tex_coords[j] = gs_graphics_vertex_buffer_create(&vdesc);
  656. }
  657. if (!desc->keep_data)
  658. {
  659. gs_free(vdata->tex_coords[j].data);
  660. }
  661. }
  662. }
  663. // Colors
  664. for (uint32_t j = 0; j < GS_GFXT_COLOR_MAX; ++j)
  665. {
  666. if (vdata->colors[j].data)
  667. {
  668. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  669. vdesc.data = vdata->colors[j].data;
  670. vdesc.size = vdata->colors[j].size;
  671. if (prim->stream.colors[j].id)
  672. {
  673. gs_graphics_vertex_buffer_update(prim->stream.colors[j], &vdesc);
  674. }
  675. else
  676. {
  677. prim->stream.colors[j] = gs_graphics_vertex_buffer_create(&vdesc);
  678. }
  679. if (!desc->keep_data)
  680. {
  681. gs_free(vdata->colors[j].data);
  682. }
  683. }
  684. }
  685. // Joints
  686. for (uint32_t j = 0; j < GS_GFXT_JOINT_MAX; ++j)
  687. {
  688. if (vdata->joints[j].data)
  689. {
  690. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  691. vdesc.data = vdata->joints[j].data;
  692. vdesc.size = vdata->joints[j].size;
  693. if (prim->stream.joints[j].id)
  694. {
  695. gs_graphics_vertex_buffer_update(prim->stream.joints[j], &vdesc);
  696. }
  697. else
  698. {
  699. prim->stream.joints[j] = gs_graphics_vertex_buffer_create(&vdesc);
  700. }
  701. if (!desc->keep_data)
  702. {
  703. gs_free(vdata->joints[j].data);
  704. }
  705. }
  706. }
  707. // Weights
  708. for (uint32_t j = 0; j < GS_GFXT_WEIGHT_MAX; ++j)
  709. {
  710. if (vdata->weights[j].data)
  711. {
  712. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  713. vdesc.data = vdata->weights[j].data;
  714. vdesc.size = vdata->weights[j].size;
  715. if (prim->stream.weights[j].id)
  716. {
  717. gs_graphics_vertex_buffer_update(prim->stream.weights[j], &vdesc);
  718. }
  719. else
  720. {
  721. prim->stream.weights[j] = gs_graphics_vertex_buffer_create(&vdesc);
  722. }
  723. if (!desc->keep_data)
  724. {
  725. gs_free(vdata->weights[j].data);
  726. }
  727. }
  728. }
  729. // Custom uint
  730. for (uint32_t j = 0; j < GS_GFXT_CUSTOM_UINT_MAX; ++j)
  731. {
  732. if (vdata->custom_uint[j].data)
  733. {
  734. gs_graphics_vertex_buffer_desc_t vdesc = gs_default_val();
  735. vdesc.data = vdata->custom_uint[j].data;
  736. vdesc.size = vdata->custom_uint[j].size;
  737. if (prim->stream.custom_uint[j].id)
  738. {
  739. gs_graphics_vertex_buffer_update(prim->stream.custom_uint[j], &vdesc);
  740. }
  741. else
  742. {
  743. prim->stream.custom_uint[j] = gs_graphics_vertex_buffer_create(&vdesc);
  744. }
  745. if (!desc->keep_data)
  746. {
  747. gs_free(vdata->custom_uint[j].data);
  748. }
  749. }
  750. }
  751. // Index buffer decl
  752. gs_graphics_index_buffer_desc_t idesc = gs_default_val();
  753. idesc.data = vdata->indices.data;
  754. idesc.size = vdata->indices.size;
  755. // Construct index buffer for primitive
  756. if (prim->indices.id)
  757. {
  758. gs_graphics_index_buffer_update(prim->indices, &idesc);
  759. }
  760. else
  761. {
  762. prim->indices = gs_graphics_index_buffer_create(&idesc);
  763. }
  764. if (!desc->keep_data)
  765. {
  766. gs_free(vdata->indices.data);
  767. }
  768. }
  769. if (!desc->keep_data)
  770. {
  771. gs_dyn_array_free(m->primitives);
  772. }
  773. }
  774. if (!desc->keep_data)
  775. {
  776. gs_free(desc->meshes);
  777. }
  778. }
  779. GS_API_DECL gs_gfxt_renderable_t
  780. gs_gfxt_renderable_create(const gs_gfxt_renderable_desc_t* desc)
  781. {
  782. gs_gfxt_renderable_t rend = gs_default_val();
  783. if (!desc) {
  784. return rend;
  785. }
  786. rend.model_matrix = gs_mat4_identity();
  787. rend.desc = *desc;
  788. return rend;
  789. }
  790. //=== Destruction ===//
  791. GS_API_DECL void
  792. gs_gfxt_texture_destroy(gs_gfxt_texture_t* texture)
  793. {
  794. gs_graphics_texture_destroy(*texture);
  795. }
  796. GS_API_DECL void
  797. gs_gfxt_material_destroy(gs_gfxt_material_t* material)
  798. {
  799. // Destroy all material data
  800. gs_byte_buffer_free(&material->uniform_data);
  801. gs_byte_buffer_free(&material->image_buffer_data);
  802. }
  803. GS_API_DECL void
  804. gs_gfxt_mesh_destroy(gs_gfxt_mesh_t* mesh)
  805. {
  806. // Iterate through all primitives, destroy all vertex and index buffers
  807. for (uint32_t p = 0; p < gs_dyn_array_size(mesh->primitives); ++p)
  808. {
  809. gs_gfxt_mesh_primitive_t* prim = &mesh->primitives[p];
  810. // Free index buffer
  811. if (prim->indices.id) gs_graphics_index_buffer_destroy(prim->indices);
  812. // Free vertex stream
  813. if (prim->stream.positions.id) gs_graphics_vertex_buffer_destroy(prim->stream.positions);
  814. if (prim->stream.normals.id) gs_graphics_vertex_buffer_destroy(prim->stream.normals);
  815. if (prim->stream.tangents.id) gs_graphics_vertex_buffer_destroy(prim->stream.tangents);
  816. for (uint32_t i = 0; i < GS_GFXT_COLOR_MAX; ++i)
  817. {
  818. if (prim->stream.colors[i].id) gs_graphics_vertex_buffer_destroy(prim->stream.colors[i]);
  819. }
  820. for (uint32_t i = 0; i < GS_GFXT_TEX_COORD_MAX; ++i)
  821. {
  822. if (prim->stream.tex_coords[i].id) gs_graphics_vertex_buffer_destroy(prim->stream.tex_coords[i]);
  823. }
  824. for (uint32_t i = 0; i < GS_GFXT_JOINT_MAX; ++i)
  825. {
  826. if (prim->stream.joints[i].id) gs_graphics_vertex_buffer_destroy(prim->stream.joints[i]);
  827. }
  828. for ( uint32_t i = 0; i < GS_GFXT_WEIGHT_MAX; ++i )
  829. {
  830. if (prim->stream.weights[i].id) gs_graphics_vertex_buffer_destroy(prim->stream.weights[i]);
  831. }
  832. }
  833. }
  834. GS_API_DECL void
  835. gs_gfxt_uniform_block_destroy(gs_gfxt_uniform_block_t* ub)
  836. {
  837. for (uint32_t i = 0; i < gs_dyn_array_size(ub->uniforms); ++i)
  838. {
  839. gs_gfxt_uniform_t* u = &ub->uniforms[i];
  840. gs_graphics_uniform_destroy(u->hndl);
  841. }
  842. gs_dyn_array_free(ub->uniforms);
  843. gs_hash_table_free(ub->lookup);
  844. }
  845. GS_API_DECL void
  846. gs_gfxt_pipeline_destroy(gs_gfxt_pipeline_t* pipeline)
  847. {
  848. // Destroy uniform block for pipeline
  849. gs_gfxt_uniform_block_destroy(&pipeline->ublock);
  850. // Free shaders (if responsible for them)
  851. gs_graphics_shader_destroy(pipeline->desc.raster.shader);
  852. // Destroy pipeline
  853. if (pipeline->desc.layout.attrs) gs_free(pipeline->desc.layout.attrs);
  854. if (pipeline->mesh_layout) gs_dyn_array_free(pipeline->mesh_layout);
  855. gs_graphics_pipeline_destroy(pipeline->hndl);
  856. }
  857. //=== Copy API ===//
  858. GS_API_DECL gs_gfxt_material_t gs_gfxt_material_deep_copy(gs_gfxt_material_t* src)
  859. {
  860. gs_gfxt_material_t mat = gs_gfxt_material_create(&src->desc);
  861. gs_byte_buffer_copy_contents(&mat.uniform_data, &src->uniform_data);
  862. return mat;
  863. }
  864. //=== Pipeline API ===//
  865. GS_API_DECL gs_gfxt_uniform_t*
  866. gs_gfxt_pipeline_get_uniform(gs_gfxt_pipeline_t* pip, const char* name)
  867. {
  868. uint64_t key = gs_hash_str64(name);
  869. if (!gs_hash_table_exists(pip->ublock.lookup, key)) {
  870. return NULL;
  871. }
  872. // Based on name, need to get uniform
  873. uint32_t uidx = gs_hash_table_get(pip->ublock.lookup, key);
  874. return &pip->ublock.uniforms[uidx];
  875. }
  876. //=== Material API ===//
  877. GS_API_DECL
  878. void gs_gfxt_material_set_uniform(gs_gfxt_material_t* mat, const char* name, const void* data)
  879. {
  880. if (!mat || !name || !data) return;
  881. gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&mat->desc.pip_func, gs_gfxt_pipeline_t);
  882. gs_assert(pip);
  883. // Get key for name lookup
  884. uint64_t key = gs_hash_str64(name);
  885. if (!gs_hash_table_exists(pip->ublock.lookup, key)) {
  886. gs_timed_action(60, {
  887. gs_log_warning("Unable to find uniform: %s", name);
  888. });
  889. return;
  890. }
  891. // Based on name, need to get uniform
  892. uint32_t uidx = gs_hash_table_get(pip->ublock.lookup, key);
  893. gs_gfxt_uniform_t* u = &pip->ublock.uniforms[uidx];
  894. // Seek to beginning of data
  895. gs_byte_buffer_seek_to_beg(&mat->uniform_data);
  896. gs_byte_buffer_seek_to_beg(&mat->image_buffer_data);
  897. // Advance by offset
  898. switch (u->type)
  899. {
  900. case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F: gs_byte_buffer_advance_position(&mat->image_buffer_data, u->offset); break;
  901. default: gs_byte_buffer_advance_position(&mat->uniform_data, u->offset); break;
  902. }
  903. switch (u->type)
  904. {
  905. case GS_GRAPHICS_UNIFORM_FLOAT: gs_byte_buffer_write(&mat->uniform_data, float, *(float*)data); break;
  906. case GS_GRAPHICS_UNIFORM_INT: gs_byte_buffer_write(&mat->uniform_data, int32_t, *(int32_t*)data); break;
  907. case GS_GRAPHICS_UNIFORM_VEC2: gs_byte_buffer_write(&mat->uniform_data, gs_vec2, *(gs_vec2*)data); break;
  908. case GS_GRAPHICS_UNIFORM_VEC3: gs_byte_buffer_write(&mat->uniform_data, gs_vec3, *(gs_vec3*)data); break;
  909. case GS_GRAPHICS_UNIFORM_VEC4: gs_byte_buffer_write(&mat->uniform_data, gs_vec4, *(gs_vec4*)data); break;
  910. case GS_GRAPHICS_UNIFORM_MAT4: gs_byte_buffer_write(&mat->uniform_data, gs_mat4, *(gs_mat4*)data); break;
  911. case GS_GRAPHICS_UNIFORM_SAMPLERCUBE:
  912. case GS_GRAPHICS_UNIFORM_SAMPLER2D:
  913. case GS_GRAPHICS_UNIFORM_USAMPLER2D:
  914. {
  915. gs_byte_buffer_write(&mat->uniform_data, gs_handle(gs_graphics_texture_t), *(gs_handle(gs_graphics_texture_t)*)data);
  916. } break;
  917. case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F: {
  918. gs_byte_buffer_write(&mat->image_buffer_data, gs_handle(gs_graphics_texture_t), *(gs_handle(gs_graphics_texture_t)*)data);
  919. } break;
  920. }
  921. }
  922. GS_API_DECL gs_gfxt_pipeline_t* gs_gfxt_material_get_pipeline(gs_gfxt_material_t* mat)
  923. {
  924. gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&mat->desc.pip_func, gs_gfxt_pipeline_t);
  925. return pip;
  926. }
  927. GS_API_DECL
  928. void gs_gfxt_material_bind(gs_command_buffer_t* cb, gs_gfxt_material_t* mat)
  929. {
  930. gs_gfxt_material_bind_pipeline(cb, mat);
  931. gs_gfxt_material_bind_uniforms(cb, mat);
  932. }
  933. GS_API_DECL
  934. void gs_gfxt_material_bind_pipeline(gs_command_buffer_t* cb, gs_gfxt_material_t* mat)
  935. {
  936. // Binds the pipeline
  937. gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&mat->desc.pip_func, gs_gfxt_pipeline_t);
  938. gs_assert(pip);
  939. gs_graphics_pipeline_bind(cb, pip->hndl);
  940. }
  941. GS_API_DECL
  942. void gs_gfxt_material_bind_uniforms(gs_command_buffer_t* cb, gs_gfxt_material_t* mat)
  943. {
  944. if (!mat) return;
  945. gs_gfxt_pipeline_t* pip = GS_GFXT_RAW_DATA(&mat->desc.pip_func, gs_gfxt_pipeline_t);
  946. gs_assert(pip);
  947. // Grab uniform layout from pipeline
  948. for (uint32_t i = 0; i < gs_dyn_array_size(pip->ublock.uniforms); ++i)
  949. {
  950. gs_gfxt_uniform_t* u = &pip->ublock.uniforms[i];
  951. gs_graphics_bind_desc_t bind = gs_default_val();
  952. // Need to buffer these up so it's a single call...
  953. switch (u->type)
  954. {
  955. case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
  956. {
  957. gs_graphics_bind_image_buffer_desc_t ibuffer[1];
  958. ibuffer[0].tex = *(gs_handle(gs_graphics_texture_t)*)(mat->image_buffer_data.data + u->offset);
  959. ibuffer[0].binding = u->binding;
  960. ibuffer[0].access = GS_GRAPHICS_ACCESS_WRITE_ONLY;
  961. bind.image_buffers.desc = ibuffer;
  962. bind.image_buffers.size = sizeof(ibuffer);
  963. gs_graphics_apply_bindings(cb, &bind);
  964. } break;
  965. default:
  966. {
  967. gs_graphics_bind_uniform_desc_t uniforms[1];
  968. uniforms[0].uniform = u->hndl;
  969. uniforms[0].data = (mat->uniform_data.data + u->offset);
  970. uniforms[0].binding = u->binding;
  971. bind.uniforms.desc = uniforms;
  972. bind.uniforms.size = sizeof(uniforms);
  973. gs_graphics_apply_bindings(cb, &bind);
  974. } break;
  975. }
  976. }
  977. }
  978. // Mesh API
  979. GS_API_DECL void
  980. gs_gfxt_mesh_draw(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mp)
  981. {
  982. /*
  983. // For each primitive in mesh
  984. for (uint32_t i = 0; i < gs_dyn_array_size(mp->primitives); ++i)
  985. {
  986. gs_gfxt_mesh_primitive_t* prim = &mp->primitives[i];
  987. // Bindings for all buffers: vertex, index, uniform, sampler
  988. gs_graphics_bind_desc_t binds = gs_default_val();
  989. gs_graphics_bind_vertex_buffer_desc_t vdesc = gs_default_val();
  990. gs_graphics_bind_index_buffer_desc_t idesc = gs_default_val();
  991. vdesc.buffer = prim->vbo;
  992. idesc.buffer = prim->indices;
  993. binds.vertex_buffers.desc = &vdesc;
  994. binds.index_buffers.desc = &idesc;
  995. gs_graphics_draw_desc_t ddesc = gs_default_val();
  996. ddesc.start = 0;
  997. ddesc.count = prim->count;
  998. gs_graphics_apply_bindings(cb, &binds);
  999. gs_graphics_draw(cb, &ddesc);
  1000. }
  1001. */
  1002. }
  1003. GS_API_DECL void
  1004. 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)
  1005. {
  1006. if (!layout || !layout_size || !prim || !cb)
  1007. {
  1008. return;
  1009. }
  1010. gs_graphics_bind_vertex_buffer_desc_t vbos[8] = {0}; // Make this a define
  1011. uint32_t l = 0;
  1012. const uint32_t ct = layout_size / sizeof(gs_gfxt_mesh_layout_t);
  1013. for (uint32_t a = 0; a < ct; ++a)
  1014. {
  1015. vbos[l].data_type = GS_GRAPHICS_VERTEX_DATA_NONINTERLEAVED;
  1016. switch (layout[a].type)
  1017. {
  1018. case GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION: {if (!prim->stream.positions.id) continue; vbos[l].buffer = prim->stream.positions;} break;
  1019. case GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL: {if (!prim->stream.normals.id) continue; vbos[l].buffer = prim->stream.normals;} break;
  1020. case GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT: {if (!prim->stream.tangents.id) continue; vbos[l].buffer = prim->stream.tangents;} break;
  1021. case GS_ASSET_MESH_ATTRIBUTE_TYPE_JOINT: {if (!prim->stream.joints[0].id) continue; vbos[l].buffer = prim->stream.joints[0];} break;
  1022. case GS_ASSET_MESH_ATTRIBUTE_TYPE_WEIGHT: {if (!prim->stream.weights[0].id) continue; vbos[l].buffer = prim->stream.weights[0];} break;
  1023. case GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD: {if (!prim->stream.tex_coords[0].id) continue; vbos[l].buffer = prim->stream.tex_coords[0];} break;
  1024. case GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR: {if (!prim->stream.colors[0].id) continue; vbos[l].buffer = prim->stream.colors[0];} break;
  1025. case GS_ASSET_MESH_ATTRIBUTE_TYPE_UINT: {if (!prim->stream.custom_uint[0].id) continue; vbos[l].buffer = prim->stream.custom_uint[0];} break;
  1026. }
  1027. ++l;
  1028. }
  1029. gs_graphics_bind_index_buffer_desc_t ibos = gs_default_val();
  1030. ibos.buffer = prim->indices;
  1031. // Bindings for all buffers: vertex, index, uniform, sampler
  1032. gs_graphics_bind_desc_t binds = gs_default_val();
  1033. // .vertex_buffers = {.desc = vbos, .size = sizeof(vbos)},
  1034. binds.vertex_buffers.desc = vbos;
  1035. binds.vertex_buffers.size = l * sizeof(gs_graphics_bind_vertex_buffer_desc_t);
  1036. binds.index_buffers.desc = &ibos;
  1037. gs_graphics_draw_desc_t ddesc = gs_default_val();
  1038. ddesc.start = 0;
  1039. ddesc.count = prim->count;
  1040. ddesc.instances = instance_count;
  1041. gs_graphics_apply_bindings(cb, &binds);
  1042. gs_graphics_draw(cb, &ddesc);
  1043. }
  1044. GS_API_DECL void
  1045. 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)
  1046. {
  1047. if (!layout || !mesh || !cb)
  1048. {
  1049. return;
  1050. }
  1051. uint32_t ct = layout_size / sizeof(gs_gfxt_mesh_layout_t);
  1052. // For each primitive in mesh
  1053. for (uint32_t i = 0; i < gs_dyn_array_size(mesh->primitives); ++i)
  1054. {
  1055. gs_gfxt_mesh_primitive_t* prim = &mesh->primitives[i];
  1056. gs_gfxt_mesh_primitive_draw_layout(cb, prim, layout, layout_size, 1);
  1057. }
  1058. }
  1059. GS_API_DECL void
  1060. gs_gfxt_mesh_draw_materials(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_material_t** mats, size_t mats_size)
  1061. {
  1062. // Iterate through primitives, draw each primitive with assigned mat
  1063. if (!mats || !mats_size || !cb || !mesh)
  1064. {
  1065. return;
  1066. }
  1067. const uint32_t ct = mats_size / sizeof(gs_gfxt_material_t*);
  1068. gs_gfxt_material_t* mat = NULL;
  1069. // For each primitive in mesh
  1070. for (uint32_t i = 0; i < gs_dyn_array_size(mesh->primitives); ++i)
  1071. {
  1072. gs_gfxt_mesh_primitive_t* prim = &mesh->primitives[i];
  1073. // Get corresponding material, if available
  1074. uint32_t mat_idx = i < ct ? i : ct - 1;
  1075. mat = mats[mat_idx] ? mats[mat_idx] : mat;
  1076. // Can't draw without a valid material present
  1077. if (!mat) continue;
  1078. // Bind material pipeline and uniforms
  1079. gs_gfxt_material_bind(cb, mat);
  1080. // Get pipeline
  1081. gs_gfxt_pipeline_t* pip = gs_gfxt_material_get_pipeline(mat);
  1082. 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);
  1083. }
  1084. }
  1085. GS_API_DECL void
  1086. gs_gfxt_mesh_draw_material(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_material_t* mat)
  1087. {
  1088. if (!mat || !mesh || !cb)
  1089. {
  1090. return;
  1091. }
  1092. gs_gfxt_pipeline_t* pip = gs_gfxt_material_get_pipeline(mat);
  1093. gs_gfxt_mesh_draw_layout(cb, mesh, pip->mesh_layout, gs_dyn_array_size(pip->mesh_layout) * sizeof(gs_gfxt_mesh_layout_t));
  1094. }
  1095. GS_API_DECL void
  1096. gs_gfxt_mesh_draw_pipeline(gs_command_buffer_t* cb, gs_gfxt_mesh_t* mesh, gs_gfxt_pipeline_t* pip)
  1097. {
  1098. if (!pip || !mesh || !cb)
  1099. {
  1100. return;
  1101. }
  1102. gs_gfxt_mesh_draw_layout(cb, mesh, pip->mesh_layout, gs_dyn_array_size(pip->mesh_layout) * sizeof(gs_gfxt_mesh_layout_t));
  1103. }
  1104. // Util API
  1105. GS_API_DECL
  1106. void* gs_gfxt_raw_data_default_impl(GS_GFXT_HNDL hndl, void* user_data)
  1107. {
  1108. return hndl;
  1109. }
  1110. GS_API_DECL void gs_gfxt_mesh_import_options_free(gs_gfxt_mesh_import_options_t* opt)
  1111. {
  1112. if (opt->layout)
  1113. {
  1114. gs_dyn_array_free(opt->layout);
  1115. }
  1116. }
  1117. GS_API_DECL
  1118. gs_gfxt_mesh_t gs_gfxt_mesh_load_from_file(const char* path, gs_gfxt_mesh_import_options_t* options)
  1119. {
  1120. gs_gfxt_mesh_t mesh = gs_default_val();
  1121. if (!gs_platform_file_exists(path)) {
  1122. gs_println("Warning:GFXT:MeshLoadFromFile:File does not exist: %s", path);
  1123. return mesh;
  1124. }
  1125. // Mesh data to fill out
  1126. uint32_t mesh_count = 0;
  1127. gs_gfxt_mesh_raw_data_t* meshes = NULL;
  1128. // Get file extension from path
  1129. gs_transient_buffer(file_ext, 32);
  1130. gs_platform_file_extension(file_ext, 32, path);
  1131. // GLTF
  1132. if (gs_string_compare_equal(file_ext, "gltf")) {
  1133. gs_gfxt_load_gltf_data_from_file(path, options, &meshes, &mesh_count);
  1134. }
  1135. // GLB
  1136. else if (gs_string_compare_equal(file_ext, "glb")) {
  1137. gs_gfxt_load_gltf_data_from_file(path, options, &meshes, &mesh_count);
  1138. }
  1139. else {
  1140. gs_println("Warning:GFXT:MeshLoadFromFile:File extension not supported: %s, file: %s", file_ext, path);
  1141. return mesh;
  1142. }
  1143. gs_gfxt_mesh_desc_t mdesc = gs_default_val();
  1144. mdesc.meshes = meshes;
  1145. mdesc.size = mesh_count * sizeof(gs_gfxt_mesh_raw_data_t);
  1146. mesh = gs_gfxt_mesh_create(&mdesc);
  1147. mesh.desc = mdesc;
  1148. return mesh;
  1149. }
  1150. GS_API_DECL bool
  1151. gs_gfxt_load_gltf_data_from_file(const char* path, gs_gfxt_mesh_import_options_t* options,
  1152. gs_gfxt_mesh_raw_data_t** out, uint32_t* mesh_count)
  1153. {
  1154. // Use cgltf like a boss
  1155. cgltf_options cgltf_options = gs_default_val();
  1156. size_t len = 0;
  1157. char* file_data = NULL;
  1158. // Get file extension from path
  1159. gs_transient_buffer(file_ext, 32);
  1160. gs_platform_file_extension(file_ext, 32, path);
  1161. // GLTF
  1162. if (gs_string_compare_equal(file_ext, "gltf")) {
  1163. file_data = gs_platform_read_file_contents(path, "rb", &len);
  1164. gs_println("GFXT:Loading GLTF: %s", path);
  1165. }
  1166. // GLB
  1167. else if (gs_string_compare_equal(file_ext, "glb")) {
  1168. file_data = gs_platform_read_file_contents(path, "rb", &len);
  1169. gs_println("GFXT:Loading GLTF: %s", path);
  1170. }
  1171. else {
  1172. gs_println("Warning:GFXT:LoadGLTFDataFromFile:File extension not supported: %s, file: %s", file_ext, path);
  1173. return false;
  1174. }
  1175. cgltf_data* data = NULL;
  1176. cgltf_result result = cgltf_parse(&cgltf_options, file_data, (cgltf_size)len, &data);
  1177. gs_free(file_data);
  1178. if (result != cgltf_result_success) {
  1179. gs_println("GFXT:Mesh:LoadFromFile:Failed load gltf");
  1180. cgltf_free(data);
  1181. return false;
  1182. }
  1183. // Load buffers as well
  1184. result = cgltf_load_buffers(&cgltf_options, data, path);
  1185. if (result != cgltf_result_success) {
  1186. cgltf_free(data);
  1187. gs_println("GFXT:Mesh:LoadFromFile:Failed to load buffers");
  1188. return false;
  1189. }
  1190. // Type of index data
  1191. size_t index_element_size = options ? options->index_buffer_element_size : 0;
  1192. // Temporary structures
  1193. gs_dyn_array(gs_vec3) positions = NULL;
  1194. gs_dyn_array(gs_vec3) normals = NULL;
  1195. gs_dyn_array(gs_vec3) tangents = NULL;
  1196. gs_dyn_array(gs_color_t) colors[GS_GFXT_COLOR_MAX] = gs_default_val();
  1197. gs_dyn_array(gs_vec2) uvs[GS_GFXT_TEX_COORD_MAX] = gs_default_val();
  1198. gs_dyn_array(float) weights[GS_GFXT_WEIGHT_MAX] = gs_default_val();
  1199. gs_dyn_array(float) joints[GS_GFXT_JOINT_MAX] = gs_default_val();
  1200. gs_dyn_array(gs_gfxt_mesh_layout_t) layouts = gs_default_val();
  1201. gs_byte_buffer_t v_data = gs_byte_buffer_new();
  1202. gs_byte_buffer_t i_data = gs_byte_buffer_new();
  1203. gs_mat4 world_mat = gs_mat4_identity();
  1204. // Allocate memory for buffers
  1205. *mesh_count = data->meshes_count;
  1206. *out = (gs_gfxt_mesh_raw_data_t*)gs_malloc(data->meshes_count * sizeof(gs_gfxt_mesh_raw_data_t));
  1207. memset(*out, 0, sizeof(gs_gfxt_mesh_raw_data_t) * data->meshes_count);
  1208. // For each node, for each mesh
  1209. uint32_t i = 0;
  1210. for (uint32_t _n = 0; _n < data->nodes_count; ++_n)
  1211. {
  1212. cgltf_node* node = &data->nodes[_n];
  1213. if (node->mesh == NULL) continue;
  1214. gs_println("Load mesh from node: %s", node->name);
  1215. // Reset matrix
  1216. world_mat = gs_mat4_identity();
  1217. // 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);
  1218. // Not sure what "local transform" does, since world gives me the actual world result...probably for animation
  1219. if (node->has_rotation || node->has_translation || node->has_scale)
  1220. {
  1221. cgltf_node_transform_world(node, (float*)&world_mat);
  1222. }
  1223. // if (node->has_matrix)
  1224. // {
  1225. // // Multiply local by world
  1226. // gs_mat4 tmp = gs_default_val();
  1227. // cgltf_node_transform_world(node, (float*)&tmp);
  1228. // world_mat = gs_mat4_mul(world_mat, tmp);
  1229. // }
  1230. // Do node mesh data
  1231. cgltf_mesh* cmesh = node->mesh;
  1232. {
  1233. // Initialize mesh data
  1234. gs_gfxt_mesh_raw_data_t* mesh = &((*out)[i]);
  1235. bool warnings[gs_enum_count(gs_asset_mesh_attribute_type)] = gs_default_val();
  1236. bool printed = false;
  1237. // For each primitive in mesh
  1238. for (uint32_t p = 0; p < cmesh->primitives_count; ++p)
  1239. {
  1240. cgltf_primitive* prim = &cmesh->primitives[p];
  1241. // Mesh primitive to fill out
  1242. gs_gfxt_mesh_vertex_data_t primitive = gs_default_val();
  1243. // Clear temp data from previous use
  1244. gs_dyn_array_clear(positions);
  1245. gs_dyn_array_clear(normals);
  1246. gs_dyn_array_clear(tangents);
  1247. for (uint32_t ci = 0; ci < GS_GFXT_COLOR_MAX; ++ci) gs_dyn_array_clear(colors[ci]);
  1248. for (uint32_t tci = 0; tci < GS_GFXT_TEX_COORD_MAX; ++tci) gs_dyn_array_clear(uvs[tci]);
  1249. for (uint32_t wi = 0; wi < GS_GFXT_WEIGHT_MAX; ++wi) gs_dyn_array_clear(weights[wi]);
  1250. for (uint32_t ji = 0; ji < GS_GFXT_JOINT_MAX; ++ji) gs_dyn_array_clear(joints[ji]);
  1251. gs_dyn_array_clear(layouts);
  1252. gs_byte_buffer_clear(&v_data);
  1253. gs_byte_buffer_clear(&i_data);
  1254. // Collect all provided attribute data for each vertex that's available in gltf data
  1255. #define __GFXT_GLTF_PUSH_ATTR(ATTR, TYPE, COUNT, ARR, ARR_TYPE, LAYOUTS, LAYOUT_TYPE)\
  1256. do {\
  1257. int32_t N = 0;\
  1258. TYPE* BUF = (TYPE*)ATTR->buffer_view->buffer->data + ATTR->buffer_view->offset/sizeof(TYPE) + ATTR->offset/sizeof(TYPE);\
  1259. gs_assert(BUF);\
  1260. TYPE V[COUNT] = gs_default_val();\
  1261. /* For each vertex */\
  1262. for (uint32_t k = 0; k < ATTR->count; k++)\
  1263. {\
  1264. /* For each element */\
  1265. for (int l = 0; l < COUNT; l++) {\
  1266. V[l] = BUF[N + l];\
  1267. }\
  1268. N += (int32_t)(ATTR->stride/sizeof(TYPE));\
  1269. /* Add to temp data array */\
  1270. ARR_TYPE ELEM = gs_default_val();\
  1271. memcpy((void*)&ELEM, (void*)V, sizeof(ARR_TYPE));\
  1272. gs_dyn_array_push(ARR, ELEM);\
  1273. }\
  1274. /* Push into layout */\
  1275. gs_gfxt_mesh_layout_t LAYOUT = gs_default_val();\
  1276. LAYOUT.type = LAYOUT_TYPE;\
  1277. gs_dyn_array_push(LAYOUTS, LAYOUT);\
  1278. } while (0)
  1279. // For each attribute in primitive
  1280. for (uint32_t a = 0; a < prim->attributes_count; ++a)
  1281. {
  1282. // Accessor for attribute data
  1283. cgltf_accessor* attr = prim->attributes[a].data;
  1284. // Index for data
  1285. int32_t aidx = prim->attributes[a].index;
  1286. // Switch on type for reading data
  1287. switch (prim->attributes[a].type)
  1288. {
  1289. case cgltf_attribute_type_position: {
  1290. int32_t N = 0;
  1291. float* BUF = (float*)attr->buffer_view->buffer->data + attr->buffer_view->offset/sizeof(float) + attr->offset/sizeof(float);
  1292. gs_assert(BUF);
  1293. float V[3] = gs_default_val();
  1294. /* For each vertex */
  1295. for (uint32_t k = 0; k < attr->count; k++)
  1296. {
  1297. /* For each element */
  1298. for (int l = 0; l < 3; l++) {
  1299. V[l] = BUF[N + l];
  1300. }
  1301. N += (int32_t)(attr->stride/sizeof(float));
  1302. /* Add to temp data array */
  1303. gs_vec3 ELEM = gs_default_val();
  1304. memcpy((void*)&ELEM, (void*)V, sizeof(gs_vec3));
  1305. // Transform into world space
  1306. ELEM = gs_mat4_mul_vec3(world_mat, ELEM);
  1307. gs_dyn_array_push(positions, ELEM);
  1308. }
  1309. /* Push into layout */
  1310. gs_gfxt_mesh_layout_t LAYOUT = gs_default_val();
  1311. LAYOUT.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION;
  1312. gs_dyn_array_push(layouts, LAYOUT);
  1313. } break;
  1314. case cgltf_attribute_type_normal: {
  1315. __GFXT_GLTF_PUSH_ATTR(attr, float, 3, normals, gs_vec3, layouts, GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL);
  1316. } break;
  1317. case cgltf_attribute_type_tangent: {
  1318. __GFXT_GLTF_PUSH_ATTR(attr, float, 3, tangents, gs_vec3, layouts, GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT);
  1319. } break;
  1320. case cgltf_attribute_type_texcoord: {
  1321. __GFXT_GLTF_PUSH_ATTR(attr, float, 2, uvs[aidx], gs_vec2, layouts, GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD);
  1322. } break;
  1323. case cgltf_attribute_type_color: {
  1324. // Need to parse color as sRGB then convert to gs_color_t
  1325. int32_t N = 0;
  1326. float* BUF = (float*)attr->buffer_view->buffer->data + attr->buffer_view->offset/sizeof(float) + attr->offset/sizeof(float);
  1327. gs_assert(BUF);
  1328. float V[3] = gs_default_val();
  1329. /* For each vertex */\
  1330. for (uint32_t k = 0; k < attr->count; k++)
  1331. {
  1332. /* For each element */
  1333. for (int l = 0; l < 3; l++) {
  1334. V[l] = BUF[N + l];
  1335. }
  1336. N += (int32_t)(attr->stride/sizeof(float));
  1337. /* Add to temp data array */
  1338. gs_color_t ELEM = gs_default_val();
  1339. // Need to convert over now
  1340. ELEM.r = (uint8_t)(V[0] * 255.f);
  1341. ELEM.g = (uint8_t)(V[1] * 255.f);
  1342. ELEM.b = (uint8_t)(V[2] * 255.f);
  1343. ELEM.a = 255;
  1344. gs_dyn_array_push(colors[aidx], ELEM);
  1345. }
  1346. /* Push into layout */
  1347. gs_gfxt_mesh_layout_t LAYOUT = gs_default_val();
  1348. LAYOUT.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR;
  1349. gs_dyn_array_push(layouts, LAYOUT);
  1350. } break;
  1351. // Not sure what to do with these for now
  1352. case cgltf_attribute_type_joints:
  1353. {
  1354. // Push into layout
  1355. gs_gfxt_mesh_layout_t layout = gs_default_val();
  1356. layout.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_JOINT;
  1357. gs_dyn_array_push(layouts, layout);
  1358. } break;
  1359. case cgltf_attribute_type_weights:
  1360. {
  1361. // Push into layout
  1362. gs_gfxt_mesh_layout_t layout = gs_default_val();
  1363. layout.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_WEIGHT;
  1364. gs_dyn_array_push(layouts, layout);
  1365. } break;
  1366. // Shouldn't hit here...
  1367. default: {
  1368. } break;
  1369. }
  1370. }
  1371. // Indices for primitive
  1372. cgltf_accessor* acc = prim->indices;
  1373. #define __GFXT_GLTF_PUSH_IDX(BB, ACC, TYPE)\
  1374. do {\
  1375. int32_t n = 0;\
  1376. TYPE* buf = (TYPE*)acc->buffer_view->buffer->data + acc->buffer_view->offset/sizeof(TYPE) + acc->offset/sizeof(TYPE);\
  1377. gs_assert(buf);\
  1378. TYPE v = 0;\
  1379. /* For each index */\
  1380. for (uint32_t k = 0; k < acc->count; k++) {\
  1381. /* For each element */\
  1382. for (int l = 0; l < 1; l++) {\
  1383. v = buf[n + l];\
  1384. }\
  1385. n += (int32_t)(acc->stride/sizeof(TYPE));\
  1386. /* Add to temp positions array */\
  1387. switch (index_element_size) {\
  1388. case 0: gs_byte_buffer_write(BB, uint16_t, (uint16_t)v); break;\
  1389. case 2: gs_byte_buffer_write(BB, uint16_t, (uint16_t)v); break;\
  1390. case 4: gs_byte_buffer_write(BB, uint32_t, (uint32_t)v); break;\
  1391. }\
  1392. }\
  1393. } while (0)
  1394. // If indices are available
  1395. if (acc)
  1396. {
  1397. switch (acc->component_type)
  1398. {
  1399. case cgltf_component_type_r_8: __GFXT_GLTF_PUSH_IDX(&i_data, acc, int8_t); break;
  1400. case cgltf_component_type_r_8u: __GFXT_GLTF_PUSH_IDX(&i_data, acc, uint8_t); break;
  1401. case cgltf_component_type_r_16: __GFXT_GLTF_PUSH_IDX(&i_data, acc, int16_t); break;
  1402. case cgltf_component_type_r_16u: __GFXT_GLTF_PUSH_IDX(&i_data, acc, uint16_t); break;
  1403. case cgltf_component_type_r_32u: __GFXT_GLTF_PUSH_IDX(&i_data, acc, uint32_t); break;
  1404. case cgltf_component_type_r_32f: __GFXT_GLTF_PUSH_IDX(&i_data, acc, float); break;
  1405. // Shouldn't hit here
  1406. default: {
  1407. } break;
  1408. }
  1409. }
  1410. else
  1411. {
  1412. // Iterate over positions size, then just push back indices
  1413. for (uint32_t i = 0; i < gs_dyn_array_size(positions); ++i)
  1414. {
  1415. switch (index_element_size)
  1416. {
  1417. default:
  1418. case 0: gs_byte_buffer_write(&i_data, uint16_t, (uint16_t)i); break;
  1419. case 2: gs_byte_buffer_write(&i_data, uint16_t, (uint16_t)i); break;
  1420. case 4: gs_byte_buffer_write(&i_data, uint32_t, (uint32_t)i); break;
  1421. }
  1422. }
  1423. }
  1424. // Grab mesh layout pointer to use
  1425. /*
  1426. gs_gfxt_mesh_layout_t* layoutp = options ? options->layout : layouts;
  1427. uint32_t layout_ct = options ? options->size / sizeof(gs_gfxt_mesh_layout_t) : gs_dyn_array_size(layouts);
  1428. // Iterate layout to fill data buffers according to provided layout
  1429. {
  1430. uint32_t vct = 0;
  1431. vct = gs_max(vct, gs_dyn_array_size(positions));
  1432. vct = gs_max(vct, gs_dyn_array_size(colors));
  1433. vct = gs_max(vct, gs_dyn_array_size(uvs));
  1434. vct = gs_max(vct, gs_dyn_array_size(normals));
  1435. vct = gs_max(vct, gs_dyn_array_size(tangents));
  1436. #define __GLTF_WRITE_DATA(IT, VDATA, ARR, ARR_TYPE, ARR_DEF_VAL, LAYOUT_TYPE)\
  1437. do {\
  1438. if (IT < gs_dyn_array_size(ARR)) {\
  1439. gs_byte_buffer_write(&(VDATA), ARR_TYPE, ARR[IT]);\
  1440. }\
  1441. else {\
  1442. gs_byte_buffer_write(&(VDATA), ARR_TYPE, ARR_DEF_VAL);\
  1443. if (!warnings[LAYOUT_TYPE]) {\
  1444. warnings[LAYOUT_TYPE] = true;\
  1445. }\
  1446. }\
  1447. } while (0)
  1448. for (uint32_t it = 0; it < vct; ++it)
  1449. {
  1450. // For each attribute in layout
  1451. for (uint32_t l = 0; l < layout_ct; ++l)
  1452. {
  1453. switch (layoutp[l].type)
  1454. {
  1455. case GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION: {
  1456. __GLTF_WRITE_DATA(it, v_data, positions, gs_vec3, gs_v3(0.f, 0.f, 0.f), GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION);
  1457. } break;
  1458. case GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD: {
  1459. __GLTF_WRITE_DATA(it, v_data, uvs, gs_vec2, gs_v2(0.f, 0.f), GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD);
  1460. } break;
  1461. case GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR: {
  1462. __GLTF_WRITE_DATA(it, v_data, colors, gs_color_t, GS_COLOR_WHITE, GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR);
  1463. } break;
  1464. case GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL: {
  1465. __GLTF_WRITE_DATA(it, v_data, normals, gs_vec3, gs_v3(0.f, 0.f, 1.f), GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL);
  1466. } break;
  1467. case GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT: {
  1468. __GLTF_WRITE_DATA(it, v_data, tangents, gs_vec3, gs_v3(0.f, 1.f, 0.f), GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT);
  1469. } break;
  1470. default:
  1471. {
  1472. } break;
  1473. }
  1474. }
  1475. }
  1476. }
  1477. // Add to out data
  1478. mesh->vertices[p] = gs_malloc(v_data.size);
  1479. mesh->indices[p] = gs_malloc(i_data.size);
  1480. mesh->vertex_sizes[p] = v_data.size;
  1481. mesh->index_sizes[p] = i_data.size;
  1482. // Copy data
  1483. memcpy(mesh->vertices[p], v_data.data, v_data.size);
  1484. memcpy(mesh->indices[p], i_data.data, i_data.size);
  1485. */
  1486. /*
  1487. typedef struct
  1488. {
  1489. void* data;
  1490. size_t size;
  1491. } gs_gfxt_mesh_vertex_attribute_t;
  1492. typedef struct
  1493. {
  1494. gs_gfxt_mesh_vertex_attribute_t positions; // All position data
  1495. gs_gfxt_mesh_vertex_attribute_t normals;
  1496. gs_gfxt_mesh_vertex_attribute_t tangents;
  1497. gs_gfxt_mesh_vertex_attribute_t tex_coords[GS_GFXT_TEX_COORD_MAX];
  1498. gs_gfxt_mesh_vertex_attribute_t joints[GS_GFXT_JOINT_MAX];
  1499. gs_gfxt_mesh_vertex_attribute_t weights[GS_GFXT_WEIGHT_MAX];
  1500. gs_gfxt_mesh_vertex_attribute_t indices;
  1501. } gs_gfxt_mesh_vertex_data_t;
  1502. // Structured/packed raw mesh data
  1503. typedef struct gs_gfxt_mesh_raw_data_t {
  1504. uint16_t prim_count;
  1505. size_t* vertex_sizes;
  1506. size_t* index_sizes;
  1507. void** vertices;
  1508. void** indices;
  1509. gs_dyn_array(gs_gfxt_mesh_vertex_data_t) primitives; // All primitive data
  1510. } gs_gfxt_mesh_raw_data_t;
  1511. */
  1512. // Count
  1513. primitive.count = prim->indices->count;
  1514. // Indices
  1515. primitive.indices.size = i_data.size;
  1516. primitive.indices.data = gs_malloc(i_data.size);
  1517. memcpy(primitive.indices.data, i_data.data, i_data.size);
  1518. // Positions
  1519. if (!gs_dyn_array_empty(positions))
  1520. {
  1521. primitive.positions.size = gs_dyn_array_size(positions) * sizeof(gs_vec3);
  1522. primitive.positions.data = gs_malloc(primitive.positions.size);
  1523. memcpy(primitive.positions.data, positions, primitive.positions.size);
  1524. }
  1525. // Normals
  1526. if (!gs_dyn_array_empty(normals))
  1527. {
  1528. primitive.normals.size = gs_dyn_array_size(normals) * sizeof(gs_vec3);
  1529. primitive.normals.data = gs_malloc(primitive.normals.size);
  1530. memcpy(primitive.normals.data, normals, primitive.normals.size);
  1531. }
  1532. // Tangents
  1533. if (!gs_dyn_array_empty(tangents))
  1534. {
  1535. primitive.tangents.size = gs_dyn_array_size(tangents) * sizeof(gs_vec3);
  1536. primitive.tangents.data = gs_malloc(primitive.tangents.size);
  1537. memcpy(primitive.tangents.data, tangents, primitive.tangents.size);
  1538. }
  1539. // Texcoords
  1540. for (uint32_t tci = 0; tci < GS_GFXT_TEX_COORD_MAX; ++tci)
  1541. {
  1542. if (!gs_dyn_array_empty(uvs[tci]))
  1543. {
  1544. primitive.tex_coords[tci].size = gs_dyn_array_size(uvs[tci]) * sizeof(gs_vec2);
  1545. primitive.tex_coords[tci].data = gs_malloc(primitive.tex_coords[tci].size);
  1546. memcpy(primitive.tex_coords[tci].data, uvs[tci], primitive.tex_coords[tci].size);
  1547. }
  1548. else
  1549. {
  1550. break;
  1551. }
  1552. }
  1553. // Colors
  1554. for (uint32_t ci = 0; ci < GS_GFXT_COLOR_MAX; ++ci)
  1555. {
  1556. if (!gs_dyn_array_empty(colors[ci]))
  1557. {
  1558. primitive.colors[ci].size = gs_dyn_array_size(colors[ci]) * sizeof(gs_color_t);
  1559. primitive.colors[ci].data = gs_malloc(primitive.colors[ci].size);
  1560. memcpy(primitive.colors[ci].data, colors[ci], primitive.colors[ci].size);
  1561. }
  1562. else
  1563. {
  1564. break;
  1565. }
  1566. }
  1567. // Joints
  1568. for (uint32_t ji = 0; ji < GS_GFXT_JOINT_MAX; ++ji)
  1569. {
  1570. if (!gs_dyn_array_empty(joints[ji]))
  1571. {
  1572. primitive.joints[ji].size = gs_dyn_array_size(joints[ji]) * sizeof(float);
  1573. primitive.joints[ji].data = gs_malloc(primitive.joints[ji].size);
  1574. memcpy(primitive.joints[ji].data, joints[ji], primitive.joints[ji].size);
  1575. }
  1576. else
  1577. {
  1578. break;
  1579. }
  1580. }
  1581. // Weights
  1582. for (uint32_t wi = 0; wi < GS_GFXT_WEIGHT_MAX; ++wi)
  1583. {
  1584. if (!gs_dyn_array_empty(weights[wi]))
  1585. {
  1586. primitive.weights[wi].size = gs_dyn_array_size(weights[wi]) * sizeof(float);
  1587. primitive.weights[wi].data = gs_malloc(primitive.weights[wi].size);
  1588. memcpy(primitive.weights[wi].data, weights[wi], primitive.weights[wi].size);
  1589. }
  1590. else
  1591. {
  1592. break;
  1593. }
  1594. }
  1595. // Add primitive to mesh
  1596. gs_dyn_array_push(mesh->primitives, primitive);
  1597. }
  1598. if (!printed)
  1599. {
  1600. printed = true;
  1601. if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION]){
  1602. gs_log_warning("Mesh attribute: POSITION not found. Resorting to default.");
  1603. }
  1604. if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD]) {
  1605. gs_log_warning("Mesh attribute: TEXCOORD not found. Resorting to default.");
  1606. }
  1607. if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR]) {
  1608. gs_log_warning("Mesh attribute: COLOR not found. Resorting to default.");
  1609. }
  1610. if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL]) {
  1611. gs_log_warning("Mesh attribute: NORMAL not found. Resorting to default.");
  1612. }
  1613. if (warnings[GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT]) {
  1614. gs_log_warning("Mesh attribute: WEIGHTS not found. Resorting to default.");
  1615. }
  1616. }
  1617. }
  1618. // Increment i if successful
  1619. i++;
  1620. }
  1621. gs_println("Finished loading mesh.");
  1622. // Free all data at the end
  1623. cgltf_free(data);
  1624. gs_dyn_array_free(positions);
  1625. gs_dyn_array_free(normals);
  1626. gs_dyn_array_free(tangents);
  1627. for (uint32_t ci = 0; ci < GS_GFXT_COLOR_MAX; ++ci) gs_dyn_array_free(colors[ci]);
  1628. for (uint32_t tci = 0; tci < GS_GFXT_TEX_COORD_MAX; ++tci) gs_dyn_array_free(uvs[tci]);
  1629. for (uint32_t wi = 0; wi < GS_GFXT_WEIGHT_MAX; ++wi) gs_dyn_array_free(weights[wi]);
  1630. for (uint32_t ji = 0; ji < GS_GFXT_JOINT_MAX; ++ji) gs_dyn_array_free(joints[ji]);
  1631. gs_dyn_array_free(layouts);
  1632. gs_byte_buffer_free(&v_data);
  1633. gs_byte_buffer_free(&i_data);
  1634. return true;
  1635. }
  1636. GS_API_DECL
  1637. gs_gfxt_mesh_t gs_gfxt_mesh_unit_quad_generate(gs_gfxt_mesh_import_options_t* options)
  1638. {
  1639. gs_gfxt_mesh_t mesh = gs_default_val();
  1640. gs_vec3 v_pos[] = {
  1641. gs_v3(-1.0f, -1.0f, 0.f), // Top Left
  1642. gs_v3(+1.0f, -1.0f, 0.f), // Top Right
  1643. gs_v3(-1.0f, +1.0f, 0.f), // Bottom Left
  1644. gs_v3(+1.0f, +1.0f, 0.f) // Bottom Right
  1645. };
  1646. // Vertex data for quad
  1647. gs_vec2 v_uvs[] = {
  1648. gs_v2(0.0f, 0.0f), // Top Left
  1649. gs_v2(1.0f, 0.0f), // Top Right
  1650. gs_v2(0.0f, 1.0f), // Bottom Left
  1651. gs_v2(1.0f, 1.0f) // Bottom Right
  1652. };
  1653. gs_vec3 v_norm[] = {
  1654. gs_v3(0.f, 0.f, 1.f),
  1655. gs_v3(0.f, 0.f, 1.f),
  1656. gs_v3(0.f, 0.f, 1.f),
  1657. gs_v3(0.f, 0.f, 1.f)
  1658. };
  1659. gs_vec3 v_tan[] = {
  1660. gs_v3(1.f, 0.f, 0.f),
  1661. gs_v3(1.f, 0.f, 0.f),
  1662. gs_v3(1.f, 0.f, 0.f),
  1663. gs_v3(1.f, 0.f, 0.f)
  1664. };
  1665. gs_color_t v_color[] = {
  1666. GS_COLOR_WHITE,
  1667. GS_COLOR_WHITE,
  1668. GS_COLOR_WHITE,
  1669. GS_COLOR_WHITE
  1670. };
  1671. // Index data for quad
  1672. uint16_t i_data[] = {
  1673. 0, 3, 2, // First Triangle
  1674. 0, 1, 3 // Second Triangle
  1675. };
  1676. // Mesh data
  1677. gs_gfxt_mesh_raw_data_t mesh_data = gs_default_val();
  1678. // Primitive to upload
  1679. gs_gfxt_mesh_vertex_data_t vert_data = gs_default_val();
  1680. vert_data.positions.data = v_pos; vert_data.positions.size = sizeof(v_pos);
  1681. vert_data.normals.data = v_norm; vert_data.normals.size = sizeof(v_norm);
  1682. vert_data.tangents.data = v_tan; vert_data.tangents.size = sizeof(v_tan);
  1683. vert_data.colors[0].data = v_color; vert_data.colors[0].size = sizeof(v_color);
  1684. vert_data.tex_coords[0].data = v_uvs; vert_data.tex_coords[0].size = sizeof(v_uvs);
  1685. vert_data.indices.data = i_data; vert_data.indices.size = sizeof(i_data);
  1686. vert_data.count = 6;
  1687. // Push into primitives
  1688. gs_dyn_array_push(mesh_data.primitives, vert_data);
  1689. // If no decl, then just use default layout
  1690. /*
  1691. gs_gfxt_mesh_import_options_t* moptions = options ? options : &def_options;
  1692. uint32_t ct = moptions->size / sizeof(gs_asset_mesh_layout_t);
  1693. */
  1694. gs_gfxt_mesh_desc_t mdesc = gs_default_val();
  1695. mdesc.meshes = &mesh_data;
  1696. mdesc.size = 1 * sizeof(gs_gfxt_mesh_raw_data_t);
  1697. mdesc.keep_data = true;
  1698. mesh = gs_gfxt_mesh_create(&mdesc);
  1699. mesh.desc = mdesc;
  1700. // Free data
  1701. if (mesh_data.primitives) gs_dyn_array_free(mesh_data.primitives);
  1702. return mesh;
  1703. }
  1704. GS_API_DECL gs_handle(gs_graphics_texture_t)
  1705. gs_gfxt_texture_generate_default()
  1706. {
  1707. // Generate procedural texture data (checkered texture)
  1708. #define GS_GFXT_ROW_COL_CT 5
  1709. gs_color_t c0 = GS_COLOR_WHITE;
  1710. gs_color_t c1 = gs_color(20, 50, 150, 255);
  1711. gs_color_t pixels[GS_GFXT_ROW_COL_CT * GS_GFXT_ROW_COL_CT] = gs_default_val();
  1712. for (uint32_t r = 0; r < GS_GFXT_ROW_COL_CT; ++r) {
  1713. for (uint32_t c = 0; c < GS_GFXT_ROW_COL_CT; ++c) {
  1714. const bool re = (r % 2) == 0;
  1715. const bool ce = (c % 2) == 0;
  1716. uint32_t idx = r * GS_GFXT_ROW_COL_CT + c;
  1717. pixels[idx] = (re && ce) ? c0 : (re) ? c1 : (ce) ? c1 : c0;
  1718. }
  1719. }
  1720. gs_graphics_texture_desc_t desc = gs_default_val();
  1721. desc.width = GS_GFXT_ROW_COL_CT;
  1722. desc.height = GS_GFXT_ROW_COL_CT;
  1723. desc.format = GS_GRAPHICS_TEXTURE_FORMAT_RGBA8;
  1724. desc.min_filter = GS_GRAPHICS_TEXTURE_FILTER_NEAREST;
  1725. desc.mag_filter = GS_GRAPHICS_TEXTURE_FILTER_NEAREST;
  1726. desc.wrap_s = GS_GRAPHICS_TEXTURE_WRAP_REPEAT;
  1727. desc.wrap_t = GS_GRAPHICS_TEXTURE_WRAP_REPEAT;
  1728. *desc.data = pixels;
  1729. // Create dynamic texture
  1730. return gs_graphics_texture_create(&desc);
  1731. }
  1732. //=== Resource Loading ===//
  1733. typedef struct tmp_buffer_t
  1734. {
  1735. char txt[1024];
  1736. } tmp_buffer_t;
  1737. typedef struct gs_shader_io_data_t
  1738. {
  1739. char type[64];
  1740. char name[64];
  1741. } gs_shader_io_data_t;
  1742. typedef struct gs_pipeline_parse_data_t
  1743. {
  1744. gs_dyn_array(gs_shader_io_data_t) io_list[3];
  1745. gs_dyn_array(gs_gfxt_mesh_layout_t) mesh_layout;
  1746. gs_dyn_array(gs_graphics_vertex_attribute_type) vertex_layout;
  1747. char* code[3];
  1748. char dir[256];
  1749. } gs_ppd_t;
  1750. #define gs_parse_warning(TXT, ...)\
  1751. do {\
  1752. gs_printf("WARNING::");\
  1753. gs_printf(TXT, ##__VA_ARGS__);\
  1754. gs_println("");\
  1755. } while (0)
  1756. #define gs_parse_error(TXT, ASSERT, ...)\
  1757. do {\
  1758. gs_printf("ERROR::");\
  1759. gs_printf(TXT, ##__VA_ARGS__);\
  1760. gs_println("");\
  1761. if (ASSERT) gs_assert(false);\
  1762. } while (0)
  1763. #define gs_parse_block(NAME, ...)\
  1764. do {\
  1765. gs_println("gs_pipeline_load_from_file::parsing::%s", #NAME);\
  1766. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))\
  1767. {\
  1768. gs_println("error::gs_pipeline_load_from_file::error parsing raster from .sf resource");\
  1769. gs_assert(false);\
  1770. }\
  1771. \
  1772. uint32_t bc = 1;\
  1773. while (gs_lexer_can_lex(lex) && bc)\
  1774. {\
  1775. gs_token_t token = gs_lexer_next_token(lex);\
  1776. switch (token.type)\
  1777. {\
  1778. case GS_TOKEN_LBRACE: {bc++;} break;\
  1779. case GS_TOKEN_RBRACE: {bc--;} break;\
  1780. \
  1781. case GS_TOKEN_IDENTIFIER:\
  1782. {\
  1783. __VA_ARGS__\
  1784. }\
  1785. }\
  1786. }\
  1787. } while (0)
  1788. const char* gs_get_vertex_attribute_string(gs_graphics_vertex_attribute_type type)
  1789. {
  1790. switch (type)
  1791. {
  1792. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT: return "float"; break;
  1793. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT2: return "vec2"; break;
  1794. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT3: return "vec3"; break;
  1795. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT4: return "vec4"; break;
  1796. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT: return "int"; break;
  1797. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT2: return "vec2"; break;
  1798. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT3: return "vec3"; break;
  1799. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT4: return "vec4"; break;
  1800. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE: return "float"; break;
  1801. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE2: return "vec2"; break;
  1802. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE3: return "vec3"; break;
  1803. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE4: return "vec4"; break;
  1804. default: return "UNKNOWN"; break;
  1805. }
  1806. }
  1807. gs_graphics_vertex_attribute_type gs_get_vertex_attribute_from_token(const gs_token_t* t)
  1808. {
  1809. if (gs_token_compare_text(t, "float")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT;
  1810. else if (gs_token_compare_text(t, "float2")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT2;
  1811. else if (gs_token_compare_text(t, "float3")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT3;
  1812. else if (gs_token_compare_text(t, "float4")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT4;
  1813. else if (gs_token_compare_text(t, "uint4")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT4;
  1814. else if (gs_token_compare_text(t, "uint3")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT3;
  1815. else if (gs_token_compare_text(t, "uint2")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT2;
  1816. else if (gs_token_compare_text(t, "uint")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT;
  1817. else if (gs_token_compare_text(t, "byte4")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE4;
  1818. else if (gs_token_compare_text(t, "byte3")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE3;
  1819. else if (gs_token_compare_text(t, "byte2")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE2;
  1820. else if (gs_token_compare_text(t, "byte")) return GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE;
  1821. return (gs_graphics_vertex_attribute_type)0x00;
  1822. }
  1823. gs_graphics_uniform_type gs_uniform_type_from_token(const gs_token_t* t)
  1824. {
  1825. if (gs_token_compare_text(t, "float")) return GS_GRAPHICS_UNIFORM_FLOAT;
  1826. else if (gs_token_compare_text(t, "int")) return GS_GRAPHICS_UNIFORM_INT;
  1827. else if (gs_token_compare_text(t, "vec2")) return GS_GRAPHICS_UNIFORM_VEC2;
  1828. else if (gs_token_compare_text(t, "vec3")) return GS_GRAPHICS_UNIFORM_VEC3;
  1829. else if (gs_token_compare_text(t, "vec4")) return GS_GRAPHICS_UNIFORM_VEC4;
  1830. else if (gs_token_compare_text(t, "mat4")) return GS_GRAPHICS_UNIFORM_MAT4;
  1831. else if (gs_token_compare_text(t, "sampler2D")) return GS_GRAPHICS_UNIFORM_SAMPLER2D;
  1832. else if (gs_token_compare_text(t, "sampler2DShadow"))return GS_GRAPHICS_UNIFORM_SAMPLER2DSHADOW;
  1833. else if (gs_token_compare_text(t, "usampler2D")) return GS_GRAPHICS_UNIFORM_USAMPLER2D;
  1834. else if (gs_token_compare_text(t, "samplerCube")) return GS_GRAPHICS_UNIFORM_SAMPLERCUBE;
  1835. else if (gs_token_compare_text(t, "img2D_rgba32f")) return GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F;
  1836. return (gs_graphics_uniform_type)0x00;
  1837. }
  1838. const char* gs_uniform_string_from_type(gs_graphics_uniform_type type)
  1839. {
  1840. switch (type)
  1841. {
  1842. case GS_GRAPHICS_UNIFORM_FLOAT: return "float"; break;
  1843. case GS_GRAPHICS_UNIFORM_INT: return "int"; break;
  1844. case GS_GRAPHICS_UNIFORM_VEC2: return "vec2"; break;
  1845. case GS_GRAPHICS_UNIFORM_VEC3: return "vec3"; break;
  1846. case GS_GRAPHICS_UNIFORM_VEC4: return "vec4"; break;
  1847. case GS_GRAPHICS_UNIFORM_MAT4: return "mat4"; break;
  1848. case GS_GRAPHICS_UNIFORM_SAMPLER2D: return "sampler2D"; break;
  1849. case GS_GRAPHICS_UNIFORM_SAMPLER2DSHADOW: return "sampler2DShadow"; break;
  1850. case GS_GRAPHICS_UNIFORM_USAMPLER2D: return "usampler2D"; break;
  1851. case GS_GRAPHICS_UNIFORM_SAMPLERCUBE: return "samplerCube"; break;
  1852. case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F: return "image2D"; break;
  1853. default: return "UNKNOWN"; break;
  1854. }
  1855. return (char*)0x00;
  1856. }
  1857. // Make this an extern function that can be bubbled up to the app
  1858. 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)
  1859. {
  1860. gs_token_t token = lex->current_token;
  1861. // Determine if uniform is one of special key defines
  1862. if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX")) {
  1863. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1864. memcpy(uniform->name, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX, sizeof(GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX));
  1865. return true;
  1866. }
  1867. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0")) {
  1868. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1869. memcpy(uniform->name, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0, sizeof(GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0));
  1870. return true;
  1871. }
  1872. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1")) {
  1873. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1874. memcpy(uniform->name, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1, sizeof(GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1));
  1875. return true;
  1876. }
  1877. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX")) {
  1878. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1879. memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX));
  1880. return true;
  1881. }
  1882. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0")) {
  1883. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1884. memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0));
  1885. return true;
  1886. }
  1887. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1")) {
  1888. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1889. memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1));
  1890. return true;
  1891. }
  1892. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2")) {
  1893. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1894. memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2));
  1895. return true;
  1896. }
  1897. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3")) {
  1898. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1899. memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3, sizeof(GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3));
  1900. return true;
  1901. }
  1902. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_MODEL_MATRIX")) {
  1903. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1904. memcpy(uniform->name, GS_GFXT_UNIFORM_MODEL_MATRIX, sizeof(GS_GFXT_UNIFORM_MODEL_MATRIX));
  1905. return true;
  1906. }
  1907. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX")) {
  1908. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1909. memcpy(uniform->name, GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX, sizeof(GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX));
  1910. return true;
  1911. }
  1912. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_PROJECTION_MATRIX")) {
  1913. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1914. memcpy(uniform->name, GS_GFXT_UNIFORM_PROJECTION_MATRIX, sizeof(GS_GFXT_UNIFORM_PROJECTION_MATRIX));
  1915. return true;
  1916. }
  1917. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_VIEW_MATRIX")) {
  1918. uniform->type = GS_GRAPHICS_UNIFORM_MAT4;
  1919. memcpy(uniform->name, GS_GFXT_UNIFORM_VIEW_MATRIX, sizeof(GS_GFXT_UNIFORM_VIEW_MATRIX));
  1920. return true;
  1921. }
  1922. else if (gs_token_compare_text(&token, "GS_GFXT_UNIFORM_TIME")) {
  1923. uniform->type = GS_GRAPHICS_UNIFORM_FLOAT;
  1924. memcpy(uniform->name, GS_GFXT_UNIFORM_TIME, sizeof(GS_GFXT_UNIFORM_TIME));
  1925. return true;
  1926. }
  1927. return false;
  1928. }
  1929. bool gs_parse_uniforms(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd, gs_graphics_shader_stage_type stage)
  1930. {
  1931. uint32_t image_binding = 0;
  1932. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
  1933. {
  1934. gs_log_warning("Unable to parsing uniforms from .sf resource");
  1935. return false;
  1936. }
  1937. uint32_t bc = 1;\
  1938. while (gs_lexer_can_lex(lex) && bc)
  1939. {
  1940. gs_token_t token = gs_lexer_next_token(lex);
  1941. switch (token.type)
  1942. {
  1943. case GS_TOKEN_LBRACE: {bc++;} break;
  1944. case GS_TOKEN_RBRACE: {bc--;} break;
  1945. case GS_TOKEN_IDENTIFIER:
  1946. {
  1947. gs_gfxt_uniform_desc_t uniform = {0};
  1948. uniform.stage = stage;
  1949. bool special = gs_parse_uniform_special_keyword(lex, desc, ppd, stage, &uniform);
  1950. // Determine if uniform is one of special key defines
  1951. if (!special)
  1952. {
  1953. uniform.type = gs_uniform_type_from_token(&token);
  1954. switch (uniform.type)
  1955. {
  1956. default: break;
  1957. case GS_GRAPHICS_UNIFORM_SAMPLER2D:
  1958. case GS_GRAPHICS_UNIFORM_USAMPLER2D:
  1959. case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
  1960. {
  1961. uniform.binding = image_binding++;
  1962. } break;
  1963. }
  1964. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  1965. {
  1966. gs_log_warning("Unidentified token (Expected identifier)");
  1967. gs_token_debug_print(&lex->current_token);
  1968. return false;
  1969. }
  1970. token = lex->current_token;
  1971. memcpy(uniform.name, token.text, token.len);
  1972. }
  1973. // Add uniform to ublock descriptor
  1974. gs_dyn_array_push(desc->ublock_desc.layout, uniform);
  1975. } break;
  1976. }
  1977. }
  1978. return true;
  1979. }
  1980. bool gs_parse_io(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd, gs_graphics_shader_stage_type type)
  1981. {
  1982. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
  1983. {
  1984. gs_log_warning("Expected opening left brace. Unable to parse io from .sf resource");\
  1985. return false;
  1986. }
  1987. uint32_t bc = 1;
  1988. while (gs_lexer_can_lex(lex) && bc)
  1989. {
  1990. gs_token_t token = gs_lexer_next_token(lex);
  1991. switch (token.type)
  1992. {
  1993. case GS_TOKEN_LBRACE: {bc++;} break;
  1994. case GS_TOKEN_RBRACE: {bc--;} break;
  1995. case GS_TOKEN_IDENTIFIER:
  1996. {
  1997. gs_shader_io_data_t io = {0};
  1998. memcpy(io.type, token.text, token.len);
  1999. switch (type)
  2000. {
  2001. case GS_GRAPHICS_SHADER_STAGE_VERTEX:
  2002. {
  2003. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2004. {
  2005. gs_log_warning("IO expected identifier name after type, shader stage vertex.");
  2006. gs_token_debug_print(&lex->current_token);
  2007. return false;
  2008. }
  2009. token = lex->current_token;
  2010. memcpy(io.name, token.text, token.len);
  2011. gs_dyn_array_push(ppd->io_list[0], io);
  2012. } break;
  2013. case GS_GRAPHICS_SHADER_STAGE_FRAGMENT:
  2014. {
  2015. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2016. {
  2017. gs_log_warning("IO expected identifier name after type, shader stage fragment.");
  2018. gs_token_debug_print(&lex->current_token);
  2019. return false;
  2020. }
  2021. token = lex->current_token;
  2022. memcpy(io.name, token.text, token.len);
  2023. gs_dyn_array_push(ppd->io_list[1], io);
  2024. } break;
  2025. case GS_GRAPHICS_SHADER_STAGE_COMPUTE:
  2026. {
  2027. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_NUMBER))
  2028. {
  2029. gs_log_warning("IO expected number after type, shader stage compute.");
  2030. gs_token_debug_print(&lex->current_token);
  2031. return false;
  2032. }
  2033. token = lex->current_token;
  2034. memcpy(io.name, token.text, token.len);
  2035. gs_dyn_array_push(ppd->io_list[2], io);
  2036. } break;
  2037. }
  2038. } break;
  2039. }
  2040. }
  2041. return true;
  2042. }
  2043. bool gs_parse_code(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd, gs_graphics_shader_stage_type stage)
  2044. {
  2045. if (!gs_lexer_require_token_type(lex, GS_TOKEN_LBRACE))
  2046. {
  2047. gs_log_warning("Expected opening left brace");
  2048. return false;
  2049. }
  2050. // Something is broken up here...
  2051. uint32_t bc = 1;
  2052. gs_token_t cur = gs_lexer_peek(lex);
  2053. gs_token_t token = lex->current_token;
  2054. while (gs_lexer_can_lex(lex) && bc)
  2055. {
  2056. token = lex->next_token(lex);
  2057. switch (token.type)
  2058. {
  2059. case GS_TOKEN_LBRACE: {bc++;} break;
  2060. case GS_TOKEN_RBRACE: {bc--;} break;
  2061. }
  2062. }
  2063. // Allocate size for code
  2064. const size_t sz = (size_t)(token.text - cur.text);
  2065. char* code = (char*)gs_malloc(sz);
  2066. memset(code, 0, sz);
  2067. memcpy(code, cur.text, sz - 1);
  2068. gs_byte_buffer_t cbuffer = gs_byte_buffer_new();
  2069. // List of include directories to gather
  2070. uint32_t iidx = 0;
  2071. typedef struct {
  2072. char path[GS_GFXT_INCLUDE_DIR_MAX];
  2073. char* start;
  2074. char* end;
  2075. } include_t;
  2076. include_t includes[256] = {0};
  2077. // Need to parse through code and replace keywords with appropriate mappings
  2078. gs_lexer_t clex = gs_lexer_c_ctor(code);
  2079. clex.skip_white_space = false;
  2080. while (clex.can_lex(&clex))
  2081. {
  2082. gs_token_t tkn = clex.next_token(&clex);
  2083. // Push back tkn text + len. Don't skip whitespace in this lexer.
  2084. switch (tkn.type)
  2085. {
  2086. default: {
  2087. gs_byte_buffer_write_bulk(&cbuffer, tkn.text, tkn.len);
  2088. } break;
  2089. case GS_TOKEN_IDENTIFIER: {
  2090. // evil replace a const char*
  2091. if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX")) {
  2092. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX, (char)32);
  2093. }
  2094. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0")) {
  2095. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_0, (char)32);
  2096. }
  2097. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1")) {
  2098. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_MODEL_VIEW_PROJECTION_MATRIX_1, (char)32);
  2099. }
  2100. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX")) {
  2101. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX, (char)32);
  2102. }
  2103. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0")) {
  2104. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_0, (char)32);
  2105. }
  2106. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1")) {
  2107. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_1, (char)32);
  2108. }
  2109. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2")) {
  2110. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_2, (char)32);
  2111. }
  2112. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3")) {
  2113. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_PROJECTION_MATRIX_3, (char)32);
  2114. }
  2115. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_MODEL_MATRIX")) {
  2116. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_MODEL_MATRIX, (char)32);
  2117. }
  2118. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX")) {
  2119. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_INVERSE_MODEL_MATRIX, (char)32);
  2120. }
  2121. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_VIEW_MATRIX")) {
  2122. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_VIEW_MATRIX, (char)32);
  2123. }
  2124. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_PROJECTION_MATRIX")) {
  2125. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_PROJECTION_MATRIX, (char)32);
  2126. }
  2127. else if (gs_token_compare_text(&tkn, "GS_GFXT_UNIFORM_TIME")) {
  2128. gs_util_string_replace((char*)tkn.text, tkn.len, GS_GFXT_UNIFORM_TIME, (char)32);
  2129. }
  2130. gs_byte_buffer_write_bulk(&cbuffer, tkn.text, tkn.len);
  2131. } break;
  2132. case GS_TOKEN_HASH: {
  2133. gs_token_t htoken = tkn;
  2134. tkn = clex.next_token(&clex);
  2135. switch (tkn.type) {
  2136. case GS_TOKEN_IDENTIFIER: {
  2137. // Parse include
  2138. if (gs_token_compare_text(&tkn, "include") && iidx < GS_GFXT_INCLUDE_DIR_MAX) {
  2139. // Length of include string
  2140. size_t ilen = 8;
  2141. // Grab next token, expect string
  2142. // Don't grab next token - advance to string
  2143. // tkn = clex.next_token(&clex);
  2144. if (gs_lexer_find_next_token_type(&clex, GS_TOKEN_STRING)) {
  2145. // if (tkn.type == GS_TOKEN_STRING) {
  2146. tkn = clex.current_token;
  2147. // Just fucking replace it here, on the spot. Then fix up the lexer. Done.
  2148. memcpy(includes[iidx].path, tkn.text + 1, tkn.len - 2);
  2149. // evil replace a const char*
  2150. // Store token text pointer, use that later for concat
  2151. gs_util_string_replace((char*)tkn.text - ilen - 1, tkn.len + ilen + 1,
  2152. " ", (char)32);
  2153. // Need to collect other uniforms from these includes (parse code)
  2154. gs_snprintfc(FINAL_PATH, 256, "%s/%s", ppd->dir, includes[iidx].path);
  2155. // Load include using final path and relative path from include
  2156. size_t len = 0;
  2157. char* inc_src = gs_platform_read_file_contents(FINAL_PATH, "rb", &len);
  2158. gs_byte_buffer_write_bulk(&cbuffer, inc_src, len);
  2159. // includes[iidx].start = tkn.text;
  2160. // includes[iidx].end = tkn.text + ilen + tkn.len;
  2161. // size_t total_len = len + (start - code);
  2162. // char* cat0 = gs_util_string_concat(start, inc_src);
  2163. // char* cat1 = gs_util_string_concat(cat0, includes[iidx].end);
  2164. // // Concat, replace text, free include src
  2165. // // gs_free(cat0);
  2166. // // gs_free(code);
  2167. // code = cat1;
  2168. // start = code;
  2169. // end = code + total_len;
  2170. // // Need to find where to place the token...ehhh...
  2171. // clex = gs_lexer_c_ctor(code);
  2172. // clex.at = code + total_len;
  2173. iidx++;
  2174. }
  2175. }
  2176. else {
  2177. gs_byte_buffer_write(&cbuffer, char, '#');
  2178. clex.current_token = tkn;
  2179. clex.at = tkn.text;
  2180. }
  2181. // else if (gs_token_compare_text(&tkn, "define")) {
  2182. // Push back # and identifier into buffer
  2183. // gs_println("Writing: %*.s", tkn.len + 1, tkn.text - tkn.len - 1);
  2184. // gs_snprintfc(TMP, 8, "#define");
  2185. // gs_byte_buffer_write_bulk(&cbuffer, TMP, sizeof(TMP));
  2186. // gs_byte_buffer_write_str(&cbuffer, "#define");
  2187. // }
  2188. } break;
  2189. // default: {
  2190. // // Push back # and identifier into buffer
  2191. // gs_println("Writing: %*.s", tkn.len + 1, tkn.text - tkn.len - 1);
  2192. // gs_byte_buffer_write_bulk(&cbuffer, tkn.text - tkn.len - 1, tkn.len + 1);
  2193. // } break;
  2194. }
  2195. } break;
  2196. }
  2197. }
  2198. // Allocate a new buffer as copy of original code. Use original for pointer references to where to cat.
  2199. // size_t ilen = 0;
  2200. // for (uint32_t i = 0; i < GS_GFXT_INCLUDE_DIR_MAX; ++i)
  2201. // {
  2202. // if (!includes[i].path[0]) continue;
  2203. // // Need to collect other uniforms from these includes (parse code)
  2204. // gs_snprintfc(FINAL_PATH, 256, "%s/%s", ppd->dir, includes[i].path);
  2205. // // gs_println("INC_DIR: %s", FINAL_PATH);
  2206. // // Load include using final path and relative path from include
  2207. // size_t len = 0;
  2208. // char* inc_src = gs_platform_read_file_contents(FINAL_PATH, "rb", &len);
  2209. // gs_assert(inc_src);
  2210. // // Concat, starting at a particular location.
  2211. // const char* src_start_slice = includes[i].start + ilen;
  2212. // const char* src_end_slice = includes[i].end + ilen;
  2213. // char* cat = gs_util_string_concat(src_start_slice, inc_src);
  2214. // char* cat2 = gs_util_string_concat(cat, src_end_slice);
  2215. // // Concat with (cat) src starting at workable range
  2216. // // Realloc previous code to greater size, shift contents around
  2217. // char* cat = gs_util_string_concat(inc_src, code);
  2218. // gs_free(code);
  2219. // code = cat;
  2220. // }
  2221. // Add a final EOF character
  2222. gs_byte_buffer_write(&cbuffer, char, '\0');
  2223. gs_free(code);
  2224. switch (stage)
  2225. {
  2226. // case GS_GRAPHICS_SHADER_STAGE_VERTEX: ppd->code[0] = code; break;
  2227. // case GS_GRAPHICS_SHADER_STAGE_FRAGMENT: ppd->code[1] = code; break;
  2228. // case GS_GRAPHICS_SHADER_STAGE_COMPUTE: ppd->code[2] = code; break;
  2229. case GS_GRAPHICS_SHADER_STAGE_VERTEX: ppd->code[0] = cbuffer.data; break;
  2230. case GS_GRAPHICS_SHADER_STAGE_FRAGMENT: ppd->code[1] = cbuffer.data; break;
  2231. case GS_GRAPHICS_SHADER_STAGE_COMPUTE: ppd->code[2] = cbuffer.data; break;
  2232. }
  2233. return true;
  2234. }
  2235. gs_gfxt_mesh_attribute_type gs_mesh_attribute_type_from_token(const gs_token_t* token)
  2236. {
  2237. if (gs_token_compare_text(token, "POSITION")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_POSITION;
  2238. else if (gs_token_compare_text(token, "NORMAL")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_NORMAL;
  2239. else if (gs_token_compare_text(token, "COLOR")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_COLOR;
  2240. else if (gs_token_compare_text(token, "TANGENT")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TANGENT;
  2241. else if (gs_token_compare_text(token, "TEXCOORD0")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2242. else if (gs_token_compare_text(token, "TEXCOORD1")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2243. else if (gs_token_compare_text(token, "TEXCOORD2")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2244. else if (gs_token_compare_text(token, "TEXCOORD3")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2245. else if (gs_token_compare_text(token, "TEXCOORD4")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2246. else if (gs_token_compare_text(token, "TEXCOORD5")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2247. else if (gs_token_compare_text(token, "TEXCOORD6")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2248. else if (gs_token_compare_text(token, "TEXCOORD7")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2249. else if (gs_token_compare_text(token, "TEXCOORD8")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2250. else if (gs_token_compare_text(token, "TEXCOORD9")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2251. else if (gs_token_compare_text(token, "TEXCOORD10")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2252. else if (gs_token_compare_text(token, "TEXCOORD11")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2253. else if (gs_token_compare_text(token, "TEXCOORD12")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_TEXCOORD;
  2254. else if (gs_token_compare_text(token, "UINT")) return GS_ASSET_MESH_ATTRIBUTE_TYPE_UINT;
  2255. // Default
  2256. return (gs_gfxt_mesh_attribute_type)0x00;
  2257. }
  2258. bool gs_parse_vertex_mesh_attributes(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
  2259. {
  2260. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
  2261. {
  2262. gs_assert(false);
  2263. }
  2264. uint32_t bc = 1;
  2265. while (gs_lexer_can_lex(lex) && bc)
  2266. {
  2267. gs_token_t token = gs_lexer_next_token(lex);
  2268. // gs_token_debug_print(&token);
  2269. switch (token.type)
  2270. {
  2271. case GS_TOKEN_LBRACE: {bc++;} break;
  2272. case GS_TOKEN_RBRACE: {bc--;} break;
  2273. case GS_TOKEN_IDENTIFIER:
  2274. {
  2275. // Get attribute name
  2276. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2277. {
  2278. gs_assert(false);
  2279. }
  2280. gs_token_t token_name = lex->current_token;
  2281. // gs_token_debug_print(&token_name);
  2282. #define PUSH_ATTR(MESH_ATTR, VERT_ATTR)\
  2283. do {\
  2284. gs_gfxt_mesh_layout_t layout = gs_default_val();\
  2285. layout.type = GS_ASSET_MESH_ATTRIBUTE_TYPE_##MESH_ATTR;\
  2286. gs_dyn_array_push(ppd->mesh_layout, layout);\
  2287. gs_graphics_vertex_attribute_desc_t attr = gs_default_val();\
  2288. memcpy(attr.name, token_name.text, token_name.len);\
  2289. attr.format = GS_GRAPHICS_VERTEX_ATTRIBUTE_##VERT_ATTR;\
  2290. gs_dyn_array_push(desc->pip_desc.layout.attrs, attr);\
  2291. /*gs_println("%s: %s", #MESH_ATTR, #VERT_ATTR);*/\
  2292. } while (0)
  2293. if (gs_token_compare_text(&token, "POSITION")) PUSH_ATTR(POSITION, FLOAT3);
  2294. else if (gs_token_compare_text(&token, "NORMAL")) PUSH_ATTR(NORMAL, FLOAT3);
  2295. else if (gs_token_compare_text(&token, "COLOR")) PUSH_ATTR(COLOR, BYTE4);
  2296. else if (gs_token_compare_text(&token, "TANGENT")) PUSH_ATTR(TANGENT, FLOAT3);
  2297. else if (gs_token_compare_text(&token, "TEXCOORD")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2298. else if (gs_token_compare_text(&token, "TEXCOORD0")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2299. else if (gs_token_compare_text(&token, "TEXCOORD1")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2300. else if (gs_token_compare_text(&token, "TEXCOORD2")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2301. else if (gs_token_compare_text(&token, "TEXCOORD3")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2302. else if (gs_token_compare_text(&token, "TEXCOORD4")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2303. else if (gs_token_compare_text(&token, "TEXCOORD5")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2304. else if (gs_token_compare_text(&token, "TEXCOORD6")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2305. else if (gs_token_compare_text(&token, "TEXCOORD8")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2306. else if (gs_token_compare_text(&token, "TEXCOORD9")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2307. else if (gs_token_compare_text(&token, "TEXCOORD10")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2308. else if (gs_token_compare_text(&token, "TEXCOORD11")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2309. else if (gs_token_compare_text(&token, "TEXCOORD12")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2310. else if (gs_token_compare_text(&token, "FLOAT")) PUSH_ATTR(WEIGHT, FLOAT4);
  2311. else if (gs_token_compare_text(&token, "FLOAT2")) PUSH_ATTR(TEXCOORD, FLOAT2);
  2312. else if (gs_token_compare_text(&token, "FLOAT3")) PUSH_ATTR(POSITION, FLOAT3);
  2313. else if (gs_token_compare_text(&token, "UINT")) PUSH_ATTR(UINT, UINT);
  2314. // else if (gs_token_compare_text(&token, "FLOAT4")) PUSH_ATTR(TANGENT, FLOAT4);
  2315. else
  2316. {
  2317. gs_log_warning("Unidentified vertex attribute: %.*s: %.*s",
  2318. token.len, token.text, token_name.len, token_name.text);
  2319. return false;
  2320. }
  2321. }
  2322. }
  2323. }
  2324. return true;
  2325. }
  2326. bool gs_parse_vertex_attributes(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
  2327. {
  2328. return gs_parse_vertex_mesh_attributes(lex, desc, ppd);
  2329. }
  2330. 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)
  2331. {
  2332. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
  2333. {
  2334. gs_println("error::gs_pipeline_load_from_file::error parsing raster from .sf resource");
  2335. gs_assert(false);
  2336. }
  2337. uint32_t bc = 1;
  2338. while (gs_lexer_can_lex(lex) && bc)
  2339. {
  2340. gs_token_t token = gs_lexer_next_token(lex);
  2341. switch (token.type)
  2342. {
  2343. case GS_TOKEN_LBRACE: {bc++;} break;
  2344. case GS_TOKEN_RBRACE: {bc--;} break;
  2345. case GS_TOKEN_IDENTIFIER:
  2346. {
  2347. if (stage == GS_GRAPHICS_SHADER_STAGE_VERTEX &&
  2348. gs_token_compare_text(&token, "attributes"))
  2349. {
  2350. gs_println("parsing attributes...");
  2351. if (!gs_parse_vertex_attributes(lex, desc, ppd))
  2352. {
  2353. gs_log_warning("Unable to parse vertex attributes.");
  2354. return false;
  2355. }
  2356. }
  2357. else if (gs_token_compare_text(&token, "uniforms"))
  2358. {
  2359. gs_println("parsing uniforms...");
  2360. if (!gs_parse_uniforms(lex, desc, ppd, stage))
  2361. {
  2362. gs_log_warning("Unable to parse 'uniforms' for stage: %zu.", (u32)stage);
  2363. return false;
  2364. }
  2365. }
  2366. else if (gs_token_compare_text(&token, "out"))
  2367. {
  2368. gs_println("parsing out...");
  2369. if (!gs_parse_io(lex, desc, ppd, stage))
  2370. {
  2371. gs_log_warning("Unable to parse 'out' for stage: %zu.", (u32)stage);
  2372. return false;
  2373. }
  2374. }
  2375. else if (gs_token_compare_text(&token, "in"))
  2376. {
  2377. gs_println("parsing in...");
  2378. if (!gs_parse_io(lex, desc, ppd, stage))
  2379. {
  2380. gs_log_warning("Unable to parse 'in' for stage: %zu.", (u32)stage);
  2381. return false;
  2382. }
  2383. }
  2384. else if (gs_token_compare_text(&token, "code"))
  2385. {
  2386. gs_println("parsing code...");
  2387. if (!gs_parse_code(lex, desc, ppd, stage))
  2388. {
  2389. gs_log_warning("Unable to parse 'code' for stage: %zu.", (u32)stage);
  2390. return false;
  2391. }
  2392. }
  2393. } break;
  2394. }
  2395. }
  2396. return true;
  2397. }
  2398. bool gs_parse_compute_shader_stage(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
  2399. {
  2400. gs_parse_block(
  2401. PIPELINE::COMPUTE_SHADER_STAGE,
  2402. {
  2403. if (gs_token_compare_text(&token, "uniforms"))
  2404. {
  2405. if (!gs_parse_uniforms(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE))
  2406. {
  2407. gs_log_warning("Unable to parse 'uniforms' for compute shader");
  2408. return false;
  2409. }
  2410. }
  2411. else if (gs_token_compare_text(&token, "in"))
  2412. {
  2413. if (!gs_parse_io(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE))
  2414. {
  2415. gs_log_warning("Unable to parse 'in' for compute shader");
  2416. return false;
  2417. }
  2418. }
  2419. else if (gs_token_compare_text(&token, "code"))
  2420. {
  2421. if (!gs_parse_code(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE))
  2422. {
  2423. gs_log_warning("Unable to parse 'code' for compute shader");
  2424. return false;
  2425. }
  2426. }
  2427. });
  2428. return true;
  2429. }
  2430. bool gs_parse_shader(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
  2431. {
  2432. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_LBRACE))
  2433. {
  2434. gs_log_warning("Unable to parse shader from .sf resource. Expected opening left brace.");
  2435. return false;
  2436. }
  2437. // Braces
  2438. uint32_t bc = 1;
  2439. while (gs_lexer_can_lex(lex) && bc)
  2440. {
  2441. gs_token_t token = lex->next_token(lex);
  2442. switch (token.type)
  2443. {
  2444. case GS_TOKEN_LBRACE: {bc++;} break;
  2445. case GS_TOKEN_RBRACE: {bc--;} break;
  2446. case GS_TOKEN_IDENTIFIER:
  2447. {
  2448. // Vertex shader
  2449. if (gs_token_compare_text(&token, "vertex"))
  2450. {
  2451. gs_println("parsing vertex shader");
  2452. if (!gs_parse_shader_stage(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_VERTEX))
  2453. {
  2454. gs_log_warning("Unable to parse shader stage: Vertex");
  2455. return false;
  2456. }
  2457. }
  2458. // Fragment shader
  2459. else if (gs_token_compare_text(&token, "fragment"))
  2460. {
  2461. gs_println("parsing fragment shader");
  2462. if (!gs_parse_shader_stage(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_FRAGMENT))
  2463. {
  2464. gs_log_warning("Unable to parse shader stage: Fragment");
  2465. return false;
  2466. }
  2467. }
  2468. // Compute shader
  2469. else if (gs_token_compare_text(&token, "compute"))
  2470. {
  2471. gs_println("parsing compute shader");
  2472. if (!gs_parse_shader_stage(lex, desc, ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE))
  2473. {
  2474. gs_log_warning("Unable to parse shader stage: Compute");
  2475. return false;
  2476. }
  2477. }
  2478. } break;
  2479. }
  2480. }
  2481. return true;
  2482. }
  2483. bool gs_parse_depth(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd)
  2484. {
  2485. gs_parse_block(
  2486. PIPELINE::DEPTH,
  2487. {
  2488. // Depth function
  2489. if (gs_token_compare_text(&token, "func"))
  2490. {
  2491. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2492. {
  2493. token = lex->current_token;
  2494. gs_log_warning("Depth func type not found after function decl: %.*s", token.len, token.text);
  2495. return false;
  2496. }
  2497. token = lex->current_token;
  2498. if (gs_token_compare_text(&token, "LESS")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_LESS;
  2499. else if (gs_token_compare_text(&token, "EQUAL")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_EQUAL;
  2500. else if (gs_token_compare_text(&token, "LEQUAL")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_LEQUAL;
  2501. else if (gs_token_compare_text(&token, "GREATER")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_GREATER;
  2502. else if (gs_token_compare_text(&token, "NOTEQUAL")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_NOTEQUAL;
  2503. else if (gs_token_compare_text(&token, "GEQUAL")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_GEQUAL;
  2504. else if (gs_token_compare_text(&token, "ALWAYS")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_ALWAYS;
  2505. else if (gs_token_compare_text(&token, "NEVER")) pdesc->pip_desc.depth.func = GS_GRAPHICS_DEPTH_FUNC_NEVER;
  2506. else
  2507. {
  2508. token = lex->current_token;
  2509. gs_log_warning("Func type %.*s not valid.", token.len, token.text);
  2510. return false;
  2511. }
  2512. }
  2513. if (gs_token_compare_text(&token, "mask"))
  2514. {
  2515. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2516. {
  2517. token = lex->current_token;
  2518. gs_log_warning("Depth mask type not found after function decl: %.*s", token.len, token.text);
  2519. return false;
  2520. }
  2521. token = lex->current_token;
  2522. if (gs_token_compare_text(&token, "ENABLED")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_ENABLED;
  2523. else if (gs_token_compare_text(&token, "TRUE")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_ENABLED;
  2524. else if (gs_token_compare_text(&token, "true")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_ENABLED;
  2525. else if (gs_token_compare_text(&token, "DISABLED")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_DISABLED;
  2526. else if (gs_token_compare_text(&token, "FALSE")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_DISABLED;
  2527. else if (gs_token_compare_text(&token, "false")) pdesc->pip_desc.depth.mask = GS_GRAPHICS_DEPTH_MASK_DISABLED;
  2528. else
  2529. {
  2530. token = lex->current_token;
  2531. gs_log_warning("Mask type %.*s not valid.", token.len, token.text);
  2532. return false;
  2533. }
  2534. gs_println("MASK: %zu", (uint32_t)pdesc->pip_desc.depth.mask);
  2535. }
  2536. });
  2537. return true;
  2538. }
  2539. bool gs_parse_blend(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd)
  2540. {
  2541. gs_parse_block(
  2542. PIPELINE::BLEND,
  2543. {
  2544. // Blend function
  2545. if (gs_token_compare_text(&token, "func"))
  2546. {
  2547. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2548. {
  2549. gs_log_warning("Blend func type not found after function decl.");
  2550. return false;
  2551. }
  2552. token = lex->current_token;
  2553. if (gs_token_compare_text(&token, "ADD")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_ADD;
  2554. else if (gs_token_compare_text(&token, "SUBTRACT")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_SUBTRACT;
  2555. else if (gs_token_compare_text(&token, "REVERSE_SUBTRACT")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_REVERSE_SUBTRACT;
  2556. else if (gs_token_compare_text(&token, "MIN")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_MIN;
  2557. else if (gs_token_compare_text(&token, "MAX")) pdesc->pip_desc.blend.func = GS_GRAPHICS_BLEND_EQUATION_MAX;
  2558. else
  2559. {
  2560. gs_log_warning("Blend func type %.*s not valid.", token.len, token.text);
  2561. return false;
  2562. }
  2563. }
  2564. // Source blend
  2565. else if (gs_token_compare_text(&token, "src"))
  2566. {
  2567. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2568. {
  2569. gs_log_warning("Blend src type not found after decl.");
  2570. return false;
  2571. }
  2572. token = lex->current_token;
  2573. if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ZERO;
  2574. else if (gs_token_compare_text(&token, "ONE")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE;
  2575. else if (gs_token_compare_text(&token, "SRC_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_SRC_COLOR;
  2576. else if (gs_token_compare_text(&token, "ONE_MINUS_SRC_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_COLOR;
  2577. else if (gs_token_compare_text(&token, "DST_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_DST_COLOR;
  2578. else if (gs_token_compare_text(&token, "ONE_MINUS_DST_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_COLOR;
  2579. else if (gs_token_compare_text(&token, "SRC_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_SRC_ALPHA;
  2580. else if (gs_token_compare_text(&token, "ONE_MINUS_SRC_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_ALPHA;
  2581. else if (gs_token_compare_text(&token, "DST_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_DST_ALPHA;
  2582. else if (gs_token_compare_text(&token, "ONE_MINUS_DST_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_ALPHA;
  2583. else if (gs_token_compare_text(&token, "CONSTANT_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_CONSTANT_COLOR;
  2584. else if (gs_token_compare_text(&token, "ONE_MINUS_CONSTANT_COLOR")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_ALPHA;
  2585. else if (gs_token_compare_text(&token, "CONSTANT_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_CONSTANT_ALPHA;
  2586. else if (gs_token_compare_text(&token, "ONE_MINUS_CONSTANT_ALPHA")) pdesc->pip_desc.blend.src = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_ALPHA;
  2587. else
  2588. {
  2589. gs_log_warning("Blend src type %.*s not valid.", token.len, token.text);
  2590. return false;
  2591. }
  2592. }
  2593. // Dest blend
  2594. else if (gs_token_compare_text(&token, "dst"))
  2595. {
  2596. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2597. {
  2598. gs_log_warning("Blend dst type not found after decl.");
  2599. return false;
  2600. }
  2601. token = lex->current_token;
  2602. if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ZERO;
  2603. else if (gs_token_compare_text(&token, "ONE")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE;
  2604. else if (gs_token_compare_text(&token, "SRC_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_SRC_COLOR;
  2605. else if (gs_token_compare_text(&token, "ONE_MINUS_SRC_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_COLOR;
  2606. else if (gs_token_compare_text(&token, "DST_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_DST_COLOR;
  2607. else if (gs_token_compare_text(&token, "ONE_MINUS_DST_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_COLOR;
  2608. else if (gs_token_compare_text(&token, "SRC_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_SRC_ALPHA;
  2609. else if (gs_token_compare_text(&token, "ONE_MINUS_SRC_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_ALPHA;
  2610. else if (gs_token_compare_text(&token, "DST_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_DST_ALPHA;
  2611. else if (gs_token_compare_text(&token, "ONE_MINUS_DST_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_ALPHA;
  2612. else if (gs_token_compare_text(&token, "CONSTANT_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_CONSTANT_COLOR;
  2613. else if (gs_token_compare_text(&token, "ONE_MINUS_CONSTANT_COLOR")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_ALPHA;
  2614. else if (gs_token_compare_text(&token, "CONSTANT_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_CONSTANT_ALPHA;
  2615. else if (gs_token_compare_text(&token, "ONE_MINUS_CONSTANT_ALPHA")) pdesc->pip_desc.blend.dst = GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_ALPHA;
  2616. else
  2617. {
  2618. gs_log_warning("Blend dst type %.*s not valid.", token.len, token.text);
  2619. return false;
  2620. }
  2621. }
  2622. });
  2623. return true;
  2624. }
  2625. bool gs_parse_stencil(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd)
  2626. {
  2627. gs_parse_block(
  2628. PIPELINE::STENCIL,
  2629. {
  2630. // Function
  2631. if (gs_token_compare_text(&token, "func"))
  2632. {
  2633. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2634. {
  2635. gs_log_warning("Stencil func type not found after decl.");
  2636. return false;
  2637. }
  2638. else
  2639. {
  2640. token = lex->current_token;
  2641. if (gs_token_compare_text(&token, "LESS")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_LESS;
  2642. else if (gs_token_compare_text(&token, "EQUAL")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_EQUAL;
  2643. else if (gs_token_compare_text(&token, "LEQUAL")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_LEQUAL;
  2644. else if (gs_token_compare_text(&token, "GREATER")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_GREATER;
  2645. else if (gs_token_compare_text(&token, "NOTEQUAL")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_NOTEQUAL;
  2646. else if (gs_token_compare_text(&token, "GEQUAL")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_GEQUAL;
  2647. else if (gs_token_compare_text(&token, "ALWAYS")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_ALWAYS;
  2648. else if (gs_token_compare_text(&token, "NEVER")) pdesc->pip_desc.stencil.func = GS_GRAPHICS_STENCIL_FUNC_NEVER;
  2649. else
  2650. {
  2651. gs_log_warning("Stencil func type %.*s not valid.", token.len, token.text);
  2652. return false;
  2653. }
  2654. }
  2655. }
  2656. // Reference value
  2657. else if (gs_token_compare_text(&token, "ref"))
  2658. {
  2659. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_NUMBER))
  2660. {
  2661. gs_log_warning("Stencil reference value not found after decl.");
  2662. return false;
  2663. }
  2664. else
  2665. {
  2666. token = lex->current_token;
  2667. gs_snprintfc(TMP, 16, "%.*s", token.len, token.text);
  2668. pdesc->pip_desc.stencil.ref = atoi(TMP);
  2669. }
  2670. }
  2671. // Component mask
  2672. else if (gs_token_compare_text(&token, "comp_mask"))
  2673. {
  2674. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_NUMBER))
  2675. {
  2676. gs_log_warning("Stencil component mask value not found after decl.");
  2677. return false;
  2678. }
  2679. else
  2680. {
  2681. token = lex->current_token;
  2682. gs_snprintfc(TMP, 16, "%.*s", token.len, token.text);
  2683. pdesc->pip_desc.stencil.comp_mask = atoi(TMP);
  2684. }
  2685. }
  2686. // Write mask
  2687. else if (gs_token_compare_text(&token, "write_mask"))
  2688. {
  2689. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_NUMBER))
  2690. {
  2691. gs_log_warning("Stencil write mask value not found after decl.");
  2692. return false;
  2693. }
  2694. else
  2695. {
  2696. token = lex->current_token;
  2697. gs_snprintfc(TMP, 16, "%.*s", token.len, token.text);
  2698. pdesc->pip_desc.stencil.write_mask = atoi(TMP);
  2699. }
  2700. }
  2701. // Stencil test failure
  2702. else if (gs_token_compare_text(&token, "sfail"))
  2703. {
  2704. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2705. {
  2706. gs_log_warning("Stencil sfail value not found after decl.");
  2707. return false;
  2708. }
  2709. else
  2710. {
  2711. token = lex->current_token;
  2712. if (gs_token_compare_text(&token, "KEEP")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_KEEP;
  2713. else if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_ZERO;
  2714. else if (gs_token_compare_text(&token, "REPLACE")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_REPLACE;
  2715. else if (gs_token_compare_text(&token, "INCR")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_INCR;
  2716. else if (gs_token_compare_text(&token, "INCR_WRAP")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_INCR_WRAP;
  2717. else if (gs_token_compare_text(&token, "DECR")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_DECR;
  2718. else if (gs_token_compare_text(&token, "DECR_WRAP")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_DECR_WRAP;
  2719. else if (gs_token_compare_text(&token, "INVERT")) pdesc->pip_desc.stencil.sfail = GS_GRAPHICS_STENCIL_OP_INVERT;
  2720. else
  2721. {
  2722. gs_log_warning("Stencil sfail type %.*s not valid.", token.len, token.text);
  2723. return false;
  2724. }
  2725. }
  2726. }
  2727. // Stencil test pass, Depth fail
  2728. else if (gs_token_compare_text(&token, "dpfail"))
  2729. {
  2730. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2731. {
  2732. gs_log_warning("Stencil dpfail value not found after decl.");
  2733. return false;
  2734. }
  2735. else
  2736. {
  2737. token = lex->current_token;
  2738. if (gs_token_compare_text(&token, "KEEP")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_KEEP;
  2739. else if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_ZERO;
  2740. else if (gs_token_compare_text(&token, "REPLACE")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_REPLACE;
  2741. else if (gs_token_compare_text(&token, "INCR")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_INCR;
  2742. else if (gs_token_compare_text(&token, "INCR_WRAP")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_INCR_WRAP;
  2743. else if (gs_token_compare_text(&token, "DECR")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_DECR;
  2744. else if (gs_token_compare_text(&token, "DECR_WRAP")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_DECR_WRAP;
  2745. else if (gs_token_compare_text(&token, "INVERT")) pdesc->pip_desc.stencil.dpfail = GS_GRAPHICS_STENCIL_OP_INVERT;
  2746. else
  2747. {
  2748. gs_log_warning("Stencil dpfail type %.*s not valid.", token.len, token.text);
  2749. return false;
  2750. }
  2751. }
  2752. }
  2753. // Stencil test pass, Depth pass
  2754. else if (gs_token_compare_text(&token, "dppass"))
  2755. {
  2756. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2757. {
  2758. gs_log_warning("Stencil dppass value not found after decl.");
  2759. return false;
  2760. }
  2761. else
  2762. {
  2763. token = lex->current_token;
  2764. if (gs_token_compare_text(&token, "KEEP")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_KEEP;
  2765. else if (gs_token_compare_text(&token, "ZERO")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_ZERO;
  2766. else if (gs_token_compare_text(&token, "REPLACE")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_REPLACE;
  2767. else if (gs_token_compare_text(&token, "INCR")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_INCR;
  2768. else if (gs_token_compare_text(&token, "INCR_WRAP")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_INCR_WRAP;
  2769. else if (gs_token_compare_text(&token, "DECR")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_DECR;
  2770. else if (gs_token_compare_text(&token, "DECR_WRAP")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_DECR_WRAP;
  2771. else if (gs_token_compare_text(&token, "INVERT")) pdesc->pip_desc.stencil.dppass = GS_GRAPHICS_STENCIL_OP_INVERT;
  2772. else
  2773. {
  2774. gs_log_warning("Stencil dppass type %.*s not valid.", token.len, token.text);
  2775. return false;
  2776. }
  2777. }
  2778. }
  2779. });
  2780. return true;
  2781. }
  2782. bool gs_parse_raster(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd)
  2783. {
  2784. gs_parse_block(
  2785. PIPELINE::RASTER,
  2786. {
  2787. // Index Buffer Element Size
  2788. if (gs_token_compare_text(&token, "index_buffer_element_size"))
  2789. {
  2790. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2791. {
  2792. gs_log_warning("Raster index buffer element size not found.", token.len, token.text);
  2793. }
  2794. token = lex->current_token;
  2795. if (gs_token_compare_text(&token, "UINT32") || gs_token_compare_text(&token, "uint32_t") || gs_token_compare_text(&token, "u32"))
  2796. {
  2797. pdesc->pip_desc.raster.index_buffer_element_size = sizeof(uint32_t);
  2798. }
  2799. else if (gs_token_compare_text(&token, "UINT16") || gs_token_compare_text(&token, "uint16_t") || gs_token_compare_text(&token, "u16"))
  2800. {
  2801. pdesc->pip_desc.raster.index_buffer_element_size = sizeof(uint16_t);
  2802. }
  2803. // Default
  2804. else
  2805. {
  2806. pdesc->pip_desc.raster.index_buffer_element_size = sizeof(uint32_t);
  2807. }
  2808. }
  2809. // Face culling
  2810. if (gs_token_compare_text(&token, "face_culling"))
  2811. {
  2812. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2813. {
  2814. gs_log_warning("Raster face culling type not found.");
  2815. return false;
  2816. }
  2817. token = lex->current_token;
  2818. if (gs_token_compare_text(&token, "FRONT")) pdesc->pip_desc.raster.face_culling = GS_GRAPHICS_FACE_CULLING_FRONT;
  2819. else if (gs_token_compare_text(&token, "BACK")) pdesc->pip_desc.raster.face_culling = GS_GRAPHICS_FACE_CULLING_BACK;
  2820. else if (gs_token_compare_text(&token, "FRONT_AND_BACK")) pdesc->pip_desc.raster.face_culling = GS_GRAPHICS_FACE_CULLING_FRONT_AND_BACK;
  2821. else
  2822. {
  2823. gs_log_warning("Raster face culling type %.*s not valid.", token.len, token.text);
  2824. return false;
  2825. }
  2826. }
  2827. // Winding order
  2828. if (gs_token_compare_text(&token, "winding_order"))
  2829. {
  2830. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2831. {
  2832. gs_log_warning("Raster winding order type not found.");
  2833. return false;
  2834. }
  2835. token = lex->current_token;
  2836. if (gs_token_compare_text(&token, "CW")) pdesc->pip_desc.raster.winding_order = GS_GRAPHICS_WINDING_ORDER_CW;
  2837. else if (gs_token_compare_text(&token, "CCW")) pdesc->pip_desc.raster.winding_order = GS_GRAPHICS_WINDING_ORDER_CCW;
  2838. else
  2839. {
  2840. gs_log_warning("Raster winding order type %.*s not valid.", token.len, token.text);
  2841. return false;
  2842. }
  2843. }
  2844. // Primtive
  2845. if (gs_token_compare_text(&token, "primitive"))
  2846. {
  2847. if (!gs_lexer_find_next_token_type(lex, GS_TOKEN_IDENTIFIER))
  2848. {
  2849. gs_log_warning("Raster primitive type not found.");
  2850. return false;
  2851. }
  2852. token = lex->current_token;
  2853. if (gs_token_compare_text(&token, "LINES")) pdesc->pip_desc.raster.primitive = GS_GRAPHICS_PRIMITIVE_LINES;
  2854. else if (gs_token_compare_text(&token, "TRIANGLES")) pdesc->pip_desc.raster.primitive = GS_GRAPHICS_PRIMITIVE_TRIANGLES;
  2855. else if (gs_token_compare_text(&token, "QUADS")) pdesc->pip_desc.raster.primitive = GS_GRAPHICS_PRIMITIVE_QUADS;
  2856. else
  2857. {
  2858. gs_log_warning("Raster primitive type %.*s not valid.", token.len, token.text);
  2859. return false;
  2860. }
  2861. }
  2862. });
  2863. return true;
  2864. }
  2865. bool gs_parse_pipeline(gs_lexer_t* lex, gs_gfxt_pipeline_desc_t* desc, gs_ppd_t* ppd)
  2866. {
  2867. // Get next identifier
  2868. while (lex->can_lex(lex))
  2869. {
  2870. gs_token_t token = lex->next_token(lex);
  2871. switch (token.type)
  2872. {
  2873. case GS_TOKEN_IDENTIFIER:
  2874. {
  2875. if (gs_token_compare_text(&token, "shader"))
  2876. {
  2877. gs_println("parsing shader");
  2878. if (!gs_parse_shader(lex, desc, ppd))
  2879. {
  2880. gs_log_warning("Unable to parse shader descriptor");
  2881. return false;
  2882. }
  2883. }
  2884. else if (gs_token_compare_text(&token, "raster"))
  2885. {
  2886. if (!gs_parse_raster(lex, desc, ppd))
  2887. {
  2888. gs_log_warning("Unable to parse raster descriptor");
  2889. return false;
  2890. }
  2891. }
  2892. else if (gs_token_compare_text(&token, "depth"))
  2893. {
  2894. if (!gs_parse_depth(lex, desc, ppd))
  2895. {
  2896. gs_log_warning("Unable to parse depth descriptor");
  2897. return false;
  2898. }
  2899. }
  2900. else if (gs_token_compare_text(&token, "stencil"))
  2901. {
  2902. if (!gs_parse_stencil(lex, desc, ppd))
  2903. {
  2904. gs_log_warning("Unable to parse stencil descriptor");
  2905. return false;
  2906. }
  2907. }
  2908. else if (gs_token_compare_text(&token, "blend"))
  2909. {
  2910. if (!gs_parse_blend(lex, desc, ppd))
  2911. {
  2912. gs_log_warning("Unable to parse blend descriptor");
  2913. return false;
  2914. }
  2915. }
  2916. } break;
  2917. }
  2918. }
  2919. return true;
  2920. }
  2921. char* gs_pipeline_generate_shader_code(gs_gfxt_pipeline_desc_t* pdesc, gs_ppd_t* ppd, gs_graphics_shader_stage_type stage)
  2922. {
  2923. gs_println("GENERATING CODE...");
  2924. // Get major/minor version of shader
  2925. gs_graphics_info_t* ginfo = gs_graphics_info();
  2926. gs_snprintfc(MAJMINSTR, 128, "#version %zu%zu0\n", ginfo->major_version, ginfo->minor_version);
  2927. // Shaders
  2928. #ifdef GS_PLATFORM_WEB
  2929. #define _GS_VERSION_STR "#version 300 es\n"
  2930. #else
  2931. #define _GS_VERSION_STR "#version 430\n"
  2932. #endif
  2933. // Source code
  2934. char* src = NULL;
  2935. uint32_t sidx = 0;
  2936. // Set sidx
  2937. switch (stage)
  2938. {
  2939. case GS_GRAPHICS_SHADER_STAGE_VERTEX: sidx = 0; break;
  2940. case GS_GRAPHICS_SHADER_STAGE_FRAGMENT: sidx = 1; break;
  2941. case GS_GRAPHICS_SHADER_STAGE_COMPUTE: sidx = 2; break;
  2942. }
  2943. // Early out for now...
  2944. if (!ppd->code[sidx])
  2945. {
  2946. return src;
  2947. }
  2948. // Shader header
  2949. gs_snprintfc(shader_header, 512, "%s precision mediump float;\n", stage == GS_GRAPHICS_SHADER_STAGE_COMPUTE ? "#version 430\n" : _GS_VERSION_STR);
  2950. // Generate shader code
  2951. if (ppd->code[sidx])
  2952. {
  2953. const size_t header_sz = (size_t)gs_string_length(shader_header);
  2954. size_t total_sz = gs_string_length(ppd->code[sidx]) + header_sz + 2048;
  2955. src = (char*)gs_malloc(total_sz);
  2956. memset(src, 0, total_sz);
  2957. strncat(src, shader_header, header_sz);
  2958. // Attributes
  2959. if (stage == GS_GRAPHICS_SHADER_STAGE_VERTEX)
  2960. {
  2961. for (uint32_t i = 0; i < gs_dyn_array_size(pdesc->pip_desc.layout.attrs); ++i)
  2962. {
  2963. const char* aname = pdesc->pip_desc.layout.attrs[i].name;
  2964. const char* atype = gs_get_vertex_attribute_string(pdesc->pip_desc.layout.attrs[i].format);
  2965. gs_snprintfc(ATTR, 64, "layout(location = %zu) in %s %s;\n", i, atype, aname);
  2966. const size_t sz = gs_string_length(ATTR);
  2967. strncat(src, ATTR, sz);
  2968. }
  2969. }
  2970. // Compute shader image buffer binding
  2971. uint32_t img_binding = 0;
  2972. // Uniforms
  2973. for (uint32_t i = 0; i < gs_dyn_array_size(pdesc->ublock_desc.layout); ++i)
  2974. {
  2975. gs_gfxt_uniform_desc_t* udesc = &pdesc->ublock_desc.layout[i];
  2976. if (udesc->stage != stage) continue;
  2977. switch (stage)
  2978. {
  2979. case GS_GRAPHICS_SHADER_STAGE_COMPUTE:
  2980. {
  2981. // Need to go from uniform type to string
  2982. const char* utype = gs_uniform_string_from_type(udesc->type);
  2983. const char* uname = udesc->name;
  2984. switch (udesc->type)
  2985. {
  2986. default:
  2987. {
  2988. gs_snprintfc(TMP, 64, "uniform %s %s;\n", utype, uname);
  2989. const size_t sz = gs_string_length(TMP);
  2990. strncat(src, TMP, sz);
  2991. } break;
  2992. case GS_GRAPHICS_UNIFORM_IMAGE2D_RGBA32F:
  2993. {
  2994. gs_snprintfc(TMP, 64, "layout (rgba32f, binding = %zu) uniform image2D %s;\n", img_binding++, uname);
  2995. const size_t sz = gs_string_length(TMP);
  2996. strncat(src, TMP, sz);
  2997. } break;
  2998. }
  2999. } break;
  3000. default:
  3001. {
  3002. // Need to go from uniform type to string
  3003. const char* utype = gs_uniform_string_from_type(udesc->type);
  3004. const char* uname = udesc->name;
  3005. gs_snprintfc(TMP, 64, "uniform %s %s;\n", utype, uname);
  3006. const size_t sz = gs_string_length(TMP);
  3007. strncat(src, TMP, sz);
  3008. } break;
  3009. }
  3010. }
  3011. // Out
  3012. switch (stage)
  3013. {
  3014. case GS_GRAPHICS_SHADER_STAGE_FRAGMENT:
  3015. case GS_GRAPHICS_SHADER_STAGE_VERTEX:
  3016. {
  3017. for (uint32_t i = 0; i < gs_dyn_array_size(ppd->io_list[sidx]); ++i)
  3018. {
  3019. gs_shader_io_data_t* out = &ppd->io_list[sidx][i];
  3020. const char* otype = out->type;
  3021. const char* oname = out->name;
  3022. gs_transient_buffer(TMP, 64);
  3023. if (stage == GS_GRAPHICS_SHADER_STAGE_FRAGMENT)
  3024. {
  3025. gs_snprintf(TMP, 64, "layout(location = %zu) out %s %s;\n", i, otype, oname);
  3026. }
  3027. else
  3028. {
  3029. gs_snprintf(TMP, 64, "out %s %s;\n", otype, oname);
  3030. }
  3031. const size_t sz = gs_string_length(TMP);
  3032. strncat(src, TMP, sz);
  3033. }
  3034. } break;
  3035. default: break;
  3036. }
  3037. // In
  3038. switch (stage)
  3039. {
  3040. case GS_GRAPHICS_SHADER_STAGE_FRAGMENT:
  3041. {
  3042. for (uint32_t i = 0; i < gs_dyn_array_size(ppd->io_list[0]); ++i)
  3043. {
  3044. gs_shader_io_data_t* out = &ppd->io_list[0][i];
  3045. const char* otype = out->type;
  3046. const char* oname = out->name;
  3047. gs_snprintfc(TMP, 64, "in %s %s;\n", otype, oname);
  3048. const size_t sz = gs_string_length(TMP);
  3049. strncat(src, TMP, sz);
  3050. }
  3051. } break;
  3052. case GS_GRAPHICS_SHADER_STAGE_COMPUTE:
  3053. {
  3054. /*
  3055. gs_snprintfc(TMP, 64, "layout(");
  3056. strncat(src, "layout(", 7);
  3057. for (uint32_t i = 0; i < gs_dyn_array_size(ppd->io_list[2]); ++i)
  3058. {
  3059. gs_shader_io_data_t* out = &ppd->io_list[2][i];
  3060. const char* otype = out->type;
  3061. const char* oname = out->name;
  3062. gs_snprintfc(TMP, 64, "%s = %s%s", otype, oname, i == gs_dyn_array_size(ppd->io_list[2]) - 1 ? "" : ", ");
  3063. const size_t sz = gs_string_length(TMP);
  3064. strncat(src, TMP, sz);
  3065. }
  3066. strncat(src, ") in;\n", 7);
  3067. */
  3068. } break;
  3069. default: break;
  3070. }
  3071. // Code
  3072. {
  3073. const size_t sz = gs_string_length(ppd->code[sidx]);
  3074. strncat(src, ppd->code[sidx], sz);
  3075. }
  3076. }
  3077. return src;
  3078. }
  3079. GS_API_DECL gs_gfxt_pipeline_t
  3080. gs_gfxt_pipeline_load_from_file(const char* path)
  3081. {
  3082. // Load file, generate lexer off of file data, parse contents for pipeline information
  3083. size_t len = 0;
  3084. char* file_data = gs_platform_read_file_contents(path, "rb", &len);
  3085. gs_assert(file_data);
  3086. gs_log_success("Parsing pipeline: %s", path);
  3087. gs_gfxt_pipeline_t pip = gs_gfxt_pipeline_load_from_memory_ext(file_data, len, path);
  3088. gs_free(file_data);
  3089. return pip;
  3090. }
  3091. GS_API_DECL gs_gfxt_pipeline_t
  3092. gs_gfxt_pipeline_load_from_memory(const char* file_data, size_t sz)
  3093. {
  3094. return gs_gfxt_pipeline_load_from_memory_ext(file_data, sz, ".");
  3095. }
  3096. GS_API_DECL gs_gfxt_pipeline_t
  3097. gs_gfxt_pipeline_load_from_memory_ext(const char* file_data, size_t sz, const char* file_path)
  3098. {
  3099. // Cast to pip
  3100. gs_gfxt_pipeline_t pip = gs_default_val();
  3101. gs_ppd_t ppd = gs_default_val();
  3102. gs_gfxt_pipeline_desc_t pdesc = gs_default_val();
  3103. pdesc.pip_desc.raster.index_buffer_element_size = sizeof(uint32_t);
  3104. // Determine original file directory from path
  3105. if (file_path)
  3106. {
  3107. gs_lexer_t lex = gs_lexer_c_ctor(file_path);
  3108. gs_token_t tparen = {0};
  3109. while (lex.can_lex(&lex))
  3110. {
  3111. gs_token_t token = lex.next_token(&lex);
  3112. // Look for last paren + identifier combo
  3113. switch (token.type)
  3114. {
  3115. case GS_TOKEN_FSLASH:
  3116. case GS_TOKEN_BSLASH:
  3117. {
  3118. tparen = token;
  3119. } break;
  3120. }
  3121. }
  3122. // Now save dir
  3123. gs_println("HERE: %zu", tparen.text - file_path);
  3124. memcpy(ppd.dir, file_path, tparen.text - file_path);
  3125. gs_println("PPD_DIR: %s", ppd.dir);
  3126. }
  3127. gs_lexer_t lex = gs_lexer_c_ctor(file_data);
  3128. while (lex.can_lex(&lex))
  3129. {
  3130. gs_token_t token = lex.next_token(&lex);
  3131. switch (token.type)
  3132. {
  3133. case GS_TOKEN_IDENTIFIER:
  3134. {
  3135. if (gs_token_compare_text(&token, "pipeline"))
  3136. {
  3137. if (!gs_parse_pipeline(&lex, &pdesc, &ppd))
  3138. {
  3139. gs_log_warning("Unable to parse pipeline");
  3140. return pip;
  3141. }
  3142. }
  3143. } break;
  3144. }
  3145. }
  3146. // Generate vertex shader code
  3147. char* v_src = gs_pipeline_generate_shader_code(&pdesc, &ppd, GS_GRAPHICS_SHADER_STAGE_VERTEX);
  3148. // gs_println("%s", v_src);
  3149. // Generate fragment shader code
  3150. char* f_src = gs_pipeline_generate_shader_code(&pdesc, &ppd, GS_GRAPHICS_SHADER_STAGE_FRAGMENT);
  3151. // gs_println("%s", f_src);
  3152. // Generate compute shader code (need to check for this first)
  3153. char* c_src = gs_pipeline_generate_shader_code(&pdesc, &ppd, GS_GRAPHICS_SHADER_STAGE_COMPUTE);
  3154. // gs_println("%s", c_src);
  3155. // Construct compute shader
  3156. if (c_src)
  3157. {
  3158. gs_graphics_shader_desc_t sdesc = gs_default_val();
  3159. gs_graphics_shader_source_desc_t source_desc[1] = gs_default_val();
  3160. source_desc[0].type = GS_GRAPHICS_SHADER_STAGE_COMPUTE;
  3161. source_desc[0].source = c_src;
  3162. sdesc.sources = source_desc;
  3163. sdesc.size = 1 * sizeof(gs_graphics_shader_source_desc_t);
  3164. pdesc.pip_desc.compute.shader = gs_graphics_shader_create(&sdesc);
  3165. }
  3166. // Construct raster shader
  3167. else
  3168. {
  3169. gs_graphics_shader_desc_t sdesc = gs_default_val();
  3170. gs_graphics_shader_source_desc_t source_desc[2] = gs_default_val();
  3171. source_desc[0].type = GS_GRAPHICS_SHADER_STAGE_VERTEX;
  3172. source_desc[0].source = v_src;
  3173. source_desc[1].type = GS_GRAPHICS_SHADER_STAGE_FRAGMENT;
  3174. source_desc[1].source = f_src;
  3175. sdesc.sources = source_desc;
  3176. sdesc.size = 2 * sizeof(gs_graphics_shader_source_desc_t);
  3177. pdesc.pip_desc.raster.shader = gs_graphics_shader_create(&sdesc);
  3178. }
  3179. // Set up layout
  3180. pdesc.pip_desc.layout.size = gs_dyn_array_size(pdesc.pip_desc.layout.attrs) * sizeof(gs_graphics_vertex_attribute_desc_t);
  3181. // Set up ublock
  3182. pdesc.ublock_desc.size = gs_dyn_array_size(pdesc.ublock_desc.layout) * sizeof(gs_gfxt_uniform_desc_t);
  3183. // Create pipeline
  3184. pip = gs_gfxt_pipeline_create(&pdesc);
  3185. // Create mesh layout
  3186. if (ppd.mesh_layout)
  3187. {
  3188. for (uint32_t i = 0; i < gs_dyn_array_size(ppd.mesh_layout); ++i)
  3189. {
  3190. gs_dyn_array_push(pip.mesh_layout, ppd.mesh_layout[i]);
  3191. }
  3192. }
  3193. // Free all malloc'd data
  3194. if (v_src) gs_free(v_src);
  3195. if (f_src) gs_free(f_src);
  3196. if (c_src) gs_free(c_src);
  3197. gs_dyn_array_free(pdesc.ublock_desc.layout);
  3198. gs_dyn_array_free(pdesc.pip_desc.layout.attrs);
  3199. gs_dyn_array_free(ppd.mesh_layout);
  3200. gs_dyn_array_free(ppd.vertex_layout);
  3201. for (uint32_t i = 0; i < 3; ++i)
  3202. {
  3203. if (ppd.code[i]) gs_free(ppd.code[i]);
  3204. gs_dyn_array_free(ppd.io_list[i]);
  3205. }
  3206. return pip;
  3207. }
  3208. GS_API_DECL gs_gfxt_texture_t
  3209. gs_gfxt_texture_load_from_file(const char* path, gs_graphics_texture_desc_t* desc, bool flip, bool keep_data)
  3210. {
  3211. gs_asset_texture_t tex = gs_default_val();
  3212. gs_asset_texture_load_from_file(path, &tex, desc, flip, keep_data);
  3213. if (desc) {
  3214. *desc = tex.desc;
  3215. }
  3216. return tex.hndl;
  3217. }
  3218. 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)
  3219. {
  3220. gs_asset_texture_t tex = gs_default_val();
  3221. gs_asset_texture_load_from_memory(data, sz, &tex, desc, flip, keep_data);
  3222. if (desc) {
  3223. *desc = tex.desc;
  3224. }
  3225. return tex.hndl;
  3226. }
  3227. #endif // GS_GFXT_IMPL
  3228. #endif // GS_GFXT_H
  3229. /*
  3230. */