#pragma once #include "core/memory.h" #include #include #include #include #include namespace Donut::rhi { enum class Format { RGBA8, RGBA16F, D32, }; enum class BufferType { Vertex, Index, Uniform }; enum class Topology { Triangles, Lines }; enum class CullMode { None, Back, Front }; enum class BlendMode { Opaque, AlphaBlend }; enum class CompareOp { Always, Less, LessEqual }; enum class Filter { Nearest, Linear }; struct VertexAttribute { uint32_t location; uint32_t components; uint32_t offset; }; struct VertexLayout { uint32_t stride = 0; std::vector attributes; }; enum class ResourceKind { UniformBuffer, Texture }; struct ResourceSlot { ResourceKind kind; uint32_t binding; }; class Buffer { public: virtual ~Buffer() = default; virtual auto update(const void* data, size_t size) -> void = 0; }; class Texture { public: virtual ~Texture() = default; }; class Pipeline{ public: virtual ~Pipeline() = default; }; class RenderTarget { public: virtual ~RenderTarget() = default; virtual auto width() const -> int = 0; virtual auto height() const -> int = 0; virtual auto color_texture() -> Texture* = 0; }; struct PipelineDesc { std::string shader; VertexLayout vertex_layout; std::vector resources; Topology topology = Topology::Triangles; CullMode cull = CullMode::None; BlendMode blend = BlendMode::Opaque; bool depth_test = false; bool depth_write = false; CompareOp depth_op = CompareOp::Less; Format color_format = Format::RGBA8; bool has_depth = false; }; class CommandList { public: virtual ~CommandList() = default; virtual auto begin_render_pass(RenderTarget* target, const glm::vec4& clear) -> void = 0; virtual auto end_render_pass() -> void = 0; virtual auto bind_pipeline(Pipeline* pipeline) -> void = 0; virtual auto set_viewport(int x, int y, int w, int h, bool flip_y = false) -> void = 0; virtual auto bind_uniform(uint32_t binding, Buffer* ubo) -> void = 0; virtual auto bind_texture(uint32_t binding, Texture* texture) -> void = 0; virtual auto bind_vertex_buffer(Buffer* vb) -> void = 0; virtual auto bind_index_buffer(Buffer* ib) -> void = 0; virtual auto draw(uint32_t vertex_count) -> void = 0; virtual auto draw_indexed(uint32_t index_count) -> void = 0; }; class Device { public: virtual ~Device() = default; virtual auto init(void* glfwWindow, int width, int height) -> bool = 0; virtual auto shutdown() -> void = 0; virtual auto resize(int width, int height) -> void = 0; virtual auto wait_idle() -> void = 0; virtual auto create_buffer(BufferType type, size_t size, const void* data = nullptr) -> Ref = 0; virtual auto create_texture(int width, int height, Format format, Filter filter, const void* data = nullptr) -> Ref = 0; virtual auto create_cubemap_from_hdri(const std::string& equirect_path) -> Ref = 0; virtual auto create_render_target(int width, int height, Format color, bool with_depth, Filter sample_filter = Filter::Linear, int mip_levels = 1) -> Ref = 0; virtual auto create_pipeline(const PipelineDesc& desc) -> Ref = 0; virtual auto begin_frame(const glm::vec4& clear) -> CommandList* = 0; virtual auto end_frame() -> void = 0; virtual auto record_offscreen(const std::function& record) -> void = 0; virtual auto init_imgui() -> void = 0; virtual auto imgui_new_frame() -> void = 0; virtual auto imgui_render(CommandList& swapchain_cmds) -> void = 0; virtual auto device_name() const -> const std::string& = 0; }; }