Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions include/gkit/graphic/Buffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#pragma once

#include <cstdint>

/**
* @brief Base class for GPU data buffers (frontend abstract interface)
*
* Common data operations shared by all GPU data buffers (vertex, index, etc.).
* Concrete backends (OpenGL/Vulkan) inherit and implement bind/unbind/update.
* The resource handle (renderer_id) only lives inside the backend implementation.
*/
namespace gkit::graphic {

class Buffer {
public:
Buffer() = default;
Buffer(const Buffer&) = delete;
auto operator=(const Buffer&) -> Buffer& = delete;

Buffer(Buffer&& other) noexcept : size(other.size) { other.size = 0; }
auto operator=(Buffer&& other) noexcept -> Buffer& {
if (this != &other) {
this->size = other.size;
other.size = 0;
}
return *this;
}

virtual ~Buffer() = default;

/**
* @brief Bind to the current backend context
*/
virtual auto bind() const -> void = 0;

/**
* @brief Unbind
*/
virtual auto unbind() const -> void = 0;

/**
* @brief Update the whole buffer; uses SubData if size is unchanged, otherwise reallocates
*/
virtual auto update_data(const void* data, uint32_t size) -> void = 0;

/**
* @brief Update a byte range starting at offset
*/
virtual auto update_sub_data(uint32_t offset, const void* data, uint32_t size) -> void = 0;

/**
* @brief Buffer size in bytes
*/
[[nodiscard]] auto get_size() const -> uint32_t { return size; }

protected:
uint32_t size = 0; // size in bytes
};

} // namespace gkit::graphic
77 changes: 77 additions & 0 deletions include/gkit/graphic/FrameBuffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#pragma once

#include "gkit/graphic/RenderBuffer.hpp"
#include "gkit/graphic/Texture.hpp"

namespace gkit::graphic {

/**
* @brief Framebuffer (frontend abstract interface)
*
* Off-screen render target combining color texture attachments and
* depth/stencil attachments. Not part of the Buffer family (it composes
* textures and renderbuffers rather than holding raw data).
*/
class FrameBuffer {
public:
FrameBuffer() = default;
FrameBuffer(const FrameBuffer&) = delete;
auto operator=(const FrameBuffer&) -> FrameBuffer& = delete;

FrameBuffer(FrameBuffer&&) noexcept = default;
auto operator=(FrameBuffer&&) noexcept -> FrameBuffer& = default;

virtual ~FrameBuffer() = default;

/**
* @brief Attach a color texture to the given slot
*/
virtual auto attach_color_texture(const Texture& texture, int slot) -> void = 0;

/**
* @brief Detach the color texture from the given slot
*/
virtual auto detach_color_texture(int slot) -> void = 0;

/**
* @brief Attach a depth/stencil renderbuffer
*/
virtual auto attach_depth_stencil(const RenderBuffer& rbo) -> void = 0;

/**
* @brief Detach the depth/stencil attachment
*/
virtual auto detach_depth_stencil() -> void = 0;

/**
* @brief Check framebuffer completeness
*/
virtual auto check() -> void = 0;

/**
* @brief Set the viewport to the framebuffer's default size
*/
virtual auto set_viewport() -> void = 0;

/**
* @brief Set a custom viewport size
*/
virtual auto set_viewport(int width, int height) -> void = 0;

/**
* @brief Set a custom viewport with offset
*/
virtual auto set_viewport(int x, int y, int width, int height) -> void = 0;

/**
* @brief Bind as the current render target
*/
virtual auto bind() const -> void = 0;

/**
* @brief Unbind, reverting to the default framebuffer (screen)
*/
virtual auto unbind() const -> void = 0;
};

} // namespace gkit::graphic
37 changes: 37 additions & 0 deletions include/gkit/graphic/IndexBuffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include "gkit/graphic/Buffer.hpp"

#include <cstdint>
#include <utility>

namespace gkit::graphic {

/**
* @brief Index data buffer (frontend abstract interface)
*
* Stores draw-order index data for efficient indexed geometry rendering.
*/
class IndexBuffer : public Buffer {
public:
IndexBuffer() = default;
IndexBuffer(const IndexBuffer&) = delete;
auto operator=(const IndexBuffer&) -> IndexBuffer& = delete;

IndexBuffer(IndexBuffer&& other) noexcept : Buffer(std::move(other)) {}
auto operator=(IndexBuffer&& other) noexcept -> IndexBuffer& {
if (this != &other) {
Buffer::operator=(std::move(other));
}
return *this;
}

~IndexBuffer() override = default;

/**
* @brief Number of indices
*/
[[nodiscard]] virtual auto get_count() const -> uint32_t = 0;
};

} // namespace gkit::graphic
35 changes: 35 additions & 0 deletions include/gkit/graphic/RenderBuffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

namespace gkit::graphic {

/**
* @brief Renderbuffer (frontend abstract interface)
*
* Off-screen renderbuffer (OpenGL renderbuffer) that cannot be sampled
* directly by shaders; typically used as the depth/stencil attachment of
* a framebuffer. Not part of the Buffer family (it is a render-target
* attachment rather than a data buffer).
*/
class RenderBuffer {
public:
RenderBuffer() = default;
RenderBuffer(const RenderBuffer&) = delete;
auto operator=(const RenderBuffer&) -> RenderBuffer& = delete;

RenderBuffer(RenderBuffer&&) noexcept = default;
auto operator=(RenderBuffer&&) noexcept -> RenderBuffer& = default;

virtual ~RenderBuffer() = default;

/**
* @brief Bind to the current backend context
*/
virtual auto bind() const -> void = 0;

/**
* @brief Unbind
*/
virtual auto unbind() const -> void = 0;
};

} // namespace gkit::graphic
84 changes: 84 additions & 0 deletions include/gkit/graphic/RenderDevice.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#pragma once

