Program.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * Copyright (c) 2022, Stephan Unverwerth <s.unverwerth@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGL/GL/gl.h>
  7. #include <LibGL/Shaders/Program.h>
  8. #include <LibGLSL/Linker.h>
  9. namespace GL {
  10. NonnullRefPtr<Program> Program::create()
  11. {
  12. return adopt_ref(*new Program());
  13. }
  14. bool Program::is_shader_attached(Shader const& shader) const
  15. {
  16. switch (shader.type()) {
  17. case GL_VERTEX_SHADER:
  18. return m_vertex_shaders.contains_slow(shader);
  19. case GL_FRAGMENT_SHADER:
  20. return m_fragment_shaders.contains_slow(shader);
  21. default:
  22. VERIFY_NOT_REACHED();
  23. }
  24. }
  25. ErrorOr<void> Program::attach_shader(Shader& shader)
  26. {
  27. if (is_shader_attached(shader))
  28. return Error::from_string_literal("Trying to attach a shader that is already attached");
  29. switch (shader.type()) {
  30. case GL_VERTEX_SHADER:
  31. TRY(m_vertex_shaders.try_append(shader));
  32. break;
  33. case GL_FRAGMENT_SHADER:
  34. TRY(m_fragment_shaders.try_append(shader));
  35. break;
  36. default:
  37. VERIFY_NOT_REACHED();
  38. }
  39. return {};
  40. }
  41. ErrorOr<void> Program::link(GPU::Device& device)
  42. {
  43. m_info_log = String {};
  44. GLSL::Linker linker;
  45. // Link vertex shader objects
  46. Vector<GLSL::ObjectFile const*> vertex_shader_object_files;
  47. for (auto vertex_shader : m_vertex_shaders)
  48. vertex_shader_object_files.append(vertex_shader->object_file());
  49. auto linked_vertex_shader_or_error = linker.link(vertex_shader_object_files);
  50. if (linked_vertex_shader_or_error.is_error()) {
  51. m_link_status = false;
  52. m_info_log = linker.messages();
  53. return linked_vertex_shader_or_error.release_error();
  54. }
  55. m_linked_vertex_shader = linked_vertex_shader_or_error.release_value();
  56. // Link fragment shader objects
  57. Vector<GLSL::ObjectFile const*> fragment_shader_object_files;
  58. for (auto fragment_shader : m_fragment_shaders)
  59. fragment_shader_object_files.append(fragment_shader->object_file());
  60. auto linked_fragment_shader_or_error = linker.link(fragment_shader_object_files);
  61. if (linked_fragment_shader_or_error.is_error()) {
  62. m_link_status = false;
  63. m_info_log = linker.messages();
  64. return linked_fragment_shader_or_error.release_error();
  65. }
  66. m_linked_fragment_shader = linked_fragment_shader_or_error.release_value();
  67. m_gpu_vertex_shader = TRY(device.create_shader(m_linked_vertex_shader->intermediate_shader_representation()));
  68. m_gpu_fragment_shader = TRY(device.create_shader(m_linked_fragment_shader->intermediate_shader_representation()));
  69. m_link_status = true;
  70. return {};
  71. }
  72. size_t Program::info_log_length() const
  73. {
  74. if (!m_info_log.has_value())
  75. return 0;
  76. // Per the spec we return the size including the null terminator
  77. return m_info_log.value().bytes().size() + 1;
  78. }
  79. }