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