💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

332 lines
7.9 KiB

  1. /*
  2. * Copyright (C) 2023 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <engine/gl/vertex-array.hpp>
  20. #include <engine/gl/opengl/gl-format-lut.hpp>
  21. #include <glad/gl.h>
  22. #include <stdexcept>
  23. namespace {
  24. // 0 = unscaled, 1 = normalized, 2 = scaled
  25. static constexpr std::uint8_t format_scale_lut[] =
  26. {
  27. 0, // undefined
  28. 1, // r4g4_unorm_pack8
  29. 1, // r4g4b4a4_unorm_pack16
  30. 1, // b4g4r4a4_unorm_pack16
  31. 1, // r5g6b5_unorm_pack16
  32. 1, // b5g6r5_unorm_pack16
  33. 1, // r5g5b5a1_unorm_pack16
  34. 1, // b5g5r5a1_unorm_pack16
  35. 1, // a1r5g5b5_unorm_pack16
  36. 1, // r8_unorm
  37. 1, // r8_snorm
  38. 2, // r8_uscaled
  39. 2, // r8_sscaled
  40. 0, // r8_uint
  41. 0, // r8_sint
  42. 0, // r8_srgb
  43. 1, // r8g8_unorm
  44. 1, // r8g8_snorm
  45. 2, // r8g8_uscaled
  46. 2, // r8g8_sscaled
  47. 0, // r8g8_uint
  48. 0, // r8g8_sint
  49. 0, // r8g8_srgb
  50. 1, // r8g8b8_unorm
  51. 1, // r8g8b8_snorm
  52. 2, // r8g8b8_uscaled
  53. 2, // r8g8b8_sscaled
  54. 0, // r8g8b8_uint
  55. 0, // r8g8b8_sint
  56. 0, // r8g8b8_srgb
  57. 1, // b8g8r8_unorm
  58. 1, // b8g8r8_snorm
  59. 2, // b8g8r8_uscaled
  60. 2, // b8g8r8_sscaled
  61. 0, // b8g8r8_uint
  62. 0, // b8g8r8_sint
  63. 0, // b8g8r8_srgb
  64. 1, // r8g8b8a8_unorm
  65. 1, // r8g8b8a8_snorm
  66. 2, // r8g8b8a8_uscaled
  67. 2, // r8g8b8a8_sscaled
  68. 0, // r8g8b8a8_uint
  69. 0, // r8g8b8a8_sint
  70. 0, // r8g8b8a8_srgb
  71. 1, // b8g8r8a8_unorm
  72. 1, // b8g8r8a8_snorm
  73. 2, // b8g8r8a8_uscaled
  74. 2, // b8g8r8a8_sscaled
  75. 0, // b8g8r8a8_uint
  76. 0, // b8g8r8a8_sint
  77. 0, // b8g8r8a8_srgb
  78. 1, // a8b8g8r8_unorm_pack32
  79. 1, // a8b8g8r8_snorm_pack32
  80. 2, // a8b8g8r8_uscaled_pack32
  81. 2, // a8b8g8r8_sscaled_pack32
  82. 0, // a8b8g8r8_uint_pack32
  83. 0, // a8b8g8r8_sint_pack32
  84. 0, // a8b8g8r8_srgb_pack32
  85. 1, // a2r10g10b10_unorm_pack32
  86. 1, // a2r10g10b10_snorm_pack32
  87. 2, // a2r10g10b10_uscaled_pack32
  88. 2, // a2r10g10b10_sscaled_pack32
  89. 0, // a2r10g10b10_uint_pack32
  90. 0, // a2r10g10b10_sint_pack32
  91. 1, // a2b10g10r10_unorm_pack32
  92. 1, // a2b10g10r10_snorm_pack32
  93. 2, // a2b10g10r10_uscaled_pack32
  94. 2, // a2b10g10r10_sscaled_pack32
  95. 0, // a2b10g10r10_uint_pack32
  96. 0, // a2b10g10r10_sint_pack32
  97. 1, // r16_unorm
  98. 1, // r16_snorm
  99. 2, // r16_uscaled
  100. 2, // r16_sscaled
  101. 0, // r16_uint
  102. 0, // r16_sint
  103. 0, // r16_sfloat
  104. 1, // r16g16_unorm
  105. 1, // r16g16_snorm
  106. 2, // r16g16_uscaled
  107. 2, // r16g16_sscaled
  108. 0, // r16g16_uint
  109. 0, // r16g16_sint
  110. 0, // r16g16_sfloat
  111. 1, // r16g16b16_unorm
  112. 1, // r16g16b16_snorm
  113. 2, // r16g16b16_uscaled
  114. 2, // r16g16b16_sscaled
  115. 0, // r16g16b16_uint
  116. 0, // r16g16b16_sint
  117. 0, // r16g16b16_sfloat
  118. 1, // r16g16b16a16_unorm
  119. 1, // r16g16b16a16_snorm
  120. 2, // r16g16b16a16_uscaled
  121. 2, // r16g16b16a16_sscaled
  122. 0, // r16g16b16a16_uint
  123. 0, // r16g16b16a16_sint
  124. 0, // r16g16b16a16_sfloat
  125. 0, // r32_uint
  126. 0, // r32_sint
  127. 0, // r32_sfloat
  128. 0, // r32g32_uint
  129. 0, // r32g32_sint
  130. 0, // r32g32_sfloat
  131. 0, // r32g32b32_uint
  132. 0, // r32g32b32_sint
  133. 0, // r32g32b32_sfloat
  134. 0, // r32g32b32a32_uint
  135. 0, // r32g32b32a32_sint
  136. 0, // r32g32b32a32_sfloat
  137. 0, // r64_uint
  138. 0, // r64_sint
  139. 0, // r64_sfloat
  140. 0, // r64g64_uint
  141. 0, // r64g64_sint
  142. 0, // r64g64_sfloat
  143. 0, // r64g64b64_uint
  144. 0, // r64g64b64_sint
  145. 0, // r64g64b64_sfloat
  146. 0, // r64g64b64a64_uint
  147. 0, // r64g64b64a64_sint
  148. 0, // r64g64b64a64_sfloat
  149. 0, // b10g11r11_ufloat_pack32
  150. 0, // e5b9g9r9_ufloat_pack32
  151. 1, // d16_unorm
  152. 1, // x8_d24_unorm_pack32
  153. 0, // d32_sfloat
  154. 0, // s8_uint
  155. 1, // d16_unorm_s8_uint
  156. 1, // d24_unorm_s8_uint
  157. 0, // d32_sfloat_s8_uint
  158. 1, // bc1_rgb_unorm_block,
  159. 0, // bc1_rgb_srgb_block,
  160. 1, // bc1_rgba_unorm_block,
  161. 0, // bc1_rgba_srgb_block,
  162. 1, // bc2_unorm_block,
  163. 0, // bc2_srgb_block,
  164. 1, // bc3_unorm_block,
  165. 0, // bc3_srgb_block,
  166. 1, // bc4_unorm_block,
  167. 1, // bc4_snorm_block,
  168. 1, // bc5_unorm_block,
  169. 1, // bc5_snorm_block,
  170. 2, // bc6h_ufloat_block,
  171. 2, // bc6h_sfloat_block,
  172. 1, // bc7_unorm_block,
  173. 0, // bc7_srgb_block,
  174. 1, // etc2_r8g8b8_unorm_block,
  175. 0, // etc2_r8g8b8_srgb_block,
  176. 1, // etc2_r8g8b8a1_unorm_block,
  177. 0, // etc2_r8g8b8a1_srgb_block,
  178. 1, // etc2_r8g8b8a8_unorm_block,
  179. 0, // etc2_r8g8b8a8_srgb_block,
  180. 1, // eac_r11_unorm_block,
  181. 1, // eac_r11_snorm_block,
  182. 1, // eac_r11g11_unorm_block,
  183. 1, // eac_r11g11_snorm_block,
  184. 1, // astc_4x4_unorm_block,
  185. 0, // astc_4x4_srgb_block,
  186. 1, // astc_5x4_unorm_block,
  187. 0, // astc_5x4_srgb_block,
  188. 1, // astc_5x5_unorm_block,
  189. 0, // astc_5x5_srgb_block,
  190. 1, // astc_6x5_unorm_block,
  191. 0, // astc_6x5_srgb_block,
  192. 1, // astc_6x6_unorm_block,
  193. 0, // astc_6x6_srgb_block,
  194. 1, // astc_8x5_unorm_block,
  195. 0, // astc_8x5_srgb_block,
  196. 1, // astc_8x6_unorm_block,
  197. 0, // astc_8x6_srgb_block,
  198. 1, // astc_8x8_unorm_block,
  199. 0, // astc_8x8_srgb_block,
  200. 1, // astc_10x5_unorm_block,
  201. 0, // astc_10x5_srgb_block,
  202. 1, // astc_10x6_unorm_block,
  203. 0, // astc_10x6_srgb_block,
  204. 1, // astc_10x8_unorm_block,
  205. 0, // astc_10x8_srgb_block,
  206. 1, // astc_10x10_unorm_block,
  207. 0, // astc_10x10_srgb_block,
  208. 1, // astc_12x10_unorm_block,
  209. 0, // astc_12x10_srgb_block,
  210. 1, // astc_12x12_unorm_block,
  211. 0, // astc_12x12_srgb_block
  212. };
  213. }
  214. namespace gl {
  215. vertex_array::vertex_array(std::span<const vertex_input_attribute> attributes)
  216. {
  217. m_attributes.assign(attributes.begin(), attributes.end());
  218. glCreateVertexArrays(1, &m_gl_named_array);
  219. for (const auto& attribute: m_attributes)
  220. {
  221. // Enable attribute
  222. glEnableVertexArrayAttrib(m_gl_named_array, static_cast<GLuint>(attribute.location));
  223. // Set attribute vertex binding index
  224. glVertexArrayAttribBinding
  225. (
  226. m_gl_named_array,
  227. static_cast<GLuint>(attribute.location),
  228. static_cast<GLuint>(attribute.binding)
  229. );
  230. const auto format_index = std::to_underlying(attribute.format);
  231. const auto gl_base_format = gl_format_lut[format_index][1];
  232. const auto gl_type = gl_format_lut[format_index][2];
  233. const auto format_scale = format_scale_lut[format_index];
  234. // Determine number of values per vertex
  235. GLint gl_size;
  236. switch (gl_base_format)
  237. {
  238. case GL_RED:
  239. case GL_RED_INTEGER:
  240. case GL_DEPTH_COMPONENT:
  241. case GL_STENCIL_INDEX:
  242. gl_size = 1;
  243. break;
  244. case GL_RG:
  245. case GL_RG_INTEGER:
  246. case GL_DEPTH_STENCIL:
  247. gl_size = 2;
  248. break;
  249. case GL_BGR:
  250. case GL_BGR_INTEGER:
  251. case GL_RGB:
  252. case GL_RGB_INTEGER:
  253. gl_size = 3;
  254. break;
  255. case GL_BGRA:
  256. case GL_BGRA_INTEGER:
  257. case GL_RGBA:
  258. case GL_RGBA_INTEGER:
  259. gl_size = 4;
  260. break;
  261. default:
  262. gl_size = 0;
  263. break;
  264. }
  265. if (gl_size == 0 || gl_type == 0)
  266. {
  267. throw std::invalid_argument("Vertex input attribute has unsupported format.");
  268. }
  269. if (format_scale > 0 || gl_type == GL_FLOAT || gl_type == GL_HALF_FLOAT)
  270. {
  271. glVertexArrayAttribFormat
  272. (
  273. m_gl_named_array,
  274. static_cast<GLuint>(attribute.location),
  275. gl_size,
  276. gl_type,
  277. (format_scale == 1),
  278. static_cast<GLuint>(attribute.offset)
  279. );
  280. }
  281. else if (gl_type == GL_DOUBLE)
  282. {
  283. glVertexArrayAttribLFormat
  284. (
  285. m_gl_named_array,
  286. static_cast<GLuint>(attribute.location),
  287. gl_size,
  288. gl_type,
  289. static_cast<GLuint>(attribute.offset)
  290. );
  291. }
  292. else
  293. {
  294. glVertexArrayAttribIFormat
  295. (
  296. m_gl_named_array,
  297. static_cast<GLuint>(attribute.location),
  298. gl_size,
  299. gl_type,
  300. static_cast<GLuint>(attribute.offset)
  301. );
  302. }
  303. }
  304. }
  305. vertex_array::vertex_array()
  306. {
  307. glCreateVertexArrays(1, &m_gl_named_array);
  308. }
  309. vertex_array::~vertex_array()
  310. {
  311. glDeleteVertexArrays(1, &m_gl_named_array);
  312. }
  313. } // namespace gl