#include "gkit/graphic/FrameBuffer.hpp"
#include "gkit/graphic/IndexBuffer.hpp"
#include "gkit/graphic/RenderBuffer.hpp"
#include "gkit/graphic/Shader.hpp"
#include "gkit/graphic/Texture.hpp"
#include "gkit/graphic/VertexArray.hpp"
#include "gkit/graphic/VertexBuffer.hpp"
#include "gkit/graphic/config.hpp"

#include <cstdint>
#include <memory>
#include <string>

namespace gkit::graphic {

/**
* @brief Backend identifier
*/
enum class Backend : std::uint8_t {
OpenGL,
// Vulkan // future
};

/**
* @brief Abstract render device: resource factory + render command entry
*
* Concrete backends (OpenGL/Vulkan) inherit and implement resource creation
* and render operations. Renderer owns a RenderDevice selected via create_device.
*/
class RenderDevice {
public:
RenderDevice(const RenderDevice&) = delete;
auto operator=(const RenderDevice&) -> RenderDevice& = delete;

RenderDevice() = default;
RenderDevice(RenderDevice&&) noexcept = default;
auto operator=(RenderDevice&&) noexcept -> RenderDevice& = default;

virtual ~RenderDevice() = default;

// ---- Resource factory ----

virtual auto create_vertex_buffer(const void* data, uint32_t size, bool dynamic)
-> std::unique_ptr<VertexBuffer> = 0;
virtual auto create_index_buffer(const uint32_t* data, uint32_t count) -> std::unique_ptr<IndexBuffer> = 0;
virtual auto create_shader(const std::string& filepath) -> std::unique_ptr<Shader> = 0;
/**
* @brief Create a texture; empty until the resource module is ready (see RHI design doc §4.4/§4.5)
*/
virtual auto create_texture() -> std::unique_ptr<Texture> = 0;
virtual auto create_vertex_array() -> std::unique_ptr<VertexArray> = 0;
virtual auto create_frame_buffer(int width, int height) -> std::unique_ptr<FrameBuffer> = 0;
virtual auto create_render_buffer(int width, int height) -> std::unique_ptr<RenderBuffer> = 0;
// future: create_storage_buffer() / create_uniform_buffer()

// ---- Render command entry ----

/**
* @brief Clear the current render target
*/
virtual auto clear(ClearFlags flags) -> void = 0;

/**
* @brief Draw indexed geometry
*/
virtual auto draw(const VertexArray& va, const IndexBuffer& ib, const Shader& shader) -> void = 0;

/**
* @brief Draw instanced indexed geometry
*/
virtual auto draw_instance(const VertexArray& va,
const IndexBuffer& ib,
const Shader& shader,
uint32_t instance_count) -> void = 0;
};

/**
* @brief Backend factory - the single switch point across the project
*/
auto create_device(Backend backend) -> std::unique_ptr<RenderDevice>;

} // namespace gkit::graphic
36 changes: 23 additions & 13 deletions include/gkit/graphic/Renderer.hpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#pragma once

#include "gkit/core/templates/singleton.hpp"
#include "gkit/graphic/Shader.hpp"
#include "gkit/graphic/opengl/IndexBuffer.hpp"
#include "gkit/graphic/opengl/VertexArray.hpp"
#include "gkit/graphic/opengl/config.hpp"
#include "gkit/graphic/RenderDevice.hpp"
#include "gkit/graphic/config.hpp"

#include <cstdint>
#include <memory>

/**
* @brief Renderer class providing public rendering interface
*
* The Renderer provides a unified interface for rendering operations.
* Uses singleton pattern for global access.
* Holds a RenderDevice selected via init(Backend).
*/
namespace gkit::graphic {

Expand All @@ -23,23 +23,27 @@ namespace gkit::graphic {
Renderer() = default;

public:
/**
* @brief Select the render backend and create the device (defaults to OpenGL)
* @param backend backend identifier
*/
auto init(Backend backend = Backend::OpenGL) -> void;

/**
* @brief Clear the current framebuffer
*
* @param flags Bitmask specifying which buffers to clear (e.g., ClearFlags::Color | ClearFlags::Depth)
* Defaults to ClearFlags::All (clears all buffers)
*/
auto clear(opengl::ClearFlags flags = opengl::ClearFlags::All) const -> void;
auto clear(ClearFlags flags = ClearFlags::All) -> void;

/**
* @brief Draw indexed geometry
* @param va Vertex array containing vertex data
* @param ib Index buffer containing indices
* @param shader Shader program to use for rendering
*/
auto draw(const gkit::graphic::opengl::VertexArray& va,
const gkit::graphic::opengl::buffer::IndexBuffer& ib,
const gkit::graphic::Shader& shader) const -> void;
auto draw(const VertexArray& va, const IndexBuffer& ib, const Shader& shader) -> void;

/**
* @brief Draw multiple instances of indexed geometry
Expand All @@ -48,10 +52,16 @@ namespace gkit::graphic {
* @param shader Shader program to use for rendering
* @param instance_count Number of instances to draw
*/
auto draw_instance(const gkit::graphic::opengl::VertexArray& va,
const gkit::graphic::opengl::buffer::IndexBuffer& ib,
const gkit::graphic::Shader& shader,
uint32_t instance_count) const -> void;
auto draw_instance(const VertexArray& va, const IndexBuffer& ib, const Shader& shader, uint32_t instance_count)
-> void;

/**
* @brief Access the current render device
*/
[[nodiscard]] auto get_device() -> RenderDevice&;

private:
std::unique_ptr<RenderDevice> device;
};

} // namespace gkit::graphic
} // namespace gkit::graphic
Loading
Loading