💿🐜 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.

1494 lines
46 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/pipeline.hpp>
  20. #include <engine/gl/clear-bits.hpp>
  21. #include <engine/gl/stencil-face-bits.hpp>
  22. #include <engine/gl/color-component-bits.hpp>
  23. #include <engine/debug/log.hpp>
  24. #include <glad/gl.h>
  25. #include <algorithm>
  26. #include <stdexcept>
  27. #include <bit>
  28. namespace {
  29. static constexpr GLenum stencil_face_lut[] =
  30. {
  31. GL_NONE, // 0
  32. GL_FRONT, // stencil_face_front_bit
  33. GL_BACK, // stencil_face_back_bit
  34. GL_FRONT_AND_BACK // stencil_face_front_and_back
  35. };
  36. static constexpr GLenum stencil_op_lut[] =
  37. {
  38. GL_KEEP, // stencil_op::keep
  39. GL_ZERO, // stencil_op::zero
  40. GL_REPLACE, // stencil_op::replace
  41. GL_INCR, // stencil_op::increment_and_clamp
  42. GL_DECR, // stencil_op::decrement_and_clamp
  43. GL_INVERT, // stencil_op::invert
  44. GL_INCR_WRAP, // stencil_op::increment_and_wrap
  45. GL_DECR_WRAP // stencil_op::decrement_and_wrap
  46. };
  47. static constexpr GLenum compare_op_lut[] =
  48. {
  49. GL_NEVER, // compare_op::never
  50. GL_LESS, // compare_op::less
  51. GL_EQUAL, // compare_op::equal
  52. GL_LEQUAL, // compare_op::less_or_equal
  53. GL_GREATER, // compare_op::greater
  54. GL_NOTEQUAL, // compare_op::not_equal
  55. GL_GEQUAL, // compare_op::greater_or_equal
  56. GL_ALWAYS // compare_op::always
  57. };
  58. static constexpr GLenum provoking_vertex_mode_lut[] =
  59. {
  60. GL_FIRST_VERTEX_CONVENTION, // provoking_vertex_mode::first
  61. GL_LAST_VERTEX_CONVENTION // provoking_vertex_mode::last
  62. };
  63. static constexpr GLenum primitive_topology_lut[] =
  64. {
  65. GL_POINTS, // primitive_topology::point_list
  66. GL_LINES, // primitive_topology::line_list
  67. GL_LINE_STRIP, // primitive_topology::line_strip,
  68. GL_TRIANGLES, // primitive_topology::triangle_list
  69. GL_TRIANGLE_STRIP, // primitive_topology::triangle_strip
  70. GL_TRIANGLE_FAN, // primitive_topology::triangle_fan
  71. GL_LINES_ADJACENCY, // primitive_topology::line_list_with_adjacency
  72. GL_LINE_STRIP_ADJACENCY, // primitive_topology::line_strip_with_adjacency
  73. GL_TRIANGLES_ADJACENCY, // primitive_topology::triangle_list_with_adjacency
  74. GL_TRIANGLE_STRIP_ADJACENCY, // primitive_topology::triangle_strip_with_adjacency
  75. GL_PATCHES // primitive_topology::patch_list
  76. };
  77. static constexpr GLenum logic_op_lut[] =
  78. {
  79. GL_CLEAR , // logic_op::bitwise_clear
  80. GL_AND , // logic_op::bitwise_and
  81. GL_AND_REVERSE , // logic_op::bitwise_and_reverse
  82. GL_COPY , // logic_op::bitwise_copy
  83. GL_AND_INVERTED , // logic_op::bitwise_and_inverted
  84. GL_NOOP , // logic_op::bitwise_no_op
  85. GL_XOR , // logic_op::bitwise_xor
  86. GL_OR , // logic_op::bitwise_or
  87. GL_NOR , // logic_op::bitwise_nor
  88. GL_EQUIV , // logic_op::bitwise_equivalent
  89. GL_INVERT , // logic_op::bitwise_invert
  90. GL_OR_REVERSE , // logic_op::bitwise_or_reverse
  91. GL_COPY_INVERTED, // logic_op::bitwise_copy_inverted
  92. GL_OR_INVERTED , // logic_op::bitwise_or_inverted
  93. GL_NAND , // logic_op::bitwise_nand
  94. GL_SET // logic_op::bitwise_set
  95. };
  96. static constexpr GLenum blend_factor_lut[] =
  97. {
  98. GL_ZERO , // blend_factor::zero
  99. GL_ONE , // blend_factor::one
  100. GL_SRC_COLOR , // blend_factor::src_color
  101. GL_ONE_MINUS_SRC_COLOR , // blend_factor::one_minus_src_color
  102. GL_DST_COLOR , // blend_factor::dst_color
  103. GL_ONE_MINUS_DST_COLOR , // blend_factor::one_minus_dst_color
  104. GL_SRC_ALPHA , // blend_factor::src_alpha
  105. GL_ONE_MINUS_SRC_ALPHA , // blend_factor::one_minus_src_alpha
  106. GL_DST_ALPHA , // blend_factor::dst_alpha
  107. GL_ONE_MINUS_DST_ALPHA , // blend_factor::one_minus_dst_alpha
  108. GL_CONSTANT_COLOR , // blend_factor::constant_color
  109. GL_ONE_MINUS_CONSTANT_COLOR, // blend_factor::one_minus_constant_color
  110. GL_CONSTANT_ALPHA , // blend_factor::constant_alpha
  111. GL_ONE_MINUS_CONSTANT_ALPHA, // blend_factor::one_minus_constant_alpha
  112. GL_SRC_ALPHA_SATURATE , // blend_factor::src_alpha_saturate
  113. GL_SRC1_COLOR , // blend_factor::src1_color
  114. GL_ONE_MINUS_SRC1_COLOR , // blend_factor::one_minus_src1_color
  115. GL_SRC1_ALPHA , // blend_factor::src1_alpha
  116. GL_ONE_MINUS_SRC1_ALPHA // blend_factor::one_minus_src1_alpha
  117. };
  118. static constexpr GLenum blend_op_lut[] =
  119. {
  120. GL_FUNC_ADD , // blend_op::add
  121. GL_FUNC_SUBTRACT , // blend_op::subtract
  122. GL_FUNC_REVERSE_SUBTRACT, // blend_op::reverse_subtract
  123. GL_MIN , // blend_op::min
  124. GL_MAX // blend_op::max
  125. };
  126. void gl_debug_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* user_param)
  127. {
  128. const auto src_str = [source]() -> const char*
  129. {
  130. switch (source)
  131. {
  132. case GL_DEBUG_SOURCE_API:
  133. return "API";
  134. case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
  135. return "window system";
  136. case GL_DEBUG_SOURCE_SHADER_COMPILER:
  137. return "shader compiler";
  138. case GL_DEBUG_SOURCE_THIRD_PARTY:
  139. return "third party";
  140. case GL_DEBUG_SOURCE_APPLICATION:
  141. return "application";
  142. case GL_DEBUG_SOURCE_OTHER:
  143. default:
  144. return "other";
  145. }
  146. }();
  147. const auto type_str = [type]() -> const char*
  148. {
  149. switch (type)
  150. {
  151. case GL_DEBUG_TYPE_ERROR:
  152. return "error";
  153. case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
  154. return "deprecated behavior";
  155. case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
  156. return "undefined behavior";
  157. case GL_DEBUG_TYPE_PORTABILITY:
  158. return "portability";
  159. case GL_DEBUG_TYPE_PERFORMANCE:
  160. return "performance";
  161. case GL_DEBUG_TYPE_MARKER:
  162. return "marker";
  163. case GL_DEBUG_TYPE_OTHER:
  164. default:
  165. return "message";
  166. }
  167. }();
  168. const auto severity_str = [severity]() -> const char*
  169. {
  170. switch (severity)
  171. {
  172. case GL_DEBUG_SEVERITY_LOW:
  173. return "low severity";
  174. case GL_DEBUG_SEVERITY_MEDIUM:
  175. return "medium severity";
  176. case GL_DEBUG_SEVERITY_HIGH:
  177. return "high severity";
  178. case GL_DEBUG_SEVERITY_NOTIFICATION:
  179. default:
  180. return "notification";
  181. }
  182. }();
  183. switch (type)
  184. {
  185. case GL_DEBUG_TYPE_ERROR:
  186. {
  187. std::string formatted_message;
  188. std::format_to(std::back_inserter(formatted_message), "OpenGL {} {} ({}) {}: {}", src_str, type_str, severity_str, id, message);
  189. debug::log_fatal("{}", formatted_message);
  190. throw std::runtime_error(formatted_message);
  191. break;
  192. }
  193. case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
  194. case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
  195. debug::log_error("OpenGL {} {} ({}) {}: {}", src_str, type_str, severity_str, id, message);
  196. break;
  197. case GL_DEBUG_TYPE_PORTABILITY:
  198. case GL_DEBUG_TYPE_PERFORMANCE:
  199. debug::log_warning("OpenGL {} {} ({}) {}: {}", src_str, type_str, severity_str, id, message);
  200. break;
  201. case GL_DEBUG_TYPE_MARKER:
  202. case GL_DEBUG_TYPE_OTHER:
  203. default:
  204. debug::log_debug("OpenGL {} {} ({}) {}: {}", src_str, type_str, severity_str, id, message);
  205. break;
  206. }
  207. }
  208. }
  209. namespace gl {
  210. pipeline::pipeline()
  211. {
  212. #if defined(DEBUG)
  213. glEnable(GL_DEBUG_OUTPUT);
  214. glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
  215. glDebugMessageCallback(gl_debug_message_callback, nullptr);
  216. #endif
  217. // Fetch limitations
  218. glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &m_max_sampler_anisotropy);
  219. // Fetch dimensions of default framebuffer
  220. GLint gl_scissor_box[4] = {0, 0, 0, 0};
  221. glGetIntegerv(GL_SCISSOR_BOX, gl_scissor_box);
  222. m_default_framebuffer_dimensions[0] = static_cast<std::uint32_t>(gl_scissor_box[2]);
  223. m_default_framebuffer_dimensions[1] = static_cast<std::uint32_t>(gl_scissor_box[3]);
  224. // Enable seamless cubemap filtering
  225. glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
  226. // Set clip control to lower left, 0 to 1
  227. glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
  228. // Disable multisampling
  229. glDisable(GL_MULTISAMPLE);
  230. // Set byte-alignment for packing and unpacking pixel rows
  231. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  232. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  233. // Fetch pipeline state
  234. fetch_vertex_input_state();
  235. fetch_input_assembly_state();
  236. fetch_viewport_state();
  237. fetch_rasterization_state();
  238. fetch_depth_stencil_state();
  239. fetch_color_blend_state();
  240. fetch_clear_value();
  241. }
  242. // void pipeline::set_vertex_input(std::span<const vertex_input_binding> vertex_bindings, std::span<const vertex_input_attribute> vertex_attributes)
  243. // {
  244. // m_vertex_input_state.vertex_bindings.assign(vertex_bindings.begin(), vertex_bindings.end());
  245. // m_vertex_input_state.vertex_attributes.assign(vertex_attributes.begin(), vertex_attributes.end());
  246. // }
  247. void pipeline::bind_framebuffer(const gl::framebuffer* framebuffer)
  248. {
  249. if (m_framebuffer != framebuffer)
  250. {
  251. m_framebuffer = framebuffer;
  252. if (m_framebuffer)
  253. {
  254. glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer->m_gl_named_framebuffer);
  255. }
  256. else
  257. {
  258. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  259. }
  260. }
  261. }
  262. void pipeline::bind_shader_program(const gl::shader_program* shader_program)
  263. {
  264. if (m_shader_program != shader_program)
  265. {
  266. m_shader_program = shader_program;
  267. if (m_shader_program)
  268. {
  269. glUseProgram(m_shader_program->gl_program_id);
  270. }
  271. else
  272. {
  273. glUseProgram(0);
  274. }
  275. }
  276. }
  277. void pipeline::bind_vertex_array(const vertex_array* array)
  278. {
  279. if (m_vertex_array != array)
  280. {
  281. m_vertex_array = array;
  282. if (m_vertex_array)
  283. {
  284. glBindVertexArray(m_vertex_array->m_gl_named_array);
  285. }
  286. else
  287. {
  288. glBindVertexArray(0);
  289. }
  290. }
  291. }
  292. void pipeline::bind_vertex_buffers(std::uint32_t first_binding, std::span<const vertex_buffer* const> buffers, std::span<const std::size_t> offsets, std::span<const std::size_t> strides)
  293. {
  294. if (!m_vertex_array)
  295. {
  296. throw std::runtime_error("Failed to bind vertex buffer: no vertex array bound.");
  297. }
  298. if (offsets.size() < buffers.size())
  299. {
  300. throw std::out_of_range("Vertex binding offset out of range.");
  301. }
  302. if (strides.size() < buffers.size())
  303. {
  304. throw std::out_of_range("Vertex binding stride out of range.");
  305. }
  306. for (std::size_t i = 0; i < buffers.size(); ++i)
  307. {
  308. glVertexArrayVertexBuffer
  309. (
  310. m_vertex_array->m_gl_named_array,
  311. static_cast<GLuint>(first_binding + i),
  312. buffers[i]->m_gl_named_buffer,
  313. static_cast<GLintptr>(offsets[i]),
  314. static_cast<GLsizei>(strides[i])
  315. );
  316. }
  317. }
  318. void pipeline::set_primitive_topology(primitive_topology topology)
  319. {
  320. if (m_input_assembly_state.topology != topology)
  321. {
  322. m_input_assembly_state.topology = topology;
  323. }
  324. }
  325. void pipeline::set_primitive_restart_enabled(bool enabled)
  326. {
  327. if (m_input_assembly_state.primitive_restart_enabled != enabled)
  328. {
  329. if (enabled)
  330. {
  331. glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
  332. }
  333. else
  334. {
  335. glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
  336. }
  337. m_input_assembly_state.primitive_restart_enabled = enabled;
  338. }
  339. }
  340. void pipeline::set_viewport(std::uint32_t first_viewport, std::span<const gl::viewport> viewports)
  341. {
  342. // Bounds check
  343. if (first_viewport + viewports.size() > m_max_viewports)
  344. {
  345. throw std::out_of_range("Viewport index out of range.");
  346. }
  347. // Ignore empty commands
  348. if (!viewports.size())
  349. {
  350. return;
  351. }
  352. const auto& active_viewport = m_viewport_state.viewports.front();
  353. const auto& viewport = viewports.front();
  354. // Update viewport position and dimensions
  355. if (active_viewport.width != viewport.width ||
  356. active_viewport.height != viewport.height ||
  357. active_viewport.x != viewport.x ||
  358. active_viewport.y != viewport.y)
  359. {
  360. glViewport
  361. (
  362. static_cast<GLint>(viewport.x),
  363. static_cast<GLint>(viewport.y),
  364. std::max(0, static_cast<GLsizei>(viewport.width)),
  365. std::max(0, static_cast<GLsizei>(viewport.height))
  366. );
  367. }
  368. // Update viewport depth range
  369. if (active_viewport.min_depth != viewport.min_depth ||
  370. active_viewport.max_depth != viewport.max_depth)
  371. {
  372. glDepthRange(viewport.min_depth, viewport.max_depth);
  373. }
  374. // Update viewport state
  375. std::copy(viewports.begin(), viewports.end(), m_viewport_state.viewports.begin() + first_viewport);
  376. }
  377. void pipeline::set_scissor(std::uint32_t first_scissor, std::span<const gl::scissor_region> scissors)
  378. {
  379. // Bounds check
  380. if (first_scissor + scissors.size() > m_max_viewports)
  381. {
  382. throw std::out_of_range("Scissor region index out of range.");
  383. }
  384. // Ignore empty commands
  385. if (scissors.empty())
  386. {
  387. return;
  388. }
  389. const auto& active_scissor = m_viewport_state.scissors.front();
  390. const auto& scissor = scissors.front();
  391. // Update scissor region
  392. if (active_scissor.width != scissor.width ||
  393. active_scissor.height != scissor.height ||
  394. active_scissor.x != scissor.x ||
  395. active_scissor.y != scissor.y)
  396. {
  397. glScissor
  398. (
  399. static_cast<GLint>(scissor.x),
  400. static_cast<GLint>(scissor.y),
  401. std::max(0, static_cast<GLsizei>(scissor.width)),
  402. std::max(0, static_cast<GLsizei>(scissor.height))
  403. );
  404. }
  405. // Update viewport state
  406. std::copy(scissors.begin(), scissors.end(), m_viewport_state.scissors.begin() + first_scissor);
  407. }
  408. void pipeline::set_rasterizer_discard_enabled(bool enabled)
  409. {
  410. if (m_rasterization_state.rasterizer_discard_enabled != enabled)
  411. {
  412. if (enabled)
  413. {
  414. glEnable(GL_RASTERIZER_DISCARD);
  415. }
  416. else
  417. {
  418. glDisable(GL_RASTERIZER_DISCARD);
  419. }
  420. m_rasterization_state.rasterizer_discard_enabled = enabled;
  421. }
  422. }
  423. void pipeline::set_fill_mode(fill_mode mode)
  424. {
  425. if (m_rasterization_state.fill_mode != mode)
  426. {
  427. switch (mode)
  428. {
  429. case fill_mode::fill:
  430. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  431. break;
  432. case fill_mode::line:
  433. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  434. break;
  435. case fill_mode::point:
  436. glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  437. break;
  438. default:
  439. break;
  440. }
  441. m_rasterization_state.fill_mode = mode;
  442. }
  443. }
  444. void pipeline::set_cull_mode(cull_mode mode)
  445. {
  446. if (m_rasterization_state.cull_mode != mode)
  447. {
  448. if (mode == cull_mode::none)
  449. {
  450. glDisable(GL_CULL_FACE);
  451. }
  452. else
  453. {
  454. if (m_rasterization_state.cull_mode == cull_mode::none)
  455. {
  456. glEnable(GL_CULL_FACE);
  457. }
  458. switch (mode)
  459. {
  460. case cull_mode::back:
  461. glCullFace(GL_BACK);
  462. break;
  463. case cull_mode::front:
  464. glCullFace(GL_FRONT);
  465. break;
  466. case cull_mode::front_and_back:
  467. glCullFace(GL_FRONT_AND_BACK);
  468. break;
  469. default:
  470. break;
  471. }
  472. }
  473. m_rasterization_state.cull_mode = mode;
  474. }
  475. }
  476. void pipeline::set_front_face(front_face face)
  477. {
  478. if (m_rasterization_state.front_face != face)
  479. {
  480. glFrontFace(face == front_face::counter_clockwise ? GL_CCW : GL_CW);
  481. m_rasterization_state.front_face = face;
  482. }
  483. }
  484. void pipeline::set_depth_bias_enabled(bool enabled)
  485. {
  486. if (m_rasterization_state.depth_bias_enabled != enabled)
  487. {
  488. if (enabled)
  489. {
  490. glEnable(GL_POLYGON_OFFSET_FILL);
  491. glEnable(GL_POLYGON_OFFSET_LINE);
  492. glEnable(GL_POLYGON_OFFSET_POINT);
  493. }
  494. else
  495. {
  496. glDisable(GL_POLYGON_OFFSET_FILL);
  497. glDisable(GL_POLYGON_OFFSET_LINE);
  498. glDisable(GL_POLYGON_OFFSET_POINT);
  499. }
  500. m_rasterization_state.depth_bias_enabled = enabled;
  501. }
  502. }
  503. void pipeline::set_depth_bias_factors(float constant_factor, float slope_factor)
  504. {
  505. // Update depth bias factors
  506. if (m_rasterization_state.depth_bias_constant_factor != constant_factor ||
  507. m_rasterization_state.depth_bias_slope_factor != slope_factor)
  508. {
  509. glPolygonOffset(slope_factor, constant_factor);
  510. m_rasterization_state.depth_bias_constant_factor = constant_factor;
  511. m_rasterization_state.depth_bias_slope_factor = slope_factor;
  512. }
  513. }
  514. void pipeline::set_depth_clamp_enabled(bool enabled)
  515. {
  516. if (m_rasterization_state.depth_clamp_enabled != enabled)
  517. {
  518. if (enabled)
  519. {
  520. glEnable(GL_DEPTH_CLAMP);
  521. }
  522. else
  523. {
  524. glDisable(GL_DEPTH_CLAMP);
  525. }
  526. m_rasterization_state.depth_clamp_enabled = enabled;
  527. }
  528. }
  529. void pipeline::set_scissor_test_enabled(bool enabled)
  530. {
  531. if (m_rasterization_state.scissor_test_enabled != enabled)
  532. {
  533. if (enabled)
  534. {
  535. glEnable(GL_SCISSOR_TEST);
  536. }
  537. else
  538. {
  539. glDisable(GL_SCISSOR_TEST);
  540. }
  541. m_rasterization_state.scissor_test_enabled = enabled;
  542. }
  543. }
  544. void pipeline::set_provoking_vertex_mode(provoking_vertex_mode mode)
  545. {
  546. if (m_rasterization_state.provoking_vertex_mode != mode)
  547. {
  548. const auto gl_provoking_vertex_mode = provoking_vertex_mode_lut[std::to_underlying(mode)];
  549. glProvokingVertex(gl_provoking_vertex_mode);
  550. m_rasterization_state.provoking_vertex_mode = mode;
  551. }
  552. }
  553. void pipeline::set_point_size(float size)
  554. {
  555. if (m_rasterization_state.point_size != size)
  556. {
  557. glPointSize(size);
  558. m_rasterization_state.point_size = size;
  559. }
  560. }
  561. void pipeline::set_line_width(float width)
  562. {
  563. if (m_rasterization_state.line_width != width)
  564. {
  565. glLineWidth(width);
  566. m_rasterization_state.line_width = width;
  567. }
  568. }
  569. void pipeline::set_depth_test_enabled(bool enabled)
  570. {
  571. if (m_depth_stencil_state.depth_test_enabled != enabled)
  572. {
  573. m_depth_stencil_state.depth_test_enabled = enabled;
  574. if (enabled)
  575. {
  576. glEnable(GL_DEPTH_TEST);
  577. }
  578. else
  579. {
  580. glDisable(GL_DEPTH_TEST);
  581. }
  582. }
  583. }
  584. void pipeline::set_depth_write_enabled(bool enabled)
  585. {
  586. if (m_depth_stencil_state.depth_write_enabled != enabled)
  587. {
  588. m_depth_stencil_state.depth_write_enabled = enabled;
  589. glDepthMask(enabled);
  590. }
  591. }
  592. void pipeline::set_depth_compare_op(gl::compare_op compare_op)
  593. {
  594. if (m_depth_stencil_state.depth_compare_op != compare_op)
  595. {
  596. m_depth_stencil_state.depth_compare_op = compare_op;
  597. const auto gl_compare_op = compare_op_lut[std::to_underlying(compare_op)];
  598. glDepthFunc(gl_compare_op);
  599. }
  600. }
  601. void pipeline::set_stencil_test_enabled(bool enabled)
  602. {
  603. if (m_depth_stencil_state.stencil_test_enabled != enabled)
  604. {
  605. m_depth_stencil_state.stencil_test_enabled = enabled;
  606. if (enabled)
  607. {
  608. glEnable(GL_STENCIL_TEST);
  609. }
  610. else
  611. {
  612. glDisable(GL_STENCIL_TEST);
  613. }
  614. }
  615. }
  616. void pipeline::set_stencil_op(std::uint8_t face_mask, stencil_op fail_op, stencil_op pass_op, stencil_op depth_fail_op, gl::compare_op compare_op)
  617. {
  618. bool stencil_op_updated = false;
  619. bool compare_op_updated = false;
  620. if (face_mask & stencil_face_front_bit)
  621. {
  622. if (m_depth_stencil_state.stencil_front.fail_op != fail_op ||
  623. m_depth_stencil_state.stencil_front.pass_op != pass_op ||
  624. m_depth_stencil_state.stencil_front.depth_fail_op != depth_fail_op)
  625. {
  626. m_depth_stencil_state.stencil_front.fail_op = fail_op;
  627. m_depth_stencil_state.stencil_front.pass_op = pass_op;
  628. m_depth_stencil_state.stencil_front.depth_fail_op = depth_fail_op;
  629. stencil_op_updated = true;
  630. }
  631. if (m_depth_stencil_state.stencil_front.compare_op != compare_op)
  632. {
  633. m_depth_stencil_state.stencil_front.compare_op = compare_op;
  634. compare_op_updated = true;
  635. }
  636. }
  637. if (face_mask & stencil_face_back_bit)
  638. {
  639. if (m_depth_stencil_state.stencil_back.fail_op != fail_op ||
  640. m_depth_stencil_state.stencil_back.pass_op != pass_op ||
  641. m_depth_stencil_state.stencil_back.depth_fail_op != depth_fail_op)
  642. {
  643. m_depth_stencil_state.stencil_back.fail_op = fail_op;
  644. m_depth_stencil_state.stencil_back.pass_op = pass_op;
  645. m_depth_stencil_state.stencil_back.depth_fail_op = depth_fail_op;
  646. stencil_op_updated = true;
  647. }
  648. if (m_depth_stencil_state.stencil_back.compare_op != compare_op)
  649. {
  650. m_depth_stencil_state.stencil_back.compare_op = compare_op;
  651. compare_op_updated = true;
  652. }
  653. }
  654. if (stencil_op_updated || compare_op_updated)
  655. {
  656. const auto gl_face = stencil_face_lut[face_mask];
  657. if (stencil_op_updated)
  658. {
  659. const auto gl_fail_op = stencil_op_lut[std::to_underlying(fail_op)];
  660. const auto gl_pass_op = stencil_op_lut[std::to_underlying(pass_op)];
  661. const auto gl_depth_fail_op = stencil_op_lut[std::to_underlying(depth_fail_op)];
  662. glStencilOpSeparate(gl_face, gl_fail_op, gl_depth_fail_op, gl_pass_op);
  663. }
  664. if (compare_op_updated)
  665. {
  666. const auto gl_compare_op = compare_op_lut[std::to_underlying(compare_op)];
  667. if (face_mask == stencil_face_front_and_back)
  668. {
  669. if (m_depth_stencil_state.stencil_front.reference == m_depth_stencil_state.stencil_back.reference &&
  670. m_depth_stencil_state.stencil_front.compare_mask == m_depth_stencil_state.stencil_back.compare_mask)
  671. {
  672. glStencilFuncSeparate(gl_face, gl_compare_op, std::bit_cast<GLint>(m_depth_stencil_state.stencil_front.reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_front.compare_mask));
  673. }
  674. else
  675. {
  676. glStencilFuncSeparate(GL_FRONT, gl_compare_op, std::bit_cast<GLint>(m_depth_stencil_state.stencil_front.reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_front.compare_mask));
  677. glStencilFuncSeparate(GL_BACK, gl_compare_op, std::bit_cast<GLint>(m_depth_stencil_state.stencil_back.reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_back.compare_mask));
  678. }
  679. }
  680. else if (face_mask == stencil_face_front_bit)
  681. {
  682. glStencilFuncSeparate(gl_face, gl_compare_op, std::bit_cast<GLint>(m_depth_stencil_state.stencil_front.reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_front.compare_mask));
  683. }
  684. else
  685. {
  686. glStencilFuncSeparate(gl_face, gl_compare_op, std::bit_cast<GLint>(m_depth_stencil_state.stencil_back.reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_back.compare_mask));
  687. }
  688. }
  689. }
  690. }
  691. void pipeline::set_stencil_compare_mask(std::uint8_t face_mask, std::uint32_t compare_mask)
  692. {
  693. bool compare_mask_updated = false;
  694. if (face_mask & stencil_face_front_bit)
  695. {
  696. if (m_depth_stencil_state.stencil_front.compare_mask != compare_mask)
  697. {
  698. m_depth_stencil_state.stencil_front.compare_mask = compare_mask;
  699. compare_mask_updated = true;
  700. }
  701. }
  702. if (face_mask & stencil_face_back_bit)
  703. {
  704. if (m_depth_stencil_state.stencil_back.compare_mask != compare_mask)
  705. {
  706. m_depth_stencil_state.stencil_back.compare_mask = compare_mask;
  707. compare_mask_updated = true;
  708. }
  709. }
  710. if (compare_mask_updated)
  711. {
  712. const auto gl_face = stencil_face_lut[face_mask];
  713. if (face_mask == stencil_face_front_and_back)
  714. {
  715. if (m_depth_stencil_state.stencil_front.reference == m_depth_stencil_state.stencil_back.reference &&
  716. m_depth_stencil_state.stencil_front.compare_op == m_depth_stencil_state.stencil_back.compare_op)
  717. {
  718. const auto gl_compare_op = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_front.compare_op)];
  719. glStencilFuncSeparate(gl_face, gl_compare_op, std::bit_cast<GLint>(m_depth_stencil_state.stencil_front.reference), static_cast<GLuint>(compare_mask));
  720. }
  721. else
  722. {
  723. const auto gl_compare_op_front = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_front.compare_op)];
  724. const auto gl_compare_op_back = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_back.compare_op)];
  725. glStencilFuncSeparate(GL_FRONT, gl_compare_op_front, std::bit_cast<GLint>(m_depth_stencil_state.stencil_front.reference), std::bit_cast<GLuint>(compare_mask));
  726. glStencilFuncSeparate(GL_BACK, gl_compare_op_back, std::bit_cast<GLint>(m_depth_stencil_state.stencil_back.reference), std::bit_cast<GLuint>(compare_mask));
  727. }
  728. }
  729. else if (face_mask == stencil_face_front_bit)
  730. {
  731. const auto gl_compare_op = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_front.compare_op)];
  732. glStencilFuncSeparate(gl_face, gl_compare_op, std::bit_cast<GLint>(m_depth_stencil_state.stencil_front.reference), std::bit_cast<GLuint>(compare_mask));
  733. }
  734. else
  735. {
  736. const auto gl_compare_op = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_back.compare_op)];
  737. glStencilFuncSeparate(gl_face, gl_compare_op, std::bit_cast<GLint>(m_depth_stencil_state.stencil_back.reference), std::bit_cast<GLuint>(compare_mask));
  738. }
  739. }
  740. }
  741. void pipeline::set_stencil_reference(std::uint8_t face_mask, std::uint32_t reference)
  742. {
  743. bool reference_updated = false;
  744. if (face_mask & stencil_face_front_bit)
  745. {
  746. if (m_depth_stencil_state.stencil_front.reference != reference)
  747. {
  748. m_depth_stencil_state.stencil_front.reference = reference;
  749. reference_updated = true;
  750. }
  751. }
  752. if (face_mask & stencil_face_back_bit)
  753. {
  754. if (m_depth_stencil_state.stencil_back.reference != reference)
  755. {
  756. m_depth_stencil_state.stencil_back.reference = reference;
  757. reference_updated = true;
  758. }
  759. }
  760. if (reference_updated)
  761. {
  762. const auto gl_face = stencil_face_lut[face_mask];
  763. if (face_mask == stencil_face_front_and_back)
  764. {
  765. if (m_depth_stencil_state.stencil_front.compare_mask == m_depth_stencil_state.stencil_back.compare_mask &&
  766. m_depth_stencil_state.stencil_front.compare_op == m_depth_stencil_state.stencil_back.compare_op)
  767. {
  768. const auto gl_compare_op = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_front.compare_op)];
  769. glStencilFuncSeparate(gl_face, gl_compare_op, std::bit_cast<GLint>(reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_front.compare_mask));
  770. }
  771. else
  772. {
  773. const auto gl_compare_op_front = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_front.compare_op)];
  774. const auto gl_compare_op_back = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_back.compare_op)];
  775. glStencilFuncSeparate(GL_FRONT, gl_compare_op_front, std::bit_cast<GLint>(reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_front.compare_mask));
  776. glStencilFuncSeparate(GL_BACK, gl_compare_op_back, std::bit_cast<GLint>(reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_back.compare_mask));
  777. }
  778. }
  779. else if (face_mask == stencil_face_front_bit)
  780. {
  781. const auto gl_compare_op = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_front.compare_op)];
  782. glStencilFuncSeparate(gl_face, gl_compare_op, std::bit_cast<GLint>(reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_front.compare_mask));
  783. }
  784. else
  785. {
  786. const auto gl_compare_op = compare_op_lut[std::to_underlying(m_depth_stencil_state.stencil_back.compare_op)];
  787. glStencilFuncSeparate(gl_face, gl_compare_op, std::bit_cast<GLint>(reference), std::bit_cast<GLuint>(m_depth_stencil_state.stencil_back.compare_mask));
  788. }
  789. }
  790. }
  791. void pipeline::set_stencil_write_mask(std::uint8_t face_mask, std::uint32_t write_mask)
  792. {
  793. bool write_mask_updated = false;
  794. if (face_mask & stencil_face_front_bit)
  795. {
  796. if (m_depth_stencil_state.stencil_front.write_mask != write_mask)
  797. {
  798. m_depth_stencil_state.stencil_front.write_mask = write_mask;
  799. write_mask_updated = true;
  800. }
  801. }
  802. if (face_mask & stencil_face_back_bit)
  803. {
  804. if (m_depth_stencil_state.stencil_back.write_mask != write_mask)
  805. {
  806. m_depth_stencil_state.stencil_back.write_mask = write_mask;
  807. write_mask_updated = true;
  808. }
  809. }
  810. if (write_mask_updated)
  811. {
  812. const auto gl_face = stencil_face_lut[face_mask];
  813. glStencilMaskSeparate(gl_face, std::bit_cast<GLuint>(write_mask));
  814. }
  815. }
  816. void pipeline::set_logic_op_enabled(bool enabled)
  817. {
  818. if (m_color_blend_state.logic_op_enabled != enabled)
  819. {
  820. m_color_blend_state.logic_op_enabled = enabled;
  821. if (enabled)
  822. {
  823. glEnable(GL_COLOR_LOGIC_OP);
  824. }
  825. else
  826. {
  827. glDisable(GL_COLOR_LOGIC_OP);
  828. }
  829. }
  830. }
  831. void pipeline::set_logic_op(gl::logic_op logic_op)
  832. {
  833. if (m_color_blend_state.logic_op != logic_op)
  834. {
  835. m_color_blend_state.logic_op = logic_op;
  836. const auto gl_logic_op = logic_op_lut[std::to_underlying(logic_op)];
  837. glLogicOp(gl_logic_op);
  838. }
  839. }
  840. void pipeline::set_color_blend_enabled(bool enabled)
  841. {
  842. if (m_color_blend_state.blend_enabled != enabled)
  843. {
  844. m_color_blend_state.blend_enabled = enabled;
  845. if (enabled)
  846. {
  847. glEnable(GL_BLEND);
  848. }
  849. else
  850. {
  851. glDisable(GL_BLEND);
  852. }
  853. }
  854. }
  855. void pipeline::set_color_blend_equation(const color_blend_equation& equation)
  856. {
  857. if (m_color_blend_state.color_blend_equation.src_color_blend_factor != equation.src_color_blend_factor ||
  858. m_color_blend_state.color_blend_equation.dst_color_blend_factor != equation.dst_color_blend_factor ||
  859. m_color_blend_state.color_blend_equation.src_alpha_blend_factor != equation.src_alpha_blend_factor ||
  860. m_color_blend_state.color_blend_equation.dst_alpha_blend_factor != equation.dst_alpha_blend_factor)
  861. {
  862. m_color_blend_state.color_blend_equation.src_color_blend_factor = equation.src_color_blend_factor;
  863. m_color_blend_state.color_blend_equation.dst_color_blend_factor = equation.dst_color_blend_factor;
  864. m_color_blend_state.color_blend_equation.src_alpha_blend_factor = equation.src_alpha_blend_factor;
  865. m_color_blend_state.color_blend_equation.dst_alpha_blend_factor = equation.dst_alpha_blend_factor;
  866. const auto gl_src_rgb = blend_factor_lut[std::to_underlying(equation.src_color_blend_factor)];
  867. const auto gl_dst_rgb = blend_factor_lut[std::to_underlying(equation.dst_color_blend_factor)];
  868. const auto gl_src_alpha = blend_factor_lut[std::to_underlying(equation.src_alpha_blend_factor)];
  869. const auto gl_dst_alpha = blend_factor_lut[std::to_underlying(equation.dst_alpha_blend_factor)];
  870. glBlendFuncSeparate(gl_src_rgb, gl_dst_rgb, gl_src_alpha, gl_dst_alpha);
  871. }
  872. if (m_color_blend_state.color_blend_equation.color_blend_op != equation.color_blend_op ||
  873. m_color_blend_state.color_blend_equation.alpha_blend_op != equation.alpha_blend_op)
  874. {
  875. m_color_blend_state.color_blend_equation.color_blend_op = equation.color_blend_op;
  876. m_color_blend_state.color_blend_equation.alpha_blend_op = equation.alpha_blend_op;
  877. const auto gl_mode_rgb = blend_op_lut[std::to_underlying(equation.color_blend_op)];
  878. const auto gl_mode_alpha = blend_op_lut[std::to_underlying(equation.alpha_blend_op)];
  879. glBlendEquationSeparate(gl_mode_rgb, gl_mode_alpha);
  880. }
  881. }
  882. void pipeline::set_color_write_mask(std::uint8_t mask)
  883. {
  884. if (m_color_blend_state.color_write_mask != mask)
  885. {
  886. m_color_blend_state.color_write_mask = mask;
  887. glColorMask
  888. (
  889. mask & color_component_r_bit,
  890. mask & color_component_g_bit,
  891. mask & color_component_b_bit,
  892. mask & color_component_a_bit
  893. );
  894. }
  895. }
  896. void pipeline::set_blend_constants(const std::array<float, 4>& blend_constants)
  897. {
  898. if (m_color_blend_state.blend_constants != blend_constants)
  899. {
  900. m_color_blend_state.blend_constants = blend_constants;
  901. glBlendColor(blend_constants[0], blend_constants[1], blend_constants[2], blend_constants[3]);
  902. }
  903. }
  904. void pipeline::draw(std::uint32_t vertex_count, std::uint32_t instance_count, std::uint32_t first_vertex, std::uint32_t first_instance)
  905. {
  906. glDrawArraysInstancedBaseInstance
  907. (
  908. primitive_topology_lut[std::to_underlying(m_input_assembly_state.topology)],
  909. static_cast<GLint>(first_vertex),
  910. static_cast<GLsizei>(vertex_count),
  911. static_cast<GLsizei>(instance_count),
  912. static_cast<GLuint>(first_instance)
  913. );
  914. }
  915. void pipeline::draw_indexed(std::uint32_t index_count, std::uint32_t instance_count, std::uint32_t first_index, std::int32_t vertex_offset, std::uint32_t first_instance)
  916. {
  917. glDrawElementsInstancedBaseInstance
  918. (
  919. primitive_topology_lut[std::to_underlying(m_input_assembly_state.topology)],
  920. static_cast<GLsizei>(instance_count),
  921. GL_UNSIGNED_INT,// GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE
  922. reinterpret_cast<const GLvoid*>(first_index * sizeof(unsigned int)),
  923. static_cast<GLsizei>(instance_count),
  924. static_cast<GLuint>(first_instance)
  925. );
  926. }
  927. void pipeline::clear_attachments(std::uint8_t mask, const clear_value& value)
  928. {
  929. GLbitfield gl_clear_mask = 0;
  930. if (mask & color_clear_bit)
  931. {
  932. // Add color attachment to OpenGL clear mask
  933. gl_clear_mask |= GL_COLOR_BUFFER_BIT;
  934. if (m_clear_value.color != value.color)
  935. {
  936. // Update color clear value
  937. glClearColor(value.color[0], value.color[1], value.color[2], value.color[3]);
  938. m_clear_value.color = value.color;
  939. }
  940. }
  941. if (mask & depth_clear_bit)
  942. {
  943. // Add depth attachment to OpenGL clear mask
  944. gl_clear_mask |= GL_DEPTH_BUFFER_BIT;
  945. if (m_clear_value.depth != value.depth)
  946. {
  947. // Update depth clear value
  948. glClearDepth(value.depth);
  949. m_clear_value.depth = value.depth;
  950. }
  951. }
  952. if (mask & stencil_clear_bit)
  953. {
  954. // Add stencil attachment to OpenGL clear mask
  955. gl_clear_mask |= GL_STENCIL_BUFFER_BIT;
  956. if (m_clear_value.stencil != value.stencil)
  957. {
  958. // Update stencil clear value
  959. glClearStencil(static_cast<GLint>(value.stencil));
  960. m_clear_value.stencil = value.stencil;
  961. }
  962. }
  963. // Clear attachments
  964. glClear(gl_clear_mask);
  965. }
  966. void pipeline::defaut_framebuffer_resized(std::uint32_t width, std::uint32_t height) noexcept
  967. {
  968. m_default_framebuffer_dimensions = {width, height};
  969. }
  970. void pipeline::fetch_vertex_input_state()
  971. {
  972. }
  973. void pipeline::fetch_input_assembly_state()
  974. {
  975. m_input_assembly_state.primitive_restart_enabled = glIsEnabled(GL_PRIMITIVE_RESTART);
  976. }
  977. void pipeline::fetch_viewport_state()
  978. {
  979. // Query viewport position and dimensions
  980. GLint gl_viewport[4];
  981. glGetIntegerv(GL_VIEWPORT, gl_viewport);
  982. // Query viewport depth range
  983. GLfloat gl_depth_range[2];
  984. glGetFloatv(GL_DEPTH_RANGE, gl_depth_range);
  985. // Query scissor box
  986. GLint gl_scissor_box[4] = {0, 0, 0, 0};
  987. glGetIntegerv(GL_SCISSOR_BOX, gl_scissor_box);
  988. // Match viewport state
  989. m_viewport_state.viewports =
  990. {{
  991. static_cast<float>(gl_viewport[0]),
  992. static_cast<float>(gl_viewport[1]),
  993. static_cast<float>(gl_viewport[2]),
  994. static_cast<float>(gl_viewport[3]),
  995. gl_depth_range[0],
  996. gl_depth_range[1]
  997. }};
  998. m_viewport_state.scissors =
  999. {{
  1000. static_cast<std::int32_t>(gl_scissor_box[0]),
  1001. static_cast<std::int32_t>(gl_scissor_box[1]),
  1002. static_cast<std::uint32_t>(std::max(0, gl_scissor_box[2])),
  1003. static_cast<std::uint32_t>(std::max(0, gl_scissor_box[3]))
  1004. }};
  1005. }
  1006. void pipeline::fetch_rasterization_state()
  1007. {
  1008. // Query rasterizer discard
  1009. bool gl_rasterizer_discard_enabled = glIsEnabled(GL_RASTERIZER_DISCARD);
  1010. // Query fill mode
  1011. GLint gl_fill_mode;
  1012. glGetIntegerv(GL_POLYGON_MODE, &gl_fill_mode);
  1013. // Query cull mode
  1014. bool gl_cull_enabled = glIsEnabled(GL_CULL_FACE);
  1015. GLint gl_cull_mode;
  1016. glGetIntegerv(GL_CULL_FACE_MODE, &gl_cull_mode);
  1017. // Query front face
  1018. GLint gl_front_face;
  1019. glGetIntegerv(GL_FRONT_FACE, &gl_front_face);
  1020. // Query depth bias
  1021. bool gl_depth_bias_enabled = glIsEnabled(GL_POLYGON_OFFSET_FILL) &&
  1022. glIsEnabled(GL_POLYGON_OFFSET_LINE) &&
  1023. glIsEnabled(GL_POLYGON_OFFSET_POINT);
  1024. float gl_depth_bias_constant_factor;
  1025. float gl_depth_bias_slope_factor;
  1026. glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl_depth_bias_constant_factor);
  1027. glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl_depth_bias_slope_factor);
  1028. // Query depth clamp
  1029. bool gl_depth_clamp_enabled = glIsEnabled(GL_DEPTH_CLAMP);
  1030. // Query scissor test
  1031. bool gl_scissor_test_enabled = glIsEnabled(GL_SCISSOR_TEST);
  1032. // Query provoking vertex
  1033. GLint gl_provoking_vertex;
  1034. glGetIntegerv(GL_PROVOKING_VERTEX, &gl_provoking_vertex);
  1035. // Query point size
  1036. float gl_point_size;
  1037. glGetFloatv(GL_POINT_SIZE, &gl_point_size);
  1038. // Query line width
  1039. float gl_line_width;
  1040. glGetFloatv(GL_LINE_WIDTH, &gl_line_width);
  1041. // Match rasterizer state
  1042. m_rasterization_state.rasterizer_discard_enabled = gl_rasterizer_discard_enabled;
  1043. m_rasterization_state.fill_mode = (gl_fill_mode == GL_POINT ? fill_mode::point : gl_fill_mode == GL_LINE ? fill_mode::line : fill_mode::fill);
  1044. if (gl_cull_enabled)
  1045. {
  1046. m_rasterization_state.cull_mode = (gl_cull_mode == GL_FRONT_AND_BACK ? cull_mode::front_and_back : gl_fill_mode == GL_FRONT ? cull_mode::front : cull_mode::back);
  1047. }
  1048. else
  1049. {
  1050. m_rasterization_state.cull_mode = cull_mode::none;
  1051. }
  1052. m_rasterization_state.front_face = (gl_front_face == GL_CW ? front_face::clockwise : front_face::counter_clockwise);
  1053. m_rasterization_state.depth_bias_enabled = gl_depth_bias_enabled;
  1054. m_rasterization_state.depth_bias_constant_factor = gl_depth_bias_constant_factor;
  1055. m_rasterization_state.depth_bias_slope_factor = gl_depth_bias_slope_factor;
  1056. m_rasterization_state.depth_clamp_enabled = gl_depth_clamp_enabled;
  1057. m_rasterization_state.scissor_test_enabled = gl_scissor_test_enabled;
  1058. m_rasterization_state.provoking_vertex_mode = (gl_provoking_vertex == GL_FIRST_VERTEX_CONVENTION ? provoking_vertex_mode::first : provoking_vertex_mode::last);
  1059. m_rasterization_state.point_size = gl_point_size;
  1060. m_rasterization_state.line_width = gl_line_width;
  1061. }
  1062. void pipeline::fetch_depth_stencil_state()
  1063. {
  1064. auto inv_compare_op_lut = [](GLint func) -> gl::compare_op
  1065. {
  1066. switch (func)
  1067. {
  1068. case GL_NEVER:
  1069. return compare_op::never;
  1070. case GL_LESS:
  1071. return compare_op::less;
  1072. case GL_EQUAL:
  1073. return compare_op::equal;
  1074. case GL_LEQUAL:
  1075. return compare_op::less_or_equal;
  1076. case GL_GREATER:
  1077. return compare_op::greater;
  1078. case GL_NOTEQUAL:
  1079. return compare_op::not_equal;
  1080. case GL_GEQUAL:
  1081. return compare_op::greater_or_equal;
  1082. case GL_ALWAYS:
  1083. default:
  1084. return compare_op::always;
  1085. }
  1086. };
  1087. auto inv_stencil_op_lut = [](GLint op) -> gl::stencil_op
  1088. {
  1089. switch (op)
  1090. {
  1091. case GL_KEEP:
  1092. return stencil_op::keep;
  1093. case GL_ZERO:
  1094. return stencil_op::zero;
  1095. case GL_REPLACE:
  1096. return stencil_op::replace;
  1097. case GL_INCR:
  1098. return stencil_op::increment_and_clamp;
  1099. case GL_DECR:
  1100. return stencil_op::decrement_and_clamp;
  1101. case GL_INVERT:
  1102. return stencil_op::invert;
  1103. case GL_INCR_WRAP:
  1104. return stencil_op::increment_and_wrap;
  1105. case GL_DECR_WRAP:
  1106. default:
  1107. return stencil_op::decrement_and_wrap;
  1108. }
  1109. };
  1110. m_depth_stencil_state.depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
  1111. GLboolean gl_depth_write_enabled;
  1112. glGetBooleanv(GL_DEPTH_WRITEMASK, &gl_depth_write_enabled);
  1113. m_depth_stencil_state.depth_write_enabled = gl_depth_write_enabled;
  1114. GLint gl_depth_compare_op;
  1115. glGetIntegerv(GL_DEPTH_FUNC, &gl_depth_compare_op);
  1116. m_depth_stencil_state.depth_compare_op = inv_compare_op_lut(gl_depth_compare_op);
  1117. m_depth_stencil_state.stencil_test_enabled = glIsEnabled(GL_STENCIL_TEST);
  1118. // Stencil front
  1119. {
  1120. GLint gl_stencil_front_fail;
  1121. GLint gl_stencil_front_pass_depth_pass;
  1122. GLint gl_stencil_front_pass_depth_fail;
  1123. GLint gl_stencil_front_func;
  1124. GLint gl_stencil_front_value_mask;
  1125. GLint gl_stencil_front_write_mask;
  1126. GLint gl_stencil_front_ref;
  1127. glGetIntegerv(GL_STENCIL_FAIL, &gl_stencil_front_fail);
  1128. glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &gl_stencil_front_pass_depth_pass);
  1129. glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &gl_stencil_front_pass_depth_fail);
  1130. glGetIntegerv(GL_STENCIL_FUNC, &gl_stencil_front_func);
  1131. glGetIntegerv(GL_STENCIL_VALUE_MASK, &gl_stencil_front_value_mask);
  1132. glGetIntegerv(GL_STENCIL_WRITEMASK, &gl_stencil_front_write_mask);
  1133. glGetIntegerv(GL_STENCIL_REF, &gl_stencil_front_ref);
  1134. m_depth_stencil_state.stencil_front.fail_op = inv_stencil_op_lut(gl_stencil_front_fail);
  1135. m_depth_stencil_state.stencil_front.pass_op = inv_stencil_op_lut(gl_stencil_front_pass_depth_pass);
  1136. m_depth_stencil_state.stencil_front.depth_fail_op = inv_stencil_op_lut(gl_stencil_front_pass_depth_fail);
  1137. m_depth_stencil_state.stencil_front.compare_op = inv_compare_op_lut(gl_stencil_front_func);
  1138. m_depth_stencil_state.stencil_front.compare_mask = std::bit_cast<std::uint32_t>(gl_stencil_front_value_mask);
  1139. m_depth_stencil_state.stencil_front.write_mask = std::bit_cast<std::uint32_t>(gl_stencil_front_write_mask);
  1140. m_depth_stencil_state.stencil_front.reference = std::bit_cast<std::uint32_t>(gl_stencil_front_ref);
  1141. }
  1142. // Stencil back
  1143. {
  1144. GLint gl_stencil_back_fail;
  1145. GLint gl_stencil_back_pass_depth_pass;
  1146. GLint gl_stencil_back_pass_depth_fail;
  1147. GLint gl_stencil_back_func;
  1148. GLint gl_stencil_back_value_mask;
  1149. GLint gl_stencil_back_write_mask;
  1150. GLint gl_stencil_back_ref;
  1151. glGetIntegerv(GL_STENCIL_BACK_FAIL, &gl_stencil_back_fail);
  1152. glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &gl_stencil_back_pass_depth_pass);
  1153. glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &gl_stencil_back_pass_depth_fail);
  1154. glGetIntegerv(GL_STENCIL_BACK_FUNC, &gl_stencil_back_func);
  1155. glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &gl_stencil_back_value_mask);
  1156. glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &gl_stencil_back_write_mask);
  1157. glGetIntegerv(GL_STENCIL_BACK_REF, &gl_stencil_back_ref);
  1158. m_depth_stencil_state.stencil_back.fail_op = inv_stencil_op_lut(gl_stencil_back_fail);
  1159. m_depth_stencil_state.stencil_back.pass_op = inv_stencil_op_lut(gl_stencil_back_pass_depth_pass);
  1160. m_depth_stencil_state.stencil_back.depth_fail_op = inv_stencil_op_lut(gl_stencil_back_pass_depth_fail);
  1161. m_depth_stencil_state.stencil_back.compare_op = inv_compare_op_lut(gl_stencil_back_func);
  1162. m_depth_stencil_state.stencil_back.compare_mask = std::bit_cast<std::uint32_t>(gl_stencil_back_value_mask);
  1163. m_depth_stencil_state.stencil_back.write_mask = std::bit_cast<std::uint32_t>(gl_stencil_back_write_mask);
  1164. m_depth_stencil_state.stencil_back.reference = std::bit_cast<std::uint32_t>(gl_stencil_back_ref);
  1165. }
  1166. }
  1167. void pipeline::fetch_color_blend_state()
  1168. {
  1169. auto inv_logic_op_lut = [](GLint op) -> gl::logic_op
  1170. {
  1171. switch (op)
  1172. {
  1173. case GL_CLEAR:
  1174. return gl::logic_op::bitwise_clear;
  1175. case GL_AND:
  1176. return gl::logic_op::bitwise_and;
  1177. case GL_AND_REVERSE:
  1178. return gl::logic_op::bitwise_and_reverse;
  1179. case GL_COPY:
  1180. return gl::logic_op::bitwise_copy;
  1181. case GL_AND_INVERTED:
  1182. return gl::logic_op::bitwise_and_inverted;
  1183. case GL_NOOP:
  1184. return gl::logic_op::bitwise_no_op;
  1185. case GL_XOR:
  1186. return gl::logic_op::bitwise_xor;
  1187. case GL_OR:
  1188. return gl::logic_op::bitwise_or;
  1189. case GL_NOR:
  1190. return gl::logic_op::bitwise_nor;
  1191. case GL_EQUIV:
  1192. return gl::logic_op::bitwise_equivalent;
  1193. case GL_INVERT:
  1194. return gl::logic_op::bitwise_invert;
  1195. case GL_OR_REVERSE:
  1196. return gl::logic_op::bitwise_or_reverse;
  1197. case GL_COPY_INVERTED:
  1198. return gl::logic_op::bitwise_copy_inverted;
  1199. case GL_OR_INVERTED:
  1200. return gl::logic_op::bitwise_or_inverted;
  1201. case GL_NAND:
  1202. return gl::logic_op::bitwise_nand;
  1203. case GL_SET:
  1204. default:
  1205. return gl::logic_op::bitwise_set;
  1206. }
  1207. };
  1208. auto inv_blend_factor_lut = [](GLint func) -> gl::blend_factor
  1209. {
  1210. switch (func)
  1211. {
  1212. case GL_ZERO:
  1213. return blend_factor::zero;
  1214. case GL_ONE:
  1215. return blend_factor::one;
  1216. case GL_SRC_COLOR:
  1217. return blend_factor::src_color;
  1218. case GL_ONE_MINUS_SRC_COLOR:
  1219. return blend_factor::one_minus_src_color;
  1220. case GL_DST_COLOR:
  1221. return blend_factor::dst_color;
  1222. case GL_ONE_MINUS_DST_COLOR:
  1223. return blend_factor::one_minus_dst_color;
  1224. case GL_SRC_ALPHA:
  1225. return blend_factor::src_alpha;
  1226. case GL_ONE_MINUS_SRC_ALPHA:
  1227. return blend_factor::one_minus_src_alpha;
  1228. case GL_DST_ALPHA:
  1229. return blend_factor::dst_alpha;
  1230. case GL_ONE_MINUS_DST_ALPHA:
  1231. return blend_factor::one_minus_dst_alpha;
  1232. case GL_CONSTANT_COLOR:
  1233. return blend_factor::constant_color;
  1234. case GL_ONE_MINUS_CONSTANT_COLOR:
  1235. return blend_factor::one_minus_constant_color;
  1236. case GL_CONSTANT_ALPHA:
  1237. return blend_factor::constant_alpha;
  1238. case GL_ONE_MINUS_CONSTANT_ALPHA:
  1239. return blend_factor::one_minus_constant_alpha;
  1240. case GL_SRC_ALPHA_SATURATE:
  1241. return blend_factor::src_alpha_saturate;
  1242. case GL_SRC1_COLOR:
  1243. return blend_factor::src1_color;
  1244. case GL_ONE_MINUS_SRC1_COLOR:
  1245. return blend_factor::one_minus_src1_color;
  1246. case GL_SRC1_ALPHA:
  1247. return blend_factor::src1_alpha;
  1248. case GL_ONE_MINUS_SRC1_ALPHA:
  1249. default:
  1250. return blend_factor::one_minus_src1_alpha;
  1251. }
  1252. };
  1253. auto inv_blend_op_lut = [](GLint mode) -> gl::blend_op
  1254. {
  1255. switch (mode)
  1256. {
  1257. case GL_FUNC_ADD:
  1258. return blend_op::add;
  1259. case GL_FUNC_SUBTRACT:
  1260. return blend_op::subtract;
  1261. case GL_FUNC_REVERSE_SUBTRACT:
  1262. return blend_op::reverse_subtract;
  1263. case GL_MIN:
  1264. return blend_op::min;
  1265. case GL_MAX:
  1266. default:
  1267. return blend_op::max;
  1268. }
  1269. };
  1270. m_color_blend_state.logic_op_enabled = glIsEnabled(GL_COLOR_LOGIC_OP);
  1271. GLint gl_logic_op;
  1272. glGetIntegerv(GL_LOGIC_OP_MODE, &gl_logic_op);
  1273. m_color_blend_state.logic_op = inv_logic_op_lut(gl_logic_op);
  1274. m_color_blend_state.blend_enabled = glIsEnabled(GL_BLEND);
  1275. GLint gl_blend_src_rgb;
  1276. GLint gl_blend_dst_rgb;
  1277. GLint gl_blend_equation_rgb;
  1278. GLint gl_blend_src_alpha;
  1279. GLint gl_blend_dst_alpha;
  1280. GLint gl_blend_equation_alpha;
  1281. glGetIntegerv(GL_BLEND_SRC_RGB, &gl_blend_src_rgb);
  1282. glGetIntegerv(GL_BLEND_DST_RGB, &gl_blend_dst_rgb);
  1283. glGetIntegerv(GL_BLEND_EQUATION_RGB, &gl_blend_equation_rgb);
  1284. glGetIntegerv(GL_BLEND_SRC_ALPHA, &gl_blend_src_alpha);
  1285. glGetIntegerv(GL_BLEND_DST_ALPHA, &gl_blend_dst_alpha);
  1286. glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &gl_blend_equation_alpha);
  1287. m_color_blend_state.color_blend_equation.src_color_blend_factor = inv_blend_factor_lut(gl_blend_src_rgb);
  1288. m_color_blend_state.color_blend_equation.dst_color_blend_factor = inv_blend_factor_lut(gl_blend_dst_rgb);
  1289. m_color_blend_state.color_blend_equation.color_blend_op = inv_blend_op_lut(gl_blend_equation_rgb);
  1290. m_color_blend_state.color_blend_equation.src_alpha_blend_factor = inv_blend_factor_lut(gl_blend_src_alpha);
  1291. m_color_blend_state.color_blend_equation.dst_alpha_blend_factor = inv_blend_factor_lut(gl_blend_dst_alpha);
  1292. m_color_blend_state.color_blend_equation.alpha_blend_op = inv_blend_op_lut(gl_blend_equation_alpha);
  1293. GLboolean gl_color_writemask[4];
  1294. glGetBooleanv(GL_COLOR_WRITEMASK, gl_color_writemask);
  1295. m_color_blend_state.color_write_mask =
  1296. static_cast<std::uint8_t>(gl_color_writemask[0]) |
  1297. (static_cast<std::uint8_t>(gl_color_writemask[1]) << 1) |
  1298. (static_cast<std::uint8_t>(gl_color_writemask[2]) << 2) |
  1299. (static_cast<std::uint8_t>(gl_color_writemask[3]) << 3);
  1300. glGetFloatv(GL_BLEND_COLOR, m_color_blend_state.blend_constants.data());
  1301. }
  1302. void pipeline::fetch_clear_value()
  1303. {
  1304. // Query clear values
  1305. GLfloat gl_color_clear[4];
  1306. GLfloat gl_depth_clear;
  1307. GLint gl_stencil_clear;
  1308. glGetFloatv(GL_COLOR_CLEAR_VALUE, gl_color_clear);
  1309. glGetFloatv(GL_DEPTH_CLEAR_VALUE, &gl_depth_clear);
  1310. glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &gl_stencil_clear);
  1311. // Match clear state
  1312. m_clear_value.color = {gl_color_clear[0], gl_color_clear[1], gl_color_clear[2], gl_color_clear[3]};
  1313. m_clear_value.depth = gl_depth_clear;
  1314. m_clear_value.stencil = static_cast<std::uint32_t>(gl_stencil_clear);
  1315. }
  1316. } // namespace gl