gs_graphics_impl.h 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524
  1. /*================================================================
  2. * Copyright: 2020 John Jackson
  3. * File: gs_graphics_impl.h
  4. All Rights Reserved
  5. =================================================================*/
  6. #ifndef __GS_GRAPHICS_IMPL_H__
  7. #define __GS_GRAPHICS_IMPL_H__
  8. #ifdef GS_GRAPHICS_IMPL_DEFAULT
  9. // Default stuff here, if any...
  10. #endif
  11. #ifdef GS_GRAPHICS_IMPL_OPENGL
  12. typedef enum gsgl_uniform_type
  13. {
  14. GSGL_UNIFORMTYPE_FLOAT,
  15. GSGL_UNIFORMTYPE_INT,
  16. GSGL_UNIFORMTYPE_VEC2,
  17. GSGL_UNIFORMTYPE_VEC3,
  18. GSGL_UNIFORMTYPE_VEC4,
  19. GSGL_UNIFORMTYPE_MAT4,
  20. GSGL_UNIFORMTYPE_SAMPLER2D,
  21. GSGL_UNIFORMTYPE_UNIFORM_BLOCK
  22. } gsgl_uniform_type;
  23. /* Uniform (stores samplers as well as primitive uniforms) */
  24. typedef struct gsgl_uniform_t {
  25. const char* name;
  26. gs_graphics_uniform_type type;
  27. uint32_t location;
  28. size_t size; // Total data size of uniform
  29. } gsgl_uniform_t;
  30. /* Pipeline */
  31. typedef struct gsgl_pipeline_t {
  32. gs_graphics_blend_state_desc_t blend;
  33. gs_graphics_depth_state_desc_t depth;
  34. gs_graphics_raster_state_desc_t raster;
  35. gs_graphics_stencil_state_desc_t stencil;
  36. gs_dyn_array(gs_graphics_vertex_attribute_type) layout;
  37. } gsgl_pipeline_t;
  38. /* Render Pass */
  39. typedef struct gsgl_render_pass_t {
  40. gs_handle(gs_graphics_buffer_t) fbo;
  41. gs_dyn_array(gs_handle(gs_graphics_texture_t)) color;
  42. gs_handle(gs_graphics_texture_t) depth;
  43. gs_handle(gs_graphics_texture_t) stencil;
  44. } gsgl_render_pass_t;
  45. /* Shader */
  46. typedef uint32_t gsgl_shader_t;
  47. /* Gfx Buffer */
  48. typedef uint32_t gsgl_buffer_t;
  49. /* Texture */
  50. typedef uint32_t gsgl_texture_t;
  51. /* Cached data between draws */
  52. typedef struct gsgl_data_cache_t
  53. {
  54. gsgl_buffer_t vao;
  55. gsgl_buffer_t ibo;
  56. size_t ibo_elem_sz;
  57. gs_handle(gs_graphics_pipeline_t) pipeline;
  58. } gsgl_data_cache_t;
  59. /* Internal Opengl Data */
  60. typedef struct gsgl_data_t
  61. {
  62. gs_slot_array(gsgl_shader_t) shaders;
  63. gs_slot_array(gsgl_texture_t) textures;
  64. gs_slot_array(gsgl_buffer_t) vertex_buffers;
  65. gs_slot_array(gsgl_buffer_t) index_buffers;
  66. gs_slot_array(gsgl_buffer_t) frame_buffers;
  67. gs_slot_array(gsgl_uniform_t) uniforms;
  68. gs_slot_array(gsgl_pipeline_t) pipelines;
  69. gs_slot_array(gsgl_render_pass_t) render_passes;
  70. // Cached data between draw calls (to minimize state changes)
  71. gsgl_data_cache_t cache;
  72. } gsgl_data_t;
  73. // Do I want to add a deferred buffer update here?... Or add that elsewhere?
  74. // Means I'd have to create a VM for the immediate mode...
  75. /* Internal OGL Command Buffer Op Code */
  76. typedef enum gs_opengl_op_code_type
  77. {
  78. GS_OPENGL_OP_BEGIN_RENDER_PASS = 0x00,
  79. GS_OPENGL_OP_END_RENDER_PASS,
  80. GS_OPENGL_OP_SET_VIEWPORT,
  81. GS_OPENGL_OP_SET_VIEW_SCISSOR,
  82. GS_OPENGL_OP_REQUEST_BUFFER_UPDATE,
  83. GS_OPENGL_OP_BIND_PIPELINE,
  84. GS_OPENGL_OP_BIND_UNIFORM_BLOCK,
  85. GS_OPENGL_OP_BIND_BINDINGS,
  86. GS_OPENGL_OP_DRAW,
  87. } gs_opengl_op_code_type;
  88. void gsgl_reset_data_cache(gsgl_data_cache_t* cache)
  89. {
  90. cache->ibo = 0;
  91. cache->ibo_elem_sz = 0;
  92. cache->pipeline = gs_handle_invalid(gs_graphics_pipeline_t);
  93. }
  94. /* GS/OGL Utilities */
  95. int32_t gsgl_buffer_usage_to_gl_enum(gs_graphics_buffer_usage_type type)
  96. {
  97. int32_t mode = GL_STATIC_DRAW;
  98. switch (type) {
  99. default:
  100. case GS_GRAPHICS_BUFFER_USAGE_STATIC: mode = GL_STATIC_DRAW; break;
  101. case GS_GRAPHICS_BUFFER_USAGE_STREAM: mode = GL_STREAM_DRAW; break;
  102. case GS_GRAPHICS_BUFFER_USAGE_DYNAMIC: mode = GL_DYNAMIC_DRAW; break;
  103. }
  104. return mode;
  105. }
  106. uint32_t gsgl_shader_stage_to_gl_stage(gs_graphics_shader_stage_type type)
  107. {
  108. uint32_t stage = GL_VERTEX_SHADER;
  109. switch (type) {
  110. default:
  111. case GS_GRAPHICS_SHADER_STAGE_VERTEX: stage = GL_VERTEX_SHADER; break;
  112. case GS_GRAPHICS_SHADER_STAGE_FRAGMENT: stage = GL_FRAGMENT_SHADER; break;
  113. case GS_GRAPHICS_SHADER_STAGE_COMPUTE: stage = GL_COMPUTE_SHADER; break;
  114. }
  115. return stage;
  116. }
  117. uint32_t gsgl_primitive_to_gl_primitive(gs_graphics_primitive_type type)
  118. {
  119. uint32_t prim = GL_TRIANGLES;
  120. switch (type) {
  121. default:
  122. case GS_GRAPHICS_PRIMITIVE_TRIANGLES: prim = GL_TRIANGLES; break;
  123. case GS_GRAPHICS_PRIMITIVE_LINES: prim = GL_LINES; break;
  124. case GS_GRAPHICS_PRIMITIVE_QUADS: prim = GL_QUADS; break;
  125. }
  126. return prim;
  127. }
  128. uint32_t gsgl_blend_equation_to_gl_blend_eq(gs_graphics_blend_equation_type eq)
  129. {
  130. uint32_t beq = GL_FUNC_ADD;
  131. switch (eq) {
  132. default:
  133. case GS_GRAPHICS_BLEND_EQUATION_ADD: eq = GL_FUNC_ADD; break;
  134. case GS_GRAPHICS_BLEND_EQUATION_SUBTRACT: eq = GL_FUNC_SUBTRACT; break;
  135. case GS_GRAPHICS_BLEND_EQUATION_REVERSE_SUBTRACT: eq = GL_FUNC_REVERSE_SUBTRACT; break;
  136. case GS_GRAPHICS_BLEND_EQUATION_MIN: eq = GL_MIN; break;
  137. case GS_GRAPHICS_BLEND_EQUATION_MAX: eq = GL_MAX; break;
  138. };
  139. return eq;
  140. }
  141. uint32_t gsgl_blend_mode_to_gl_blend_mode(gs_graphics_blend_mode_type type, uint32_t def)
  142. {
  143. uint32_t mode = def;
  144. switch (type) {
  145. case GS_GRAPHICS_BLEND_MODE_ZERO: mode = GL_ZERO; break;
  146. case GS_GRAPHICS_BLEND_MODE_ONE: mode = GL_ONE; break;
  147. case GS_GRAPHICS_BLEND_MODE_SRC_COLOR: mode = GL_SRC_COLOR; break;
  148. case GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_COLOR: mode = GL_ONE_MINUS_SRC_COLOR; break;
  149. case GS_GRAPHICS_BLEND_MODE_DST_COLOR: mode = GL_DST_COLOR; break;
  150. case GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_COLOR: mode = GL_ONE_MINUS_DST_COLOR; break;
  151. case GS_GRAPHICS_BLEND_MODE_SRC_ALPHA: mode = GL_SRC_ALPHA; break;
  152. case GS_GRAPHICS_BLEND_MODE_ONE_MINUS_SRC_ALPHA: mode = GL_ONE_MINUS_SRC_ALPHA; break;
  153. case GS_GRAPHICS_BLEND_MODE_DST_ALPHA: mode = GL_DST_ALPHA; break;
  154. case GS_GRAPHICS_BLEND_MODE_ONE_MINUS_DST_ALPHA: mode = GL_ONE_MINUS_DST_ALPHA; break;
  155. case GS_GRAPHICS_BLEND_MODE_CONSTANT_COLOR: mode = GL_CONSTANT_COLOR; break;
  156. case GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_COLOR: mode = GL_ONE_MINUS_CONSTANT_COLOR; break;
  157. case GS_GRAPHICS_BLEND_MODE_CONSTANT_ALPHA: mode = GL_CONSTANT_ALPHA; break;
  158. case GS_GRAPHICS_BLEND_MODE_ONE_MINUS_CONSTANT_ALPHA: mode = GL_ONE_MINUS_CONSTANT_ALPHA; break;
  159. }
  160. return mode;
  161. }
  162. uint32_t gsgl_cull_face_to_gl_cull_face(gs_graphics_face_culling_type type)
  163. {
  164. uint32_t fc = GL_BACK;
  165. switch (type) {
  166. default:
  167. case GS_GRAPHICS_FACE_CULLING_BACK: fc = GL_BACK; break;
  168. case GS_GRAPHICS_FACE_CULLING_FRONT: fc = GL_FRONT; break;
  169. case GS_GRAPHICS_FACE_CULLING_FRONT_AND_BACK: fc = GL_FRONT_AND_BACK; break;
  170. }
  171. return fc;
  172. }
  173. uint32_t gsgl_winding_order_to_gl_winding_order(gs_graphics_winding_order_type type)
  174. {
  175. uint32_t wo = GL_CCW;
  176. switch (type)
  177. {
  178. case GS_GRAPHICS_WINDING_ORDER_CCW: wo = GL_CCW; break;
  179. case GS_GRAPHICS_WINDING_ORDER_CW: wo = GL_CW; break;
  180. }
  181. return wo;
  182. }
  183. uint32_t gsgl_depth_func_to_gl_depth_func(gs_graphics_depth_func_type type)
  184. {
  185. uint32_t func = GL_LESS;
  186. switch (type) {
  187. default:
  188. case GS_GRAPHICS_DEPTH_FUNC_LESS: func = GL_LESS; break;
  189. case GS_GRAPHICS_DEPTH_FUNC_NEVER: func = GL_NEVER; break;
  190. case GS_GRAPHICS_DEPTH_FUNC_EQUAL: func = GL_EQUAL; break;
  191. case GS_GRAPHICS_DEPTH_FUNC_LEQUAL: func = GL_LEQUAL; break;
  192. case GS_GRAPHICS_DEPTH_FUNC_GREATER: func = GL_GREATER; break;
  193. case GS_GRAPHICS_DEPTH_FUNC_NOTEQUAL: func = GL_NOTEQUAL; break;
  194. case GS_GRAPHICS_DEPTH_FUNC_GEQUAL: func = GL_GEQUAL; break;
  195. case GS_GRAPHICS_DEPTH_FUNC_ALWAYS: func = GL_ALWAYS; break;
  196. }
  197. return func;
  198. }
  199. uint32_t gsgl_stencil_func_to_gl_stencil_func(gs_graphics_stencil_func_type type)
  200. {
  201. uint32_t func = GL_ALWAYS;
  202. switch (type) {
  203. default:
  204. case GS_GRAPHICS_STENCIL_FUNC_LESS: func = GL_LESS; break;
  205. case GS_GRAPHICS_STENCIL_FUNC_NEVER: func = GL_NEVER; break;
  206. case GS_GRAPHICS_STENCIL_FUNC_EQUAL: func = GL_EQUAL; break;
  207. case GS_GRAPHICS_STENCIL_FUNC_LEQUAL: func = GL_LEQUAL; break;
  208. case GS_GRAPHICS_STENCIL_FUNC_GREATER: func = GL_GREATER; break;
  209. case GS_GRAPHICS_STENCIL_FUNC_NOTEQUAL: func = GL_NOTEQUAL; break;
  210. case GS_GRAPHICS_STENCIL_FUNC_GEQUAL: func = GL_GEQUAL; break;
  211. case GS_GRAPHICS_STENCIL_FUNC_ALWAYS: func = GL_ALWAYS; break;
  212. }
  213. return func;
  214. }
  215. uint32_t gsgl_stencil_op_to_gl_stencil_op(gs_graphics_stencil_op_type type)
  216. {
  217. uint32_t op = GL_KEEP;
  218. switch (type) {
  219. default:
  220. case GS_GRAPHICS_STENCIL_OP_KEEP: op = GL_KEEP; break;
  221. case GS_GRAPHICS_STENCIL_OP_ZERO: op = GL_ZERO; break;
  222. case GS_GRAPHICS_STENCIL_OP_REPLACE: op = GL_REPLACE; break;
  223. case GS_GRAPHICS_STENCIL_OP_INCR: op = GL_INCR; break;
  224. case GS_GRAPHICS_STENCIL_OP_INCR_WRAP: op = GL_INCR_WRAP; break;
  225. case GS_GRAPHICS_STENCIL_OP_DECR: op = GL_DECR; break;
  226. case GS_GRAPHICS_STENCIL_OP_DECR_WRAP: op = GL_DECR_WRAP; break;
  227. case GS_GRAPHICS_STENCIL_OP_INVERT: op = GL_INVERT; break;
  228. }
  229. return op;
  230. }
  231. gsgl_uniform_type gsgl_uniform_type_to_gl_uniform_type(gs_graphics_uniform_type gstype)
  232. {
  233. gsgl_uniform_type type = GSGL_UNIFORMTYPE_FLOAT;
  234. switch (gstype) {
  235. default:
  236. case GS_GRAPHICS_UNIFORM_FLOAT: type = GSGL_UNIFORMTYPE_FLOAT; break;
  237. case GS_GRAPHICS_UNIFORM_INT: type = GSGL_UNIFORMTYPE_INT; break;
  238. case GS_GRAPHICS_UNIFORM_VEC2: type = GSGL_UNIFORMTYPE_VEC2; break;
  239. case GS_GRAPHICS_UNIFORM_VEC3: type = GSGL_UNIFORMTYPE_VEC3; break;
  240. case GS_GRAPHICS_UNIFORM_VEC4: type = GSGL_UNIFORMTYPE_VEC4; break;
  241. case GS_GRAPHICS_UNIFORM_MAT4: type = GSGL_UNIFORMTYPE_MAT4; break;
  242. }
  243. return type;
  244. }
  245. uint32_t gsgl_index_buffer_size_to_gl_index_type(size_t sz)
  246. {
  247. uint32_t type = GL_UNSIGNED_INT;
  248. switch (sz) {
  249. default:
  250. case 4: type = GL_UNSIGNED_INT; break;
  251. case 2: type = GL_UNSIGNED_SHORT; break;
  252. case 1: type = GL_UNSIGNED_BYTE; break;
  253. }
  254. return type;
  255. }
  256. size_t gsgl_get_byte_size_of_vertex_attribute(gs_graphics_vertex_attribute_type type)
  257. {
  258. size_t byte_size = 0;
  259. switch (type) {
  260. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT4: { byte_size = sizeof(float32_t) * 4; } break;
  261. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT3: { byte_size = sizeof(float32_t) * 3; } break;
  262. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT2: { byte_size = sizeof(float32_t) * 2; } break;
  263. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT: { byte_size = sizeof(float32_t) * 1; } break;
  264. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT4: { byte_size = sizeof(uint32_t) * 4; } break;
  265. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT3: { byte_size = sizeof(uint32_t) * 3; } break;
  266. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT2: { byte_size = sizeof(uint32_t) * 2; } break;
  267. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT: { byte_size = sizeof(uint32_t) * 1; } break;
  268. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE4: { byte_size = sizeof(uint8_t) * 4; } break;
  269. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE3: { byte_size = sizeof(uint8_t) * 3; } break;
  270. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE2: { byte_size = sizeof(uint8_t) * 2; } break;
  271. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE: { byte_size = sizeof(uint8_t) * 1; } break;
  272. }
  273. return byte_size;
  274. }
  275. size_t gsgl_calculate_vertex_size_in_bytes(gs_graphics_vertex_attribute_type* layout, uint32_t count)
  276. {
  277. // Iterate through all formats in delcarations and calculate total size
  278. size_t sz = 0;
  279. for (uint32_t i = 0; i < count; ++i) {
  280. gs_graphics_vertex_attribute_type type = layout[i];
  281. sz += gsgl_get_byte_size_of_vertex_attribute(type);
  282. }
  283. return sz;
  284. }
  285. size_t gsgl_get_vertex_attr_byte_offest(gs_dyn_array(gs_graphics_vertex_attribute_type) layout, uint32_t idx)
  286. {
  287. // Recursively calculate offset
  288. size_t total_offset = 0;
  289. // Base case
  290. if (idx == 0) {
  291. return total_offset;
  292. }
  293. // Calculate total offset up to this point
  294. for (uint32_t i = 0; i < idx; ++i) {
  295. total_offset += gsgl_get_byte_size_of_vertex_attribute(layout[i]);
  296. }
  297. return total_offset;
  298. }
  299. size_t gsgl_uniform_data_size_in_bytes(gs_graphics_uniform_type type)
  300. {
  301. size_t sz = 0;
  302. switch (type) {
  303. case GS_GRAPHICS_UNIFORM_FLOAT: sz = sizeof(float); break;
  304. case GS_GRAPHICS_UNIFORM_INT: sz = sizeof(int32_t); break;
  305. case GS_GRAPHICS_UNIFORM_VEC2: sz = 2 * sizeof(float); break;
  306. case GS_GRAPHICS_UNIFORM_VEC3: sz = 3 * sizeof(float); break;
  307. case GS_GRAPHICS_UNIFORM_VEC4: sz = 4 * sizeof(float); break;
  308. case GS_GRAPHICS_UNIFORM_MAT4: sz = 16 * sizeof(float); break;
  309. default: {
  310. sz = 0;
  311. } break;
  312. }
  313. return sz;
  314. }
  315. /* Graphics Interface Creation / Initialization / Shutdown / Destruction */
  316. gs_graphics_i* gs_graphics_create()
  317. {
  318. // Construct new graphics interface
  319. gs_graphics_i* gfx = gs_malloc_init(gs_graphics_i);
  320. // Construct internal data for opengl
  321. gfx->user_data = gs_malloc_init(gsgl_data_t);
  322. return gfx;
  323. }
  324. void gs_graphics_destroy(gs_graphics_i* graphics)
  325. {
  326. // Free all resources (assuming they've been freed from the GPU already)
  327. if (graphics == NULL) return;
  328. gsgl_data_t* ogl = (gsgl_data_t*)graphics->user_data;
  329. // Free all pipeline data
  330. if (ogl->pipelines) {
  331. for (uint32_t i = 1; i < gs_slot_array_size(ogl->pipelines); ++i) {
  332. gs_dyn_array_free(ogl->pipelines->data[i].layout);
  333. }
  334. }
  335. // Free all render pass data
  336. if (ogl->render_passes) {
  337. for (uint32_t i = 1; i < gs_slot_array_size(ogl->render_passes); ++i) {
  338. gs_dyn_array_free(ogl->render_passes->data[i].color);
  339. }
  340. }
  341. gs_slot_array_free(ogl->shaders);
  342. gs_slot_array_free(ogl->vertex_buffers);
  343. gs_slot_array_free(ogl->index_buffers);
  344. gs_slot_array_free(ogl->frame_buffers);
  345. gs_slot_array_free(ogl->uniforms);
  346. gs_slot_array_free(ogl->textures);
  347. gs_slot_array_free(ogl->pipelines);
  348. gs_slot_array_free(ogl->render_passes);
  349. gs_free(graphics);
  350. graphics = NULL;
  351. }
  352. gs_result gs_graphics_init(gs_graphics_i* graphics)
  353. {
  354. // Push back 0 handles into slot arrays (for 0 init validation)
  355. gsgl_data_t* ogl = (gsgl_data_t*)graphics->user_data;
  356. gs_slot_array_insert(ogl->shaders, 0);
  357. gs_slot_array_insert(ogl->vertex_buffers, 0);
  358. gs_slot_array_insert(ogl->index_buffers, 0);
  359. gs_slot_array_insert(ogl->frame_buffers, 0);
  360. gs_slot_array_insert(ogl->textures, 0);
  361. gsgl_uniform_t uni = gs_default_val();
  362. gsgl_pipeline_t pip = gs_default_val();
  363. gsgl_render_pass_t rp = gs_default_val();
  364. gs_slot_array_insert(ogl->uniforms, uni);
  365. gs_slot_array_insert(ogl->pipelines, pip);
  366. gs_slot_array_insert(ogl->render_passes, rp);
  367. // Construct vao then bind
  368. glGenVertexArrays(1, &ogl->cache.vao);
  369. glBindVertexArray(ogl->cache.vao);
  370. // Init ibo to zero
  371. gsgl_reset_data_cache(&ogl->cache);
  372. return GS_RESULT_SUCCESS;
  373. }
  374. gs_result gs_graphics_shutdown(gs_graphics_i* graphics)
  375. {
  376. return GS_RESULT_SUCCESS;
  377. }
  378. /* Resource Creation */
  379. gs_handle(gs_graphics_texture_t) gs_graphics_texture_create(gs_graphics_texture_desc_t* desc)
  380. {
  381. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  382. gsgl_texture_t tex;
  383. uint32_t width = desc->width;
  384. uint32_t height = desc->height;
  385. void* data = desc->data;
  386. // TODO(john): allow for user to specify explicitly whether to allocate texture as 'render buffer storage'
  387. // Construct 'normal' texture
  388. glGenTextures(1, &tex);
  389. glBindTexture(GL_TEXTURE_2D, tex);
  390. // Construct texture based on appropriate format
  391. switch(desc->format)
  392. {
  393. case GS_GRAPHICS_TEXTURE_FORMAT_A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data); break;
  394. case GS_GRAPHICS_TEXTURE_FORMAT_R8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, data); break;
  395. case GS_GRAPHICS_TEXTURE_FORMAT_RGB8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); break;
  396. case GS_GRAPHICS_TEXTURE_FORMAT_RGBA8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); break;
  397. case GS_GRAPHICS_TEXTURE_FORMAT_RGBA16F: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, data); break;
  398. case GS_GRAPHICS_TEXTURE_FORMAT_DEPTH8: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, data); break;
  399. case GS_GRAPHICS_TEXTURE_FORMAT_DEPTH16: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, data); break;
  400. case GS_GRAPHICS_TEXTURE_FORMAT_DEPTH24: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, data); break;
  401. case GS_GRAPHICS_TEXTURE_FORMAT_DEPTH32F: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, data); break;
  402. case GS_GRAPHICS_TEXTURE_FORMAT_DEPTH24_STENCIL8: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, data);
  403. case GS_GRAPHICS_TEXTURE_FORMAT_DEPTH32F_STENCIL8: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, data); break;
  404. // NOTE(john): Because Apple is a shit company, I have to section this off and provide support for 4.1 only features.
  405. // case GS_GRAPHICS_TEXTURE_FORMAT_STENCIL8: glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT8, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, data); break;
  406. default: break;
  407. }
  408. int32_t mag_filter = desc->mag_filter == GS_GRAPHICS_TEXTURE_FILTER_NEAREST ? GL_NEAREST : GL_LINEAR;
  409. int32_t min_filter = desc->min_filter == GS_GRAPHICS_TEXTURE_FILTER_NEAREST ? GL_NEAREST : GL_LINEAR;
  410. if (desc->num_mips) {
  411. if (desc->min_filter == GS_GRAPHICS_TEXTURE_FILTER_NEAREST) {
  412. min_filter = desc->mip_filter == GS_GRAPHICS_TEXTURE_FILTER_NEAREST ? GL_NEAREST_MIPMAP_NEAREST :
  413. GL_NEAREST_MIPMAP_LINEAR;
  414. }
  415. else {
  416. min_filter = desc->mip_filter == GS_GRAPHICS_TEXTURE_FILTER_NEAREST ? GL_LINEAR_MIPMAP_NEAREST :
  417. GL_NEAREST_MIPMAP_LINEAR;
  418. }
  419. }
  420. int32_t texture_wrap_s = desc->wrap_s == GS_GRAPHICS_TEXTURE_WRAP_REPEAT ? GL_REPEAT :
  421. desc->wrap_s == GS_GRAPHICS_TEXTURE_WRAP_MIRRORED_REPEAT ? GL_MIRRORED_REPEAT :
  422. desc->wrap_s == GS_GRAPHICS_TEXTURE_WRAP_CLAMP_TO_EDGE ? GL_CLAMP_TO_EDGE :
  423. GL_CLAMP_TO_BORDER;
  424. int32_t texture_wrap_t = desc->wrap_t == GS_GRAPHICS_TEXTURE_WRAP_REPEAT ? GL_REPEAT :
  425. desc->wrap_t == GS_GRAPHICS_TEXTURE_WRAP_MIRRORED_REPEAT ? GL_MIRRORED_REPEAT :
  426. desc->wrap_t == GS_GRAPHICS_TEXTURE_WRAP_CLAMP_TO_EDGE ? GL_CLAMP_TO_EDGE :
  427. GL_CLAMP_TO_BORDER;
  428. if (desc->num_mips) {
  429. glGenerateMipmap(GL_TEXTURE_2D);
  430. }
  431. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texture_wrap_s);
  432. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texture_wrap_t);
  433. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
  434. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
  435. // Unbind buffers
  436. glBindTexture(GL_TEXTURE_2D, 0);
  437. glBindRenderbuffer(GL_RENDERBUFFER, 0);
  438. // Add texture to internal resource pool and return handle
  439. return (gs_handle_create(gs_graphics_texture_t, gs_slot_array_insert(ogl->textures, tex)));
  440. }
  441. gs_handle(gs_graphics_buffer_t) gs_graphics_buffer_create(gs_graphics_buffer_desc_t* desc)
  442. {
  443. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  444. gs_handle(gs_graphics_buffer_t) hndl = gs_default_val();
  445. gsgl_buffer_t buffer = 0;
  446. switch (desc->type)
  447. {
  448. // Vertex Buffer
  449. default:
  450. case GS_GRAPHICS_BUFFER_VERTEX:
  451. {
  452. // Assert if data isn't filled for vertex data when static draw enabled
  453. if (desc->usage == GS_GRAPHICS_BUFFER_USAGE_STATIC && !desc->data) {
  454. gs_println("Error: Vertex buffer desc must contain data when GS_GRAPHICS_BUFFER_USAGE_STATIC set.");
  455. gs_assert(false);
  456. }
  457. glGenBuffers(1, &buffer);
  458. glBindBuffer(GL_ARRAY_BUFFER, buffer);
  459. glBufferData(GL_ARRAY_BUFFER, desc->size, desc->data, gsgl_buffer_usage_to_gl_enum(desc->usage));
  460. glBindBuffer(GL_ARRAY_BUFFER, 0);
  461. hndl = gs_handle_create(gs_graphics_buffer_t, gs_slot_array_insert(ogl->vertex_buffers, buffer));
  462. } break;
  463. // Index Buffer
  464. case GS_GRAPHICS_BUFFER_INDEX:
  465. {
  466. // Assert if data isn't filled for vertex data when static draw enabled
  467. if (desc->usage == GS_GRAPHICS_BUFFER_USAGE_STATIC && !desc->data) {
  468. gs_println("Error: Index buffer desc must contain data when GS_GRAPHICS_BUFFER_USAGE_STATIC set.");
  469. gs_assert(false);
  470. }
  471. glGenBuffers(1, &buffer);
  472. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
  473. glBufferData(GL_ELEMENT_ARRAY_BUFFER, desc->size, desc->data, gsgl_buffer_usage_to_gl_enum(desc->usage));
  474. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  475. hndl = gs_handle_create(gs_graphics_buffer_t, gs_slot_array_insert(ogl->index_buffers, buffer));
  476. } break;
  477. case GS_GRAPHICS_BUFFER_FRAME:
  478. {
  479. // Construct and bind frame buffer
  480. glGenFramebuffers(1, &buffer);
  481. hndl = gs_handle_create(gs_graphics_buffer_t, gs_slot_array_insert(ogl->frame_buffers, buffer));
  482. } break;
  483. case GS_GRAPHICS_BUFFER_UNIFORM:
  484. {
  485. // Assert if data isn't named
  486. if (desc->name == NULL) {
  487. gs_println("Warning: Uniform buffer must be named for OpenGL.");
  488. }
  489. uint32_t ct = desc->size / sizeof(gs_graphics_uniform_desc_t);
  490. if (ct < 1) {
  491. gs_println("Warning: Uniform buffer description is empty.");
  492. return gs_handle_invalid(gs_graphics_buffer_t);
  493. }
  494. gsgl_uniform_t u = gs_default_val();
  495. u.name = desc->name;
  496. // If size > 1, store type as uniform buffer, other store type as type of first element of data description
  497. u.type = ct > 1 ? GSGL_UNIFORMTYPE_UNIFORM_BLOCK : gsgl_uniform_type_to_gl_uniform_type(((gs_graphics_uniform_desc_t*)desc->data)[0].type);
  498. u.location = UINT32_MAX;
  499. // Calculate size
  500. for (uint32_t i = 0; i < ct; ++i) {
  501. u.size += gsgl_uniform_data_size_in_bytes(((gs_graphics_uniform_desc_t*)desc->data)[i].type);
  502. }
  503. hndl = gs_handle_create(gs_graphics_buffer_t, gs_slot_array_insert(ogl->uniforms, u));
  504. } break;
  505. case GS_GRAPHICS_BUFFER_SAMPLER:
  506. {
  507. // Assert if data isn't named
  508. if (desc->name == NULL) {
  509. gs_println("Warning: Uniform buffer must be named for OpenGL.");
  510. }
  511. uint32_t ct = desc->size / sizeof(gs_graphics_sampler_desc_t);
  512. gsgl_uniform_t u = gs_default_val();
  513. u.name = desc->name;
  514. u.type = GSGL_UNIFORMTYPE_SAMPLER2D;
  515. u.location = UINT32_MAX;
  516. hndl = gs_handle_create(gs_graphics_buffer_t, gs_slot_array_insert(ogl->uniforms, u));
  517. } break;
  518. }
  519. return hndl;
  520. }
  521. #define GSGL_GRAPHICS_SHADER_PIPELINE_GFX 0x01
  522. #define GSGL_GRAPHICS_SHADER_PIPELINE_COMPUTE 0x02
  523. #define GSGL_GRAPHICS_MAX_SID 128
  524. gs_handle(gs_graphics_shader_t) gs_graphics_shader_create(gs_graphics_shader_desc_t* desc)
  525. {
  526. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  527. gsgl_shader_t shader = 0;
  528. uint32_t pip = 0x00;
  529. uint32_t sid_ct = 0;
  530. uint32_t sids[GSGL_GRAPHICS_MAX_SID] = gs_default_val();
  531. // Create shader program
  532. shader = glCreateProgram();
  533. uint32_t ct = desc->size / sizeof(gs_graphics_shader_source_desc_t);
  534. for (uint32_t i = 0; i < ct; ++i)
  535. {
  536. if (desc->sources[i].type == GS_GRAPHICS_SHADER_STAGE_VERTEX) pip |= GSGL_GRAPHICS_SHADER_PIPELINE_GFX;
  537. if (desc->sources[i].type == GS_GRAPHICS_SHADER_STAGE_COMPUTE) pip |= GSGL_GRAPHICS_SHADER_PIPELINE_COMPUTE;
  538. // Validity Check: Desc must have vertex source if compute not selected. All other source is optional.
  539. if ((pip & GSGL_GRAPHICS_SHADER_PIPELINE_COMPUTE) && ((pip & GSGL_GRAPHICS_SHADER_PIPELINE_GFX))) {
  540. gs_println("Error: Cannot have compute and graphics stages for shader program.");
  541. gs_assert(false);
  542. }
  543. uint32_t stage = gsgl_shader_stage_to_gl_stage(desc->sources[i].type);
  544. uint32_t sid = glCreateShader(stage);
  545. if (!sid) {
  546. gs_println ("Error: Failed to allocate memory for shader: '%s': stage: {put stage id here}.", desc->name);
  547. gs_assert(sid);
  548. }
  549. // Set source
  550. glShaderSource(sid, 1, &desc->sources[i].source, NULL);
  551. // Compile shader
  552. glCompileShader(sid);
  553. //Check for errors
  554. GLint success = 0;
  555. glGetShaderiv(sid, GL_COMPILE_STATUS, &success);
  556. if (success == GL_FALSE)
  557. {
  558. GLint max_len = 0;
  559. glGetShaderiv(sid, GL_INFO_LOG_LENGTH, &max_len);
  560. char* log = gs_malloc(max_len);
  561. memset(log, 0, max_len);
  562. //The max_len includes the NULL character
  563. glGetShaderInfoLog(sid, max_len, &max_len, log);
  564. // Delete shader.
  565. glDeleteShader(shader);
  566. //Provide the infolog
  567. gs_println("Opengl::opengl_compile_shader::shader: '%s'\nFAILED_TO_COMPILE: %s\n %s", desc->name, log, desc->sources[i].source);
  568. free(log);
  569. log = NULL;
  570. gs_assert(false);
  571. }
  572. // Attach shader to program
  573. glAttachShader(shader, sid);
  574. // Add to shader array
  575. sids[sid_ct++] = sid;
  576. }
  577. // Link shaders into final program
  578. glLinkProgram(shader);
  579. //Create info log for errors
  580. s32 is_linked = 0;
  581. glGetProgramiv(shader, GL_LINK_STATUS, (s32*)&is_linked);
  582. if (is_linked == GL_FALSE)
  583. {
  584. GLint max_len = 0;
  585. glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &max_len);
  586. char* log = gs_malloc(max_len);
  587. memset(log, 0, max_len);
  588. glGetProgramInfoLog(shader, max_len, &max_len, log);
  589. // Print error
  590. gs_println("Error: Fail To Link::opengl_link_shaders::shader: '%s', \n%s", desc->name, log);
  591. // //We don't need the program anymore.
  592. glDeleteProgram(shader);
  593. free(log);
  594. log = NULL;
  595. // Just assert for now
  596. gs_assert(false);
  597. }
  598. // Free shaders after use
  599. for (uint32_t i = 0; i < sid_ct; ++i) {
  600. glDeleteShader(sids[i]);
  601. }
  602. // Add to pool and return handle
  603. return (gs_handle_create(gs_graphics_shader_t, gs_slot_array_insert(ogl->shaders, shader)));
  604. }
  605. gs_handle(gs_graphics_render_pass_t) gs_graphics_render_pass_create(gs_graphics_render_pass_desc_t* desc)
  606. {
  607. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  608. gsgl_render_pass_t pass = gs_default_val();
  609. // Set fbo
  610. pass.fbo = desc->fbo;
  611. // Set color attachments
  612. uint32_t ct = desc->color_size / sizeof(gs_handle(gs_graphics_texture_t));
  613. for (uint32_t i = 0; i < ct; ++i)
  614. {
  615. gs_dyn_array_push(pass.color, desc->color[i]);
  616. }
  617. // Set depth attachment
  618. pass.depth = desc->depth;
  619. // Create handle and return
  620. return (gs_handle_create(gs_graphics_render_pass_t, gs_slot_array_insert(ogl->render_passes, pass)));
  621. }
  622. gs_handle(gs_graphics_pipeline_t) gs_graphics_pipeline_create(gs_graphics_pipeline_desc_t* desc)
  623. {
  624. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  625. gsgl_pipeline_t pipe = gs_default_val();
  626. // Add states
  627. pipe.blend = desc->blend;
  628. pipe.depth = desc->depth;
  629. pipe.raster = desc->raster;
  630. pipe.stencil = desc->stencil;
  631. // Add layout
  632. uint32_t ct = desc->size / sizeof(gs_graphics_vertex_attribute_type);
  633. gs_dyn_array_reserve(pipe.layout, ct);
  634. for (uint32_t i = 0; i < ct; ++i)
  635. {
  636. gs_dyn_array_push(pipe.layout, desc->layout[i]);
  637. }
  638. // Create handle and return
  639. return (gs_handle_create(gs_graphics_pipeline_t, gs_slot_array_insert(ogl->pipelines, pipe)));
  640. }
  641. /* Resource Destruction */
  642. void gs_graphics_texture_destroy(gs_handle(gs_graphics_texture_t) hndl)
  643. {
  644. }
  645. void gs_graphics_buffer_destroy(gs_handle(gs_graphics_buffer_t) hndl)
  646. {
  647. }
  648. void gs_graphics_shader_destroy(gs_handle(gs_graphics_shader_t) hndl)
  649. {
  650. }
  651. void gs_graphics_uniform_block_destroy(gs_handle(gs_graphics_uniform_block_t) hndl)
  652. {
  653. }
  654. void gs_graphics_render_pass_destroy(gs_handle(gs_graphics_render_pass_t) hndl)
  655. {
  656. }
  657. void gs_graphics_pipeline_destroy(gs_handle(gs_graphics_pipeline_t) hndl)
  658. {
  659. }
  660. /* Resource Update*/
  661. void gs_graphics_texture_update(gs_handle(gs_graphics_texture_t) hndl, gs_graphics_texture_desc_t* desc)
  662. {
  663. }
  664. void gs_graphics_buffer_update(gs_handle(gs_graphics_buffer_t) hndl, gs_graphics_buffer_desc_t* desc)
  665. {
  666. }
  667. #define __ogl_push_command(CB, OP_CODE, ...)\
  668. do {\
  669. gsgl_data_t* DATA = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;\
  670. gs_byte_buffer_write(&CB->commands, u32, OP_CODE);\
  671. __VA_ARGS__\
  672. CB->num_commands++;\
  673. } while (0)
  674. /* Command Buffer Ops: Pipeline / Pass / Bind / Draw */
  675. void gs_graphics_begin_render_pass(gs_command_buffer_t* cb, gs_handle(gs_graphics_render_pass_t) hndl, gs_graphics_render_pass_action_t* actions, size_t actions_size)
  676. {
  677. __ogl_push_command(cb, GS_OPENGL_OP_BEGIN_RENDER_PASS, {
  678. gs_byte_buffer_write(&cb->commands, uint32_t, hndl.id);
  679. uint32_t count = actions_size / sizeof(gs_graphics_render_pass_action_t);
  680. gs_byte_buffer_write(&cb->commands, uint32_t, count);
  681. for (uint32_t i = 0; i < count; ++i) {
  682. gs_byte_buffer_write(&cb->commands, gs_graphics_render_pass_action_t, actions[i]);
  683. }
  684. });
  685. }
  686. void gs_graphics_end_render_pass(gs_command_buffer_t* cb)
  687. {
  688. __ogl_push_command(cb, GS_OPENGL_OP_END_RENDER_PASS, {
  689. // Nothing...
  690. });
  691. }
  692. void gs_graphics_set_viewport(gs_command_buffer_t* cb, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
  693. {
  694. __ogl_push_command(cb, GS_OPENGL_OP_SET_VIEWPORT, {
  695. gs_byte_buffer_write(&cb->commands, uint32_t, x);
  696. gs_byte_buffer_write(&cb->commands, uint32_t, y);
  697. gs_byte_buffer_write(&cb->commands, uint32_t, w);
  698. gs_byte_buffer_write(&cb->commands, uint32_t, h);
  699. });
  700. }
  701. void gs_graphics_set_view_scissor(gs_command_buffer_t* cb, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
  702. {
  703. __ogl_push_command(cb, GS_OPENGL_OP_SET_VIEW_SCISSOR, {
  704. gs_byte_buffer_write(&cb->commands, uint32_t, x);
  705. gs_byte_buffer_write(&cb->commands, uint32_t, y);
  706. gs_byte_buffer_write(&cb->commands, uint32_t, w);
  707. gs_byte_buffer_write(&cb->commands, uint32_t, h);
  708. });
  709. }
  710. void gs_graphics_texture_request_update(gs_command_buffer_t* cb, gs_handle(gs_graphics_texture_t) hndl, gs_graphics_texture_desc_t* desc)
  711. {
  712. }
  713. void gs_graphics_buffer_request_update(gs_command_buffer_t* cb, gs_handle(gs_graphics_buffer_t) hndl, gs_graphics_buffer_desc_t* desc)
  714. {
  715. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  716. // Need to just store all buffers into single buffer slot array. This is goofy.
  717. if (!hndl.id) return;
  718. // Write type
  719. __ogl_push_command(cb, GS_OPENGL_OP_REQUEST_BUFFER_UPDATE, {
  720. // Write handle id
  721. gs_byte_buffer_write(&cb->commands, uint32_t, hndl.id);
  722. // Write type
  723. gs_byte_buffer_write(&cb->commands, gs_graphics_buffer_type, desc->type);
  724. // Write usage
  725. gs_byte_buffer_write(&cb->commands, gs_graphics_buffer_usage_type, desc->usage);
  726. // Write data size
  727. gs_byte_buffer_write(&cb->commands, size_t, desc->size);
  728. // Write data
  729. gs_byte_buffer_write_bulk(&cb->commands, desc->data, desc->size);
  730. });
  731. }
  732. void gs_graphics_bind_bindings(gs_command_buffer_t* cb, gs_graphics_bind_desc_t* binds, size_t binds_size)
  733. {
  734. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  735. __ogl_push_command(cb, GS_OPENGL_OP_BIND_BINDINGS,
  736. {
  737. uint32_t ct = binds_size / sizeof(gs_graphics_bind_desc_t);
  738. gs_byte_buffer_write(&cb->commands, uint32_t, ct);
  739. for (uint32_t i = 0; i < ct; ++i)
  740. {
  741. gs_byte_buffer_write(&cb->commands, gs_graphics_bind_type, binds[i].type);
  742. switch (binds[i].type)
  743. {
  744. case GS_GRAPHICS_BIND_VERTEX_BUFFER:
  745. case GS_GRAPHICS_BIND_INDEX_BUFFER:
  746. {
  747. gs_byte_buffer_write(&cb->commands, uint32_t, binds[i].buffer.id);
  748. } break;
  749. case GS_GRAPHICS_BIND_UNIFORM_BUFFER:
  750. {
  751. // Get uniform to get size
  752. uint32_t id = binds[i].buffer.id;
  753. if (id && gs_slot_array_exists(ogl->uniforms, id))
  754. {
  755. size_t sz = (size_t)(gs_slot_array_getp(ogl->uniforms, id))->size;
  756. // Write slot id of uniform buffer
  757. gs_byte_buffer_write(&cb->commands, uint32_t, binds[i].buffer.id);
  758. // Write data size
  759. gs_byte_buffer_write(&cb->commands, size_t, sz);
  760. // Write data (bulk write of void* data)
  761. gs_byte_buffer_write_bulk(&cb->commands, binds[i].data, sz);
  762. }
  763. } break;
  764. case GS_GRAPHICS_BIND_SAMPLER_BUFFER:
  765. {
  766. // Write slot id of sampler buffer
  767. gs_byte_buffer_write(&cb->commands, uint32_t, binds[i].buffer.id);
  768. // Write id texture
  769. gs_byte_buffer_write(&cb->commands, uint32_t, ((gs_handle(gs_graphics_texture_t)*)binds[i].data)->id);
  770. // Write binding
  771. gs_byte_buffer_write(&cb->commands, uint32_t, binds[i].binding);
  772. } break;
  773. default: gs_assert(false); break;
  774. }
  775. }
  776. });
  777. }
  778. void gs_graphics_bind_pipeline(gs_command_buffer_t* cb, gs_handle(gs_graphics_pipeline_t) hndl)
  779. {
  780. // NOTE(john): Not sure if this is safe in the future, since the data for pipelines is on the main thread and MIGHT be tampered with on a separate thread.
  781. __ogl_push_command(cb, GS_OPENGL_OP_BIND_PIPELINE, {
  782. gs_byte_buffer_write(&cb->commands, uint32_t, hndl.id);
  783. });
  784. }
  785. void gs_graphics_bind_uniform_block(gs_command_buffer_t* cb, gs_handle(gs_graphics_uniform_block_t) hndl, void* data, size_t data_size)
  786. {
  787. __ogl_push_command(cb, GS_OPENGL_OP_BIND_UNIFORM_BLOCK, {
  788. gs_byte_buffer_write(&cb->commands, uint32_t, hndl.id);
  789. gs_byte_buffer_write_bulk(&cb->commands, data, data_size);
  790. });
  791. }
  792. void gs_graphics_draw(gs_command_buffer_t* cb, uint32_t start, uint32_t count)
  793. {
  794. __ogl_push_command(cb, GS_OPENGL_OP_DRAW, {
  795. gs_byte_buffer_write(&cb->commands, uint32_t, start);
  796. gs_byte_buffer_write(&cb->commands, uint32_t, count);
  797. });
  798. }
  799. /* Submission (Main Thread) */
  800. void gs_graphics_submit_command_buffer(gs_command_buffer_t* cb)
  801. {
  802. /*
  803. // Structure of command:
  804. - Op code
  805. - Data packet
  806. */
  807. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  808. // Set read position of buffer to beginning
  809. gs_byte_buffer_seek_to_beg(&cb->commands);
  810. // For each command in buffer
  811. gs_for_range(cb->num_commands)
  812. {
  813. // Read in op code of command
  814. gs_byte_buffer_readc(&cb->commands, gs_opengl_op_code_type, op_code);
  815. switch (op_code)
  816. {
  817. case GS_OPENGL_OP_BEGIN_RENDER_PASS:
  818. {
  819. // Bind render pass stuff
  820. gs_byte_buffer_readc(&cb->commands, uint32_t, rpid);
  821. // If render pass exists, then we'll bind frame buffer and attachments
  822. if (rpid && gs_slot_array_exists(ogl->render_passes, rpid))
  823. {
  824. gsgl_render_pass_t* rp = gs_slot_array_getp(ogl->render_passes, rpid);
  825. // Bind frame buffer since it actually exists
  826. if (rp->fbo.id && gs_slot_array_exists(ogl->frame_buffers, rp->fbo.id))
  827. {
  828. // Bind frame buffer
  829. glBindFramebuffer(GL_FRAMEBUFFER, gs_slot_array_get(ogl->frame_buffers, rp->fbo.id));
  830. // Bind color attachments
  831. for (uint32_t r = 0; r < gs_dyn_array_size(rp->color); ++r)
  832. {
  833. uint32_t cid = rp->color[r].id;
  834. if (cid && gs_slot_array_exists(ogl->textures, cid))
  835. {
  836. gsgl_texture_t rt = gs_slot_array_get(ogl->textures, cid);
  837. glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + r, rt, 0);
  838. }
  839. }
  840. }
  841. }
  842. // Actions
  843. gs_byte_buffer_readc(&cb->commands, uint32_t, action_count);
  844. for (uint32_t j = 0; j < action_count; ++j)
  845. {
  846. gs_byte_buffer_readc(&cb->commands, gs_graphics_render_pass_action_t, action);
  847. // No clear
  848. if (action.flag & GS_GRAPHICS_RENDER_PASS_ACTION_CLEAR_NONE) {
  849. continue;
  850. }
  851. // Default flag val
  852. if (action.flag == 0x00) action.flag = GS_GRAPHICS_RENDER_PASS_ACTION_CLEAR_ALL;
  853. uint32_t bit = 0x00;
  854. if (action.flag & GS_GRAPHICS_RENDER_PASS_ACTION_CLEAR_COLOR) {
  855. glClearColor(action.color[0], action.color[1], action.color[2], action.color[3]);
  856. bit |= GL_COLOR_BUFFER_BIT;
  857. }
  858. if (action.flag & GS_GRAPHICS_RENDER_PASS_ACTION_CLEAR_DEPTH) {
  859. bit |= GL_DEPTH_BUFFER_BIT;
  860. }
  861. if (action.flag & GS_GRAPHICS_RENDER_PASS_ACTION_CLEAR_STENCIL) {
  862. bit |= GL_STENCIL_BUFFER_BIT;
  863. }
  864. glClear(bit);
  865. }
  866. } break;
  867. case GS_OPENGL_OP_END_RENDER_PASS:
  868. {
  869. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  870. gsgl_reset_data_cache(&ogl->cache);
  871. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  872. glBindBuffer(GL_ARRAY_BUFFER, 0);
  873. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  874. glDisable(GL_SCISSOR_TEST);
  875. glDisable(GL_DEPTH_TEST);
  876. glDisable(GL_STENCIL_TEST);
  877. glDisable(GL_BLEND);
  878. } break;
  879. case GS_OPENGL_OP_SET_VIEWPORT:
  880. {
  881. gs_byte_buffer_readc(&cb->commands, uint32_t, x);
  882. gs_byte_buffer_readc(&cb->commands, uint32_t, y);
  883. gs_byte_buffer_readc(&cb->commands, uint32_t, w);
  884. gs_byte_buffer_readc(&cb->commands, uint32_t, h);
  885. glViewport(x, y, w, h);
  886. } break;
  887. case GS_OPENGL_OP_SET_VIEW_SCISSOR:
  888. {
  889. gs_byte_buffer_readc(&cb->commands, uint32_t, x);
  890. gs_byte_buffer_readc(&cb->commands, uint32_t, y);
  891. gs_byte_buffer_readc(&cb->commands, uint32_t, w);
  892. gs_byte_buffer_readc(&cb->commands, uint32_t, h);
  893. glEnable(GL_SCISSOR_TEST);
  894. glScissor(x, y, w, h);
  895. } break;
  896. case GS_OPENGL_OP_BIND_BINDINGS:
  897. {
  898. gs_byte_buffer_readc(&cb->commands, uint32_t, ct);
  899. for (uint32_t i = 0; i < ct; ++i)
  900. {
  901. gs_byte_buffer_readc(&cb->commands, gs_graphics_bind_type, type);
  902. switch (type)
  903. {
  904. case GS_GRAPHICS_BIND_VERTEX_BUFFER:
  905. {
  906. gs_byte_buffer_readc(&cb->commands, uint32_t, id);
  907. if (!id || !gs_slot_array_exists(ogl->vertex_buffers, id))
  908. {
  909. gs_timed_action(60,
  910. {
  911. gs_println("Warning:Opengl:BindBindings:VertexBuffer %d does not exist.", id);
  912. continue;
  913. });
  914. }
  915. gsgl_buffer_t vbo = gs_slot_array_get(ogl->vertex_buffers, id);
  916. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  917. } break;
  918. case GS_GRAPHICS_BIND_INDEX_BUFFER:
  919. {
  920. gs_byte_buffer_readc(&cb->commands, uint32_t, id);
  921. if (!gs_slot_array_exists(ogl->index_buffers, id))
  922. {
  923. gs_timed_action(60,
  924. {
  925. gs_println("Warning:Opengl:BindBindings:IndexBuffer %d does not exist.", id);
  926. });
  927. }
  928. else
  929. {
  930. gsgl_buffer_t ibo = gs_slot_array_get(ogl->index_buffers, id);
  931. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
  932. // Store in cache
  933. ogl->cache.ibo = id;
  934. }
  935. } break;
  936. case GS_GRAPHICS_BIND_UNIFORM_BUFFER:
  937. {
  938. // Read slot id of uniform buffer
  939. gs_byte_buffer_readc(&cb->commands, uint32_t, id);
  940. // Read data size
  941. gs_byte_buffer_readc(&cb->commands, size_t, sz);
  942. // Check buffer id. If invalid, then we can't operate, and instead just need to pass over the data.
  943. if (!id || !gs_slot_array_exists(ogl->uniforms, id)) {
  944. gs_timed_action(60, {
  945. gs_println("Warning:Bind Uniform Buffer:Uniform %d does not exist.", ogl->cache.pipeline.id);
  946. });
  947. gs_byte_buffer_advance_position(&cb->commands, sz);
  948. continue;
  949. }
  950. // Grab currently bound pipeline (TODO(john): assert if this isn't valid)
  951. if (!ogl->cache.pipeline.id || !gs_slot_array_exists(ogl->pipelines, ogl->cache.pipeline.id)){
  952. gs_timed_action(60, {
  953. gs_println("Warning:Bind Uniform Buffer:Pipeline %d does not exist.", ogl->cache.pipeline.id);
  954. });
  955. gs_byte_buffer_advance_position(&cb->commands, sz);
  956. continue;
  957. }
  958. gsgl_pipeline_t* pip = gs_slot_array_getp(ogl->pipelines, ogl->cache.pipeline.id);
  959. // Get uniform
  960. gsgl_uniform_t* u = gs_slot_array_getp(ogl->uniforms, id);
  961. // Check uniform location. If UINT32_T max, then must construct and place location
  962. if (u->location == UINT32_MAX && u->location != UINT32_MAX - 1)
  963. {
  964. if (!pip->raster.shader.id || !gs_slot_array_exists(ogl->shaders, pip->raster.shader.id)) {
  965. gs_timed_action(60, {
  966. gs_println("Warning:Bind Uniform Buffer:Shader %d does not exist.", pip->raster.shader.id);
  967. });
  968. gs_byte_buffer_advance_position(&cb->commands, sz);
  969. continue;
  970. }
  971. gsgl_shader_t shader = gs_slot_array_get(ogl->shaders, pip->raster.shader.id);
  972. // Grab location of uniform
  973. u->location = glGetUniformLocation(shader, u->name ? u->name : "__EMPTY_UNIFORM_NAME");
  974. if (u->location >= UINT32_MAX) {
  975. gs_println("Warning: uniform not found: \"%s\"", u->name);
  976. u->location = UINT32_MAX - 1;
  977. }
  978. }
  979. // Switch on uniform type to upload data
  980. switch (u->type)
  981. {
  982. case GSGL_UNIFORMTYPE_FLOAT:
  983. {
  984. gs_assert(sz == sizeof(float));
  985. gs_byte_buffer_read_bulkc(&cb->commands, float, v, sz);
  986. glUniform1f(u->location, v);
  987. } break;
  988. case GSGL_UNIFORMTYPE_INT:
  989. {
  990. gs_assert(sz == sizeof(int32_t));
  991. gs_byte_buffer_read_bulkc(&cb->commands, int32_t, v, sz);
  992. glUniform1f(u->location, v);
  993. } break;
  994. case GSGL_UNIFORMTYPE_VEC2:
  995. {
  996. gs_assert(sz == sizeof(gs_vec2));
  997. gs_byte_buffer_read_bulkc(&cb->commands, gs_vec2, v, sz);
  998. glUniform2f(u->location, v.x, v.y);
  999. } break;
  1000. case GSGL_UNIFORMTYPE_VEC3:
  1001. {
  1002. gs_assert(sz == sizeof(gs_vec3));
  1003. gs_byte_buffer_read_bulkc(&cb->commands, gs_vec3, v, sz);
  1004. glUniform3f(u->location, v.x, v.y, v.z);
  1005. } break;
  1006. case GSGL_UNIFORMTYPE_VEC4:
  1007. {
  1008. gs_assert(sz == sizeof(gs_vec4));
  1009. gs_byte_buffer_read_bulkc(&cb->commands, gs_vec4, v, sz);
  1010. glUniform4f(u->location, v.x, v.y, v.z, v.w);
  1011. } break;
  1012. case GSGL_UNIFORMTYPE_MAT4:
  1013. {
  1014. gs_assert(sz == sizeof(gs_mat4));
  1015. gs_byte_buffer_read_bulkc(&cb->commands, gs_mat4, v, sz);
  1016. glUniformMatrix4fv(u->location, 1, false, (float*)(v.elements));
  1017. } break;
  1018. default: {
  1019. // Shouldn't hit here
  1020. } break;
  1021. }
  1022. } break;
  1023. case GS_GRAPHICS_BIND_SAMPLER_BUFFER:
  1024. {
  1025. // Read slot id of sampler buffer
  1026. gs_byte_buffer_readc(&cb->commands, uint32_t, sampler_slot_id);
  1027. // Read id texture
  1028. gs_byte_buffer_readc(&cb->commands, uint32_t, tex_slot_id);
  1029. // Read binding
  1030. gs_byte_buffer_readc(&cb->commands, uint32_t, binding);
  1031. // Grab uniform from sampler id
  1032. if (!sampler_slot_id || !gs_slot_array_exists(ogl->uniforms, sampler_slot_id)) {
  1033. gs_timed_action(60, {
  1034. gs_println("Warning:Bind Sampler Buffer:Sampler %d does not exist.", sampler_slot_id);
  1035. });
  1036. continue;
  1037. }
  1038. // Grab texture from sampler id
  1039. if (!tex_slot_id || !gs_slot_array_exists(ogl->textures, tex_slot_id)) {
  1040. gs_timed_action(60, {
  1041. gs_println("Warning:Bind Sampler Buffer:Texture %d does not exist.", tex_slot_id);
  1042. });
  1043. continue;
  1044. }
  1045. // Grab currently bound pipeline (TODO(john): assert if this isn't valid)
  1046. if (!ogl->cache.pipeline.id || !gs_slot_array_exists(ogl->pipelines, ogl->cache.pipeline.id)){
  1047. gs_timed_action(60, {
  1048. gs_println("Warning:Bind Sampler Buffer:Pipeline %d does not exist.", ogl->cache.pipeline.id);
  1049. });
  1050. continue;
  1051. }
  1052. gsgl_uniform_t* u = gs_slot_array_getp(ogl->uniforms, sampler_slot_id);
  1053. gsgl_texture_t tex = gs_slot_array_get(ogl->textures, tex_slot_id);
  1054. gsgl_pipeline_t* pip = gs_slot_array_getp(ogl->pipelines, ogl->cache.pipeline.id);
  1055. // Check uniform location. If UINT32_T max, then must construct and place location
  1056. if (u->location == UINT32_MAX && u->location != UINT32_MAX - 1)
  1057. {
  1058. if (!pip->raster.shader.id || !gs_slot_array_exists(ogl->shaders, pip->raster.shader.id)) {
  1059. gs_timed_action(60, {
  1060. gs_println("Warning:Bind Uniform Buffer:Shader %d does not exist.", pip->raster.shader.id);
  1061. });
  1062. continue;
  1063. }
  1064. gsgl_shader_t shader = gs_slot_array_get(ogl->shaders, pip->raster.shader.id);
  1065. // Grab location of uniform
  1066. u->location = glGetUniformLocation(shader, u->name ? u->name : "__EMPTY_UNIFORM_NAME");
  1067. if (u->location >= UINT32_MAX) {
  1068. gs_println("Warning: uniform not found: \"%s\"", u->name);
  1069. u->location = UINT32_MAX - 1;
  1070. }
  1071. }
  1072. // Invalid texture
  1073. if (u->location == UINT32_MAX - 1) {
  1074. continue;
  1075. }
  1076. // Activate texture slot
  1077. glActiveTexture(GL_TEXTURE0 + binding);
  1078. // Bind texture
  1079. glBindTexture(GL_TEXTURE_2D, tex);
  1080. // Bind uniform
  1081. glUniform1i(u->location, binding);
  1082. } break;
  1083. default: gs_assert(false); break;
  1084. }
  1085. }
  1086. } break;
  1087. case GS_OPENGL_OP_BIND_PIPELINE:
  1088. {
  1089. // Bind pipeline stuff
  1090. gs_byte_buffer_readc(&cb->commands, uint32_t, pipid);
  1091. // Make sure pipeline exists
  1092. if (!pipid || !gs_slot_array_exists(ogl->pipelines, pipid)) {
  1093. gs_println("Warning: Pipeline %d does not exist.", pipid);
  1094. continue;
  1095. }
  1096. // Reset cache
  1097. gsgl_reset_data_cache(&ogl->cache);
  1098. /* Cache pipeline id */
  1099. ogl->cache.pipeline = gs_handle_create(gs_graphics_pipeline_t, pipid);
  1100. gsgl_pipeline_t* pip = gs_slot_array_getp(ogl->pipelines, pipid);
  1101. /* Depth */
  1102. if (!pip->depth.func) {
  1103. // If no depth function (default), then disable
  1104. glDisable(GL_DEPTH_TEST);
  1105. }
  1106. else {
  1107. glEnable(GL_DEPTH_TEST);
  1108. gsgl_depth_func_to_gl_depth_func(pip->depth.func);
  1109. }
  1110. /* Stencil */
  1111. if (!pip->stencil.func) {
  1112. // If no stencil function (default), then disable
  1113. glDisable(GL_STENCIL_TEST);
  1114. } else {
  1115. glEnable(GL_STENCIL_TEST);
  1116. uint32_t func = gsgl_stencil_func_to_gl_stencil_func(pip->stencil.func);
  1117. uint32_t sfail = gsgl_stencil_op_to_gl_stencil_op(pip->stencil.sfail);
  1118. uint32_t dpfail = gsgl_stencil_op_to_gl_stencil_op(pip->stencil.dpfail);
  1119. uint32_t dppass = gsgl_stencil_op_to_gl_stencil_op(pip->stencil.dppass);
  1120. glStencilFunc(func, pip->stencil.ref, pip->stencil.mask);
  1121. glStencilOp(sfail, dpfail, dppass);
  1122. }
  1123. /* Blend */
  1124. if (!pip->blend.func) {
  1125. glDisable(GL_BLEND);
  1126. } else {
  1127. glEnable(GL_BLEND);
  1128. glBlendEquation(gsgl_blend_equation_to_gl_blend_eq(pip->blend.func));
  1129. glBlendFunc(gsgl_blend_mode_to_gl_blend_mode(pip->blend.src, GL_ONE),
  1130. gsgl_blend_mode_to_gl_blend_mode(pip->blend.dst, GL_ZERO));
  1131. //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1132. }
  1133. /* Raster */
  1134. // Face culling
  1135. if (!pip->raster.face_culling) {
  1136. glDisable(GL_CULL_FACE);
  1137. } else {
  1138. glEnable(GL_CULL_FACE);
  1139. glCullFace(gsgl_cull_face_to_gl_cull_face(pip->raster.face_culling));
  1140. }
  1141. // Winding order
  1142. glFrontFace(gsgl_winding_order_to_gl_winding_order(pip->raster.winding_order));
  1143. /* Shader */
  1144. if (pip->raster.shader.id && gs_slot_array_exists(ogl->shaders, pip->raster.shader.id)) {
  1145. glUseProgram(gs_slot_array_get(ogl->shaders, pip->raster.shader.id));
  1146. }
  1147. else {
  1148. gs_timed_action(60, {
  1149. gs_println("Warning:Opengl:BindPipeline:Shader %d does not exist.", pip->raster.shader.id);
  1150. });
  1151. }
  1152. } break;
  1153. case GS_OPENGL_OP_DRAW:
  1154. {
  1155. // Grab currently bound pipeline (TODO(john): assert if this isn't valid)
  1156. gsgl_pipeline_t* pip = gs_slot_array_getp(ogl->pipelines, ogl->cache.pipeline.id);
  1157. // Enable vertex attrib pointers based on pipeline layout
  1158. // TODO(john): allow user to specify offset and stride for layout decl
  1159. uint32_t total_size = gsgl_calculate_vertex_size_in_bytes(pip->layout, gs_dyn_array_size(pip->layout));
  1160. for (uint32_t i = 0; i < gs_dyn_array_size(pip->layout); ++i)
  1161. {
  1162. gs_graphics_vertex_attribute_type type = pip->layout[i];
  1163. size_t byte_offset = gsgl_get_vertex_attr_byte_offest(pip->layout, i);
  1164. switch (type)
  1165. {
  1166. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT4: glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, total_size, gs_int_2_voidp(byte_offset)); break;
  1167. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT3: glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, total_size, gs_int_2_voidp(byte_offset)); break;
  1168. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT2: glVertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, total_size, gs_int_2_voidp(byte_offset)); break;
  1169. case GS_GRAPHICS_VERTEX_ATTRIBUTE_FLOAT: glVertexAttribPointer(i, 1, GL_FLOAT, GL_FALSE, total_size, gs_int_2_voidp(byte_offset)); break;
  1170. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT4: glVertexAttribIPointer(i, 4, GL_UNSIGNED_INT, total_size, gs_int_2_voidp(byte_offset)); break;
  1171. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT3: glVertexAttribIPointer(i, 3, GL_UNSIGNED_INT, total_size, gs_int_2_voidp(byte_offset)); break;
  1172. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT2: glVertexAttribIPointer(i, 2, GL_UNSIGNED_INT, total_size, gs_int_2_voidp(byte_offset)); break;
  1173. case GS_GRAPHICS_VERTEX_ATTRIBUTE_UINT: glVertexAttribIPointer(i, 1, GL_UNSIGNED_INT, total_size, gs_int_2_voidp(byte_offset)); break;
  1174. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE: glVertexAttribPointer(i, 1, GL_UNSIGNED_BYTE, GL_TRUE, total_size, gs_int_2_voidp(byte_offset)); break;
  1175. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE2: glVertexAttribPointer(i, 2, GL_UNSIGNED_BYTE, GL_TRUE, total_size, gs_int_2_voidp(byte_offset)); break;
  1176. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE3: glVertexAttribPointer(i, 3, GL_UNSIGNED_BYTE, GL_TRUE, total_size, gs_int_2_voidp(byte_offset)); break;
  1177. case GS_GRAPHICS_VERTEX_ATTRIBUTE_BYTE4: glVertexAttribPointer(i, 4, GL_UNSIGNED_BYTE, GL_TRUE, total_size, gs_int_2_voidp(byte_offset)); break;
  1178. default:
  1179. {
  1180. // Shouldn't get here
  1181. gs_assert(false);
  1182. } break;
  1183. }
  1184. // Enable the vertex attribute pointer
  1185. glEnableVertexAttribArray(i);
  1186. }
  1187. // Draw based on bound primitive type in raster
  1188. gs_byte_buffer_readc(&cb->commands, uint32_t, start);
  1189. gs_byte_buffer_readc(&cb->commands, uint32_t, count);
  1190. uint32_t prim = gsgl_primitive_to_gl_primitive(pip->raster.primitive);
  1191. uint32_t itype = gsgl_index_buffer_size_to_gl_index_type(pip->raster.index_buffer_element_size);
  1192. /* Draw */
  1193. if (ogl->cache.ibo)
  1194. {
  1195. glDrawElements(prim, count, itype, gs_int_2_voidp(start));
  1196. }
  1197. else
  1198. {
  1199. glDrawArrays(prim, start, count);
  1200. }
  1201. } break;
  1202. case GS_OPENGL_OP_REQUEST_BUFFER_UPDATE:
  1203. {
  1204. gsgl_data_t* ogl = (gsgl_data_t*)gs_engine_subsystem(graphics)->user_data;
  1205. // Read handle id
  1206. gs_byte_buffer_readc(&cb->commands, uint32_t, id);
  1207. // Read type
  1208. gs_byte_buffer_readc(&cb->commands, gs_graphics_buffer_type, type);
  1209. // Read usage
  1210. gs_byte_buffer_readc(&cb->commands, gs_graphics_buffer_usage_type, usage);
  1211. // Read data size
  1212. gs_byte_buffer_readc(&cb->commands, size_t, sz);
  1213. switch (type)
  1214. {
  1215. // Vertex Buffer
  1216. default:
  1217. case GS_GRAPHICS_BUFFER_VERTEX:
  1218. {
  1219. gsgl_buffer_t buffer = gs_slot_array_get(ogl->vertex_buffers, id);
  1220. glBindBuffer(GL_ARRAY_BUFFER, buffer);
  1221. glBufferData(GL_ARRAY_BUFFER, sz, (u8*)(cb->commands.data + cb->commands.position), gsgl_buffer_usage_to_gl_enum(usage));
  1222. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1223. } break;
  1224. }
  1225. // Advance past data
  1226. gs_byte_buffer_advance_position(&cb->commands, sz);
  1227. } break;
  1228. default:
  1229. {
  1230. // Op code not supported yet!
  1231. gs_println("Op code not supported yet: %zu", (uint32_t)op_code);
  1232. gs_assert(false);
  1233. }
  1234. }
  1235. }
  1236. // Clear byte buffer of commands
  1237. gs_byte_buffer_clear(&cb->commands);
  1238. // Set num commands to 0
  1239. cb->num_commands = 0;
  1240. }
  1241. void gs_graphics_submit_frame()
  1242. {
  1243. }
  1244. #endif // GS_GRAPHICS_IMPL_OPENGL
  1245. #endif // __GS_GRAPHICS_IMPL_H__