sokol_gfx_imgui.h 133 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455
  1. #pragma once
  2. /*
  3. sokol_gfx_imgui.h -- debug-inspection UI for sokol_gfx.h using Dear ImGui
  4. Do this:
  5. #define SOKOL_GFX_IMGUI_IMPL
  6. before you include this file in *one* C++ file to create the
  7. implementation.
  8. NOTE that the implementation must be compiled as C++ or Objective-C++
  9. because it calls into the ImGui C++ API. The sokol_gfx_imgui.h API
  10. itself is plain C though.
  11. Include the following file(s) before including sokol_gfx_imgui.h:
  12. sokol_gfx.h
  13. Additionally, include the following files(s) beforing including
  14. the implementation of sokol_gfx_imgui.h:
  15. imgui.h
  16. The sokol_gfx.h implementation must be compiled with debug trace hooks
  17. enabled by defining:
  18. SOKOL_TRACE_HOOKS
  19. ...before including the sokol_gfx.h implementation.
  20. Before including the sokol_gfx_imgui.h implementation, optionally
  21. override the following macros:
  22. SOKOL_ASSERT(c) -- your own assert macro, default: assert(c)
  23. SOKOL_UNREACHABLE -- your own macro to annotate unreachable code,
  24. default: SOKOL_ASSERT(false)
  25. SOKOL_MALLOC(s) -- your own memory allocation function, default: malloc(s)
  26. SOKOL_FREE(p) -- your own memory free function, default: free(p)
  27. SOKOL_API_DECL - public function declaration prefix (default: extern)
  28. SOKOL_API_IMPL - public function implementation prefix (default: -)
  29. STEP BY STEP:
  30. =============
  31. --- create an sg_imgui_t struct (which must be preserved between frames)
  32. and initialize it with:
  33. sg_imgui_init(&sg_imgui);
  34. --- somewhere in the per-frame code call:
  35. sg_imgui_draw(&sg_imgui)
  36. this won't draw anything yet, since no windows are open.
  37. --- open and close windows directly by setting the following public
  38. booleans in the sg_imgui_t struct:
  39. sg_imgui.buffers.open = true;
  40. sg_imgui.images.open = true;
  41. sg_imgui.shaders.open = true;
  42. sg_imgui.pipelines.open = true;
  43. sg_imgui.passes.open = true;
  44. sg_imgui.capture.open = true;
  45. ...for instance, to control the window visibility through
  46. menu items, the following code can be used:
  47. if (ImGui::BeginMainMenuBar()) {
  48. if (ImGui::BeginMenu("sokol-gfx")) {
  49. ImGui::MenuItem("Buffers", 0, &sg_imgui.buffers.open);
  50. ImGui::MenuItem("Images", 0, &sg_imgui.images.open);
  51. ImGui::MenuItem("Shaders", 0, &sg_imgui.shaders.open);
  52. ImGui::MenuItem("Pipelines", 0, &sg_imgui.pipelines.open);
  53. ImGui::MenuItem("Passes", 0, &sg_imgui.passes.open);
  54. ImGui::MenuItem("Calls", 0, &sg_imgui.capture.open);
  55. ImGui::EndMenu();
  56. }
  57. ImGui::EndMainMenuBar();
  58. }
  59. --- before application shutdown, call:
  60. sg_imgui_discard(&sg_imgui);
  61. ...this is not strictly necessary because the application exits
  62. anyway, but not doing this may trigger memory leak detection tools.
  63. --- finally, your application needs an ImGui renderer, you can either
  64. provide your own, or drop in the sokol_imgui.h utility header
  65. ALTERNATIVE DRAWING FUNCTIONS:
  66. ==============================
  67. Instead of the convenient, but all-in-one sg_imgui_draw() function,
  68. you can also use the following granular functions which might allow
  69. better integration with your existing UI:
  70. The following functions only render the window *content* (so you
  71. can integrate the UI into you own windows):
  72. void sg_imgui_draw_buffers_content(sg_imgui_t* ctx);
  73. void sg_imgui_draw_images_content(sg_imgui_t* ctx);
  74. void sg_imgui_draw_shaders_content(sg_imgui_t* ctx);
  75. void sg_imgui_draw_pipelines_content(sg_imgui_t* ctx);
  76. void sg_imgui_draw_passes_content(sg_imgui_t* ctx);
  77. void sg_imgui_draw_capture_content(sg_imgui_t* ctx);
  78. And these are the 'full window' drawing functions:
  79. void sg_imgui_draw_buffers_window(sg_imgui_t* ctx);
  80. void sg_imgui_draw_images_window(sg_imgui_t* ctx);
  81. void sg_imgui_draw_shaders_window(sg_imgui_t* ctx);
  82. void sg_imgui_draw_pipelines_window(sg_imgui_t* ctx);
  83. void sg_imgui_draw_passes_window(sg_imgui_t* ctx);
  84. void sg_imgui_draw_capture_window(sg_imgui_t* ctx);
  85. Finer-grained drawing functions may be moved to the public API
  86. in the future as needed.
  87. LICENSE
  88. =======
  89. zlib/libpng license
  90. Copyright (c) 2018 Andre Weissflog
  91. This software is provided 'as-is', without any express or implied warranty.
  92. In no event will the authors be held liable for any damages arising from the
  93. use of this software.
  94. Permission is granted to anyone to use this software for any purpose,
  95. including commercial applications, and to alter it and redistribute it
  96. freely, subject to the following restrictions:
  97. 1. The origin of this software must not be misrepresented; you must not
  98. claim that you wrote the original software. If you use this software in a
  99. product, an acknowledgment in the product documentation would be
  100. appreciated but is not required.
  101. 2. Altered source versions must be plainly marked as such, and must not
  102. be misrepresented as being the original software.
  103. 3. This notice may not be removed or altered from any source
  104. distribution.
  105. */
  106. #include <stdint.h>
  107. #include <stdbool.h>
  108. #if !defined(SOKOL_GFX_INCLUDED)
  109. #error "Please include sokol_gfx.h before sokol_gfx_imgui.h"
  110. #endif
  111. #ifndef SOKOL_API_DECL
  112. #define SOKOL_API_DECL extern
  113. #endif
  114. #if defined(__cplusplus)
  115. extern "C" {
  116. #endif
  117. #define SG_IMGUI_STRBUF_LEN (96)
  118. /* max number of captured calls per frame */
  119. #define SG_IMGUI_MAX_FRAMECAPTURE_ITEMS (4096)
  120. typedef struct {
  121. char buf[SG_IMGUI_STRBUF_LEN];
  122. } sg_imgui_str_t;
  123. typedef struct {
  124. sg_buffer res_id;
  125. sg_imgui_str_t label;
  126. sg_buffer_desc desc;
  127. } sg_imgui_buffer_t;
  128. typedef struct {
  129. sg_image res_id;
  130. float ui_scale;
  131. sg_imgui_str_t label;
  132. sg_image_desc desc;
  133. } sg_imgui_image_t;
  134. typedef struct {
  135. sg_shader res_id;
  136. sg_imgui_str_t label;
  137. sg_imgui_str_t vs_entry;
  138. sg_imgui_str_t vs_image_name[SG_MAX_SHADERSTAGE_IMAGES];
  139. sg_imgui_str_t vs_uniform_name[SG_MAX_SHADERSTAGE_UBS][SG_MAX_UB_MEMBERS];
  140. sg_imgui_str_t fs_entry;
  141. sg_imgui_str_t fs_image_name[SG_MAX_SHADERSTAGE_IMAGES];
  142. sg_imgui_str_t fs_uniform_name[SG_MAX_SHADERSTAGE_UBS][SG_MAX_UB_MEMBERS];
  143. sg_shader_desc desc;
  144. } sg_imgui_shader_t;
  145. typedef struct {
  146. sg_pipeline res_id;
  147. sg_imgui_str_t label;
  148. sg_imgui_str_t attr_name[SG_MAX_VERTEX_ATTRIBUTES];
  149. sg_imgui_str_t attr_sem_name[SG_MAX_VERTEX_ATTRIBUTES];
  150. sg_pipeline_desc desc;
  151. } sg_imgui_pipeline_t;
  152. typedef struct {
  153. sg_pass res_id;
  154. sg_imgui_str_t label;
  155. float color_image_scale[SG_MAX_COLOR_ATTACHMENTS];
  156. float ds_image_scale;
  157. sg_pass_desc desc;
  158. } sg_imgui_pass_t;
  159. typedef struct {
  160. bool open;
  161. int num_slots;
  162. sg_buffer sel_buf;
  163. sg_imgui_buffer_t* slots;
  164. } sg_imgui_buffers_t;
  165. typedef struct {
  166. bool open;
  167. int num_slots;
  168. sg_image sel_img;
  169. sg_imgui_image_t* slots;
  170. } sg_imgui_images_t;
  171. typedef struct {
  172. bool open;
  173. int num_slots;
  174. sg_shader sel_shd;
  175. sg_imgui_shader_t* slots;
  176. } sg_imgui_shaders_t;
  177. typedef struct {
  178. bool open;
  179. int num_slots;
  180. sg_pipeline sel_pip;
  181. sg_imgui_pipeline_t* slots;
  182. } sg_imgui_pipelines_t;
  183. typedef struct {
  184. bool open;
  185. int num_slots;
  186. sg_pass sel_pass;
  187. sg_imgui_pass_t* slots;
  188. } sg_imgui_passes_t;
  189. typedef enum {
  190. SG_IMGUI_CMD_INVALID,
  191. SG_IMGUI_CMD_QUERY_FEATURE,
  192. SG_IMGUI_CMD_RESET_STATE_CACHE,
  193. SG_IMGUI_CMD_MAKE_BUFFER,
  194. SG_IMGUI_CMD_MAKE_IMAGE,
  195. SG_IMGUI_CMD_MAKE_SHADER,
  196. SG_IMGUI_CMD_MAKE_PIPELINE,
  197. SG_IMGUI_CMD_MAKE_PASS,
  198. SG_IMGUI_CMD_DESTROY_BUFFER,
  199. SG_IMGUI_CMD_DESTROY_IMAGE,
  200. SG_IMGUI_CMD_DESTROY_SHADER,
  201. SG_IMGUI_CMD_DESTROY_PIPELINE,
  202. SG_IMGUI_CMD_DESTROY_PASS,
  203. SG_IMGUI_CMD_UPDATE_BUFFER,
  204. SG_IMGUI_CMD_UPDATE_IMAGE,
  205. SG_IMGUI_CMD_APPEND_BUFFER,
  206. SG_IMGUI_CMD_BEGIN_DEFAULT_PASS,
  207. SG_IMGUI_CMD_BEGIN_PASS,
  208. SG_IMGUI_CMD_APPLY_VIEWPORT,
  209. SG_IMGUI_CMD_APPLY_SCISSOR_RECT,
  210. SG_IMGUI_CMD_APPLY_PIPELINE,
  211. SG_IMGUI_CMD_APPLY_BINDINGS,
  212. SG_IMGUI_CMD_APPLY_UNIFORMS,
  213. SG_IMGUI_CMD_DRAW,
  214. SG_IMGUI_CMD_END_PASS,
  215. SG_IMGUI_CMD_COMMIT,
  216. SG_IMGUI_CMD_ALLOC_BUFFER,
  217. SG_IMGUI_CMD_ALLOC_IMAGE,
  218. SG_IMGUI_CMD_ALLOC_SHADER,
  219. SG_IMGUI_CMD_ALLOC_PIPELINE,
  220. SG_IMGUI_CMD_ALLOC_PASS,
  221. SG_IMGUI_CMD_INIT_BUFFER,
  222. SG_IMGUI_CMD_INIT_IMAGE,
  223. SG_IMGUI_CMD_INIT_SHADER,
  224. SG_IMGUI_CMD_INIT_PIPELINE,
  225. SG_IMGUI_CMD_INIT_PASS,
  226. SG_IMGUI_CMD_FAIL_BUFFER,
  227. SG_IMGUI_CMD_FAIL_IMAGE,
  228. SG_IMGUI_CMD_FAIL_SHADER,
  229. SG_IMGUI_CMD_FAIL_PIPELINE,
  230. SG_IMGUI_CMD_FAIL_PASS,
  231. SG_IMGUI_CMD_PUSH_DEBUG_GROUP,
  232. SG_IMGUI_CMD_POP_DEBUG_GROUP,
  233. SG_IMGUI_CMD_ERR_BUFFER_POOL_EXHAUSTED,
  234. SG_IMGUI_CMD_ERR_IMAGE_POOL_EXHAUSTED,
  235. SG_IMGUI_CMD_ERR_SHADER_POOL_EXHAUSTED,
  236. SG_IMGUI_CMD_ERR_PIPELINE_POOL_EXHAUSTED,
  237. SG_IMGUI_CMD_ERR_PASS_POOL_EXHAUSTED,
  238. SG_IMGUI_CMD_ERR_CONTEXT_MISMATCH,
  239. SG_IMGUI_CMD_ERR_PASS_INVALID,
  240. SG_IMGUI_CMD_ERR_DRAW_INVALID,
  241. SG_IMGUI_CMD_ERR_BINDINGS_INVALID,
  242. } sg_imgui_cmd_t;
  243. typedef struct {
  244. sg_feature feature;
  245. bool result;
  246. } sg_imgui_args_query_feature_t;
  247. typedef struct {
  248. sg_buffer result;
  249. } sg_imgui_args_make_buffer_t;
  250. typedef struct {
  251. sg_image result;
  252. } sg_imgui_args_make_image_t;
  253. typedef struct {
  254. sg_shader result;
  255. } sg_imgui_args_make_shader_t;
  256. typedef struct {
  257. sg_pipeline result;
  258. } sg_imgui_args_make_pipeline_t;
  259. typedef struct {
  260. sg_pass result;
  261. } sg_imgui_args_make_pass_t;
  262. typedef struct {
  263. sg_buffer buffer;
  264. } sg_imgui_args_destroy_buffer_t;
  265. typedef struct {
  266. sg_image image;
  267. } sg_imgui_args_destroy_image_t;
  268. typedef struct {
  269. sg_shader shader;
  270. } sg_imgui_args_destroy_shader_t;
  271. typedef struct {
  272. sg_pipeline pipeline;
  273. } sg_imgui_args_destroy_pipeline_t;
  274. typedef struct {
  275. sg_pass pass;
  276. } sg_imgui_args_destroy_pass_t;
  277. typedef struct {
  278. sg_buffer buffer;
  279. int data_size;
  280. } sg_imgui_args_update_buffer_t;
  281. typedef struct {
  282. sg_image image;
  283. } sg_imgui_args_update_image_t;
  284. typedef struct {
  285. sg_buffer buffer;
  286. int data_size;
  287. int result;
  288. } sg_imgui_args_append_buffer_t;
  289. typedef struct {
  290. sg_pass_action action;
  291. int width;
  292. int height;
  293. } sg_imgui_args_begin_default_pass_t;
  294. typedef struct {
  295. sg_pass pass;
  296. sg_pass_action action;
  297. } sg_imgui_args_begin_pass_t;
  298. typedef struct {
  299. int x, y, width, height;
  300. bool origin_top_left;
  301. } sg_imgui_args_apply_viewport_t;
  302. typedef struct {
  303. int x, y, width, height;
  304. bool origin_top_left;
  305. } sg_imgui_args_apply_scissor_rect_t;
  306. typedef struct {
  307. sg_pipeline pipeline;
  308. } sg_imgui_args_apply_pipeline_t;
  309. typedef struct {
  310. sg_bindings bindings;
  311. } sg_imgui_args_apply_bindings_t;
  312. typedef struct {
  313. sg_shader_stage stage;
  314. int ub_index;
  315. const void* data;
  316. int num_bytes;
  317. sg_pipeline pipeline; /* the pipeline which was active at this call */
  318. uint32_t ubuf_pos; /* start of copied data in capture buffer */
  319. } sg_imgui_args_apply_uniforms_t;
  320. typedef struct {
  321. int base_element;
  322. int num_elements;
  323. int num_instances;
  324. } sg_imgui_args_draw_t;
  325. typedef struct {
  326. sg_buffer result;
  327. } sg_imgui_args_alloc_buffer_t;
  328. typedef struct {
  329. sg_image result;
  330. } sg_imgui_args_alloc_image_t;
  331. typedef struct {
  332. sg_shader result;
  333. } sg_imgui_args_alloc_shader_t;
  334. typedef struct {
  335. sg_pipeline result;
  336. } sg_imgui_args_alloc_pipeline_t;
  337. typedef struct {
  338. sg_pass result;
  339. } sg_imgui_args_alloc_pass_t;
  340. typedef struct {
  341. sg_buffer buffer;
  342. } sg_imgui_args_init_buffer_t;
  343. typedef struct {
  344. sg_image image;
  345. } sg_imgui_args_init_image_t;
  346. typedef struct {
  347. sg_shader shader;
  348. } sg_imgui_args_init_shader_t;
  349. typedef struct {
  350. sg_pipeline pipeline;
  351. } sg_imgui_args_init_pipeline_t;
  352. typedef struct {
  353. sg_pass pass;
  354. } sg_imgui_args_init_pass_t;
  355. typedef struct {
  356. sg_buffer buffer;
  357. } sg_imgui_args_fail_buffer_t;
  358. typedef struct {
  359. sg_image image;
  360. } sg_imgui_args_fail_image_t;
  361. typedef struct {
  362. sg_shader shader;
  363. } sg_imgui_args_fail_shader_t;
  364. typedef struct {
  365. sg_pipeline pipeline;
  366. } sg_imgui_args_fail_pipeline_t;
  367. typedef struct {
  368. sg_pass pass;
  369. } sg_imgui_args_fail_pass_t;
  370. typedef struct {
  371. sg_imgui_str_t name;
  372. } sg_imgui_args_push_debug_group_t;
  373. typedef union {
  374. sg_imgui_args_query_feature_t query_feature;
  375. sg_imgui_args_make_buffer_t make_buffer;
  376. sg_imgui_args_make_image_t make_image;
  377. sg_imgui_args_make_shader_t make_shader;
  378. sg_imgui_args_make_pipeline_t make_pipeline;
  379. sg_imgui_args_make_pass_t make_pass;
  380. sg_imgui_args_destroy_buffer_t destroy_buffer;
  381. sg_imgui_args_destroy_image_t destroy_image;
  382. sg_imgui_args_destroy_shader_t destroy_shader;
  383. sg_imgui_args_destroy_pipeline_t destroy_pipeline;
  384. sg_imgui_args_destroy_pass_t destroy_pass;
  385. sg_imgui_args_update_buffer_t update_buffer;
  386. sg_imgui_args_update_image_t update_image;
  387. sg_imgui_args_append_buffer_t append_buffer;
  388. sg_imgui_args_begin_default_pass_t begin_default_pass;
  389. sg_imgui_args_begin_pass_t begin_pass;
  390. sg_imgui_args_apply_viewport_t apply_viewport;
  391. sg_imgui_args_apply_scissor_rect_t apply_scissor_rect;
  392. sg_imgui_args_apply_pipeline_t apply_pipeline;
  393. sg_imgui_args_apply_bindings_t apply_bindings;
  394. sg_imgui_args_apply_uniforms_t apply_uniforms;
  395. sg_imgui_args_draw_t draw;
  396. sg_imgui_args_alloc_buffer_t alloc_buffer;
  397. sg_imgui_args_alloc_image_t alloc_image;
  398. sg_imgui_args_alloc_shader_t alloc_shader;
  399. sg_imgui_args_alloc_pipeline_t alloc_pipeline;
  400. sg_imgui_args_alloc_pass_t alloc_pass;
  401. sg_imgui_args_init_buffer_t init_buffer;
  402. sg_imgui_args_init_image_t init_image;
  403. sg_imgui_args_init_shader_t init_shader;
  404. sg_imgui_args_init_pipeline_t init_pipeline;
  405. sg_imgui_args_init_pass_t init_pass;
  406. sg_imgui_args_fail_buffer_t fail_buffer;
  407. sg_imgui_args_fail_image_t fail_image;
  408. sg_imgui_args_fail_shader_t fail_shader;
  409. sg_imgui_args_fail_pipeline_t fail_pipeline;
  410. sg_imgui_args_fail_pass_t fail_pass;
  411. sg_imgui_args_push_debug_group_t push_debug_group;
  412. } sg_imgui_args_t;
  413. typedef struct {
  414. sg_imgui_cmd_t cmd;
  415. uint32_t color;
  416. sg_imgui_args_t args;
  417. } sg_imgui_capture_item_t;
  418. typedef struct {
  419. uint32_t ubuf_size; /* size of uniform capture buffer in bytes */
  420. uint32_t ubuf_pos; /* current uniform buffer pos */
  421. uint8_t* ubuf; /* buffer for capturing uniform updates */
  422. uint32_t num_items;
  423. sg_imgui_capture_item_t items[SG_IMGUI_MAX_FRAMECAPTURE_ITEMS];
  424. } sg_imgui_capture_bucket_t;
  425. /* double-buffered call-capture buckets, one bucket is currently recorded,
  426. the previous bucket is displayed
  427. */
  428. typedef struct {
  429. bool open;
  430. uint32_t bucket_index; /* which bucket to record to, 0 or 1 */
  431. uint32_t sel_item; /* currently selected capture item by index */
  432. sg_imgui_capture_bucket_t bucket[2];
  433. } sg_imgui_capture_t;
  434. typedef struct {
  435. uint32_t init_tag;
  436. sg_imgui_buffers_t buffers;
  437. sg_imgui_images_t images;
  438. sg_imgui_shaders_t shaders;
  439. sg_imgui_pipelines_t pipelines;
  440. sg_imgui_passes_t passes;
  441. sg_imgui_capture_t capture;
  442. sg_pipeline cur_pipeline;
  443. sg_trace_hooks hooks;
  444. } sg_imgui_t;
  445. SOKOL_API_DECL void sg_imgui_init(sg_imgui_t* ctx);
  446. SOKOL_API_DECL void sg_imgui_discard(sg_imgui_t* ctx);
  447. SOKOL_API_DECL void sg_imgui_draw(sg_imgui_t* ctx);
  448. SOKOL_API_DECL void sg_imgui_draw_buffers_content(sg_imgui_t* ctx);
  449. SOKOL_API_DECL void sg_imgui_draw_images_content(sg_imgui_t* ctx);
  450. SOKOL_API_DECL void sg_imgui_draw_shaders_content(sg_imgui_t* ctx);
  451. SOKOL_API_DECL void sg_imgui_draw_pipelines_content(sg_imgui_t* ctx);
  452. SOKOL_API_DECL void sg_imgui_draw_passes_content(sg_imgui_t* ctx);
  453. SOKOL_API_DECL void sg_imgui_draw_capture_content(sg_imgui_t* ctx);
  454. SOKOL_API_DECL void sg_imgui_draw_buffers_window(sg_imgui_t* ctx);
  455. SOKOL_API_DECL void sg_imgui_draw_images_window(sg_imgui_t* ctx);
  456. SOKOL_API_DECL void sg_imgui_draw_shaders_window(sg_imgui_t* ctx);
  457. SOKOL_API_DECL void sg_imgui_draw_pipelines_window(sg_imgui_t* ctx);
  458. SOKOL_API_DECL void sg_imgui_draw_passes_window(sg_imgui_t* ctx);
  459. SOKOL_API_DECL void sg_imgui_draw_capture_window(sg_imgui_t* ctx);
  460. #if defined(__cplusplus)
  461. } /* extern "C" */
  462. #endif
  463. /*=== IMPLEMENTATION =========================================================*/
  464. #if defined SOKOL_GFX_IMGUI_IMPL
  465. #if !defined(IMGUI_VERSION)
  466. #error "Please include imgui.h before the sokol_gfx_imgui.h implementation"
  467. #endif
  468. #ifndef SOKOL_ASSERT
  469. #include <assert.h>
  470. #define SOKOL_ASSERT(c) assert(c)
  471. #endif
  472. #ifndef SOKOL_UNREACHABLE
  473. #define SOKOL_UNREACHABLE SOKOL_ASSERT(false)
  474. #endif
  475. #ifndef SOKOL_MALLOC
  476. #include <stdlib.h>
  477. #define SOKOL_MALLOC(s) malloc(s)
  478. #define SOKOL_FREE(p) free(p)
  479. #endif
  480. #ifndef _SOKOL_PRIVATE
  481. #if defined(__GNUC__)
  482. #define _SOKOL_PRIVATE __attribute__((unused)) static
  483. #else
  484. #define _SOKOL_PRIVATE static
  485. #endif
  486. #endif
  487. #ifndef SOKOL_API_IMPL
  488. #define SOKOL_API_IMPL
  489. #endif
  490. #include <string.h>
  491. #include <stdio.h> /* snprintf */
  492. #define _SG_IMGUI_SLOT_MASK (0xFFFF)
  493. #define _SG_IMGUI_LIST_WIDTH (192)
  494. #define _SG_IMGUI_COLOR_OTHER ImColor(0.75f, 0.75f, 0.75f, 1.0f)
  495. #define _SG_IMGUI_COLOR_RSRC ImColor(1.0f, 1.0f, 0.0f, 1.0f)
  496. #define _SG_IMGUI_COLOR_DRAW ImColor(0.0f, 1.0f, 0.0f, 1.0f)
  497. #define _SG_IMGUI_COLOR_ERR ImColor(1.0f, 0.5f, 0.5f, 1.0f)
  498. /*--- UTILS ------------------------------------------------------------------*/
  499. _SOKOL_PRIVATE int _sg_imgui_slot_index(uint32_t id) {
  500. int slot_index = (int) (id & _SG_IMGUI_SLOT_MASK);
  501. SOKOL_ASSERT(0 != slot_index);
  502. return slot_index;
  503. }
  504. _SOKOL_PRIVATE int _sg_imgui_uniform_size(sg_uniform_type type, int count) {
  505. switch (type) {
  506. case SG_UNIFORMTYPE_INVALID: return 0;
  507. case SG_UNIFORMTYPE_FLOAT: return 4 * count;
  508. case SG_UNIFORMTYPE_FLOAT2: return 8 * count;
  509. case SG_UNIFORMTYPE_FLOAT3: return 12 * count; /* FIXME: std140??? */
  510. case SG_UNIFORMTYPE_FLOAT4: return 16 * count;
  511. case SG_UNIFORMTYPE_MAT4: return 64 * count;
  512. default:
  513. SOKOL_UNREACHABLE;
  514. return -1;
  515. }
  516. }
  517. _SOKOL_PRIVATE void* _sg_imgui_alloc(int size) {
  518. SOKOL_ASSERT(size > 0);
  519. return SOKOL_MALLOC(size);
  520. }
  521. _SOKOL_PRIVATE void _sg_imgui_free(void* ptr) {
  522. if (ptr) {
  523. SOKOL_FREE(ptr);
  524. }
  525. }
  526. _SOKOL_PRIVATE void* _sg_imgui_realloc(void* old_ptr, int old_size, int new_size) {
  527. SOKOL_ASSERT((new_size > 0) && (new_size > old_size));
  528. void* new_ptr = SOKOL_MALLOC(new_size);
  529. SOKOL_ASSERT(new_ptr);
  530. if (old_ptr) {
  531. if (old_size > 0) {
  532. memcpy(new_ptr, old_ptr, old_size);
  533. }
  534. _sg_imgui_free(old_ptr);
  535. }
  536. return new_ptr;
  537. }
  538. _SOKOL_PRIVATE void _sg_imgui_strcpy(sg_imgui_str_t* dst, const char* src) {
  539. SOKOL_ASSERT(dst);
  540. if (src) {
  541. #if defined(_MSC_VER)
  542. strncpy_s(dst->buf, SG_IMGUI_STRBUF_LEN, src, (SG_IMGUI_STRBUF_LEN-1));
  543. #else
  544. strncpy(dst->buf, src, SG_IMGUI_STRBUF_LEN);
  545. #endif
  546. dst->buf[SG_IMGUI_STRBUF_LEN-1] = 0;
  547. }
  548. else {
  549. memset(dst->buf, 0, SG_IMGUI_STRBUF_LEN);
  550. }
  551. }
  552. _SOKOL_PRIVATE sg_imgui_str_t _sg_imgui_make_str(const char* str) {
  553. sg_imgui_str_t res;
  554. _sg_imgui_strcpy(&res, str);
  555. return res;
  556. }
  557. _SOKOL_PRIVATE const char* _sg_imgui_str_dup(const char* src) {
  558. SOKOL_ASSERT(src);
  559. int len = (int) strlen(src) + 1;
  560. char* dst = (char*) _sg_imgui_alloc(len);
  561. memcpy(dst, src, len);
  562. return (const char*) dst;
  563. }
  564. _SOKOL_PRIVATE const uint8_t* _sg_imgui_bin_dup(const uint8_t* src, int num_bytes) {
  565. SOKOL_ASSERT(src && (num_bytes > 0));
  566. uint8_t* dst = (uint8_t*) _sg_imgui_alloc(num_bytes);
  567. memcpy(dst, src, num_bytes);
  568. return (const uint8_t*) dst;
  569. }
  570. /*--- STRING CONVERSION ------------------------------------------------------*/
  571. _SOKOL_PRIVATE const char* _sg_imgui_feature_string(sg_feature f) {
  572. switch (f) {
  573. case SG_FEATURE_INSTANCING: return "SG_FEATURE_INSTANCING";
  574. case SG_FEATURE_TEXTURE_COMPRESSION_DXT: return "SG_FEATURE_TEXTURE_COMPRESSION_DXT";
  575. case SG_FEATURE_TEXTURE_COMPRESSION_PVRTC: return "SG_FEATURE_TEXTURE_COMPRESSION_PVRTC";
  576. case SG_FEATURE_TEXTURE_COMPRESSION_ATC: return "SG_FEATURE_TEXTURE_COMPRESSION_ATC";
  577. case SG_FEATURE_TEXTURE_COMPRESSION_ETC2: return "SG_FEATURE_TEXTURE_COMPRESSION_ETC2";
  578. case SG_FEATURE_TEXTURE_FLOAT: return "SG_FEATURE_TEXTURE_FLOAT";
  579. case SG_FEATURE_TEXTURE_HALF_FLOAT: return "SG_FEATURE_TEXTURE_HALF_FLOAT";
  580. case SG_FEATURE_ORIGIN_BOTTOM_LEFT: return "SG_FEATURE_ORIGIN_BOTTOM_LEFT";
  581. case SG_FEATURE_ORIGIN_TOP_LEFT: return "SG_FEATURE_ORIGIN_TOP_LEFT";
  582. case SG_FEATURE_MSAA_RENDER_TARGETS: return "SG_FEATURE_MSAA_RENDER_TARGETS";
  583. case SG_FEATURE_PACKED_VERTEX_FORMAT_10_2: return "SG_FEATURE_PACKED_VERTEX_FORMAT_10_2";
  584. case SG_FEATURE_MULTIPLE_RENDER_TARGET: return "SG_FEATURE_MULTIPLE_RENDER_TARGET";
  585. case SG_FEATURE_IMAGETYPE_3D: return "SG_FEATURE_IMAGETYPE_3D";
  586. case SG_FEATURE_IMAGETYPE_ARRAY: return "SG_FEATURE_IMAGETYPE_ARRAY";
  587. default: return "???";
  588. }
  589. }
  590. _SOKOL_PRIVATE const char* _sg_imgui_resourcestate_string(sg_resource_state s) {
  591. switch (s) {
  592. case SG_RESOURCESTATE_INITIAL: return "SG_RESOURCESTATE_INITIAL";
  593. case SG_RESOURCESTATE_ALLOC: return "SG_RESOURCESTATE_ALLOC";
  594. case SG_RESOURCESTATE_VALID: return "SG_RESOURCESTATE_VALID";
  595. case SG_RESOURCESTATE_FAILED: return "SG_RESOURCESTATE_FAILED";
  596. default: return "SG_RESOURCESTATE_INVALID";
  597. }
  598. }
  599. _SOKOL_PRIVATE void _sg_imgui_draw_resource_slot(const sg_slot_info* slot) {
  600. ImGui::Text("ResId: %08X", slot->res_id);
  601. ImGui::Text("CtxId: %08X", slot->ctx_id);
  602. ImGui::Text("State: %s", _sg_imgui_resourcestate_string(slot->state));
  603. }
  604. _SOKOL_PRIVATE const char* _sg_imgui_buffertype_string(sg_buffer_type t) {
  605. switch (t) {
  606. case SG_BUFFERTYPE_VERTEXBUFFER: return "SG_BUFFERTYPE_VERTEXBUFFER";
  607. case SG_BUFFERTYPE_INDEXBUFFER: return "SG_BUFFERTYPE_INDEXBUFFER";
  608. default: return "???";
  609. }
  610. }
  611. _SOKOL_PRIVATE const char* _sg_imgui_usage_string(sg_usage u) {
  612. switch (u) {
  613. case SG_USAGE_IMMUTABLE: return "SG_USAGE_IMMUTABLE";
  614. case SG_USAGE_DYNAMIC: return "SG_USAGE_DYNAMIC";
  615. case SG_USAGE_STREAM: return "SG_USAGE_STREAM";
  616. default: return "???";
  617. }
  618. }
  619. _SOKOL_PRIVATE const char* _sg_imgui_imagetype_string(sg_image_type t) {
  620. switch (t) {
  621. case SG_IMAGETYPE_2D: return "SG_IMAGETYPE_2D";
  622. case SG_IMAGETYPE_CUBE: return "SG_IMAGETYPE_CUBE";
  623. case SG_IMAGETYPE_3D: return "SG_IMAGETYPE_3D";
  624. case SG_IMAGETYPE_ARRAY: return "SG_IMAGETYPE_ARRAY";
  625. default: return "???";
  626. }
  627. }
  628. _SOKOL_PRIVATE const char* _sg_imgui_pixelformat_string(sg_pixel_format fmt) {
  629. switch (fmt) {
  630. case SG_PIXELFORMAT_NONE: return "SG_PIXELFORMAT_NONE";
  631. case SG_PIXELFORMAT_RGBA8: return "SG_PIXELFORMAT_RGBA8";
  632. case SG_PIXELFORMAT_RGB8: return "SG_PIXELFORMAT_RGB8";
  633. case SG_PIXELFORMAT_RGBA4: return "SG_PIXELFORMAT_RGBA4";
  634. case SG_PIXELFORMAT_R5G6B5: return "SG_PIXELFORMAT_R5G6B5";
  635. case SG_PIXELFORMAT_R5G5B5A1: return "SG_PIXELFORMAT_R5G5B5A1";
  636. case SG_PIXELFORMAT_R10G10B10A2: return "SG_PIXELFORMAT_R10G10B10A2";
  637. case SG_PIXELFORMAT_RGBA32F: return "SG_PIXELFORMAT_RGBA32F";
  638. case SG_PIXELFORMAT_RGBA16F: return "SG_PIXELFORMAT_RGBA16F";
  639. case SG_PIXELFORMAT_R32F: return "SG_PIXELFORMAT_R32F";
  640. case SG_PIXELFORMAT_R16F: return "SG_PIXELFORMAT_R16F";
  641. case SG_PIXELFORMAT_L8: return "SG_PIXELFORMAT_L8";
  642. case SG_PIXELFORMAT_DXT1: return "SG_PIXELFORMAT_DXT1";
  643. case SG_PIXELFORMAT_DXT3: return "SG_PIXELFORMAT_DXT3";
  644. case SG_PIXELFORMAT_DXT5: return "SG_PIXELFORMAT_DXT5";
  645. case SG_PIXELFORMAT_DEPTH: return "SG_PIXELFORMAT_DEPTH";
  646. case SG_PIXELFORMAT_DEPTHSTENCIL: return "SG_PIXELFORMAT_DEPTHSTENCIL";
  647. case SG_PIXELFORMAT_PVRTC2_RGB: return "SG_PIXELFORMAT_PVRTC2_RGB";
  648. case SG_PIXELFORMAT_PVRTC4_RGB: return "SG_PIXELFORMAT_PVRTC4_RGB";
  649. case SG_PIXELFORMAT_PVRTC2_RGBA: return "SG_PIXELFORMAT_PVRTC2_RGBA";
  650. case SG_PIXELFORMAT_PVRTC4_RGBA: return "SG_PIXELFORMAT_PVRTC4_RGBA";
  651. case SG_PIXELFORMAT_ETC2_RGB8: return "SG_PIXELFORMAT_ETC2_RGB8";
  652. case SG_PIXELFORMAT_ETC2_SRGB8: return "SG_PIXELFORMAT_ETC2_SRGB8";
  653. default: return "???";
  654. }
  655. }
  656. _SOKOL_PRIVATE const char* _sg_imgui_filter_string(sg_filter f) {
  657. switch (f) {
  658. case SG_FILTER_NEAREST: return "SG_FILTER_NEAREST";
  659. case SG_FILTER_LINEAR: return "SG_FILTER_LINEAR";
  660. case SG_FILTER_NEAREST_MIPMAP_NEAREST: return "SG_FILTER_NEAREST_MIPMAP_NEAREST";
  661. case SG_FILTER_NEAREST_MIPMAP_LINEAR: return "SG_FILTER_NEAREST_MIPMAP_LINEAR";
  662. case SG_FILTER_LINEAR_MIPMAP_NEAREST: return "SG_FILTER_LINEAR_MIPMAP_NEAREST";
  663. case SG_FILTER_LINEAR_MIPMAP_LINEAR: return "SG_FILTER_LINEAR_MIPMAP_LINEAR";
  664. default: return "???";
  665. }
  666. }
  667. _SOKOL_PRIVATE const char* _sg_imgui_wrap_string(sg_wrap w) {
  668. switch (w) {
  669. case SG_WRAP_REPEAT: return "SG_WRAP_REPEAT";
  670. case SG_WRAP_CLAMP_TO_EDGE: return "SG_WRAP_CLAMP_TO_EDGE";
  671. case SG_WRAP_MIRRORED_REPEAT: return "SG_WRAP_MIRRORED_REPEAT";
  672. default: return "???";
  673. }
  674. }
  675. _SOKOL_PRIVATE const char* _sg_imgui_uniformtype_string(sg_uniform_type t) {
  676. switch (t) {
  677. case SG_UNIFORMTYPE_FLOAT: return "SG_UNIFORMTYPE_FLOAT";
  678. case SG_UNIFORMTYPE_FLOAT2: return "SG_UNIFORMTYPE_FLOAT2";
  679. case SG_UNIFORMTYPE_FLOAT3: return "SG_UNIFORMTYPE_FLOAT3";
  680. case SG_UNIFORMTYPE_FLOAT4: return "SG_UNIFORMTYPE_FLOAT4";
  681. case SG_UNIFORMTYPE_MAT4: return "SG_UNIFORMTYPE_MAT4";
  682. default: return "???";
  683. }
  684. }
  685. _SOKOL_PRIVATE const char* _sg_imgui_vertexstep_string(sg_vertex_step s) {
  686. switch (s) {
  687. case SG_VERTEXSTEP_PER_VERTEX: return "SG_VERTEXSTEP_PER_VERTEX";
  688. case SG_VERTEXSTEP_PER_INSTANCE: return "SG_VERTEXSTEP_PER_INSTANCE";
  689. default: return "???";
  690. }
  691. }
  692. _SOKOL_PRIVATE const char* _sg_imgui_vertexformat_string(sg_vertex_format f) {
  693. switch (f) {
  694. case SG_VERTEXFORMAT_FLOAT: return "SG_VERTEXFORMAT_FLOAT";
  695. case SG_VERTEXFORMAT_FLOAT2: return "SG_VERTEXFORMAT_FLOAT2";
  696. case SG_VERTEXFORMAT_FLOAT3: return "SG_VERTEXFORMAT_FLOAT3";
  697. case SG_VERTEXFORMAT_FLOAT4: return "SG_VERTEXFORMAT_FLOAT4";
  698. case SG_VERTEXFORMAT_BYTE4: return "SG_VERTEXFORMAT_BYTE4";
  699. case SG_VERTEXFORMAT_BYTE4N: return "SG_VERTEXFORMAT_BYTE4N";
  700. case SG_VERTEXFORMAT_UBYTE4: return "SG_VERTEXFORMAT_UBYTE4";
  701. case SG_VERTEXFORMAT_UBYTE4N: return "SG_VERTEXFORMAT_UBYTE4N";
  702. case SG_VERTEXFORMAT_SHORT2: return "SG_VERTEXFORMAT_SHORT2";
  703. case SG_VERTEXFORMAT_SHORT2N: return "SG_VERTEXFORMAT_SHORT2N";
  704. case SG_VERTEXFORMAT_SHORT4: return "SG_VERTEXFORMAT_SHORT4";
  705. case SG_VERTEXFORMAT_SHORT4N: return "SG_VERTEXFORMAT_SHORT4N";
  706. case SG_VERTEXFORMAT_UINT10_N2: return "SG_VERTEXFORMAT_UINT10_N2";
  707. default: return "???";
  708. }
  709. }
  710. _SOKOL_PRIVATE const char* _sg_imgui_primitivetype_string(sg_primitive_type t) {
  711. switch (t) {
  712. case SG_PRIMITIVETYPE_POINTS: return "SG_PRIMITIVETYPE_POINTS";
  713. case SG_PRIMITIVETYPE_LINES: return "SG_PRIMITIVETYPE_LINES";
  714. case SG_PRIMITIVETYPE_LINE_STRIP: return "SG_PRIMITIVETYPE_LINE_STRIP";
  715. case SG_PRIMITIVETYPE_TRIANGLES: return "SG_PRIMITIVETYPE_TRIANGLES";
  716. case SG_PRIMITIVETYPE_TRIANGLE_STRIP: return "SG_PRIMITIVETYPE_TRIANGLE_STRIP";
  717. default: return "???";
  718. }
  719. }
  720. _SOKOL_PRIVATE const char* _sg_imgui_indextype_string(sg_index_type t) {
  721. switch (t) {
  722. case SG_INDEXTYPE_NONE: return "SG_INDEXTYPE_NONE";
  723. case SG_INDEXTYPE_UINT16: return "SG_INDEXTYPE_UINT16";
  724. case SG_INDEXTYPE_UINT32: return "SG_INDEXTYPE_UINT32";
  725. default: return "???";
  726. }
  727. }
  728. _SOKOL_PRIVATE const char* _sg_imgui_stencilop_string(sg_stencil_op op) {
  729. switch (op) {
  730. case SG_STENCILOP_KEEP: return "SG_STENCILOP_KEEP";
  731. case SG_STENCILOP_ZERO: return "SG_STENCILOP_ZERO";
  732. case SG_STENCILOP_REPLACE: return "SG_STENCILOP_REPLACE";
  733. case SG_STENCILOP_INCR_CLAMP: return "SG_STENCILOP_INCR_CLAMP";
  734. case SG_STENCILOP_DECR_CLAMP: return "SG_STENCILOP_DECR_CLAMP";
  735. case SG_STENCILOP_INVERT: return "SG_STENCILOP_INVERT";
  736. case SG_STENCILOP_INCR_WRAP: return "SG_STENCILOP_INCR_WRAP";
  737. case SG_STENCILOP_DECR_WRAP: return "SG_STENCILOP_DECR_WRAP";
  738. default: return "???";
  739. }
  740. }
  741. _SOKOL_PRIVATE const char* _sg_imgui_comparefunc_string(sg_compare_func f) {
  742. switch (f) {
  743. case SG_COMPAREFUNC_NEVER: return "SG_COMPAREFUNC_NEVER";
  744. case SG_COMPAREFUNC_LESS: return "SG_COMPAREFUNC_LESS";
  745. case SG_COMPAREFUNC_EQUAL: return "SG_COMPAREFUNC_EQUAL";
  746. case SG_COMPAREFUNC_LESS_EQUAL: return "SG_COMPAREFUNC_LESS_EQUAL";
  747. case SG_COMPAREFUNC_GREATER: return "SG_COMPAREFUNC_GREATER";
  748. case SG_COMPAREFUNC_NOT_EQUAL: return "SG_COMPAREFUNC_NOT_EQUAL";
  749. case SG_COMPAREFUNC_GREATER_EQUAL: return "SG_COMPAREFUNC_GREATER_EQUAL";
  750. case SG_COMPAREFUNC_ALWAYS: return "SG_COMPAREFUNC_ALWAYS";
  751. default: return "???";
  752. }
  753. }
  754. _SOKOL_PRIVATE const char* _sg_imgui_blendfactor_string(sg_blend_factor f) {
  755. switch (f) {
  756. case SG_BLENDFACTOR_ZERO: return "SG_BLENDFACTOR_ZERO";
  757. case SG_BLENDFACTOR_ONE: return "SG_BLENDFACTOR_ONE";
  758. case SG_BLENDFACTOR_SRC_COLOR: return "SG_BLENDFACTOR_SRC_COLOR";
  759. case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR: return "SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR";
  760. case SG_BLENDFACTOR_SRC_ALPHA: return "SG_BLENDFACTOR_SRC_ALPHA";
  761. case SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA: return "SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA";
  762. case SG_BLENDFACTOR_DST_COLOR: return "SG_BLENDFACTOR_DST_COLOR";
  763. case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR: return "SG_BLENDFACTOR_ONE_MINUS_DST_COLOR";
  764. case SG_BLENDFACTOR_DST_ALPHA: return "SG_BLENDFACTOR_DST_ALPHA";
  765. case SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA: return "SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA";
  766. case SG_BLENDFACTOR_SRC_ALPHA_SATURATED: return "SG_BLENDFACTOR_SRC_ALPHA_SATURATED";
  767. case SG_BLENDFACTOR_BLEND_COLOR: return "SG_BLENDFACTOR_BLEND_COLOR";
  768. case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR: return "SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR";
  769. case SG_BLENDFACTOR_BLEND_ALPHA: return "SG_BLENDFACTOR_BLEND_ALPHA";
  770. case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA: return "SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA";
  771. default: return "???";
  772. }
  773. }
  774. _SOKOL_PRIVATE const char* _sg_imgui_blendop_string(sg_blend_op op) {
  775. switch (op) {
  776. case SG_BLENDOP_ADD: return "SG_BLENDOP_ADD";
  777. case SG_BLENDOP_SUBTRACT: return "SG_BLENDOP_SUBTRACT";
  778. case SG_BLENDOP_REVERSE_SUBTRACT: return "SG_BLENDOP_REVERSE_SUBTRACT";
  779. default: return "???";
  780. }
  781. }
  782. _SOKOL_PRIVATE const char* _sg_imgui_colormask_string(uint8_t m) {
  783. static const char* str[] = {
  784. "NONE",
  785. "R",
  786. "G",
  787. "RG",
  788. "B",
  789. "RB",
  790. "GB",
  791. "RGB",
  792. "A",
  793. "RA",
  794. "GA",
  795. "RGA",
  796. "BA",
  797. "RBA",
  798. "GBA",
  799. "RGBA",
  800. };
  801. return str[m & 0xF];
  802. }
  803. _SOKOL_PRIVATE const char* _sg_imgui_cullmode_string(sg_cull_mode cm) {
  804. switch (cm) {
  805. case SG_CULLMODE_NONE: return "SG_CULLMODE_NONE";
  806. case SG_CULLMODE_FRONT: return "SG_CULLMODE_FRONT";
  807. case SG_CULLMODE_BACK: return "SG_CULLMODE_BACK";
  808. default: return "???";
  809. }
  810. }
  811. _SOKOL_PRIVATE const char* _sg_imgui_facewinding_string(sg_face_winding fw) {
  812. switch (fw) {
  813. case SG_FACEWINDING_CCW: return "SG_FACEWINDING_CCW";
  814. case SG_FACEWINDING_CW: return "SG_FACEWINDING_CW";
  815. default: return "???";
  816. }
  817. }
  818. _SOKOL_PRIVATE const char* _sg_imgui_shaderstage_string(sg_shader_stage stage) {
  819. switch (stage) {
  820. case SG_SHADERSTAGE_VS: return "SG_SHADERSTAGE_VS";
  821. case SG_SHADERSTAGE_FS: return "SG_SHADERSTAGE_FS";
  822. default: return "???";
  823. }
  824. }
  825. _SOKOL_PRIVATE const char* _sg_imgui_bool_string(bool b) {
  826. return b ? "true" : "false";
  827. }
  828. _SOKOL_PRIVATE sg_imgui_str_t _sg_imgui_res_id_string(uint32_t res_id, const char* label) {
  829. SOKOL_ASSERT(label);
  830. sg_imgui_str_t res;
  831. if (label[0]) {
  832. snprintf(res.buf, sizeof(res.buf), "'%s'", label);
  833. }
  834. else {
  835. snprintf(res.buf, sizeof(res.buf), "0x%08X", res_id);
  836. }
  837. return res;
  838. }
  839. _SOKOL_PRIVATE sg_imgui_str_t _sg_imgui_buffer_id_string(sg_imgui_t* ctx, sg_buffer buf_id) {
  840. if (buf_id.id != SG_INVALID_ID) {
  841. const sg_imgui_buffer_t* buf_ui = &ctx->buffers.slots[_sg_imgui_slot_index(buf_id.id)];
  842. return _sg_imgui_res_id_string(buf_id.id, buf_ui->label.buf);
  843. }
  844. else {
  845. return _sg_imgui_make_str("<invalid>");
  846. }
  847. }
  848. _SOKOL_PRIVATE sg_imgui_str_t _sg_imgui_image_id_string(sg_imgui_t* ctx, sg_image img_id) {
  849. if (img_id.id != SG_INVALID_ID) {
  850. const sg_imgui_image_t* img_ui = &ctx->images.slots[_sg_imgui_slot_index(img_id.id)];
  851. return _sg_imgui_res_id_string(img_id.id, img_ui->label.buf);
  852. }
  853. else {
  854. return _sg_imgui_make_str("<invalid>");
  855. }
  856. }
  857. _SOKOL_PRIVATE sg_imgui_str_t _sg_imgui_shader_id_string(sg_imgui_t* ctx, sg_shader shd_id) {
  858. if (shd_id.id != SG_INVALID_ID) {
  859. const sg_imgui_shader_t* shd_ui = &ctx->shaders.slots[_sg_imgui_slot_index(shd_id.id)];
  860. return _sg_imgui_res_id_string(shd_id.id, shd_ui->label.buf);
  861. }
  862. else {
  863. return _sg_imgui_make_str("<invalid>");
  864. }
  865. }
  866. _SOKOL_PRIVATE sg_imgui_str_t _sg_imgui_pipeline_id_string(sg_imgui_t* ctx, sg_pipeline pip_id) {
  867. if (pip_id.id != SG_INVALID_ID) {
  868. const sg_imgui_pipeline_t* pip_ui = &ctx->pipelines.slots[_sg_imgui_slot_index(pip_id.id)];
  869. return _sg_imgui_res_id_string(pip_id.id, pip_ui->label.buf);
  870. }
  871. else {
  872. return _sg_imgui_make_str("<invalid>");
  873. }
  874. }
  875. _SOKOL_PRIVATE sg_imgui_str_t _sg_imgui_pass_id_string(sg_imgui_t* ctx, sg_pass pass_id) {
  876. if (pass_id.id != SG_INVALID_ID) {
  877. const sg_imgui_pass_t* pass_ui = &ctx->passes.slots[_sg_imgui_slot_index(pass_id.id)];
  878. return _sg_imgui_res_id_string(pass_id.id, pass_ui->label.buf);
  879. }
  880. else {
  881. return _sg_imgui_make_str("<invalid>");
  882. }
  883. }
  884. /*--- RESOURCE HELPERS -------------------------------------------------------*/
  885. _SOKOL_PRIVATE void _sg_imgui_buffer_created(sg_imgui_t* ctx, sg_buffer res_id, int slot_index, const sg_buffer_desc* desc) {
  886. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->buffers.num_slots));
  887. sg_imgui_buffer_t* buf = &ctx->buffers.slots[slot_index];
  888. buf->res_id = res_id;
  889. buf->desc = *desc;
  890. buf->label = _sg_imgui_make_str(desc->label);
  891. }
  892. _SOKOL_PRIVATE void _sg_imgui_buffer_destroyed(sg_imgui_t* ctx, int slot_index) {
  893. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->buffers.num_slots));
  894. sg_imgui_buffer_t* buf = &ctx->buffers.slots[slot_index];
  895. buf->res_id.id = SG_INVALID_ID;
  896. }
  897. _SOKOL_PRIVATE void _sg_imgui_image_created(sg_imgui_t* ctx, sg_image res_id, int slot_index, const sg_image_desc* desc) {
  898. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->images.num_slots));
  899. sg_imgui_image_t* img = &ctx->images.slots[slot_index];
  900. img->res_id = res_id;
  901. img->desc = *desc;
  902. img->ui_scale = 1.0f;
  903. img->label = _sg_imgui_make_str(desc->label);
  904. }
  905. _SOKOL_PRIVATE void _sg_imgui_image_destroyed(sg_imgui_t* ctx, int slot_index) {
  906. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->images.num_slots));
  907. sg_imgui_image_t* img = &ctx->images.slots[slot_index];
  908. img->res_id.id = SG_INVALID_ID;
  909. }
  910. _SOKOL_PRIVATE void _sg_imgui_shader_created(sg_imgui_t* ctx, sg_shader res_id, int slot_index, const sg_shader_desc* desc) {
  911. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->shaders.num_slots));
  912. sg_imgui_shader_t* shd = &ctx->shaders.slots[slot_index];
  913. shd->res_id = res_id;
  914. shd->desc = *desc;
  915. shd->label = _sg_imgui_make_str(desc->label);
  916. if (shd->desc.vs.entry) {
  917. shd->vs_entry = _sg_imgui_make_str(shd->desc.vs.entry);
  918. shd->desc.vs.entry = shd->vs_entry.buf;
  919. }
  920. if (shd->desc.fs.entry) {
  921. shd->fs_entry = _sg_imgui_make_str(shd->desc.fs.entry);
  922. shd->desc.fs.entry = shd->fs_entry.buf;
  923. }
  924. for (int i = 0; i < SG_MAX_SHADERSTAGE_UBS; i++) {
  925. for (int j = 0; j < SG_MAX_UB_MEMBERS; j++) {
  926. sg_shader_uniform_desc* ud = &shd->desc.vs.uniform_blocks[i].uniforms[j];
  927. if (ud->name) {
  928. shd->vs_uniform_name[i][j] = _sg_imgui_make_str(ud->name);
  929. ud->name = shd->vs_uniform_name[i][j].buf;
  930. }
  931. }
  932. }
  933. for (int i = 0; i < SG_MAX_SHADERSTAGE_UBS; i++) {
  934. for (int j = 0; j < SG_MAX_UB_MEMBERS; j++) {
  935. sg_shader_uniform_desc* ud = &shd->desc.fs.uniform_blocks[i].uniforms[j];
  936. if (ud->name) {
  937. shd->fs_uniform_name[i][j] = _sg_imgui_make_str(ud->name);
  938. ud->name = shd->fs_uniform_name[i][j].buf;
  939. }
  940. }
  941. }
  942. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  943. if (shd->desc.vs.images[i].name) {
  944. shd->vs_image_name[i] = _sg_imgui_make_str(shd->desc.vs.images[i].name);
  945. shd->desc.vs.images[i].name = shd->vs_image_name[i].buf;
  946. }
  947. }
  948. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  949. if (shd->desc.fs.images[i].name) {
  950. shd->fs_image_name[i] = _sg_imgui_make_str(shd->desc.fs.images[i].name);
  951. shd->desc.fs.images[i].name = shd->fs_image_name[i].buf;
  952. }
  953. }
  954. if (shd->desc.vs.source) {
  955. shd->desc.vs.source = _sg_imgui_str_dup(shd->desc.vs.source);
  956. }
  957. if (shd->desc.vs.byte_code) {
  958. shd->desc.vs.byte_code = _sg_imgui_bin_dup(shd->desc.vs.byte_code, shd->desc.vs.byte_code_size);
  959. }
  960. if (shd->desc.fs.source) {
  961. shd->desc.fs.source = _sg_imgui_str_dup(shd->desc.fs.source);
  962. }
  963. if (shd->desc.fs.byte_code) {
  964. shd->desc.fs.byte_code = _sg_imgui_bin_dup(shd->desc.fs.byte_code, shd->desc.fs.byte_code_size);
  965. }
  966. }
  967. _SOKOL_PRIVATE void _sg_imgui_shader_destroyed(sg_imgui_t* ctx, int slot_index) {
  968. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->shaders.num_slots));
  969. sg_imgui_shader_t* shd = &ctx->shaders.slots[slot_index];
  970. shd->res_id.id = SG_INVALID_ID;
  971. if (shd->desc.vs.source) {
  972. _sg_imgui_free((void*)shd->desc.vs.source);
  973. shd->desc.vs.source = 0;
  974. }
  975. if (shd->desc.vs.byte_code) {
  976. _sg_imgui_free((void*)shd->desc.vs.byte_code);
  977. shd->desc.vs.byte_code = 0;
  978. }
  979. if (shd->desc.fs.source) {
  980. _sg_imgui_free((void*)shd->desc.fs.source);
  981. shd->desc.fs.source = 0;
  982. }
  983. if (shd->desc.fs.byte_code) {
  984. _sg_imgui_free((void*)shd->desc.fs.byte_code);
  985. shd->desc.fs.byte_code = 0;
  986. }
  987. }
  988. _SOKOL_PRIVATE void _sg_imgui_pipeline_created(sg_imgui_t* ctx, sg_pipeline res_id, int slot_index, const sg_pipeline_desc* desc) {
  989. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->pipelines.num_slots));
  990. sg_imgui_pipeline_t* pip = &ctx->pipelines.slots[slot_index];
  991. pip->res_id = res_id;
  992. pip->label = _sg_imgui_make_str(desc->label);
  993. pip->desc = *desc;
  994. /* copy strings in vertex layout to persistent location */
  995. for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
  996. sg_vertex_attr_desc* ad = &pip->desc.layout.attrs[i];
  997. if (ad->name) {
  998. pip->attr_name[i] = _sg_imgui_make_str(ad->name);
  999. ad->name = pip->attr_name[i].buf;
  1000. }
  1001. if (ad->sem_name) {
  1002. pip->attr_sem_name[i] = _sg_imgui_make_str(ad->sem_name);
  1003. ad->sem_name = pip->attr_sem_name[i].buf;
  1004. }
  1005. }
  1006. }
  1007. _SOKOL_PRIVATE void _sg_imgui_pipeline_destroyed(sg_imgui_t* ctx, int slot_index) {
  1008. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->pipelines.num_slots));
  1009. sg_imgui_pipeline_t* pip = &ctx->pipelines.slots[slot_index];
  1010. pip->res_id.id = SG_INVALID_ID;
  1011. }
  1012. _SOKOL_PRIVATE void _sg_imgui_pass_created(sg_imgui_t* ctx, sg_pass res_id, int slot_index, const sg_pass_desc* desc) {
  1013. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->passes.num_slots));
  1014. sg_imgui_pass_t* pass = &ctx->passes.slots[slot_index];
  1015. pass->res_id = res_id;
  1016. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  1017. pass->color_image_scale[i] = 0.25f;
  1018. }
  1019. pass->ds_image_scale = 0.25f;
  1020. pass->label = _sg_imgui_make_str(desc->label);
  1021. pass->desc = *desc;
  1022. }
  1023. _SOKOL_PRIVATE void _sg_imgui_pass_destroyed(sg_imgui_t* ctx, int slot_index) {
  1024. SOKOL_ASSERT((slot_index > 0) && (slot_index < ctx->passes.num_slots));
  1025. sg_imgui_pass_t* pass = &ctx->passes.slots[slot_index];
  1026. pass->res_id.id = SG_INVALID_ID;
  1027. }
  1028. /*--- COMMAND CAPTURING ------------------------------------------------------*/
  1029. _SOKOL_PRIVATE void _sg_imgui_capture_init(sg_imgui_t* ctx) {
  1030. const int ubuf_initial_size = 256 * 1024;
  1031. for (int i = 0; i < 2; i++) {
  1032. sg_imgui_capture_bucket_t* bucket = &ctx->capture.bucket[i];
  1033. bucket->ubuf_size = ubuf_initial_size;
  1034. bucket->ubuf = (uint8_t*) _sg_imgui_alloc(bucket->ubuf_size);
  1035. SOKOL_ASSERT(bucket->ubuf);
  1036. }
  1037. }
  1038. _SOKOL_PRIVATE void _sg_imgui_capture_discard(sg_imgui_t* ctx) {
  1039. for (int i = 0; i < 2; i++) {
  1040. sg_imgui_capture_bucket_t* bucket = &ctx->capture.bucket[i];
  1041. SOKOL_ASSERT(bucket->ubuf);
  1042. _sg_imgui_free(bucket->ubuf);
  1043. bucket->ubuf = 0;
  1044. }
  1045. }
  1046. _SOKOL_PRIVATE sg_imgui_capture_bucket_t* _sg_imgui_capture_get_write_bucket(sg_imgui_t* ctx) {
  1047. return &ctx->capture.bucket[ctx->capture.bucket_index & 1];
  1048. }
  1049. _SOKOL_PRIVATE sg_imgui_capture_bucket_t* _sg_imgui_capture_get_read_bucket(sg_imgui_t* ctx) {
  1050. return &ctx->capture.bucket[(ctx->capture.bucket_index + 1) & 1];
  1051. }
  1052. _SOKOL_PRIVATE void _sg_imgui_capture_next_frame(sg_imgui_t* ctx) {
  1053. ctx->capture.bucket_index = (ctx->capture.bucket_index + 1) & 1;
  1054. sg_imgui_capture_bucket_t* bucket = &ctx->capture.bucket[ctx->capture.bucket_index];
  1055. bucket->num_items = 0;
  1056. bucket->ubuf_pos = 0;
  1057. }
  1058. _SOKOL_PRIVATE void _sg_imgui_capture_grow_ubuf(sg_imgui_t* ctx, uint32_t required_size) {
  1059. sg_imgui_capture_bucket_t* bucket = _sg_imgui_capture_get_write_bucket(ctx);
  1060. SOKOL_ASSERT(required_size > bucket->ubuf_size);
  1061. int old_size = bucket->ubuf_size;
  1062. int new_size = required_size + (required_size>>1); /* allocate a bit ahead */
  1063. bucket->ubuf_size = new_size;
  1064. bucket->ubuf = (uint8_t*) _sg_imgui_realloc(bucket->ubuf, old_size, new_size);
  1065. }
  1066. _SOKOL_PRIVATE sg_imgui_capture_item_t* _sg_imgui_capture_next_write_item(sg_imgui_t* ctx) {
  1067. sg_imgui_capture_bucket_t* bucket = _sg_imgui_capture_get_write_bucket(ctx);
  1068. if (bucket->num_items < SG_IMGUI_MAX_FRAMECAPTURE_ITEMS) {
  1069. sg_imgui_capture_item_t* item = &bucket->items[bucket->num_items++];
  1070. return item;
  1071. }
  1072. else {
  1073. return 0;
  1074. }
  1075. }
  1076. _SOKOL_PRIVATE uint32_t _sg_imgui_capture_num_read_items(sg_imgui_t* ctx) {
  1077. sg_imgui_capture_bucket_t* bucket = _sg_imgui_capture_get_read_bucket(ctx);
  1078. return bucket->num_items;
  1079. }
  1080. _SOKOL_PRIVATE sg_imgui_capture_item_t* _sg_imgui_capture_read_item_at(sg_imgui_t* ctx, uint32_t index) {
  1081. sg_imgui_capture_bucket_t* bucket = _sg_imgui_capture_get_read_bucket(ctx);
  1082. SOKOL_ASSERT(index < bucket->num_items);
  1083. return &bucket->items[index];
  1084. }
  1085. _SOKOL_PRIVATE uint32_t _sg_imgui_capture_uniforms(sg_imgui_t* ctx, const void* data, int num_bytes) {
  1086. sg_imgui_capture_bucket_t* bucket = _sg_imgui_capture_get_write_bucket(ctx);
  1087. const uint32_t required_size = bucket->ubuf_pos + num_bytes;
  1088. if (required_size > bucket->ubuf_size) {
  1089. _sg_imgui_capture_grow_ubuf(ctx, required_size);
  1090. }
  1091. SOKOL_ASSERT(required_size <= bucket->ubuf_size);
  1092. memcpy(bucket->ubuf + bucket->ubuf_pos, data, num_bytes);
  1093. const uint32_t pos = bucket->ubuf_pos;
  1094. bucket->ubuf_pos += num_bytes;
  1095. SOKOL_ASSERT(bucket->ubuf_pos <= bucket->ubuf_size);
  1096. return pos;
  1097. }
  1098. _SOKOL_PRIVATE sg_imgui_str_t _sg_imgui_capture_item_string(sg_imgui_t* ctx, int index, const sg_imgui_capture_item_t* item) {
  1099. sg_imgui_str_t str = _sg_imgui_make_str(0);
  1100. sg_imgui_str_t res_id = _sg_imgui_make_str(0);
  1101. const int len = sizeof(str.buf);
  1102. switch (item->cmd) {
  1103. case SG_IMGUI_CMD_QUERY_FEATURE:
  1104. snprintf(str.buf, len, "%d: sg_query_feature(feature=%s) => %s",
  1105. index,
  1106. _sg_imgui_feature_string(item->args.query_feature.feature),
  1107. _sg_imgui_bool_string(item->args.query_feature.result));
  1108. break;
  1109. case SG_IMGUI_CMD_RESET_STATE_CACHE:
  1110. snprintf(str.buf, len, "%d: sg_reset_state_cache()", index);
  1111. break;
  1112. case SG_IMGUI_CMD_MAKE_BUFFER:
  1113. res_id = _sg_imgui_buffer_id_string(ctx, item->args.make_buffer.result);
  1114. snprintf(str.buf, len, "%d: sg_make_buffer(desc=..) => %s", index, res_id.buf);
  1115. break;
  1116. case SG_IMGUI_CMD_MAKE_IMAGE:
  1117. res_id = _sg_imgui_image_id_string(ctx, item->args.make_image.result);
  1118. snprintf(str.buf, len, "%d: sg_make_image(desc=..) => %s", index, res_id.buf);
  1119. break;
  1120. case SG_IMGUI_CMD_MAKE_SHADER:
  1121. res_id = _sg_imgui_shader_id_string(ctx, item->args.make_shader.result);
  1122. snprintf(str.buf, len, "%d: sg_make_shader(desc=..) => %s", index, res_id.buf);
  1123. break;
  1124. case SG_IMGUI_CMD_MAKE_PIPELINE:
  1125. res_id = _sg_imgui_pipeline_id_string(ctx, item->args.make_pipeline.result);
  1126. snprintf(str.buf, len, "%d: sg_make_pipeline(desc=..) => %s", index, res_id.buf);
  1127. break;
  1128. case SG_IMGUI_CMD_MAKE_PASS:
  1129. res_id = _sg_imgui_pass_id_string(ctx, item->args.make_pass.result);
  1130. snprintf(str.buf, len, "%d: sg_make_pass(desc=..) => %s", index, res_id.buf);
  1131. break;
  1132. case SG_IMGUI_CMD_DESTROY_BUFFER:
  1133. res_id = _sg_imgui_buffer_id_string(ctx, item->args.destroy_buffer.buffer);
  1134. snprintf(str.buf, len, "%d: sg_destroy_buffer(buf=%s)", index, res_id.buf);
  1135. break;
  1136. case SG_IMGUI_CMD_DESTROY_IMAGE:
  1137. res_id = _sg_imgui_image_id_string(ctx, item->args.destroy_image.image);
  1138. snprintf(str.buf, len, "%d: sg_destroy_image(img=%s)", index, res_id.buf);
  1139. break;
  1140. case SG_IMGUI_CMD_DESTROY_SHADER:
  1141. res_id = _sg_imgui_shader_id_string(ctx, item->args.destroy_shader.shader);
  1142. snprintf(str.buf, len, "%d: sg_destroy_shader(shd=%s)", index, res_id.buf);
  1143. break;
  1144. case SG_IMGUI_CMD_DESTROY_PIPELINE:
  1145. res_id = _sg_imgui_pipeline_id_string(ctx, item->args.destroy_pipeline.pipeline);
  1146. snprintf(str.buf, len, "%d: sg_destroy_pipeline(pip=%s)", index, res_id.buf);
  1147. break;
  1148. case SG_IMGUI_CMD_DESTROY_PASS:
  1149. res_id = _sg_imgui_pass_id_string(ctx, item->args.destroy_pass.pass);
  1150. snprintf(str.buf, len, "%d: sg_destroy_pass(pass=%s)", index, res_id.buf);
  1151. break;
  1152. case SG_IMGUI_CMD_UPDATE_BUFFER:
  1153. res_id = _sg_imgui_buffer_id_string(ctx, item->args.update_buffer.buffer);
  1154. snprintf(str.buf, len, "%d: sg_update_buffer(buf=%s, data_ptr=.., data_size=%d)",
  1155. index, res_id.buf,
  1156. item->args.update_buffer.data_size);
  1157. break;
  1158. case SG_IMGUI_CMD_UPDATE_IMAGE:
  1159. res_id = _sg_imgui_image_id_string(ctx, item->args.update_image.image);
  1160. snprintf(str.buf, len, "%d: sg_update_image(img=%s, data=..)", index, res_id.buf);
  1161. break;
  1162. case SG_IMGUI_CMD_APPEND_BUFFER:
  1163. res_id = _sg_imgui_buffer_id_string(ctx, item->args.append_buffer.buffer);
  1164. snprintf(str.buf, len, "%d: sg_append_buffer(buf=%s, data_ptr=.., data_size=%d) => %d",
  1165. index, res_id.buf,
  1166. item->args.append_buffer.data_size,
  1167. item->args.append_buffer.result);
  1168. break;
  1169. case SG_IMGUI_CMD_BEGIN_DEFAULT_PASS:
  1170. snprintf(str.buf, len, "%d: sg_begin_default_pass(pass_action=.., width=%d, height=%d)",
  1171. index,
  1172. item->args.begin_default_pass.width,
  1173. item->args.begin_default_pass.height);
  1174. break;
  1175. case SG_IMGUI_CMD_BEGIN_PASS:
  1176. res_id = _sg_imgui_pass_id_string(ctx, item->args.begin_pass.pass);
  1177. snprintf(str.buf, len, "%d: sg_begin_pass(pass=%s, pass_action=..)", index, res_id.buf);
  1178. break;
  1179. case SG_IMGUI_CMD_APPLY_VIEWPORT:
  1180. snprintf(str.buf, len, "%d: sg_apply_viewport(x=%d, y=%d, width=%d, height=%d, origin_top_left=%s)",
  1181. index,
  1182. item->args.apply_viewport.x,
  1183. item->args.apply_viewport.y,
  1184. item->args.apply_viewport.width,
  1185. item->args.apply_viewport.height,
  1186. _sg_imgui_bool_string(item->args.apply_viewport.origin_top_left));
  1187. break;
  1188. case SG_IMGUI_CMD_APPLY_SCISSOR_RECT:
  1189. snprintf(str.buf, len, "%d: sg_apply_scissor_rect(x=%d, y=%d, width=%d, height=%d, origin_top_left=%s)",
  1190. index,
  1191. item->args.apply_scissor_rect.x,
  1192. item->args.apply_scissor_rect.y,
  1193. item->args.apply_scissor_rect.width,
  1194. item->args.apply_scissor_rect.height,
  1195. _sg_imgui_bool_string(item->args.apply_scissor_rect.origin_top_left));
  1196. break;
  1197. case SG_IMGUI_CMD_APPLY_PIPELINE:
  1198. res_id = _sg_imgui_pipeline_id_string(ctx, item->args.apply_pipeline.pipeline);
  1199. snprintf(str.buf, len, "%d: sg_apply_pipeline(pip=%s)", index, res_id.buf);
  1200. break;
  1201. case SG_IMGUI_CMD_APPLY_BINDINGS:
  1202. snprintf(str.buf, len, "%d: sg_apply_bindings(bindings=..)", index);
  1203. break;
  1204. case SG_IMGUI_CMD_APPLY_UNIFORMS:
  1205. snprintf(str.buf, len, "%d: sg_apply_uniforms(stage=%s, ub_index=%d, data=.., num_bytes=%d)",
  1206. index,
  1207. _sg_imgui_shaderstage_string(item->args.apply_uniforms.stage),
  1208. item->args.apply_uniforms.ub_index,
  1209. item->args.apply_uniforms.num_bytes);
  1210. break;
  1211. case SG_IMGUI_CMD_DRAW:
  1212. snprintf(str.buf, len, "%d: sg_draw(base_element=%d, num_elements=%d, num_instances=%d)",
  1213. index,
  1214. item->args.draw.base_element,
  1215. item->args.draw.num_elements,
  1216. item->args.draw.num_instances);
  1217. break;
  1218. case SG_IMGUI_CMD_END_PASS:
  1219. snprintf(str.buf, len, "%d: sg_end_pass()", index);
  1220. break;
  1221. case SG_IMGUI_CMD_COMMIT:
  1222. snprintf(str.buf, len, "%d: sg_commit()", index);
  1223. break;
  1224. case SG_IMGUI_CMD_ALLOC_BUFFER:
  1225. res_id = _sg_imgui_buffer_id_string(ctx, item->args.alloc_buffer.result);
  1226. snprintf(str.buf, len, "%d: sg_alloc_buffer() => %s", index, res_id.buf);
  1227. break;
  1228. case SG_IMGUI_CMD_ALLOC_IMAGE:
  1229. res_id = _sg_imgui_image_id_string(ctx, item->args.alloc_image.result);
  1230. snprintf(str.buf, len, "%d: sg_alloc_image() => %s", index, res_id.buf);
  1231. break;
  1232. case SG_IMGUI_CMD_ALLOC_SHADER:
  1233. res_id = _sg_imgui_shader_id_string(ctx, item->args.alloc_shader.result);
  1234. snprintf(str.buf, len, "%d: sg_alloc_shader() => %s", index, res_id.buf);
  1235. break;
  1236. case SG_IMGUI_CMD_ALLOC_PIPELINE:
  1237. res_id = _sg_imgui_pipeline_id_string(ctx, item->args.alloc_pipeline.result);
  1238. snprintf(str.buf, len, "%d: sg_alloc_pipeline() => %s", index, res_id.buf);
  1239. break;
  1240. case SG_IMGUI_CMD_ALLOC_PASS:
  1241. res_id = _sg_imgui_pass_id_string(ctx, item->args.alloc_pass.result);
  1242. snprintf(str.buf, len, "%d: sg_alloc_pass() => %s", index, res_id.buf);
  1243. break;
  1244. case SG_IMGUI_CMD_INIT_BUFFER:
  1245. res_id = _sg_imgui_buffer_id_string(ctx, item->args.init_buffer.buffer);
  1246. snprintf(str.buf, len, "%d: sg_init_buffer(buf=%s, desc=..)", index, res_id.buf);
  1247. break;
  1248. case SG_IMGUI_CMD_INIT_IMAGE:
  1249. res_id = _sg_imgui_image_id_string(ctx, item->args.init_image.image);
  1250. snprintf(str.buf, len, "%d: sg_init_image(img=%s, desc=..)", index, res_id.buf);
  1251. break;
  1252. case SG_IMGUI_CMD_INIT_SHADER:
  1253. res_id = _sg_imgui_shader_id_string(ctx, item->args.init_shader.shader);
  1254. snprintf(str.buf, len, "%d: sg_init_shader(shd=%s, desc=..)", index, res_id.buf);
  1255. break;
  1256. case SG_IMGUI_CMD_INIT_PIPELINE:
  1257. res_id = _sg_imgui_pipeline_id_string(ctx, item->args.init_pipeline.pipeline);
  1258. snprintf(str.buf, len, "%d: sg_init_pipeline(pip=%s, desc=..)", index, res_id.buf);
  1259. break;
  1260. case SG_IMGUI_CMD_INIT_PASS:
  1261. res_id = _sg_imgui_pass_id_string(ctx, item->args.init_pass.pass);
  1262. snprintf(str.buf, len, "%d: sg_init_pass(pass=%s, desc=..)", index, res_id.buf);
  1263. break;
  1264. case SG_IMGUI_CMD_FAIL_BUFFER:
  1265. res_id = _sg_imgui_buffer_id_string(ctx, item->args.fail_buffer.buffer);
  1266. snprintf(str.buf, len, "%d: sg_fail_buffer(buf=%s)", index, res_id.buf);
  1267. break;
  1268. case SG_IMGUI_CMD_FAIL_IMAGE:
  1269. res_id = _sg_imgui_image_id_string(ctx, item->args.fail_image.image);
  1270. snprintf(str.buf, len, "%d: sg_fail_image(img=%s)", index, res_id.buf);
  1271. break;
  1272. case SG_IMGUI_CMD_FAIL_SHADER:
  1273. res_id = _sg_imgui_shader_id_string(ctx, item->args.fail_shader.shader);
  1274. snprintf(str.buf, len, "%d: sg_fail_shader(shd=%s)", index, res_id.buf);
  1275. break;
  1276. case SG_IMGUI_CMD_FAIL_PIPELINE:
  1277. res_id = _sg_imgui_pipeline_id_string(ctx, item->args.fail_pipeline.pipeline);
  1278. snprintf(str.buf, len, "%d: sg_fail_pipeline(shd=%s)", index, res_id.buf);
  1279. break;
  1280. case SG_IMGUI_CMD_FAIL_PASS:
  1281. res_id = _sg_imgui_pass_id_string(ctx, item->args.fail_pass.pass);
  1282. snprintf(str.buf, len, "%d: sg_fail_pass(pass=%s)", index, res_id.buf);
  1283. break;
  1284. case SG_IMGUI_CMD_PUSH_DEBUG_GROUP:
  1285. snprintf(str.buf, len, "%d: sg_push_debug_group(name=%s)", index,
  1286. item->args.push_debug_group.name.buf);
  1287. break;
  1288. case SG_IMGUI_CMD_POP_DEBUG_GROUP:
  1289. snprintf(str.buf, len, "%d: sg_pop_debug_group()", index);
  1290. break;
  1291. case SG_IMGUI_CMD_ERR_BUFFER_POOL_EXHAUSTED:
  1292. snprintf(str.buf, len, "%d: sg_err_buffer_pool_exhausted()", index);
  1293. break;
  1294. case SG_IMGUI_CMD_ERR_IMAGE_POOL_EXHAUSTED:
  1295. snprintf(str.buf, len, "%d: sg_err_image_pool_exhausted()", index);
  1296. break;
  1297. case SG_IMGUI_CMD_ERR_SHADER_POOL_EXHAUSTED:
  1298. snprintf(str.buf, len, "%d: sg_err_shader_pool_exhausted()", index);
  1299. break;
  1300. case SG_IMGUI_CMD_ERR_PIPELINE_POOL_EXHAUSTED:
  1301. snprintf(str.buf, len, "%d: sg_err_pipeline_pool_exhausted()", index);
  1302. break;
  1303. case SG_IMGUI_CMD_ERR_PASS_POOL_EXHAUSTED:
  1304. snprintf(str.buf, len, "%d: sg_err_pass_pool_exhausted()", index);
  1305. break;
  1306. case SG_IMGUI_CMD_ERR_CONTEXT_MISMATCH:
  1307. snprintf(str.buf, len, "%d: sg_err_context_mismatch()", index);
  1308. break;
  1309. case SG_IMGUI_CMD_ERR_PASS_INVALID:
  1310. snprintf(str.buf, len, "%d: sg_err_pass_invalid()", index);
  1311. break;
  1312. case SG_IMGUI_CMD_ERR_DRAW_INVALID:
  1313. snprintf(str.buf, len, "%d: sg_err_draw_invalid()", index);
  1314. break;
  1315. case SG_IMGUI_CMD_ERR_BINDINGS_INVALID:
  1316. snprintf(str.buf, len, "%d: sg_err_bindings_invalid()", index);
  1317. break;
  1318. default:
  1319. snprintf(str.buf, len, "%d: ???", index);
  1320. break;
  1321. }
  1322. str.buf[len-1] = 0;
  1323. return str;
  1324. }
  1325. /*--- CAPTURE CALLBACKS ------------------------------------------------------*/
  1326. _SOKOL_PRIVATE void _sg_imgui_query_feature(sg_feature feature, bool result, void* user_data) {
  1327. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1328. SOKOL_ASSERT(ctx);
  1329. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1330. if (item) {
  1331. item->cmd = SG_IMGUI_CMD_QUERY_FEATURE;
  1332. item->color = _SG_IMGUI_COLOR_OTHER;
  1333. item->args.query_feature.feature = feature;
  1334. item->args.query_feature.result = result;
  1335. }
  1336. if (ctx->hooks.query_feature) {
  1337. ctx->hooks.query_feature(feature, result, ctx->hooks.user_data);
  1338. }
  1339. }
  1340. _SOKOL_PRIVATE void _sg_imgui_reset_state_cache(void* user_data) {
  1341. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1342. SOKOL_ASSERT(ctx);
  1343. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1344. if (item) {
  1345. item->cmd = SG_IMGUI_CMD_RESET_STATE_CACHE;
  1346. item->color = _SG_IMGUI_COLOR_OTHER;
  1347. }
  1348. if (ctx->hooks.reset_state_cache) {
  1349. ctx->hooks.reset_state_cache(ctx->hooks.user_data);
  1350. }
  1351. }
  1352. _SOKOL_PRIVATE void _sg_imgui_make_buffer(const sg_buffer_desc* desc, sg_buffer buf_id, void* user_data) {
  1353. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1354. SOKOL_ASSERT(ctx);
  1355. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1356. if (item) {
  1357. item->cmd = SG_IMGUI_CMD_MAKE_BUFFER;
  1358. item->color = _SG_IMGUI_COLOR_RSRC;
  1359. item->args.make_buffer.result = buf_id;
  1360. }
  1361. if (ctx->hooks.make_buffer) {
  1362. ctx->hooks.make_buffer(desc, buf_id, ctx->hooks.user_data);
  1363. }
  1364. if (buf_id.id != SG_INVALID_ID) {
  1365. _sg_imgui_buffer_created(ctx, buf_id, _sg_imgui_slot_index(buf_id.id), desc);
  1366. }
  1367. }
  1368. _SOKOL_PRIVATE void _sg_imgui_make_image(const sg_image_desc* desc, sg_image img_id, void* user_data) {
  1369. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1370. SOKOL_ASSERT(ctx);
  1371. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1372. if (item) {
  1373. item->cmd = SG_IMGUI_CMD_MAKE_IMAGE;
  1374. item->color = _SG_IMGUI_COLOR_RSRC;
  1375. item->args.make_image.result = img_id;
  1376. }
  1377. if (ctx->hooks.make_image) {
  1378. ctx->hooks.make_image(desc, img_id, ctx->hooks.user_data);
  1379. }
  1380. if (img_id.id != SG_INVALID_ID) {
  1381. _sg_imgui_image_created(ctx, img_id, _sg_imgui_slot_index(img_id.id), desc);
  1382. }
  1383. }
  1384. _SOKOL_PRIVATE void _sg_imgui_make_shader(const sg_shader_desc* desc, sg_shader shd_id, void* user_data) {
  1385. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1386. SOKOL_ASSERT(ctx);
  1387. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1388. if (item) {
  1389. item->cmd = SG_IMGUI_CMD_MAKE_SHADER;
  1390. item->color = _SG_IMGUI_COLOR_RSRC;
  1391. item->args.make_shader.result = shd_id;
  1392. }
  1393. if (ctx->hooks.make_shader) {
  1394. ctx->hooks.make_shader(desc, shd_id, ctx->hooks.user_data);
  1395. }
  1396. if (shd_id.id != SG_INVALID_ID) {
  1397. _sg_imgui_shader_created(ctx, shd_id, _sg_imgui_slot_index(shd_id.id), desc);
  1398. }
  1399. }
  1400. _SOKOL_PRIVATE void _sg_imgui_make_pipeline(const sg_pipeline_desc* desc, sg_pipeline pip_id, void* user_data) {
  1401. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1402. SOKOL_ASSERT(ctx);
  1403. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1404. if (item) {
  1405. item->cmd = SG_IMGUI_CMD_MAKE_PIPELINE;
  1406. item->color = _SG_IMGUI_COLOR_RSRC;
  1407. item->args.make_pipeline.result = pip_id;
  1408. }
  1409. if (ctx->hooks.make_pipeline) {
  1410. ctx->hooks.make_pipeline(desc, pip_id, ctx->hooks.user_data);
  1411. }
  1412. if (pip_id.id != SG_INVALID_ID) {
  1413. _sg_imgui_pipeline_created(ctx, pip_id, _sg_imgui_slot_index(pip_id.id), desc);
  1414. }
  1415. }
  1416. _SOKOL_PRIVATE void _sg_imgui_make_pass(const sg_pass_desc* desc, sg_pass pass_id, void* user_data) {
  1417. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1418. SOKOL_ASSERT(ctx);
  1419. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1420. if (item) {
  1421. item->cmd = SG_IMGUI_CMD_MAKE_PASS;
  1422. item->color = _SG_IMGUI_COLOR_RSRC;
  1423. item->args.make_pass.result = pass_id;
  1424. }
  1425. if (ctx->hooks.make_pass) {
  1426. ctx->hooks.make_pass(desc, pass_id, ctx->hooks.user_data);
  1427. }
  1428. if (pass_id.id != SG_INVALID_ID) {
  1429. _sg_imgui_pass_created(ctx, pass_id, _sg_imgui_slot_index(pass_id.id), desc);
  1430. }
  1431. }
  1432. _SOKOL_PRIVATE void _sg_imgui_destroy_buffer(sg_buffer buf, void* user_data) {
  1433. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1434. SOKOL_ASSERT(ctx);
  1435. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1436. if (item) {
  1437. item->cmd = SG_IMGUI_CMD_DESTROY_BUFFER;
  1438. item->color = _SG_IMGUI_COLOR_RSRC;
  1439. item->args.destroy_buffer.buffer = buf;
  1440. }
  1441. if (ctx->hooks.destroy_buffer) {
  1442. ctx->hooks.destroy_buffer(buf, ctx->hooks.user_data);
  1443. }
  1444. if (buf.id != SG_INVALID_ID) {
  1445. _sg_imgui_buffer_destroyed(ctx, _sg_imgui_slot_index(buf.id));
  1446. }
  1447. }
  1448. _SOKOL_PRIVATE void _sg_imgui_destroy_image(sg_image img, void* user_data) {
  1449. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1450. SOKOL_ASSERT(ctx);
  1451. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1452. if (item) {
  1453. item->cmd = SG_IMGUI_CMD_DESTROY_IMAGE;
  1454. item->color = _SG_IMGUI_COLOR_RSRC;
  1455. item->args.destroy_image.image = img;
  1456. }
  1457. if (ctx->hooks.destroy_image) {
  1458. ctx->hooks.destroy_image(img, ctx->hooks.user_data);
  1459. }
  1460. if (img.id != SG_INVALID_ID) {
  1461. _sg_imgui_image_destroyed(ctx, _sg_imgui_slot_index(img.id));
  1462. }
  1463. }
  1464. _SOKOL_PRIVATE void _sg_imgui_destroy_shader(sg_shader shd, void* user_data) {
  1465. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1466. SOKOL_ASSERT(ctx);
  1467. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1468. if (item) {
  1469. item->cmd = SG_IMGUI_CMD_DESTROY_SHADER;
  1470. item->color = _SG_IMGUI_COLOR_RSRC;
  1471. item->args.destroy_shader.shader = shd;
  1472. }
  1473. if (ctx->hooks.destroy_shader) {
  1474. ctx->hooks.destroy_shader(shd, ctx->hooks.user_data);
  1475. }
  1476. if (shd.id != SG_INVALID_ID) {
  1477. _sg_imgui_shader_destroyed(ctx, _sg_imgui_slot_index(shd.id));
  1478. }
  1479. }
  1480. _SOKOL_PRIVATE void _sg_imgui_destroy_pipeline(sg_pipeline pip, void* user_data) {
  1481. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1482. SOKOL_ASSERT(ctx);
  1483. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1484. if (item) {
  1485. item->cmd = SG_IMGUI_CMD_DESTROY_PIPELINE;
  1486. item->color = _SG_IMGUI_COLOR_RSRC;
  1487. item->args.destroy_pipeline.pipeline = pip;
  1488. }
  1489. if (ctx->hooks.destroy_pipeline) {
  1490. ctx->hooks.destroy_pipeline(pip, ctx->hooks.user_data);
  1491. }
  1492. if (pip.id != SG_INVALID_ID) {
  1493. _sg_imgui_pipeline_destroyed(ctx, _sg_imgui_slot_index(pip.id));
  1494. }
  1495. }
  1496. _SOKOL_PRIVATE void _sg_imgui_destroy_pass(sg_pass pass, void* user_data) {
  1497. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1498. SOKOL_ASSERT(ctx);
  1499. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1500. if (item) {
  1501. item->cmd = SG_IMGUI_CMD_DESTROY_PASS;
  1502. item->color = _SG_IMGUI_COLOR_RSRC;
  1503. item->args.destroy_pass.pass = pass;
  1504. }
  1505. if (ctx->hooks.destroy_pass) {
  1506. ctx->hooks.destroy_pass(pass, ctx->hooks.user_data);
  1507. }
  1508. if (pass.id != SG_INVALID_ID) {
  1509. _sg_imgui_pass_destroyed(ctx, _sg_imgui_slot_index(pass.id));
  1510. }
  1511. }
  1512. _SOKOL_PRIVATE void _sg_imgui_update_buffer(sg_buffer buf, const void* data_ptr, int data_size, void* user_data) {
  1513. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1514. SOKOL_ASSERT(ctx);
  1515. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1516. if (item) {
  1517. item->cmd = SG_IMGUI_CMD_UPDATE_BUFFER;
  1518. item->color = _SG_IMGUI_COLOR_RSRC;
  1519. item->args.update_buffer.buffer = buf;
  1520. item->args.update_buffer.data_size = data_size;
  1521. }
  1522. if (ctx->hooks.update_buffer) {
  1523. ctx->hooks.update_buffer(buf, data_ptr, data_size, ctx->hooks.user_data);
  1524. }
  1525. }
  1526. _SOKOL_PRIVATE void _sg_imgui_update_image(sg_image img, const sg_image_content* data, void* user_data) {
  1527. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1528. SOKOL_ASSERT(ctx);
  1529. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1530. if (item) {
  1531. item->cmd = SG_IMGUI_CMD_UPDATE_IMAGE;
  1532. item->color = _SG_IMGUI_COLOR_RSRC;
  1533. item->args.update_image.image = img;
  1534. }
  1535. if (ctx->hooks.update_image) {
  1536. ctx->hooks.update_image(img, data, ctx->hooks.user_data);
  1537. }
  1538. }
  1539. _SOKOL_PRIVATE void _sg_imgui_append_buffer(sg_buffer buf, const void* data_ptr, int data_size, int result, void* user_data) {
  1540. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1541. SOKOL_ASSERT(ctx);
  1542. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1543. if (item) {
  1544. item->cmd = SG_IMGUI_CMD_APPEND_BUFFER;
  1545. item->color = _SG_IMGUI_COLOR_RSRC;
  1546. item->args.append_buffer.buffer = buf;
  1547. item->args.append_buffer.data_size = data_size;
  1548. item->args.append_buffer.result = result;
  1549. }
  1550. if (ctx->hooks.append_buffer) {
  1551. ctx->hooks.append_buffer(buf, data_ptr, data_size, result, ctx->hooks.user_data);
  1552. }
  1553. }
  1554. _SOKOL_PRIVATE void _sg_imgui_begin_default_pass(const sg_pass_action* pass_action, int width, int height, void* user_data) {
  1555. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1556. SOKOL_ASSERT(ctx);
  1557. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1558. if (item) {
  1559. SOKOL_ASSERT(pass_action);
  1560. item->cmd = SG_IMGUI_CMD_BEGIN_DEFAULT_PASS;
  1561. item->color = _SG_IMGUI_COLOR_DRAW;
  1562. item->args.begin_default_pass.action = *pass_action;
  1563. item->args.begin_default_pass.width = width;
  1564. item->args.begin_default_pass.height = height;
  1565. }
  1566. if (ctx->hooks.begin_default_pass) {
  1567. ctx->hooks.begin_default_pass(pass_action, width, height, ctx->hooks.user_data);
  1568. }
  1569. }
  1570. _SOKOL_PRIVATE void _sg_imgui_begin_pass(sg_pass pass, const sg_pass_action* pass_action, void* user_data) {
  1571. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1572. SOKOL_ASSERT(ctx);
  1573. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1574. if (item) {
  1575. SOKOL_ASSERT(pass_action);
  1576. item->cmd = SG_IMGUI_CMD_BEGIN_PASS;
  1577. item->color = _SG_IMGUI_COLOR_DRAW;
  1578. item->args.begin_pass.pass = pass;
  1579. item->args.begin_pass.action = *pass_action;
  1580. }
  1581. if (ctx->hooks.begin_pass) {
  1582. ctx->hooks.begin_pass(pass, pass_action, ctx->hooks.user_data);
  1583. }
  1584. }
  1585. _SOKOL_PRIVATE void _sg_imgui_apply_viewport(int x, int y, int width, int height, bool origin_top_left, void* user_data) {
  1586. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1587. SOKOL_ASSERT(ctx);
  1588. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1589. if (item) {
  1590. item->cmd = SG_IMGUI_CMD_APPLY_VIEWPORT;
  1591. item->color = _SG_IMGUI_COLOR_DRAW;
  1592. item->args.apply_viewport.x = x;
  1593. item->args.apply_viewport.y = y;
  1594. item->args.apply_viewport.width = width;
  1595. item->args.apply_viewport.height = height;
  1596. item->args.apply_viewport.origin_top_left = origin_top_left;
  1597. }
  1598. if (ctx->hooks.apply_viewport) {
  1599. ctx->hooks.apply_viewport(x, y, width, height, origin_top_left, ctx->hooks.user_data);
  1600. }
  1601. }
  1602. _SOKOL_PRIVATE void _sg_imgui_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left, void* user_data) {
  1603. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1604. SOKOL_ASSERT(ctx);
  1605. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1606. if (item) {
  1607. item->cmd = SG_IMGUI_CMD_APPLY_SCISSOR_RECT;
  1608. item->color = _SG_IMGUI_COLOR_DRAW;
  1609. item->args.apply_scissor_rect.x = x;
  1610. item->args.apply_scissor_rect.y = y;
  1611. item->args.apply_scissor_rect.width = width;
  1612. item->args.apply_scissor_rect.height = height;
  1613. item->args.apply_scissor_rect.origin_top_left = origin_top_left;
  1614. }
  1615. if (ctx->hooks.apply_scissor_rect) {
  1616. ctx->hooks.apply_scissor_rect(x, y, width, height, origin_top_left, ctx->hooks.user_data);
  1617. }
  1618. }
  1619. _SOKOL_PRIVATE void _sg_imgui_apply_pipeline(sg_pipeline pip, void* user_data) {
  1620. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1621. SOKOL_ASSERT(ctx);
  1622. ctx->cur_pipeline = pip; /* stored for _sg_imgui_apply_uniforms */
  1623. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1624. if (item) {
  1625. item->cmd = SG_IMGUI_CMD_APPLY_PIPELINE;
  1626. item->color = _SG_IMGUI_COLOR_DRAW;
  1627. item->args.apply_pipeline.pipeline = pip;
  1628. }
  1629. if (ctx->hooks.apply_pipeline) {
  1630. ctx->hooks.apply_pipeline(pip, ctx->hooks.user_data);
  1631. }
  1632. }
  1633. _SOKOL_PRIVATE void _sg_imgui_apply_bindings(const sg_bindings* bindings, void* user_data) {
  1634. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1635. SOKOL_ASSERT(ctx);
  1636. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1637. if (item) {
  1638. SOKOL_ASSERT(bindings);
  1639. item->cmd = SG_IMGUI_CMD_APPLY_BINDINGS;
  1640. item->color = _SG_IMGUI_COLOR_DRAW;
  1641. item->args.apply_bindings.bindings = *bindings;
  1642. }
  1643. if (ctx->hooks.apply_bindings) {
  1644. ctx->hooks.apply_bindings(bindings, ctx->hooks.user_data);
  1645. }
  1646. }
  1647. _SOKOL_PRIVATE void _sg_imgui_apply_uniforms(sg_shader_stage stage, int ub_index, const void* data, int num_bytes, void* user_data) {
  1648. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1649. SOKOL_ASSERT(ctx);
  1650. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1651. if (item) {
  1652. item->cmd = SG_IMGUI_CMD_APPLY_UNIFORMS;
  1653. item->color = _SG_IMGUI_COLOR_DRAW;
  1654. sg_imgui_args_apply_uniforms_t* args = &item->args.apply_uniforms;
  1655. args->stage = stage;
  1656. args->ub_index = ub_index;
  1657. args->data = data;
  1658. args->num_bytes = num_bytes;
  1659. args->pipeline = ctx->cur_pipeline;
  1660. args->ubuf_pos = _sg_imgui_capture_uniforms(ctx, data, num_bytes);
  1661. }
  1662. if (ctx->hooks.apply_uniforms) {
  1663. ctx->hooks.apply_uniforms(stage, ub_index, data, num_bytes, ctx->hooks.user_data);
  1664. }
  1665. }
  1666. _SOKOL_PRIVATE void _sg_imgui_draw(int base_element, int num_elements, int num_instances, void* user_data) {
  1667. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1668. SOKOL_ASSERT(ctx);
  1669. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1670. if (item) {
  1671. item->cmd = SG_IMGUI_CMD_DRAW;
  1672. item->color = _SG_IMGUI_COLOR_DRAW;
  1673. item->args.draw.base_element = base_element;
  1674. item->args.draw.num_elements = num_elements;
  1675. item->args.draw.num_instances = num_instances;
  1676. }
  1677. if (ctx->hooks.draw) {
  1678. ctx->hooks.draw(base_element, num_elements, num_instances, ctx->hooks.user_data);
  1679. }
  1680. }
  1681. _SOKOL_PRIVATE void _sg_imgui_end_pass(void* user_data) {
  1682. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1683. SOKOL_ASSERT(ctx);
  1684. ctx->cur_pipeline.id = SG_INVALID_ID;
  1685. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1686. if (item) {
  1687. item->cmd = SG_IMGUI_CMD_END_PASS;
  1688. item->color = _SG_IMGUI_COLOR_DRAW;
  1689. }
  1690. if (ctx->hooks.end_pass) {
  1691. ctx->hooks.end_pass(ctx->hooks.user_data);
  1692. }
  1693. }
  1694. _SOKOL_PRIVATE void _sg_imgui_commit(void* user_data) {
  1695. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1696. SOKOL_ASSERT(ctx);
  1697. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1698. if (item) {
  1699. item->cmd = SG_IMGUI_CMD_COMMIT;
  1700. item->color = _SG_IMGUI_COLOR_DRAW;
  1701. }
  1702. _sg_imgui_capture_next_frame(ctx);
  1703. if (ctx->hooks.commit) {
  1704. ctx->hooks.commit(ctx->hooks.user_data);
  1705. }
  1706. }
  1707. _SOKOL_PRIVATE void _sg_imgui_alloc_buffer(sg_buffer result, void* user_data) {
  1708. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1709. SOKOL_ASSERT(ctx);
  1710. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1711. if (item) {
  1712. item->cmd = SG_IMGUI_CMD_ALLOC_BUFFER;
  1713. item->color = _SG_IMGUI_COLOR_RSRC;
  1714. item->args.alloc_buffer.result = result;
  1715. }
  1716. if (ctx->hooks.alloc_buffer) {
  1717. ctx->hooks.alloc_buffer(result, ctx->hooks.user_data);
  1718. }
  1719. }
  1720. _SOKOL_PRIVATE void _sg_imgui_alloc_image(sg_image result, void* user_data) {
  1721. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1722. SOKOL_ASSERT(ctx);
  1723. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1724. if (item) {
  1725. item->cmd = SG_IMGUI_CMD_ALLOC_IMAGE;
  1726. item->color = _SG_IMGUI_COLOR_RSRC;
  1727. item->args.alloc_image.result = result;
  1728. }
  1729. if (ctx->hooks.alloc_image) {
  1730. ctx->hooks.alloc_image(result, ctx->hooks.user_data);
  1731. }
  1732. }
  1733. _SOKOL_PRIVATE void _sg_imgui_alloc_shader(sg_shader result, void* user_data) {
  1734. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1735. SOKOL_ASSERT(ctx);
  1736. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1737. if (item) {
  1738. item->cmd = SG_IMGUI_CMD_ALLOC_SHADER;
  1739. item->color = _SG_IMGUI_COLOR_RSRC;
  1740. item->args.alloc_shader.result = result;
  1741. }
  1742. if (ctx->hooks.alloc_shader) {
  1743. ctx->hooks.alloc_shader(result, ctx->hooks.user_data);
  1744. }
  1745. }
  1746. _SOKOL_PRIVATE void _sg_imgui_alloc_pipeline(sg_pipeline result, void* user_data) {
  1747. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1748. SOKOL_ASSERT(ctx);
  1749. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1750. if (item) {
  1751. item->cmd = SG_IMGUI_CMD_ALLOC_PIPELINE;
  1752. item->color = _SG_IMGUI_COLOR_RSRC;
  1753. item->args.alloc_pipeline.result = result;
  1754. }
  1755. if (ctx->hooks.alloc_pipeline) {
  1756. ctx->hooks.alloc_pipeline(result, ctx->hooks.user_data);
  1757. }
  1758. }
  1759. _SOKOL_PRIVATE void _sg_imgui_alloc_pass(sg_pass result, void* user_data) {
  1760. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1761. SOKOL_ASSERT(ctx);
  1762. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1763. if (item) {
  1764. item->cmd = SG_IMGUI_CMD_ALLOC_PASS;
  1765. item->color = _SG_IMGUI_COLOR_RSRC;
  1766. item->args.alloc_pass.result = result;
  1767. }
  1768. if (ctx->hooks.alloc_pass) {
  1769. ctx->hooks.alloc_pass(result, ctx->hooks.user_data);
  1770. }
  1771. }
  1772. _SOKOL_PRIVATE void _sg_imgui_init_buffer(sg_buffer buf_id, const sg_buffer_desc* desc, void* user_data) {
  1773. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1774. SOKOL_ASSERT(ctx);
  1775. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1776. if (item) {
  1777. item->cmd = SG_IMGUI_CMD_INIT_BUFFER;
  1778. item->color = _SG_IMGUI_COLOR_RSRC;
  1779. item->args.init_buffer.buffer = buf_id;
  1780. }
  1781. if (ctx->hooks.init_buffer) {
  1782. ctx->hooks.init_buffer(buf_id, desc, ctx->hooks.user_data);
  1783. }
  1784. if (buf_id.id != SG_INVALID_ID) {
  1785. _sg_imgui_buffer_created(ctx, buf_id, _sg_imgui_slot_index(buf_id.id), desc);
  1786. }
  1787. }
  1788. _SOKOL_PRIVATE void _sg_imgui_init_image(sg_image img_id, const sg_image_desc* desc, void* user_data) {
  1789. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1790. SOKOL_ASSERT(ctx);
  1791. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1792. if (item) {
  1793. item->cmd = SG_IMGUI_CMD_INIT_IMAGE;
  1794. item->color = _SG_IMGUI_COLOR_RSRC;
  1795. item->args.init_image.image = img_id;
  1796. }
  1797. if (ctx->hooks.init_image) {
  1798. ctx->hooks.init_image(img_id, desc, ctx->hooks.user_data);
  1799. }
  1800. if (img_id.id != SG_INVALID_ID) {
  1801. _sg_imgui_image_created(ctx, img_id, _sg_imgui_slot_index(img_id.id), desc);
  1802. }
  1803. }
  1804. _SOKOL_PRIVATE void _sg_imgui_init_shader(sg_shader shd_id, const sg_shader_desc* desc, void* user_data) {
  1805. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1806. SOKOL_ASSERT(ctx);
  1807. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1808. if (item) {
  1809. item->cmd = SG_IMGUI_CMD_INIT_SHADER;
  1810. item->color = _SG_IMGUI_COLOR_RSRC;
  1811. item->args.init_shader.shader = shd_id;
  1812. }
  1813. if (ctx->hooks.init_shader) {
  1814. ctx->hooks.init_shader(shd_id, desc, ctx->hooks.user_data);
  1815. }
  1816. if (shd_id.id != SG_INVALID_ID) {
  1817. _sg_imgui_shader_created(ctx, shd_id, _sg_imgui_slot_index(shd_id.id), desc);
  1818. }
  1819. }
  1820. _SOKOL_PRIVATE void _sg_imgui_init_pipeline(sg_pipeline pip_id, const sg_pipeline_desc* desc, void* user_data) {
  1821. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1822. SOKOL_ASSERT(ctx);
  1823. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1824. if (item) {
  1825. item->cmd = SG_IMGUI_CMD_INIT_PIPELINE;
  1826. item->color = _SG_IMGUI_COLOR_RSRC;
  1827. item->args.init_pipeline.pipeline = pip_id;
  1828. }
  1829. if (ctx->hooks.init_pipeline) {
  1830. ctx->hooks.init_pipeline(pip_id, desc, ctx->hooks.user_data);
  1831. }
  1832. if (pip_id.id != SG_INVALID_ID) {
  1833. _sg_imgui_pipeline_created(ctx, pip_id, _sg_imgui_slot_index(pip_id.id), desc);
  1834. }
  1835. }
  1836. _SOKOL_PRIVATE void _sg_imgui_init_pass(sg_pass pass_id, const sg_pass_desc* desc, void* user_data) {
  1837. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1838. SOKOL_ASSERT(ctx);
  1839. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1840. if (item) {
  1841. item->cmd = SG_IMGUI_CMD_INIT_PASS;
  1842. item->color = _SG_IMGUI_COLOR_RSRC;
  1843. item->args.init_pass.pass = pass_id;
  1844. }
  1845. if (ctx->hooks.init_pass) {
  1846. ctx->hooks.init_pass(pass_id, desc, ctx->hooks.user_data);
  1847. }
  1848. if (pass_id.id != SG_INVALID_ID) {
  1849. _sg_imgui_pass_created(ctx, pass_id, _sg_imgui_slot_index(pass_id.id), desc);
  1850. }
  1851. }
  1852. _SOKOL_PRIVATE void _sg_imgui_fail_buffer(sg_buffer buf_id, void* user_data) {
  1853. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1854. SOKOL_ASSERT(ctx);
  1855. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1856. if (item) {
  1857. item->cmd = SG_IMGUI_CMD_FAIL_BUFFER;
  1858. item->color = _SG_IMGUI_COLOR_RSRC;
  1859. item->args.fail_buffer.buffer = buf_id;
  1860. }
  1861. if (ctx->hooks.fail_buffer) {
  1862. ctx->hooks.fail_buffer(buf_id, ctx->hooks.user_data);
  1863. }
  1864. }
  1865. _SOKOL_PRIVATE void _sg_imgui_fail_image(sg_image img_id, void* user_data) {
  1866. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1867. SOKOL_ASSERT(ctx);
  1868. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1869. if (item) {
  1870. item->cmd = SG_IMGUI_CMD_FAIL_IMAGE;
  1871. item->color = _SG_IMGUI_COLOR_RSRC;
  1872. item->args.fail_image.image = img_id;
  1873. }
  1874. if (ctx->hooks.fail_image) {
  1875. ctx->hooks.fail_image(img_id, ctx->hooks.user_data);
  1876. }
  1877. }
  1878. _SOKOL_PRIVATE void _sg_imgui_fail_shader(sg_shader shd_id, void* user_data) {
  1879. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1880. SOKOL_ASSERT(ctx);
  1881. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1882. if (item) {
  1883. item->cmd = SG_IMGUI_CMD_FAIL_SHADER;
  1884. item->color = _SG_IMGUI_COLOR_RSRC;
  1885. item->args.fail_shader.shader = shd_id;
  1886. }
  1887. if (ctx->hooks.fail_shader) {
  1888. ctx->hooks.fail_shader(shd_id, ctx->hooks.user_data);
  1889. }
  1890. }
  1891. _SOKOL_PRIVATE void _sg_imgui_fail_pipeline(sg_pipeline pip_id, void* user_data) {
  1892. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1893. SOKOL_ASSERT(ctx);
  1894. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1895. if (item) {
  1896. item->cmd = SG_IMGUI_CMD_FAIL_PIPELINE;
  1897. item->color = _SG_IMGUI_COLOR_RSRC;
  1898. item->args.fail_pipeline.pipeline = pip_id;
  1899. }
  1900. if (ctx->hooks.fail_pipeline) {
  1901. ctx->hooks.fail_pipeline(pip_id, ctx->hooks.user_data);
  1902. }
  1903. }
  1904. _SOKOL_PRIVATE void _sg_imgui_fail_pass(sg_pass pass_id, void* user_data) {
  1905. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1906. SOKOL_ASSERT(ctx);
  1907. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1908. if (item) {
  1909. item->cmd = SG_IMGUI_CMD_FAIL_PASS;
  1910. item->color = _SG_IMGUI_COLOR_RSRC;
  1911. item->args.fail_pass.pass = pass_id;
  1912. }
  1913. if (ctx->hooks.fail_pass) {
  1914. ctx->hooks.fail_pass(pass_id, ctx->hooks.user_data);
  1915. }
  1916. }
  1917. _SOKOL_PRIVATE void _sg_imgui_push_debug_group(const char* name, void* user_data) {
  1918. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1919. SOKOL_ASSERT(ctx);
  1920. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1921. if (item) {
  1922. item->cmd = SG_IMGUI_CMD_PUSH_DEBUG_GROUP;
  1923. item->color = _SG_IMGUI_COLOR_OTHER;
  1924. item->args.push_debug_group.name = _sg_imgui_make_str(name);
  1925. }
  1926. if (ctx->hooks.push_debug_group) {
  1927. ctx->hooks.push_debug_group(name, ctx->hooks.user_data);
  1928. }
  1929. }
  1930. _SOKOL_PRIVATE void _sg_imgui_pop_debug_group(void* user_data) {
  1931. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1932. SOKOL_ASSERT(ctx);
  1933. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1934. if (item) {
  1935. item->cmd = SG_IMGUI_CMD_POP_DEBUG_GROUP;
  1936. item->color = _SG_IMGUI_COLOR_OTHER;
  1937. }
  1938. if (ctx->hooks.pop_debug_group) {
  1939. ctx->hooks.pop_debug_group(ctx->hooks.user_data);
  1940. }
  1941. }
  1942. _SOKOL_PRIVATE void _sg_imgui_err_buffer_pool_exhausted(void* user_data) {
  1943. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1944. SOKOL_ASSERT(ctx);
  1945. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1946. if (item) {
  1947. item->cmd = SG_IMGUI_CMD_ERR_BUFFER_POOL_EXHAUSTED;
  1948. item->color = _SG_IMGUI_COLOR_ERR;
  1949. }
  1950. if (ctx->hooks.err_buffer_pool_exhausted) {
  1951. ctx->hooks.err_buffer_pool_exhausted(ctx->hooks.user_data);
  1952. }
  1953. }
  1954. _SOKOL_PRIVATE void _sg_imgui_err_image_pool_exhausted(void* user_data) {
  1955. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1956. SOKOL_ASSERT(ctx);
  1957. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1958. if (item) {
  1959. item->cmd = SG_IMGUI_CMD_ERR_IMAGE_POOL_EXHAUSTED;
  1960. item->color = _SG_IMGUI_COLOR_ERR;
  1961. }
  1962. if (ctx->hooks.err_image_pool_exhausted) {
  1963. ctx->hooks.err_image_pool_exhausted(ctx->hooks.user_data);
  1964. }
  1965. }
  1966. _SOKOL_PRIVATE void _sg_imgui_err_shader_pool_exhausted(void* user_data) {
  1967. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1968. SOKOL_ASSERT(ctx);
  1969. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1970. if (item) {
  1971. item->cmd = SG_IMGUI_CMD_ERR_SHADER_POOL_EXHAUSTED;
  1972. item->color = _SG_IMGUI_COLOR_ERR;
  1973. }
  1974. if (ctx->hooks.err_shader_pool_exhausted) {
  1975. ctx->hooks.err_shader_pool_exhausted(ctx->hooks.user_data);
  1976. }
  1977. }
  1978. _SOKOL_PRIVATE void _sg_imgui_err_pipeline_pool_exhausted(void* user_data) {
  1979. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1980. SOKOL_ASSERT(ctx);
  1981. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1982. if (item) {
  1983. item->cmd = SG_IMGUI_CMD_ERR_PIPELINE_POOL_EXHAUSTED;
  1984. item->color = _SG_IMGUI_COLOR_ERR;
  1985. }
  1986. if (ctx->hooks.err_pipeline_pool_exhausted) {
  1987. ctx->hooks.err_pipeline_pool_exhausted(ctx->hooks.user_data);
  1988. }
  1989. }
  1990. _SOKOL_PRIVATE void _sg_imgui_err_pass_pool_exhausted(void* user_data) {
  1991. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  1992. SOKOL_ASSERT(ctx);
  1993. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  1994. if (item) {
  1995. item->cmd = SG_IMGUI_CMD_ERR_PASS_POOL_EXHAUSTED;
  1996. item->color = _SG_IMGUI_COLOR_ERR;
  1997. }
  1998. if (ctx->hooks.err_pass_pool_exhausted) {
  1999. ctx->hooks.err_pass_pool_exhausted(ctx->hooks.user_data);
  2000. }
  2001. }
  2002. _SOKOL_PRIVATE void _sg_imgui_err_context_mismatch(void* user_data) {
  2003. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  2004. SOKOL_ASSERT(ctx);
  2005. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  2006. if (item) {
  2007. item->cmd = SG_IMGUI_CMD_ERR_CONTEXT_MISMATCH;
  2008. item->color = _SG_IMGUI_COLOR_ERR;
  2009. }
  2010. if (ctx->hooks.err_context_mismatch) {
  2011. ctx->hooks.err_context_mismatch(ctx->hooks.user_data);
  2012. }
  2013. }
  2014. _SOKOL_PRIVATE void _sg_imgui_err_pass_invalid(void* user_data) {
  2015. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  2016. SOKOL_ASSERT(ctx);
  2017. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  2018. if (item) {
  2019. item->cmd = SG_IMGUI_CMD_ERR_PASS_INVALID;
  2020. item->color = _SG_IMGUI_COLOR_ERR;
  2021. }
  2022. if (ctx->hooks.err_pass_invalid) {
  2023. ctx->hooks.err_pass_invalid(ctx->hooks.user_data);
  2024. }
  2025. }
  2026. _SOKOL_PRIVATE void _sg_imgui_err_draw_invalid(void* user_data) {
  2027. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  2028. SOKOL_ASSERT(ctx);
  2029. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  2030. if (item) {
  2031. item->cmd = SG_IMGUI_CMD_ERR_DRAW_INVALID;
  2032. item->color = _SG_IMGUI_COLOR_ERR;
  2033. }
  2034. if (ctx->hooks.err_draw_invalid) {
  2035. ctx->hooks.err_draw_invalid(ctx->hooks.user_data);
  2036. }
  2037. }
  2038. _SOKOL_PRIVATE void _sg_imgui_err_bindings_invalid(void* user_data) {
  2039. sg_imgui_t* ctx = (sg_imgui_t*) user_data;
  2040. SOKOL_ASSERT(ctx);
  2041. sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx);
  2042. if (item) {
  2043. item->cmd = SG_IMGUI_CMD_ERR_BINDINGS_INVALID;
  2044. item->color = _SG_IMGUI_COLOR_ERR;
  2045. }
  2046. if (ctx->hooks.err_bindings_invalid) {
  2047. ctx->hooks.err_bindings_invalid(ctx->hooks.user_data);
  2048. }
  2049. }
  2050. /*--- IMGUI HELPERS ----------------------------------------------------------*/
  2051. _SOKOL_PRIVATE bool _sg_imgui_draw_resid_list_item(uint32_t res_id, const char* label, bool selected) {
  2052. ImGui::PushID((int)res_id);
  2053. bool res;
  2054. if (label[0]) {
  2055. res = ImGui::Selectable(label, selected);
  2056. }
  2057. else {
  2058. char buf[32];
  2059. snprintf(buf, sizeof(buf), "0x%08X", res_id);
  2060. res = ImGui::Selectable(buf, selected);
  2061. }
  2062. ImGui::PopID();
  2063. return res;
  2064. }
  2065. _SOKOL_PRIVATE bool _sg_imgui_draw_resid_link(uint32_t res_id, const char* label) {
  2066. SOKOL_ASSERT(label);
  2067. char buf[32];
  2068. const char* str;
  2069. if (label[0]) {
  2070. str = label;
  2071. }
  2072. else {
  2073. snprintf(buf, sizeof(buf), "0x%08X", res_id);
  2074. str = buf;
  2075. }
  2076. ImGui::PushID((int)res_id);
  2077. bool res = ImGui::SmallButton(str);
  2078. ImGui::PopID();
  2079. return res;
  2080. }
  2081. _SOKOL_PRIVATE bool _sg_imgui_draw_buffer_link(sg_imgui_t* ctx, sg_buffer buf) {
  2082. bool retval = false;
  2083. if (buf.id != SG_INVALID_ID) {
  2084. const sg_imgui_buffer_t* buf_ui = &ctx->buffers.slots[_sg_imgui_slot_index(buf.id)];
  2085. retval = _sg_imgui_draw_resid_link(buf.id, buf_ui->label.buf);
  2086. }
  2087. return retval;
  2088. }
  2089. _SOKOL_PRIVATE bool _sg_imgui_draw_image_link(sg_imgui_t* ctx, sg_image img) {
  2090. bool retval = false;
  2091. if (img.id != SG_INVALID_ID) {
  2092. const sg_imgui_image_t* img_ui = &ctx->images.slots[_sg_imgui_slot_index(img.id)];
  2093. retval = _sg_imgui_draw_resid_link(img.id, img_ui->label.buf);
  2094. }
  2095. return retval;
  2096. }
  2097. _SOKOL_PRIVATE bool _sg_imgui_draw_shader_link(sg_imgui_t* ctx, sg_shader shd) {
  2098. bool retval = false;
  2099. if (shd.id != SG_INVALID_ID) {
  2100. const sg_imgui_shader_t* shd_ui = &ctx->shaders.slots[_sg_imgui_slot_index(shd.id)];
  2101. retval = _sg_imgui_draw_resid_link(shd.id, shd_ui->label.buf);
  2102. }
  2103. return retval;
  2104. }
  2105. _SOKOL_PRIVATE void _sg_imgui_show_buffer(sg_imgui_t* ctx, sg_buffer buf) {
  2106. ctx->buffers.open = true;
  2107. ctx->buffers.sel_buf = buf;
  2108. }
  2109. _SOKOL_PRIVATE void _sg_imgui_show_image(sg_imgui_t* ctx, sg_image img) {
  2110. ctx->images.open = true;
  2111. ctx->images.sel_img = img;
  2112. }
  2113. _SOKOL_PRIVATE void _sg_imgui_show_shader(sg_imgui_t* ctx, sg_shader shd) {
  2114. ctx->shaders.open = true;
  2115. ctx->shaders.sel_shd = shd;
  2116. }
  2117. _SOKOL_PRIVATE void _sg_imgui_draw_buffer_list(sg_imgui_t* ctx) {
  2118. ImGui::BeginChild("buffer_list", ImVec2(_SG_IMGUI_LIST_WIDTH,0), true);
  2119. for (int i = 0; i < ctx->buffers.num_slots; i++) {
  2120. sg_buffer buf = ctx->buffers.slots[i].res_id;
  2121. sg_resource_state state = sg_query_buffer_state(buf);
  2122. if ((state != SG_RESOURCESTATE_INVALID) && (state != SG_RESOURCESTATE_INITIAL)) {
  2123. bool selected = ctx->buffers.sel_buf.id == buf.id;
  2124. if (_sg_imgui_draw_resid_list_item(buf.id, ctx->buffers.slots[i].label.buf, selected)) {
  2125. ctx->buffers.sel_buf.id = buf.id;
  2126. }
  2127. }
  2128. }
  2129. ImGui::EndChild();
  2130. }
  2131. _SOKOL_PRIVATE void _sg_imgui_draw_image_list(sg_imgui_t* ctx) {
  2132. ImGui::BeginChild("image_list", ImVec2(_SG_IMGUI_LIST_WIDTH,0), true);
  2133. for (int i = 0; i < ctx->images.num_slots; i++) {
  2134. sg_image img = ctx->images.slots[i].res_id;
  2135. sg_resource_state state = sg_query_image_state(img);
  2136. if ((state != SG_RESOURCESTATE_INVALID) && (state != SG_RESOURCESTATE_INITIAL)) {
  2137. bool selected = ctx->images.sel_img.id == img.id;
  2138. if (_sg_imgui_draw_resid_list_item(img.id, ctx->images.slots[i].label.buf, selected)) {
  2139. ctx->images.sel_img.id = img.id;
  2140. }
  2141. }
  2142. }
  2143. ImGui::EndChild();
  2144. }
  2145. _SOKOL_PRIVATE void _sg_imgui_draw_shader_list(sg_imgui_t* ctx) {
  2146. ImGui::BeginChild("shader_list", ImVec2(_SG_IMGUI_LIST_WIDTH,0), true);
  2147. for (int i = 0; i < ctx->shaders.num_slots; i++) {
  2148. sg_shader shd = ctx->shaders.slots[i].res_id;
  2149. sg_resource_state state = sg_query_shader_state(shd);
  2150. if ((state != SG_RESOURCESTATE_INVALID) && (state != SG_RESOURCESTATE_INITIAL)) {
  2151. bool selected = ctx->shaders.sel_shd.id == shd.id;
  2152. if (_sg_imgui_draw_resid_list_item(shd.id, ctx->shaders.slots[i].label.buf, selected)) {
  2153. ctx->shaders.sel_shd.id = shd.id;
  2154. }
  2155. }
  2156. }
  2157. ImGui::EndChild();
  2158. }
  2159. _SOKOL_PRIVATE void _sg_imgui_draw_pipeline_list(sg_imgui_t* ctx) {
  2160. ImGui::BeginChild("pipeline_list", ImVec2(_SG_IMGUI_LIST_WIDTH,0), true);
  2161. for (int i = 1; i < ctx->pipelines.num_slots; i++) {
  2162. sg_pipeline pip = ctx->pipelines.slots[i].res_id;
  2163. sg_resource_state state = sg_query_pipeline_state(pip);
  2164. if ((state != SG_RESOURCESTATE_INVALID) && (state != SG_RESOURCESTATE_INITIAL)) {
  2165. bool selected = ctx->pipelines.sel_pip.id == pip.id;
  2166. if (_sg_imgui_draw_resid_list_item(pip.id, ctx->pipelines.slots[i].label.buf, selected)) {
  2167. ctx->pipelines.sel_pip.id = pip.id;
  2168. }
  2169. }
  2170. }
  2171. ImGui::EndChild();
  2172. }
  2173. _SOKOL_PRIVATE void _sg_imgui_draw_pass_list(sg_imgui_t* ctx) {
  2174. ImGui::BeginChild("pass_list", ImVec2(_SG_IMGUI_LIST_WIDTH,0), true);
  2175. for (int i = 1; i < ctx->passes.num_slots; i++) {
  2176. sg_pass pass = ctx->passes.slots[i].res_id;
  2177. sg_resource_state state = sg_query_pass_state(pass);
  2178. if ((state != SG_RESOURCESTATE_INVALID) && (state != SG_RESOURCESTATE_INITIAL)) {
  2179. bool selected = ctx->passes.sel_pass.id == pass.id;
  2180. if (_sg_imgui_draw_resid_list_item(pass.id, ctx->passes.slots[i].label.buf, selected)) {
  2181. ctx->passes.sel_pass.id = pass.id;
  2182. }
  2183. }
  2184. }
  2185. ImGui::EndChild();
  2186. }
  2187. _SOKOL_PRIVATE void _sg_imgui_draw_capture_list(sg_imgui_t* ctx) {
  2188. ImGui::BeginChild("capture_list", ImVec2(_SG_IMGUI_LIST_WIDTH,0), true);
  2189. const uint32_t num_items = _sg_imgui_capture_num_read_items(ctx);
  2190. uint64_t group_stack = 1; /* bit set: group unfolded, cleared: folded */
  2191. for (uint32_t i = 0; i < num_items; i++) {
  2192. const sg_imgui_capture_item_t* item = _sg_imgui_capture_read_item_at(ctx, i);
  2193. sg_imgui_str_t item_string = _sg_imgui_capture_item_string(ctx, i, item);
  2194. ImGui::PushStyleColor(ImGuiCol_Text, item->color);
  2195. if (item->cmd == SG_IMGUI_CMD_PUSH_DEBUG_GROUP) {
  2196. if (group_stack & 1) {
  2197. group_stack <<= 1;
  2198. const char* group_name = item->args.push_debug_group.name.buf;
  2199. if (ImGui::TreeNode(group_name, "Group: %s", group_name)) {
  2200. group_stack |= 1;
  2201. }
  2202. }
  2203. else {
  2204. group_stack <<= 1;
  2205. }
  2206. }
  2207. else if (item->cmd == SG_IMGUI_CMD_POP_DEBUG_GROUP) {
  2208. if (group_stack & 1) {
  2209. ImGui::TreePop();
  2210. }
  2211. group_stack >>= 1;
  2212. }
  2213. else if (group_stack & 1) {
  2214. ImGui::PushID(i);
  2215. if (ImGui::Selectable(item_string.buf, ctx->capture.sel_item == i)) {
  2216. ctx->capture.sel_item = i;
  2217. }
  2218. if (ImGui::IsItemHovered()) {
  2219. ImGui::SetTooltip("%s", item_string.buf);
  2220. }
  2221. ImGui::PopID();
  2222. }
  2223. ImGui::PopStyleColor();
  2224. }
  2225. ImGui::EndChild();
  2226. }
  2227. _SOKOL_PRIVATE void _sg_imgui_draw_buffer_panel(sg_imgui_t* ctx, sg_buffer buf) {
  2228. if (buf.id != SG_INVALID_ID) {
  2229. ImGui::BeginChild("buffer", ImVec2(0,0), false);
  2230. sg_buffer_info info = sg_query_buffer_info(buf);
  2231. if (info.slot.res_id != SG_INVALID_ID) {
  2232. const sg_imgui_buffer_t* buf_ui = &ctx->buffers.slots[_sg_imgui_slot_index(buf.id)];
  2233. ImGui::Text("Label: %s", buf_ui->label.buf[0] ? buf_ui->label.buf : "---");
  2234. _sg_imgui_draw_resource_slot(&info.slot);
  2235. ImGui::Separator();
  2236. ImGui::Text("Type: %s", _sg_imgui_buffertype_string(buf_ui->desc.type));
  2237. ImGui::Text("Usage: %s", _sg_imgui_usage_string(buf_ui->desc.usage));
  2238. ImGui::Text("Size: %d", buf_ui->desc.size);
  2239. if (buf_ui->desc.usage != SG_USAGE_IMMUTABLE) {
  2240. ImGui::Separator();
  2241. ImGui::Text("Num Slots: %d", info.num_slots);
  2242. ImGui::Text("Active Slot: %d", info.active_slot);
  2243. ImGui::Text("Update Frame Index: %d", info.update_frame_index);
  2244. ImGui::Text("Append Frame Index: %d", info.append_frame_index);
  2245. ImGui::Text("Append Pos: %d", info.append_pos);
  2246. ImGui::Text("Append Overflow: %s", info.append_overflow ? "YES":"NO");
  2247. }
  2248. }
  2249. else {
  2250. ImGui::Text("Buffer 0x%08X not alive.", buf.id);
  2251. }
  2252. ImGui::EndChild();
  2253. }
  2254. }
  2255. _SOKOL_PRIVATE bool _sg_imgui_image_renderable(sg_imgui_t* ctx, sg_image_type type, sg_pixel_format fmt) {
  2256. if ((SG_IMAGETYPE_2D != type) || (SG_PIXELFORMAT_DEPTH == fmt) || (SG_PIXELFORMAT_DEPTHSTENCIL == fmt)) {
  2257. return false;
  2258. }
  2259. else {
  2260. return true;
  2261. }
  2262. }
  2263. _SOKOL_PRIVATE void _sg_imgui_draw_embedded_image(sg_imgui_t* ctx, sg_image img, float* scale) {
  2264. if (sg_query_image_state(img) == SG_RESOURCESTATE_VALID) {
  2265. sg_imgui_image_t* img_ui = &ctx->images.slots[_sg_imgui_slot_index(img.id)];
  2266. if (_sg_imgui_image_renderable(ctx, img_ui->desc.type, img_ui->desc.pixel_format)) {
  2267. ImGui::PushID((int)img.id);
  2268. ImGui::SliderFloat("Scale", scale, 0.125f, 8.0f, "%.3f", 2.0f);
  2269. float w = (float)img_ui->desc.width * (*scale);
  2270. float h = (float)img_ui->desc.height * (*scale);
  2271. ImGui::Image((ImTextureID)(intptr_t)img.id, ImVec2(w, h));
  2272. ImGui::PopID();
  2273. }
  2274. else {
  2275. ImGui::Text("Image not renderable.");
  2276. }
  2277. }
  2278. }
  2279. _SOKOL_PRIVATE void _sg_imgui_draw_image_panel(sg_imgui_t* ctx, sg_image img) {
  2280. if (img.id != SG_INVALID_ID) {
  2281. ImGui::BeginChild("image", ImVec2(0,0), false);
  2282. sg_image_info info = sg_query_image_info(img);
  2283. if (info.slot.state != SG_INVALID_ID) {
  2284. sg_imgui_image_t* img_ui = &ctx->images.slots[_sg_imgui_slot_index(img.id)];
  2285. const sg_image_desc* desc = &img_ui->desc;
  2286. ImGui::Text("Label: %s", img_ui->label.buf[0] ? img_ui->label.buf : "---");
  2287. _sg_imgui_draw_resource_slot(&info.slot);
  2288. ImGui::Separator();
  2289. _sg_imgui_draw_embedded_image(ctx, img, &img_ui->ui_scale);
  2290. ImGui::Separator();
  2291. ImGui::Text("Type: %s", _sg_imgui_imagetype_string(desc->type));
  2292. ImGui::Text("Usage: %s", _sg_imgui_usage_string(desc->usage));
  2293. ImGui::Text("Render Target: %s", desc->render_target ? "YES":"NO");
  2294. ImGui::Text("Width: %d", desc->width);
  2295. ImGui::Text("Height: %d", desc->height);
  2296. ImGui::Text("Depth: %d", desc->depth);
  2297. ImGui::Text("Num Mipmaps: %d", desc->num_mipmaps);
  2298. ImGui::Text("Pixel Format: %s", _sg_imgui_pixelformat_string(desc->pixel_format));
  2299. ImGui::Text("Sample Count: %d", desc->sample_count);
  2300. ImGui::Text("Min Filter: %s", _sg_imgui_filter_string(desc->min_filter));
  2301. ImGui::Text("Mag Filter: %s", _sg_imgui_filter_string(desc->mag_filter));
  2302. ImGui::Text("Wrap U: %s", _sg_imgui_wrap_string(desc->wrap_u));
  2303. ImGui::Text("Wrap V: %s", _sg_imgui_wrap_string(desc->wrap_v));
  2304. ImGui::Text("Wrap W: %s", _sg_imgui_wrap_string(desc->wrap_w));
  2305. ImGui::Text("Max Anisotropy: %d", desc->max_anisotropy);
  2306. ImGui::Text("Min LOD: %.3f", desc->min_lod);
  2307. ImGui::Text("Max LOD: %.3f", desc->max_lod);
  2308. if (desc->usage != SG_USAGE_IMMUTABLE) {
  2309. ImGui::Separator();
  2310. ImGui::Text("Num Slots: %d", info.num_slots);
  2311. ImGui::Text("Active Slot: %d", info.active_slot);
  2312. ImGui::Text("Update Frame Index: %d", info.upd_frame_index);
  2313. }
  2314. }
  2315. else {
  2316. ImGui::Text("Image 0x%08X not alive.", img.id);
  2317. }
  2318. ImGui::EndChild();
  2319. }
  2320. }
  2321. _SOKOL_PRIVATE void _sg_imgui_draw_shader_stage(sg_imgui_t* ctx, const sg_shader_stage_desc* stage) {
  2322. int num_valid_ubs = 0;
  2323. for (int i = 0; i < SG_MAX_SHADERSTAGE_UBS; i++) {
  2324. const sg_shader_uniform_block_desc* ub = &stage->uniform_blocks[i];
  2325. for (int j = 0; j < SG_MAX_UB_MEMBERS; j++) {
  2326. const sg_shader_uniform_desc* u = &ub->uniforms[j];
  2327. if (SG_UNIFORMTYPE_INVALID != u->type) {
  2328. num_valid_ubs++;
  2329. break;
  2330. }
  2331. }
  2332. }
  2333. int num_valid_images = 0;
  2334. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  2335. if (_SG_IMAGETYPE_DEFAULT != stage->images[i].type) {
  2336. num_valid_images++;
  2337. }
  2338. else {
  2339. break;
  2340. }
  2341. }
  2342. if (num_valid_ubs > 0) {
  2343. if (ImGui::TreeNode("Uniform Blocks")) {
  2344. for (int i = 0; i < num_valid_ubs; i++) {
  2345. ImGui::Text("#%d:", i);
  2346. const sg_shader_uniform_block_desc* ub = &stage->uniform_blocks[i];
  2347. for (int j = 0; j < SG_MAX_UB_MEMBERS; j++) {
  2348. const sg_shader_uniform_desc* u = &ub->uniforms[j];
  2349. if (SG_UNIFORMTYPE_INVALID != u->type) {
  2350. if (u->array_count == 0) {
  2351. ImGui::Text(" %s %s", _sg_imgui_uniformtype_string(u->type), u->name ? u->name : "");
  2352. }
  2353. else {
  2354. ImGui::Text(" %s[%d] %s", _sg_imgui_uniformtype_string(u->type), u->array_count, u->name ? u->name : "");
  2355. }
  2356. }
  2357. }
  2358. }
  2359. ImGui::TreePop();
  2360. }
  2361. }
  2362. if (num_valid_images > 0) {
  2363. if (ImGui::TreeNode("Images")) {
  2364. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  2365. const sg_shader_image_desc* sid = &stage->images[i];
  2366. if (sid->type != _SG_IMAGETYPE_DEFAULT) {
  2367. ImGui::Text("%s %s", _sg_imgui_imagetype_string(sid->type), sid->name ? sid->name : "");
  2368. }
  2369. else {
  2370. break;
  2371. }
  2372. }
  2373. ImGui::TreePop();
  2374. }
  2375. }
  2376. if (stage->entry) {
  2377. ImGui::Text("Entry: %s", stage->entry);
  2378. }
  2379. if (stage->source) {
  2380. if (ImGui::TreeNode("Source")) {
  2381. ImGui::Text("%s", stage->source);
  2382. ImGui::TreePop();
  2383. }
  2384. }
  2385. else if (stage->byte_code) {
  2386. if (ImGui::TreeNode("Byte Code")) {
  2387. ImGui::Text("Byte-code display currently not supported.");
  2388. ImGui::TreePop();
  2389. }
  2390. }
  2391. }
  2392. _SOKOL_PRIVATE void _sg_imgui_draw_shader_panel(sg_imgui_t* ctx, sg_shader shd) {
  2393. if (shd.id != SG_INVALID_ID) {
  2394. ImGui::BeginChild("shader", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
  2395. sg_shader_info info = sg_query_shader_info(shd);
  2396. if (info.slot.state != SG_INVALID_ID) {
  2397. const sg_imgui_shader_t* shd_ui = &ctx->shaders.slots[_sg_imgui_slot_index(shd.id)];
  2398. ImGui::Text("Label: %s", shd_ui->label.buf[0] ? shd_ui->label.buf : "---");
  2399. _sg_imgui_draw_resource_slot(&info.slot);
  2400. ImGui::Separator();
  2401. if (ImGui::TreeNode("Vertex Shader Stage")) {
  2402. _sg_imgui_draw_shader_stage(ctx, &shd_ui->desc.vs);
  2403. ImGui::TreePop();
  2404. }
  2405. if (ImGui::TreeNode("Fragment Shader Stage")) {
  2406. _sg_imgui_draw_shader_stage(ctx, &shd_ui->desc.fs);
  2407. ImGui::TreePop();
  2408. }
  2409. }
  2410. else {
  2411. ImGui::Text("Shader 0x%08X no longer alive", shd.id);
  2412. }
  2413. ImGui::EndChild();
  2414. }
  2415. }
  2416. _SOKOL_PRIVATE void _sg_imgui_draw_vertex_layout(const sg_layout_desc* layout) {
  2417. if (ImGui::TreeNode("Buffers")) {
  2418. for (int i = 0; i < SG_MAX_SHADERSTAGE_BUFFERS; i++) {
  2419. const sg_buffer_layout_desc* l_desc = &layout->buffers[i];
  2420. if (l_desc->stride > 0) {
  2421. ImGui::Text("#%d:", i);
  2422. ImGui::Text(" Stride: %d", l_desc->stride);
  2423. ImGui::Text(" Step Func: %s", _sg_imgui_vertexstep_string(l_desc->step_func));
  2424. ImGui::Text(" Step Rate: %d", l_desc->step_rate);
  2425. }
  2426. }
  2427. ImGui::TreePop();
  2428. }
  2429. if (ImGui::TreeNode("Attrs")) {
  2430. for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {
  2431. const sg_vertex_attr_desc* a_desc = &layout->attrs[i];
  2432. if (a_desc->format != SG_VERTEXFORMAT_INVALID) {
  2433. ImGui::Text("#%d:", i);
  2434. ImGui::Text(" Format: %s", _sg_imgui_vertexformat_string(a_desc->format));
  2435. ImGui::Text(" Name: %s", a_desc->name ? a_desc->name : "---");
  2436. ImGui::Text(" Sem Name: %s", a_desc->sem_name ? a_desc->sem_name : "---");
  2437. ImGui::Text(" Sem Index: %d", a_desc->sem_index);
  2438. ImGui::Text(" Offset: %d", a_desc->offset);
  2439. ImGui::Text(" Buffer Index: %d", a_desc->buffer_index);
  2440. }
  2441. }
  2442. ImGui::TreePop();
  2443. }
  2444. }
  2445. _SOKOL_PRIVATE void _sg_imgui_draw_stencil_state(const sg_stencil_state* ss) {
  2446. ImGui::Text("Fail Op: %s", _sg_imgui_stencilop_string(ss->fail_op));
  2447. ImGui::Text("Depth Fail Op: %s", _sg_imgui_stencilop_string(ss->depth_fail_op));
  2448. ImGui::Text("Pass Op: %s", _sg_imgui_stencilop_string(ss->pass_op));
  2449. ImGui::Text("Compare Func: %s", _sg_imgui_comparefunc_string(ss->compare_func));
  2450. }
  2451. _SOKOL_PRIVATE void _sg_imgui_draw_depth_stencil_state(const sg_depth_stencil_state* dss) {
  2452. ImGui::Text("Depth Compare Func: %s", _sg_imgui_comparefunc_string(dss->depth_compare_func));
  2453. ImGui::Text("Depth Write Enabled: %s", dss->depth_write_enabled ? "YES":"NO");
  2454. ImGui::Text("Stencil Enabled: %s", dss->stencil_enabled ? "YES":"NO");
  2455. ImGui::Text("Stencil Read Mask: 0x%02X", dss->stencil_read_mask);
  2456. ImGui::Text("Stencil Write Mask: 0x%02X", dss->stencil_write_mask);
  2457. ImGui::Text("Stencil Ref: 0x%02X", dss->stencil_ref);
  2458. if (ImGui::TreeNode("Stencil Front")) {
  2459. _sg_imgui_draw_stencil_state(&dss->stencil_front);
  2460. ImGui::TreePop();
  2461. }
  2462. if (ImGui::TreeNode("Stencil Back")) {
  2463. _sg_imgui_draw_stencil_state(&dss->stencil_back);
  2464. ImGui::TreePop();
  2465. }
  2466. }
  2467. _SOKOL_PRIVATE void _sg_imgui_draw_blend_state(const sg_blend_state* bs) {
  2468. ImGui::Text("Blend Enabled: %s", bs->enabled ? "YES":"NO");
  2469. ImGui::Text("Src Factor RGB: %s", _sg_imgui_blendfactor_string(bs->src_factor_rgb));
  2470. ImGui::Text("Dst Factor RGB: %s", _sg_imgui_blendfactor_string(bs->dst_factor_rgb));
  2471. ImGui::Text("Op RGB: %s", _sg_imgui_blendop_string(bs->op_rgb));
  2472. ImGui::Text("Src Factor Alpha: %s", _sg_imgui_blendfactor_string(bs->src_factor_alpha));
  2473. ImGui::Text("Dst Factor Alpha: %s", _sg_imgui_blendfactor_string(bs->dst_factor_alpha));
  2474. ImGui::Text("Op Alpha: %s", _sg_imgui_blendop_string(bs->op_alpha));
  2475. ImGui::Text("Color Write Mask: %s", _sg_imgui_colormask_string(bs->color_write_mask));
  2476. ImGui::Text("Attachment Count: %d", bs->color_attachment_count);
  2477. ImGui::Text("Color Format: %s", _sg_imgui_pixelformat_string(bs->color_format));
  2478. ImGui::Text("Depth Format: %s", _sg_imgui_pixelformat_string(bs->depth_format));
  2479. ImGui::Text("Blend Color: %.3f %.3f %.3f %.3f", bs->blend_color[0], bs->blend_color[1], bs->blend_color[2], bs->blend_color[3]);
  2480. }
  2481. _SOKOL_PRIVATE void _sg_imgui_draw_rasterizer_state(const sg_rasterizer_state* rs) {
  2482. ImGui::Text("Alpha to Coverage: %s", rs->alpha_to_coverage_enabled ? "YES":"NO");
  2483. ImGui::Text("Cull Mode: %s", _sg_imgui_cullmode_string(rs->cull_mode));
  2484. ImGui::Text("Face Winding: %s", _sg_imgui_facewinding_string(rs->face_winding));
  2485. ImGui::Text("Sample Count: %d", rs->sample_count);
  2486. ImGui::Text("Depth Bias: %f", rs->depth_bias);
  2487. ImGui::Text("Depth Bias Slope: %f", rs->depth_bias_slope_scale);
  2488. ImGui::Text("Depth Bias Clamp: %f", rs->depth_bias_clamp);
  2489. }
  2490. _SOKOL_PRIVATE void _sg_imgui_draw_pipeline_panel(sg_imgui_t* ctx, sg_pipeline pip) {
  2491. if (pip.id != SG_INVALID_ID) {
  2492. ImGui::BeginChild("pipeline", ImVec2(0,0), false);
  2493. sg_pipeline_info info = sg_query_pipeline_info(pip);
  2494. if (info.slot.state != SG_INVALID_ID) {
  2495. const sg_imgui_pipeline_t* pip_ui = &ctx->pipelines.slots[_sg_imgui_slot_index(pip.id)];
  2496. ImGui::Text("Label: %s", pip_ui->label.buf[0] ? pip_ui->label.buf : "---");
  2497. _sg_imgui_draw_resource_slot(&info.slot);
  2498. ImGui::Separator();
  2499. ImGui::Text("Shader: "); ImGui::SameLine();
  2500. if (_sg_imgui_draw_shader_link(ctx, pip_ui->desc.shader)) {
  2501. _sg_imgui_show_shader(ctx, pip_ui->desc.shader);
  2502. }
  2503. ImGui::Text("Prim Type: %s", _sg_imgui_primitivetype_string(pip_ui->desc.primitive_type));
  2504. ImGui::Text("Index Type: %s", _sg_imgui_indextype_string(pip_ui->desc.index_type));
  2505. if (ImGui::TreeNode("Vertex Layout")) {
  2506. _sg_imgui_draw_vertex_layout(&pip_ui->desc.layout);
  2507. ImGui::TreePop();
  2508. }
  2509. if (ImGui::TreeNode("Depth Stencil State")) {
  2510. _sg_imgui_draw_depth_stencil_state(&pip_ui->desc.depth_stencil);
  2511. ImGui::TreePop();
  2512. }
  2513. if (ImGui::TreeNode("Blend State")) {
  2514. _sg_imgui_draw_blend_state(&pip_ui->desc.blend);
  2515. ImGui::TreePop();
  2516. }
  2517. if (ImGui::TreeNode("Rasterizer State")) {
  2518. _sg_imgui_draw_rasterizer_state(&pip_ui->desc.rasterizer);
  2519. ImGui::TreePop();
  2520. }
  2521. }
  2522. else {
  2523. ImGui::Text("Pipeline 0x%08X not alive.", pip.id);
  2524. }
  2525. ImGui::EndChild();
  2526. }
  2527. }
  2528. _SOKOL_PRIVATE void _sg_imgui_draw_attachment(sg_imgui_t* ctx, const sg_attachment_desc* att, float* img_scale) {
  2529. ImGui::Text(" Image: "); ImGui::SameLine();
  2530. if (_sg_imgui_draw_image_link(ctx, att->image)) {
  2531. _sg_imgui_show_image(ctx, att->image);
  2532. }
  2533. ImGui::Text(" Mip Level: %d", att->mip_level);
  2534. ImGui::Text(" Face/Layer/Slice: %d", att->layer);
  2535. _sg_imgui_draw_embedded_image(ctx, att->image, img_scale);
  2536. }
  2537. _SOKOL_PRIVATE void _sg_imgui_draw_pass_panel(sg_imgui_t* ctx, sg_pass pass) {
  2538. if (pass.id != SG_INVALID_ID) {
  2539. ImGui::BeginChild("pass", ImVec2(0,0), false);
  2540. sg_pass_info info = sg_query_pass_info(pass);
  2541. if (info.slot.res_id != SG_INVALID_ID) {
  2542. sg_imgui_pass_t* pass_ui = &ctx->passes.slots[_sg_imgui_slot_index(pass.id)];
  2543. ImGui::Text("Label: %s", pass_ui->label.buf[0] ? pass_ui->label.buf : "---");
  2544. _sg_imgui_draw_resource_slot(&info.slot);
  2545. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  2546. if (pass_ui->desc.color_attachments[i].image.id == SG_INVALID_ID) {
  2547. break;
  2548. }
  2549. ImGui::Separator();
  2550. ImGui::Text("Color Attachment #%d:", i);
  2551. _sg_imgui_draw_attachment(ctx, &pass_ui->desc.color_attachments[i], &pass_ui->color_image_scale[i]);
  2552. }
  2553. if (pass_ui->desc.depth_stencil_attachment.image.id != SG_INVALID_ID) {
  2554. ImGui::Separator();
  2555. ImGui::Text("Depth-Stencil Attachemnt:");
  2556. _sg_imgui_draw_attachment(ctx, &pass_ui->desc.depth_stencil_attachment, &pass_ui->ds_image_scale);
  2557. }
  2558. }
  2559. else {
  2560. ImGui::Text("Pass 0x%08X no longer alive.", pass.id);
  2561. }
  2562. ImGui::EndChild();
  2563. }
  2564. }
  2565. _SOKOL_PRIVATE void _sg_imgui_draw_bindings_panel(sg_imgui_t* ctx, const sg_bindings* bnd) {
  2566. for (int i = 0; i < SG_MAX_SHADERSTAGE_BUFFERS; i++) {
  2567. sg_buffer buf = bnd->vertex_buffers[i];
  2568. if (buf.id != SG_INVALID_ID) {
  2569. ImGui::Separator();
  2570. ImGui::Text("Vertex Buffer Slot #%d:", i);
  2571. ImGui::Text(" Buffer: "); ImGui::SameLine();
  2572. if (_sg_imgui_draw_buffer_link(ctx, buf)) {
  2573. _sg_imgui_show_buffer(ctx, buf);
  2574. }
  2575. ImGui::Text(" Offset: %d", bnd->vertex_buffer_offsets[i]);
  2576. }
  2577. else {
  2578. break;
  2579. }
  2580. }
  2581. if (bnd->index_buffer.id != SG_INVALID_ID) {
  2582. sg_buffer buf = bnd->index_buffer;
  2583. if (buf.id != SG_INVALID_ID) {
  2584. ImGui::Separator();
  2585. ImGui::Text("Index Buffer Slot:");
  2586. ImGui::Text(" Buffer: "); ImGui::SameLine();
  2587. if (_sg_imgui_draw_buffer_link(ctx, buf)) {
  2588. _sg_imgui_show_buffer(ctx, buf);
  2589. }
  2590. ImGui::Text(" Offset: %d", bnd->index_buffer_offset);
  2591. }
  2592. }
  2593. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  2594. sg_image img = bnd->vs_images[i];
  2595. if (img.id != SG_INVALID_ID) {
  2596. ImGui::Separator();
  2597. ImGui::Text("Vertex Stage Image Slot #%d:", i);
  2598. ImGui::Text(" Image: "); ImGui::SameLine();
  2599. if (_sg_imgui_draw_image_link(ctx, img)) {
  2600. _sg_imgui_show_image(ctx, img);
  2601. }
  2602. }
  2603. else {
  2604. break;
  2605. }
  2606. }
  2607. for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {
  2608. sg_image img = bnd->fs_images[i];
  2609. if (img.id != SG_INVALID_ID) {
  2610. ImGui::Separator();
  2611. ImGui::Text("Fragment Stage Image Slot #%d:", i);
  2612. ImGui::Text(" Image: "); ImGui::SameLine();
  2613. if (_sg_imgui_draw_image_link(ctx, img)) {
  2614. _sg_imgui_show_image(ctx, img);
  2615. }
  2616. }
  2617. }
  2618. }
  2619. _SOKOL_PRIVATE void _sg_imgui_draw_uniforms_panel(sg_imgui_t* ctx, const sg_imgui_args_apply_uniforms_t* args) {
  2620. SOKOL_ASSERT(args->ub_index < SG_MAX_SHADERSTAGE_BUFFERS);
  2621. /* check if all the required information for drawing the structured uniform block content
  2622. is available, otherwise just render a generic hexdump
  2623. */
  2624. if (sg_query_pipeline_state(args->pipeline) == SG_INVALID_ID) {
  2625. ImGui::Text("Pipeline object no longer alive!");
  2626. return;
  2627. }
  2628. sg_imgui_pipeline_t* pip_ui = &ctx->pipelines.slots[_sg_imgui_slot_index(args->pipeline.id)];
  2629. if (sg_query_shader_state(pip_ui->desc.shader) == SG_INVALID_ID) {
  2630. ImGui::Text("Shader object no longer alive!");
  2631. return;
  2632. }
  2633. sg_imgui_shader_t* shd_ui = &ctx->shaders.slots[_sg_imgui_slot_index(pip_ui->desc.shader.id)];
  2634. SOKOL_ASSERT(shd_ui->res_id.id == pip_ui->desc.shader.id);
  2635. const sg_shader_uniform_block_desc* ub_desc = (args->stage == SG_SHADERSTAGE_VS) ?
  2636. ub_desc = &shd_ui->desc.vs.uniform_blocks[args->ub_index] :
  2637. ub_desc = &shd_ui->desc.fs.uniform_blocks[args->ub_index];
  2638. SOKOL_ASSERT(args->num_bytes <= ub_desc->size);
  2639. bool draw_dump = false;
  2640. if (ub_desc->uniforms[0].type == SG_UNIFORMTYPE_INVALID) {
  2641. draw_dump = true;
  2642. }
  2643. sg_imgui_capture_bucket_t* bucket = _sg_imgui_capture_get_read_bucket(ctx);
  2644. SOKOL_ASSERT((args->ubuf_pos + args->num_bytes) <= bucket->ubuf_size);
  2645. const float* uptrf = (const float*) (bucket->ubuf + args->ubuf_pos);
  2646. if (!draw_dump) {
  2647. for (int i = 0; i < SG_MAX_UB_MEMBERS; i++) {
  2648. const sg_shader_uniform_desc* ud = &ub_desc->uniforms[i];
  2649. if (ud->type == SG_UNIFORMTYPE_INVALID) {
  2650. break;
  2651. }
  2652. int num_items = (ud->array_count > 1) ? ud->array_count : 1;
  2653. if (num_items > 1) {
  2654. ImGui::Text("%d: %s %s[%d] =", i, _sg_imgui_uniformtype_string(ud->type), ud->name?ud->name:"", ud->array_count);
  2655. }
  2656. else {
  2657. ImGui::Text("%d: %s %s =", i, _sg_imgui_uniformtype_string(ud->type), ud->name?ud->name:"");
  2658. }
  2659. for (int i = 0; i < num_items; i++) {
  2660. switch (ud->type) {
  2661. case SG_UNIFORMTYPE_FLOAT:
  2662. ImGui::Text(" %.3f", *uptrf);
  2663. break;
  2664. case SG_UNIFORMTYPE_FLOAT2:
  2665. ImGui::Text(" %.3f, %.3f", uptrf[0], uptrf[1]);
  2666. break;
  2667. case SG_UNIFORMTYPE_FLOAT3:
  2668. ImGui::Text(" %.3f, %.3f, %.3f", uptrf[0], uptrf[1], uptrf[2]);
  2669. break;
  2670. case SG_UNIFORMTYPE_FLOAT4:
  2671. ImGui::Text(" %.3f, %.3f, %.3f, %.3f", uptrf[0], uptrf[1], uptrf[2], uptrf[3]);
  2672. break;
  2673. case SG_UNIFORMTYPE_MAT4:
  2674. ImGui::Text(" %.3f, %.3f, %.3f, %.3f\n"
  2675. " %.3f, %.3f, %.3f, %.3f\n"
  2676. " %.3f, %.3f, %.3f, %.3f\n"
  2677. " %.3f, %.3f, %.3f, %.3f",
  2678. uptrf[0], uptrf[1], uptrf[2], uptrf[3],
  2679. uptrf[4], uptrf[5], uptrf[6], uptrf[7],
  2680. uptrf[8], uptrf[9], uptrf[10], uptrf[11],
  2681. uptrf[12], uptrf[13], uptrf[14], uptrf[15]);
  2682. break;
  2683. default:
  2684. ImGui::Text("???");
  2685. break;
  2686. }
  2687. uptrf += _sg_imgui_uniform_size(ud->type, 1) / sizeof(float);
  2688. }
  2689. }
  2690. }
  2691. else {
  2692. const uint32_t num_floats = ub_desc->size / sizeof(float);
  2693. for (uint32_t i = 0; i < num_floats; i++) {
  2694. ImGui::Text("%.3f, ", uptrf[i]);
  2695. if (((i + 1) % 4) != 0) {
  2696. ImGui::SameLine();
  2697. }
  2698. }
  2699. }
  2700. }
  2701. _SOKOL_PRIVATE void _sg_imgui_draw_passaction_panel(sg_imgui_t* ctx, sg_pass pass, const sg_pass_action* action) {
  2702. /* determine number of valid color attachments in the pass */
  2703. int num_color_atts = 0;
  2704. if (SG_INVALID_ID == pass.id) {
  2705. /* default pass: one color attachment */
  2706. num_color_atts = 1;
  2707. }
  2708. else {
  2709. const sg_imgui_pass_t* pass_ui = &ctx->passes.slots[_sg_imgui_slot_index(pass.id)];
  2710. for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
  2711. if (pass_ui->desc.color_attachments[i].image.id != SG_INVALID_ID) {
  2712. num_color_atts++;
  2713. }
  2714. }
  2715. }
  2716. ImGui::Text("Pass Action: ");
  2717. for (int i = 0; i < num_color_atts; i++) {
  2718. const sg_color_attachment_action* c_att = &action->colors[i];
  2719. ImGui::Text(" Color Attachment %d:", i);
  2720. switch (c_att->action) {
  2721. case SG_ACTION_LOAD: ImGui::Text(" SG_ACTION_LOAD"); break;
  2722. case SG_ACTION_DONTCARE: ImGui::Text(" SG_ACTION_DONTCARE"); break;
  2723. default:
  2724. ImGui::Text(" SG_ACTION_CLEAR: %.3f, %.3f, %.3f, %.3f",
  2725. c_att->val[0],
  2726. c_att->val[1],
  2727. c_att->val[2],
  2728. c_att->val[3]);
  2729. break;
  2730. }
  2731. }
  2732. const sg_depth_attachment_action* d_att = &action->depth;
  2733. ImGui::Text(" Depth Attachment:");
  2734. switch (d_att->action) {
  2735. case SG_ACTION_LOAD: ImGui::Text(" SG_ACTION_LOAD"); break;
  2736. case SG_ACTION_DONTCARE: ImGui::Text(" SG_ACTION_DONTCARE"); break;
  2737. default: ImGui::Text(" SG_ACTION_CLEAR: %.3f", d_att->val); break;
  2738. }
  2739. const sg_stencil_attachment_action* s_att = &action->stencil;
  2740. ImGui::Text(" Stencil Attachment");
  2741. switch (s_att->action) {
  2742. case SG_ACTION_LOAD: ImGui::Text(" SG_ACTION_LOAD"); break;
  2743. case SG_ACTION_DONTCARE: ImGui::Text(" SG_ACTION_DONTCARE"); break;
  2744. default: ImGui::Text(" SG_ACTION_CLEAR: 0x%02X", s_att->val); break;
  2745. }
  2746. }
  2747. _SOKOL_PRIVATE void _sg_imgui_draw_capture_panel(sg_imgui_t* ctx) {
  2748. uint32_t sel_item_index = ctx->capture.sel_item;
  2749. if (sel_item_index >= _sg_imgui_capture_num_read_items(ctx)) {
  2750. return;
  2751. }
  2752. sg_imgui_capture_item_t* item = _sg_imgui_capture_read_item_at(ctx, sel_item_index);
  2753. ImGui::BeginChild("capture_item", ImVec2(0, 0), false);
  2754. ImGui::PushStyleColor(ImGuiCol_Text, item->color);
  2755. ImGui::Text("%s", _sg_imgui_capture_item_string(ctx, sel_item_index, item).buf);
  2756. ImGui::PopStyleColor();
  2757. ImGui::Separator();
  2758. switch (item->cmd) {
  2759. case SG_IMGUI_CMD_QUERY_FEATURE:
  2760. break;
  2761. case SG_IMGUI_CMD_RESET_STATE_CACHE:
  2762. break;
  2763. case SG_IMGUI_CMD_MAKE_BUFFER:
  2764. _sg_imgui_draw_buffer_panel(ctx, item->args.make_buffer.result);
  2765. break;
  2766. case SG_IMGUI_CMD_MAKE_IMAGE:
  2767. _sg_imgui_draw_image_panel(ctx, item->args.make_image.result);
  2768. break;
  2769. case SG_IMGUI_CMD_MAKE_SHADER:
  2770. _sg_imgui_draw_shader_panel(ctx, item->args.make_shader.result);
  2771. break;
  2772. case SG_IMGUI_CMD_MAKE_PIPELINE:
  2773. _sg_imgui_draw_pipeline_panel(ctx, item->args.make_pipeline.result);
  2774. break;
  2775. case SG_IMGUI_CMD_MAKE_PASS:
  2776. _sg_imgui_draw_pass_panel(ctx, item->args.make_pass.result);
  2777. break;
  2778. case SG_IMGUI_CMD_DESTROY_BUFFER:
  2779. _sg_imgui_draw_buffer_panel(ctx, item->args.destroy_buffer.buffer);
  2780. break;
  2781. case SG_IMGUI_CMD_DESTROY_IMAGE:
  2782. _sg_imgui_draw_image_panel(ctx, item->args.destroy_image.image);
  2783. break;
  2784. case SG_IMGUI_CMD_DESTROY_SHADER:
  2785. _sg_imgui_draw_shader_panel(ctx, item->args.destroy_shader.shader);
  2786. break;
  2787. case SG_IMGUI_CMD_DESTROY_PIPELINE:
  2788. _sg_imgui_draw_pipeline_panel(ctx, item->args.destroy_pipeline.pipeline);
  2789. break;
  2790. case SG_IMGUI_CMD_DESTROY_PASS:
  2791. _sg_imgui_draw_pass_panel(ctx, item->args.destroy_pass.pass);
  2792. break;
  2793. case SG_IMGUI_CMD_UPDATE_BUFFER:
  2794. _sg_imgui_draw_buffer_panel(ctx, item->args.update_buffer.buffer);
  2795. break;
  2796. case SG_IMGUI_CMD_UPDATE_IMAGE:
  2797. _sg_imgui_draw_image_panel(ctx, item->args.update_image.image);
  2798. break;
  2799. case SG_IMGUI_CMD_APPEND_BUFFER:
  2800. _sg_imgui_draw_buffer_panel(ctx, item->args.update_buffer.buffer);
  2801. break;
  2802. case SG_IMGUI_CMD_BEGIN_DEFAULT_PASS:
  2803. {
  2804. sg_pass inv_pass = { SG_INVALID_ID };
  2805. _sg_imgui_draw_passaction_panel(ctx, inv_pass, &item->args.begin_default_pass.action);
  2806. }
  2807. break;
  2808. case SG_IMGUI_CMD_BEGIN_PASS:
  2809. _sg_imgui_draw_passaction_panel(ctx, item->args.begin_pass.pass, &item->args.begin_pass.action);
  2810. ImGui::Separator();
  2811. _sg_imgui_draw_pass_panel(ctx, item->args.begin_pass.pass);
  2812. break;
  2813. case SG_IMGUI_CMD_APPLY_VIEWPORT:
  2814. case SG_IMGUI_CMD_APPLY_SCISSOR_RECT:
  2815. break;
  2816. case SG_IMGUI_CMD_APPLY_PIPELINE:
  2817. _sg_imgui_draw_pipeline_panel(ctx, item->args.apply_pipeline.pipeline);
  2818. break;
  2819. case SG_IMGUI_CMD_APPLY_BINDINGS:
  2820. _sg_imgui_draw_bindings_panel(ctx, &item->args.apply_bindings.bindings);
  2821. break;
  2822. case SG_IMGUI_CMD_APPLY_UNIFORMS:
  2823. _sg_imgui_draw_uniforms_panel(ctx, &item->args.apply_uniforms);
  2824. break;
  2825. case SG_IMGUI_CMD_DRAW:
  2826. case SG_IMGUI_CMD_END_PASS:
  2827. case SG_IMGUI_CMD_COMMIT:
  2828. break;
  2829. case SG_IMGUI_CMD_ALLOC_BUFFER:
  2830. _sg_imgui_draw_buffer_panel(ctx, item->args.alloc_buffer.result);
  2831. break;
  2832. case SG_IMGUI_CMD_ALLOC_IMAGE:
  2833. _sg_imgui_draw_image_panel(ctx, item->args.alloc_image.result);
  2834. break;
  2835. case SG_IMGUI_CMD_ALLOC_SHADER:
  2836. _sg_imgui_draw_shader_panel(ctx, item->args.alloc_shader.result);
  2837. break;
  2838. case SG_IMGUI_CMD_ALLOC_PIPELINE:
  2839. _sg_imgui_draw_pipeline_panel(ctx, item->args.alloc_pipeline.result);
  2840. break;
  2841. case SG_IMGUI_CMD_ALLOC_PASS:
  2842. _sg_imgui_draw_pass_panel(ctx, item->args.alloc_pass.result);
  2843. break;
  2844. case SG_IMGUI_CMD_INIT_BUFFER:
  2845. _sg_imgui_draw_buffer_panel(ctx, item->args.init_buffer.buffer);
  2846. break;
  2847. case SG_IMGUI_CMD_INIT_IMAGE:
  2848. _sg_imgui_draw_image_panel(ctx, item->args.init_image.image);
  2849. break;
  2850. case SG_IMGUI_CMD_INIT_SHADER:
  2851. _sg_imgui_draw_shader_panel(ctx, item->args.init_shader.shader);
  2852. break;
  2853. case SG_IMGUI_CMD_INIT_PIPELINE:
  2854. _sg_imgui_draw_pipeline_panel(ctx, item->args.init_pipeline.pipeline);
  2855. break;
  2856. case SG_IMGUI_CMD_INIT_PASS:
  2857. _sg_imgui_draw_pass_panel(ctx, item->args.init_pass.pass);
  2858. break;
  2859. case SG_IMGUI_CMD_FAIL_BUFFER:
  2860. _sg_imgui_draw_buffer_panel(ctx, item->args.fail_buffer.buffer);
  2861. break;
  2862. case SG_IMGUI_CMD_FAIL_IMAGE:
  2863. _sg_imgui_draw_image_panel(ctx, item->args.fail_image.image);
  2864. break;
  2865. case SG_IMGUI_CMD_FAIL_SHADER:
  2866. _sg_imgui_draw_shader_panel(ctx, item->args.fail_shader.shader);
  2867. break;
  2868. case SG_IMGUI_CMD_FAIL_PIPELINE:
  2869. _sg_imgui_draw_pipeline_panel(ctx, item->args.fail_pipeline.pipeline);
  2870. break;
  2871. case SG_IMGUI_CMD_FAIL_PASS:
  2872. _sg_imgui_draw_pass_panel(ctx, item->args.fail_pass.pass);
  2873. break;
  2874. default:
  2875. break;
  2876. }
  2877. ImGui::EndChild();
  2878. }
  2879. /*--- PUBLIC FUNCTIONS -------------------------------------------------------*/
  2880. SOKOL_API_IMPL void sg_imgui_init(sg_imgui_t* ctx) {
  2881. SOKOL_ASSERT(ctx);
  2882. memset(ctx, 0, sizeof(sg_imgui_t));
  2883. ctx->init_tag = 0xABCDABCD;
  2884. _sg_imgui_capture_init(ctx);
  2885. /* hook into sokol_gfx functions */
  2886. sg_trace_hooks hooks;
  2887. memset(&hooks, 0, sizeof(hooks));
  2888. hooks.user_data = (void*) ctx;
  2889. hooks.query_feature = _sg_imgui_query_feature;
  2890. hooks.reset_state_cache = _sg_imgui_reset_state_cache;
  2891. hooks.make_buffer = _sg_imgui_make_buffer;
  2892. hooks.make_image = _sg_imgui_make_image;
  2893. hooks.make_shader = _sg_imgui_make_shader;
  2894. hooks.make_pipeline = _sg_imgui_make_pipeline;
  2895. hooks.make_pass = _sg_imgui_make_pass;
  2896. hooks.destroy_buffer = _sg_imgui_destroy_buffer;
  2897. hooks.destroy_image = _sg_imgui_destroy_image;
  2898. hooks.destroy_shader = _sg_imgui_destroy_shader;
  2899. hooks.destroy_pipeline = _sg_imgui_destroy_pipeline;
  2900. hooks.destroy_pass = _sg_imgui_destroy_pass;
  2901. hooks.update_buffer = _sg_imgui_update_buffer;
  2902. hooks.update_image = _sg_imgui_update_image;
  2903. hooks.append_buffer = _sg_imgui_append_buffer;
  2904. hooks.begin_default_pass = _sg_imgui_begin_default_pass;
  2905. hooks.begin_pass = _sg_imgui_begin_pass;
  2906. hooks.apply_viewport = _sg_imgui_apply_viewport;
  2907. hooks.apply_scissor_rect = _sg_imgui_apply_scissor_rect;
  2908. hooks.apply_pipeline = _sg_imgui_apply_pipeline;
  2909. hooks.apply_bindings = _sg_imgui_apply_bindings;
  2910. hooks.apply_uniforms = _sg_imgui_apply_uniforms;
  2911. hooks.draw = _sg_imgui_draw;
  2912. hooks.end_pass = _sg_imgui_end_pass;
  2913. hooks.commit = _sg_imgui_commit;
  2914. hooks.alloc_buffer = _sg_imgui_alloc_buffer;
  2915. hooks.alloc_image = _sg_imgui_alloc_image;
  2916. hooks.alloc_shader = _sg_imgui_alloc_shader;
  2917. hooks.alloc_pipeline = _sg_imgui_alloc_pipeline;
  2918. hooks.alloc_pass = _sg_imgui_alloc_pass;
  2919. hooks.init_buffer = _sg_imgui_init_buffer;
  2920. hooks.init_image = _sg_imgui_init_image;
  2921. hooks.init_shader = _sg_imgui_init_shader;
  2922. hooks.init_pipeline = _sg_imgui_init_pipeline;
  2923. hooks.init_pass = _sg_imgui_init_pass;
  2924. hooks.fail_buffer = _sg_imgui_fail_buffer;
  2925. hooks.fail_image = _sg_imgui_fail_image;
  2926. hooks.fail_shader = _sg_imgui_fail_shader;
  2927. hooks.fail_pipeline = _sg_imgui_fail_pipeline;
  2928. hooks.fail_pass = _sg_imgui_fail_pass;
  2929. hooks.push_debug_group = _sg_imgui_push_debug_group;
  2930. hooks.pop_debug_group = _sg_imgui_pop_debug_group;
  2931. hooks.err_buffer_pool_exhausted = _sg_imgui_err_buffer_pool_exhausted;
  2932. hooks.err_image_pool_exhausted = _sg_imgui_err_image_pool_exhausted;
  2933. hooks.err_shader_pool_exhausted = _sg_imgui_err_shader_pool_exhausted;
  2934. hooks.err_pipeline_pool_exhausted = _sg_imgui_err_pipeline_pool_exhausted;
  2935. hooks.err_pass_pool_exhausted = _sg_imgui_err_pass_pool_exhausted;
  2936. hooks.err_context_mismatch = _sg_imgui_err_context_mismatch;
  2937. hooks.err_pass_invalid = _sg_imgui_err_pass_invalid;
  2938. hooks.err_draw_invalid = _sg_imgui_err_draw_invalid;
  2939. hooks.err_bindings_invalid = _sg_imgui_err_bindings_invalid;
  2940. ctx->hooks = sg_install_trace_hooks(&hooks);
  2941. /* allocate resource debug-info slots */
  2942. sg_desc desc = sg_query_desc();
  2943. ctx->buffers.num_slots = desc.buffer_pool_size;
  2944. ctx->images.num_slots = desc.image_pool_size;
  2945. ctx->shaders.num_slots = desc.shader_pool_size;
  2946. ctx->pipelines.num_slots = desc.pipeline_pool_size;
  2947. ctx->passes.num_slots = desc.pass_pool_size;
  2948. const int buffer_pool_size = ctx->buffers.num_slots * sizeof(sg_imgui_buffer_t);
  2949. ctx->buffers.slots = (sg_imgui_buffer_t*) _sg_imgui_alloc(buffer_pool_size);
  2950. SOKOL_ASSERT(ctx->buffers.slots);
  2951. memset(ctx->buffers.slots, 0, buffer_pool_size);
  2952. const int image_pool_size = ctx->images.num_slots * sizeof(sg_imgui_image_t);
  2953. ctx->images.slots = (sg_imgui_image_t*) _sg_imgui_alloc(image_pool_size);
  2954. SOKOL_ASSERT(ctx->images.slots);
  2955. memset(ctx->images.slots, 0, image_pool_size);
  2956. const int shader_pool_size = ctx->shaders.num_slots * sizeof(sg_imgui_shader_t);
  2957. ctx->shaders.slots = (sg_imgui_shader_t*) _sg_imgui_alloc(shader_pool_size);
  2958. SOKOL_ASSERT(ctx->shaders.slots);
  2959. memset(ctx->shaders.slots, 0, shader_pool_size);
  2960. const int pipeline_pool_size = ctx->pipelines.num_slots * sizeof(sg_imgui_pipeline_t);
  2961. ctx->pipelines.slots = (sg_imgui_pipeline_t*) _sg_imgui_alloc(pipeline_pool_size);
  2962. SOKOL_ASSERT(ctx->pipelines.slots);
  2963. memset(ctx->pipelines.slots, 0, pipeline_pool_size);
  2964. const int pass_pool_size = ctx->passes.num_slots * sizeof(sg_imgui_pass_t);
  2965. ctx->passes.slots = (sg_imgui_pass_t*) _sg_imgui_alloc(pass_pool_size);
  2966. SOKOL_ASSERT(ctx->passes.slots);
  2967. memset(ctx->passes.slots, 0, pass_pool_size);
  2968. }
  2969. SOKOL_API_IMPL void sg_imgui_discard(sg_imgui_t* ctx) {
  2970. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  2971. /* restore original trace hooks */
  2972. sg_install_trace_hooks(&ctx->hooks);
  2973. ctx->init_tag = 0;
  2974. _sg_imgui_capture_discard(ctx);
  2975. if (ctx->buffers.slots) {
  2976. for (int i = 0; i < ctx->buffers.num_slots; i++) {
  2977. if (ctx->buffers.slots[i].res_id.id != SG_INVALID_ID) {
  2978. _sg_imgui_buffer_destroyed(ctx, i);
  2979. }
  2980. }
  2981. _sg_imgui_free((void*)ctx->buffers.slots);
  2982. ctx->buffers.slots = 0;
  2983. }
  2984. if (ctx->images.slots) {
  2985. for (int i = 0; i < ctx->images.num_slots; i++) {
  2986. if (ctx->images.slots[i].res_id.id != SG_INVALID_ID) {
  2987. _sg_imgui_image_destroyed(ctx, i);
  2988. }
  2989. }
  2990. _sg_imgui_free((void*)ctx->images.slots);
  2991. ctx->images.slots = 0;
  2992. }
  2993. if (ctx->shaders.slots) {
  2994. for (int i = 0; i < ctx->shaders.num_slots; i++) {
  2995. if (ctx->shaders.slots[i].res_id.id != SG_INVALID_ID) {
  2996. _sg_imgui_shader_destroyed(ctx, i);
  2997. }
  2998. }
  2999. _sg_imgui_free((void*)ctx->shaders.slots);
  3000. ctx->shaders.slots = 0;
  3001. }
  3002. if (ctx->pipelines.slots) {
  3003. for (int i = 0; i < ctx->pipelines.num_slots; i++) {
  3004. if (ctx->pipelines.slots[i].res_id.id != SG_INVALID_ID) {
  3005. _sg_imgui_pipeline_destroyed(ctx, i);
  3006. }
  3007. }
  3008. _sg_imgui_free((void*)ctx->pipelines.slots);
  3009. ctx->pipelines.slots = 0;
  3010. }
  3011. if (ctx->passes.slots) {
  3012. for (int i = 0; i < ctx->passes.num_slots; i++) {
  3013. if (ctx->passes.slots[i].res_id.id != SG_INVALID_ID) {
  3014. _sg_imgui_pass_destroyed(ctx, i);
  3015. }
  3016. }
  3017. _sg_imgui_free((void*)ctx->passes.slots);
  3018. ctx->passes.slots = 0;
  3019. }
  3020. }
  3021. SOKOL_API_IMPL void sg_imgui_draw(sg_imgui_t* ctx) {
  3022. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3023. sg_imgui_draw_buffers_window(ctx);
  3024. sg_imgui_draw_images_window(ctx);
  3025. sg_imgui_draw_shaders_window(ctx);
  3026. sg_imgui_draw_pipelines_window(ctx);
  3027. sg_imgui_draw_passes_window(ctx);
  3028. sg_imgui_draw_capture_window(ctx);
  3029. }
  3030. SOKOL_API_IMPL void sg_imgui_draw_buffers_window(sg_imgui_t* ctx) {
  3031. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3032. if (!ctx->buffers.open) {
  3033. return;
  3034. }
  3035. ImGui::SetNextWindowSize(ImVec2(440, 280), ImGuiSetCond_Once);
  3036. if (ImGui::Begin("Buffers", &ctx->buffers.open)) {
  3037. sg_imgui_draw_buffers_content(ctx);
  3038. }
  3039. ImGui::End();
  3040. }
  3041. SOKOL_API_IMPL void sg_imgui_draw_images_window(sg_imgui_t* ctx) {
  3042. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3043. if (!ctx->images.open) {
  3044. return;
  3045. }
  3046. ImGui::SetNextWindowSize(ImVec2(440, 400), ImGuiSetCond_Once);
  3047. if (ImGui::Begin("Images", &ctx->images.open)) {
  3048. sg_imgui_draw_images_content(ctx);
  3049. }
  3050. ImGui::End();
  3051. }
  3052. SOKOL_API_IMPL void sg_imgui_draw_shaders_window(sg_imgui_t* ctx) {
  3053. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3054. if (!ctx->shaders.open) {
  3055. return;
  3056. }
  3057. ImGui::SetNextWindowSize(ImVec2(440, 400), ImGuiSetCond_Once);
  3058. if (ImGui::Begin("Shaders", &ctx->shaders.open)) {
  3059. sg_imgui_draw_shaders_content(ctx);
  3060. }
  3061. ImGui::End();
  3062. }
  3063. SOKOL_API_IMPL void sg_imgui_draw_pipelines_window(sg_imgui_t* ctx) {
  3064. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3065. if (!ctx->pipelines.open) {
  3066. return;
  3067. }
  3068. ImGui::SetNextWindowSize(ImVec2(540, 400), ImGuiSetCond_Once);
  3069. if (ImGui::Begin("Pipelines", &ctx->pipelines.open)) {
  3070. sg_imgui_draw_pipelines_content(ctx);
  3071. }
  3072. ImGui::End();
  3073. }
  3074. SOKOL_API_IMPL void sg_imgui_draw_passes_window(sg_imgui_t* ctx) {
  3075. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3076. if (!ctx->passes.open) {
  3077. return;
  3078. }
  3079. ImGui::SetNextWindowSize(ImVec2(440, 400), ImGuiSetCond_Once);
  3080. if (ImGui::Begin("Passes", &ctx->passes.open)) {
  3081. sg_imgui_draw_passes_content(ctx);
  3082. }
  3083. ImGui::End();
  3084. }
  3085. SOKOL_API_IMPL void sg_imgui_draw_capture_window(sg_imgui_t* ctx) {
  3086. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3087. if (!ctx->capture.open) {
  3088. return;
  3089. }
  3090. ImGui::SetNextWindowSize(ImVec2(640, 400), ImGuiSetCond_Once);
  3091. if (ImGui::Begin("Frame Capture", &ctx->capture.open)) {
  3092. sg_imgui_draw_capture_content(ctx);
  3093. }
  3094. ImGui::End();
  3095. }
  3096. SOKOL_API_IMPL void sg_imgui_draw_buffers_content(sg_imgui_t* ctx) {
  3097. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3098. _sg_imgui_draw_buffer_list(ctx);
  3099. ImGui::SameLine();
  3100. _sg_imgui_draw_buffer_panel(ctx, ctx->buffers.sel_buf);
  3101. }
  3102. SOKOL_API_IMPL void sg_imgui_draw_images_content(sg_imgui_t* ctx) {
  3103. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3104. _sg_imgui_draw_image_list(ctx);
  3105. ImGui::SameLine();
  3106. _sg_imgui_draw_image_panel(ctx, ctx->images.sel_img);
  3107. }
  3108. SOKOL_API_IMPL void sg_imgui_draw_shaders_content(sg_imgui_t* ctx) {
  3109. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3110. _sg_imgui_draw_shader_list(ctx);
  3111. ImGui::SameLine();
  3112. _sg_imgui_draw_shader_panel(ctx, ctx->shaders.sel_shd);
  3113. }
  3114. SOKOL_API_IMPL void sg_imgui_draw_pipelines_content(sg_imgui_t* ctx) {
  3115. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3116. _sg_imgui_draw_pipeline_list(ctx);
  3117. ImGui::SameLine();
  3118. _sg_imgui_draw_pipeline_panel(ctx, ctx->pipelines.sel_pip);
  3119. }
  3120. SOKOL_API_IMPL void sg_imgui_draw_passes_content(sg_imgui_t* ctx) {
  3121. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3122. _sg_imgui_draw_pass_list(ctx);
  3123. ImGui::SameLine();
  3124. _sg_imgui_draw_pass_panel(ctx, ctx->passes.sel_pass);
  3125. }
  3126. SOKOL_API_IMPL void sg_imgui_draw_capture_content(sg_imgui_t* ctx) {
  3127. SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD));
  3128. _sg_imgui_draw_capture_list(ctx);
  3129. ImGui::SameLine();
  3130. _sg_imgui_draw_capture_panel(ctx);
  3131. }
  3132. #endif /* SOKOL_GFX_IMGUI_IMPL */