// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2023 by Ronald "Eidolon" Kinard // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- #ifndef __SRB2_RHI_GL2_RHI_HPP__ #define __SRB2_RHI_GL2_RHI_HPP__ #include #include #include #include #include #include #include #include "../rhi.hpp" namespace srb2::rhi { struct Gl2FramebufferKey { Handle color; std::optional> depth_stencil; bool operator==(const Gl2FramebufferKey& rhs) const noexcept { return color == rhs.color && depth_stencil == rhs.depth_stencil; } bool operator!=(const Gl2FramebufferKey& rhs) const noexcept { return !(*this == rhs); } }; } // namespace srb2::rhi // To make sure the compiler selects the struct specialization of std::hash for Gl2FramebufferKey, // we need to split the namespace declarations _before_ the instantiation of std::unordered_map. template <> struct std::hash { std::size_t operator()(const srb2::rhi::Gl2FramebufferKey& key) const { std::size_t color_hash = std::hash>()(key.color); std::size_t depth_stencil_hash = 0; if (key.depth_stencil) { depth_stencil_hash = std::hash>()(*key.depth_stencil); } return color_hash ^ (depth_stencil_hash << 1); } }; struct GladGLContext; namespace srb2::rhi { typedef void (*GlProc)(void); typedef GlProc (*GlLoadFunc)(const char* name); /// @brief Platform-specific implementation details for the GL2 backend. struct Gl2Platform { virtual ~Gl2Platform(); virtual void present() = 0; virtual std::tuple, std::vector> find_shader_sources(PipelineProgram program) = 0; virtual Rect get_default_framebuffer_dimensions() = 0; }; struct Gl2Texture : public rhi::Texture { uint32_t texture; rhi::TextureDesc desc; }; struct Gl2Buffer : public rhi::Buffer { uint32_t buffer; rhi::BufferDesc desc; }; struct Gl2RenderPass : public rhi::RenderPass { rhi::RenderPassDesc desc; }; struct Gl2Renderbuffer : public rhi::Renderbuffer { uint32_t renderbuffer; rhi::RenderbufferDesc desc; }; struct Gl2UniformSet : public rhi::UniformSet { std::vector uniforms; }; struct Gl2BindingSet : public rhi::BindingSet { std::vector vertex_buffer_bindings; std::unordered_map textures {4}; }; struct Gl2Pipeline : public rhi::Pipeline { uint32_t vertex_shader = 0; uint32_t fragment_shader = 0; uint32_t program = 0; std::unordered_map attrib_locations {2}; std::unordered_map uniform_locations {2}; std::unordered_map sampler_locations {2}; rhi::PipelineDesc desc; }; struct Gl2GraphicsContext : public rhi::GraphicsContext { }; struct Gl2ActiveUniform { uint32_t type; uint32_t location; }; class Gl2Rhi final : public Rhi { std::unique_ptr platform_; std::unique_ptr gl_; Slab render_pass_slab_; Slab texture_slab_; Slab buffer_slab_; Slab renderbuffer_slab_; Slab pipeline_slab_; Slab uniform_set_slab_; Slab binding_set_slab_; Handle current_index_buffer_; std::unordered_map framebuffers_ {16}; struct DefaultRenderPassState { }; using RenderPassState = std::variant; std::optional current_render_pass_; std::optional> current_pipeline_; PrimitiveType current_primitive_type_ = PrimitiveType::kPoints; bool graphics_context_active_ = false; uint32_t graphics_context_generation_ = 1; uint32_t index_buffer_offset_ = 0; uint8_t stencil_front_reference_ = 0; uint8_t stencil_front_compare_mask_ = 0xFF; uint8_t stencil_front_write_mask_ = 0xFF; uint8_t stencil_back_reference_ = 0; uint8_t stencil_back_compare_mask_ = 0xFF; uint8_t stencil_back_write_mask_ = 0xFF; public: Gl2Rhi(std::unique_ptr&& platform, GlLoadFunc load_func); virtual ~Gl2Rhi(); virtual Handle create_render_pass(const RenderPassDesc& desc) override; virtual void destroy_render_pass(Handle handle) override; virtual Handle create_pipeline(const PipelineDesc& desc) override; virtual void destroy_pipeline(Handle handle) override; virtual Handle create_texture(const TextureDesc& desc) override; virtual void destroy_texture(Handle handle) override; virtual Handle create_buffer(const BufferDesc& desc) override; virtual void destroy_buffer(Handle handle) override; virtual Handle create_renderbuffer(const RenderbufferDesc& desc) override; virtual void destroy_renderbuffer(Handle handle) override; virtual TextureDetails get_texture_details(Handle texture) override; virtual Rect get_renderbuffer_size(Handle renderbuffer) override; virtual uint32_t get_buffer_size(Handle buffer) override; virtual void update_buffer( Handle ctx, Handle buffer, uint32_t offset, tcb::span data ) override; virtual void update_texture( Handle ctx, Handle texture, Rect region, srb2::rhi::PixelFormat data_format, tcb::span data ) override; virtual Handle create_uniform_set(Handle ctx, const CreateUniformSetInfo& info) override; virtual Handle create_binding_set(Handle ctx, Handle pipeline, const CreateBindingSetInfo& info) override; virtual Handle begin_graphics() override; virtual void end_graphics(Handle ctx) override; // Graphics context functions virtual void begin_default_render_pass(Handle ctx, bool clear) override; virtual void begin_render_pass(Handle ctx, const RenderPassBeginInfo& info) override; virtual void end_render_pass(Handle ctx) override; virtual void bind_pipeline(Handle ctx, Handle pipeline) override; virtual void bind_uniform_set(Handle ctx, uint32_t slot, Handle set) override; virtual void bind_binding_set(Handle ctx, Handle set) override; virtual void bind_index_buffer(Handle ctx, Handle buffer) override; virtual void set_scissor(Handle ctx, const Rect& rect) override; virtual void set_viewport(Handle ctx, const Rect& rect) override; virtual void draw(Handle ctx, uint32_t vertex_count, uint32_t first_vertex) override; virtual void draw_indexed(Handle ctx, uint32_t index_count, uint32_t first_index) override; virtual void read_pixels(Handle ctx, const Rect& rect, PixelFormat format, tcb::span out) override; virtual void copy_framebuffer_to_texture( Handle ctx, Handle dst_tex, const Rect& dst_region, const Rect& src_region ) override; virtual void set_stencil_reference(Handle ctx, CullMode face, uint8_t reference) override; virtual void set_stencil_compare_mask(Handle ctx, CullMode face, uint8_t mask) override; virtual void set_stencil_write_mask(Handle ctx, CullMode face, uint8_t mask) override; virtual void present() override; virtual void finish() override; }; } // namespace srb2::rhi #endif // __SRB2_RHI_GL2_RHI_HPP__