Flint Engine
Modular C++20 2D game engine powered by SDL3
Loading...
Searching...
No Matches
renderer.h
1// SPDX-License-Identifier: MIT
2// SPDX-FileCopyrightText: 2025-2026 Manuel Osorio
3#pragma once
4
5#include "flint/camera/camera.h"
6#include "flint/core/asset-loader.h"
7#include "flint/graphics/drawable.h"
8#include "flint/graphics/pipelines/batch-pipeline.h"
9#include "flint/graphics/pipelines/primitives-pipeline.h"
10#include "flint/graphics/pipelines/ui-pipeline.h"
11#include "flint/graphics/types/color.h"
12#include "flint/window/IWindow.h"
13
14#include <SDL3/SDL_gpu.h>
15#include <SDL3/SDL_render.h>
16
17#include <functional>
18#include <memory>
19#include <string>
20#include <vector>
21
22namespace Flint {
23 struct FrameData;
24
40 public:
48 explicit GPURenderer(IWindow *window, IAssetLoader &assetLoader, ShaderFormat shaderFormat);
49 virtual ~GPURenderer();
50
58 bool beginFrame();
59
71 void draw(const std::function<void(RenderQueue &)> &overlayEmit = {});
77 void endFrame();
78
85 void submit(std::shared_ptr<const Drawable> drawable, DrawLayer layer = DrawLayer::Midground);
86
96 [[deprecated("Use submit(std::shared_ptr<const Drawable>, DrawLayer) instead.")]]
97 void submit(const Drawable *drawable, DrawLayer layer = DrawLayer::Midground);
98
103 void setClearColor(Color color);
104
109 void setViewport(const SDL_GPUViewport &viewport);
110
115 void setCamera(const Camera &camera);
116
121 [[nodiscard]] std::unique_ptr<Shader> createShader() const {
122 return std::make_unique<Shader>(m_gpuDevice, m_shaderFormat);
123 }
124
130 [[nodiscard]] std::vector<char> loadShader(const std::string &basePath) const;
131
137 [[nodiscard]] std::string getShaderPath(const std::string &basePath) const;
138
140 [[nodiscard]] ShaderFormat getShaderFormat() const {
141 return m_shaderFormat;
142 }
143
151 [[deprecated("Do not query getRenderPass() during emission. Use RenderQueue::custom() for "
152 "custom GPU draw passes.")]] [[nodiscard]] SDL_GPURenderPass *
154 return m_renderPass;
155 }
156
161 void setGPUPresentMode(SDL_GPUPresentMode mode) {
162 if (mode != SDL_GPU_PRESENTMODE_VSYNC &&
163 !SDL_WindowSupportsGPUPresentMode(m_gpuDevice, m_sdlWindow, mode)) {
164 FLINT_ENGINE_WARN("Present mode {} unsupported, falling back to VSYNC",
165 static_cast<int>(mode));
166 mode = SDL_GPU_PRESENTMODE_VSYNC;
167 }
168 if (!SDL_SetGPUSwapchainParameters(m_gpuDevice, m_sdlWindow,
169 SDL_GPU_SWAPCHAINCOMPOSITION_SDR, mode)) {
170 FLINT_ENGINE_ERROR("SDL_SetGPUSwapchainParameters failed: {}", SDL_GetError());
171 }
172 }
173
181 [[deprecated(
182 "Do not query getCommandBuffer() during emission. Use RenderQueue::deferUpload() or "
183 "RenderQueue::custom().")]] [[nodiscard]] SDL_GPUCommandBuffer *
185 return m_commandBuffer;
186 }
187
189 [[nodiscard]] const FloatRect &getCurrentCameraView() const {
190 return m_currentCameraView;
191 }
192
194 [[nodiscard]] SDL_GPUDevice *getGPUDevice() const {
195 return m_gpuDevice;
196 }
197
199 [[nodiscard]] IAssetLoader &getAssetLoader() const {
200 return m_assetLoader;
201 }
202
204 [[nodiscard]] const SDL_GPUViewport &getDefaultViewport() const {
205 return m_defaultViewport;
206 }
207
210 [[nodiscard]] SDL_Renderer *getSDLRenderer() const;
211
213 [[nodiscard]] UIPipeline &getUIPipeline() {
214 return m_uiPipeline;
215 }
216
219 return m_primitivePipeline;
220 }
221
223 [[nodiscard]] SDL_GPUTexture *getWhiteTexture() {
224 return m_defaultWhiteTexture;
225 }
226
227 private:
228 IWindow *m_iWindow = nullptr;
229 SDL_Window *m_sdlWindow = nullptr;
230 ShaderFormat m_shaderFormat;
231 SDL_GPURenderPass *m_renderPass = nullptr;
232 SDL_GPUDevice *m_gpuDevice = nullptr;
233 SDL_GPUCommandBuffer *m_commandBuffer = nullptr;
234 SDL_GPUTexture *m_swapTexture = nullptr;
235 Uint32 m_swapWidth = 0, m_swapHeight = 0;
236
237 std::vector<DrawCommand> m_commands;
238 FloatRect m_currentCameraView = FloatRect({0, 0}, {320, 180});
239
240 UIPipeline m_uiPipeline;
241 BatchPipeline m_batchPipeline;
242 PrimitivePipeline m_primitivePipeline;
243
244 Color m_clearColor = {0, 0, 0, 255};
245
246 SDL_GPUTexture *m_defaultWhiteTexture = nullptr;
247 SDL_GPUSampler *m_defaultSampler = nullptr;
248 SDL_GPUViewport m_defaultViewport{};
249
250 IAssetLoader &m_assetLoader;
251
252 std::unique_ptr<FrameData>
253 m_frame;
254
259 bool uploadFrameBuffers();
260
271 void ensureBuffer(SDL_GPUBuffer *&buffer, Uint32 &capacity, Uint32 neededBytes,
272 SDL_GPUBufferUsageFlags usage, const char *debugName);
273
278 void resetFrameData();
279
283 void destroyFrameBuffers();
284
285 void createDefaultViewport(SDL_GPURenderPass *renderPass);
286 bool createDefaultTexture();
287 void initializePipelines();
288 void cleanupPipelines();
289 };
290
291}
Interface for objects that contribute ordered work to a rendered frame.
Definition drawable.h:21
ShaderFormat getShaderFormat() const
Get the active GPU shader format.
Definition renderer.h:140
void setCamera(const Camera &camera)
Update the active camera view transform used for batch coordinate projection.
PrimitivePipeline & getPrimitivePipeline()
Return reference to the primitive point/line pipeline wrapper.
Definition renderer.h:218
void draw(const std::function< void(RenderQueue &)> &overlayEmit={})
Execute all queued draw commands in layer and submission order.
SDL_GPURenderPass * getRenderPass() const
Return the current frame's active SDL GPU render pass handle.
Definition renderer.h:153
IAssetLoader & getAssetLoader() const
Return reference to the core asset loader.
Definition renderer.h:199
SDL_GPUCommandBuffer * getCommandBuffer() const
Return the current frame's active SDL GPU command buffer handle.
Definition renderer.h:184
SDL_GPUTexture * getWhiteTexture()
Return shared 1x1 fallback white GPU texture handle.
Definition renderer.h:223
std::unique_ptr< Shader > createShader() const
Factory method creating a new Shader instance bound to this GPU device.
Definition renderer.h:121
void setViewport(const SDL_GPUViewport &viewport)
Set or override the default rendering viewport.
void submit(const Drawable *drawable, DrawLayer layer=DrawLayer::Midground)
Queue a raw Drawable pointer for rendering in the current frame.
UIPipeline & getUIPipeline()
Return reference to the UI pipeline wrapper.
Definition renderer.h:213
void setClearColor(Color color)
Set the RGBA clear color applied at the start of each frame.
bool beginFrame()
Acquire the next swapchain texture and prepare the initial GPU command buffer.
void submit(std::shared_ptr< const Drawable > drawable, DrawLayer layer=DrawLayer::Midground)
Queue a shared Drawable for rendering in the current frame.
GPURenderer(IWindow *window, IAssetLoader &assetLoader, ShaderFormat shaderFormat)
Construct the renderer and initialize the underlying GPU device for the window.
void endFrame()
Close active render passes, submit the command buffer to the GPU, and present.
std::vector< char > loadShader(const std::string &basePath) const
Load raw shader bytecode bytes from the asset loader.
const FloatRect & getCurrentCameraView() const
Return the camera view rectangle used for the current frame projection.
Definition renderer.h:189
std::string getShaderPath(const std::string &basePath) const
Get the full asset path for a shader base name including system format extension.
void setGPUPresentMode(SDL_GPUPresentMode mode)
Configure GPU swapchain presentation mode for the window.
Definition renderer.h:161
const SDL_GPUViewport & getDefaultViewport() const
Return default full-screen viewport bounds.
Definition renderer.h:204
SDL_GPUDevice * getGPUDevice() const
Return the native SDL GPU device owned by this renderer.
Definition renderer.h:194
High-level SDL GPU renderer managing pipeline state, batching, and frame presentation.
Definition renderer.h:39
SDL_Renderer * getSDLRenderer() const
Return legacy SDL_Renderer handle if running alongside an SDL software fallback pass.
Abstract interface for loading raw asset data by path.
Abstract interface for a platform window.
Definition IWindow.h:27
Batches drawables into sorted geometry, primitive, and custom execution passes for GPURenderer.
Alpha-blended pipeline for rendering UI elements (text, panels, icons).
Definition ui-pipeline.h:36
RGBA color with 8-bit unsigned components.
Definition color.h:13