Stylizer::API is a modern C++ graphics API. It provides a clean, RAII-friendly API for managing GPU resources, rendering pipelines, shaders, surfaces, and error handling.
The library is designed to minimize boilerplate and maximize safety by leveraging C++ idioms such as smart handle like wrappers (auto_release) and unified error reporting.
-
Error Handling Centralized, severity-aware error reporting system with user-defined handlers.
-
RAII Resource Management Automatic cleanup of GPU objects, surfaces, and other resources via
auto_release. -
SDL3 and GLFW Integration Easily create rendering surfaces from
SDL_WindoworGLFWwindow*. -
Works on Major Desktop Platforms (WiP)
- Windows (theoretical)
- Linux (tested)
- Mac (theoretical)
-
Multiple Supported Backends (WiP)
- WebGPU (Vulkan, DirectX, Metal, OpenGL)
-
Shader Management (WiP) Compile shaders from multiple common languages:
- SPIR-V
- WGSL
- Slang
-
Add Stylizer.API to your cmake project:
set(CMAKE_CXX_STANDARD 26) add_subdirectory(stylizer.api) target_link_libraries(app PUBLIC stylizer::api::webgpu) # Swap webgpu with whichever backend you prefer
-
Optionally install extra dependencies:
Below is a minimal example showing how to initialize SDL, set up a WebGPU surface, compile a WGSL shader, and render a triangle:
#include "sdl3.hpp"
#include <GL/gl.h>
#include <iostream>
#include <webgpu/webgpu.hpp>
int main() {
using namespace stylizer::api::operators;
// Error handler setup
auto& errors = stylizer::get_error_handler();
stylizer::auto_release c = errors.connect([](stylizer::api::error::severity severity, std::string_view message, size_t) {
if (severity >= stylizer::api::error::severity::Error)
throw stylizer::api::error(message);
std::cerr << message << std::endl;
});
// Initialize SDL
if (!SDL_Init(SDL_INIT_VIDEO)) {
errors(stylizer::api::error::severity::Error, "Failed to initialize SDL", 0);
return -1;
}
SDL_Window* window = SDL_CreateWindow("Stylizer.API Test", 800, 600, 0);
if (!window) {
errors(stylizer::api::error::severity::Error, "Failed to create SDL window", 0);
return -1;
}
// Create surface + device
stylizer::auto_release<stylizer::api::current_backend::device> device;
stylizer::auto_release<stylizer::api::current_backend::surface> surface;
std::tie(device, surface) = stylizer::api::sdl3::create_surface_and_device<stylizer::api::current_backend::device, stylizer::api::current_backend::surface>(window);
surface.configure(device, surface.determine_optimal_default_config(device, {800, 600}));
// Compile WGSL shader
stylizer::auto_release shader = device.create_shader_from_source(
stylizer::api::shader::language::WGSL,
R"(
@vertex
fn vertex(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4f {
var p = vec2f(0.0, 0.0);
if (in_vertex_index == 0u) {
p = vec2f(-0.5, -0.5);
} else if (in_vertex_index == 1u) {
p = vec2f(0.5, -0.5);
} else {
p = vec2f(0.0, 0.5);
}
return vec4f(p, 0.0, 1.0);
}
@fragment
fn fragment() -> @location(0) vec4f {
return vec4f(1.0, 0.4, 1.0, 1.0);
})");
// Render pipeline
std::vector<stylizer::api::color_attachment> color_attachments = {{
.texture_format = surface.configured_texture_format(device),
.clear_value = {{.3f, .5f, 1}},
}};
stylizer::auto_release pipeline = device.create_render_pipeline(
{
{stylizer::api::shader::stage::Vertex, {&shader, "vertex"}},
{stylizer::api::shader::stage::Fragment, {&shader, "fragment"}}
},
color_attachments
);
// Main loop
bool should_close = false;
while (!should_close) {
for (SDL_Event event; SDL_PollEvent(&event);) switch (event.type) {
break; case SDL_EVENT_QUIT:
should_close = true;
}
device.process_events();
try {
auto texture = std::unique_ptr<stylizer::api::texture>(
surface.next_texture(stylizer::api::temporary_return, device).move_temporary_to_heap()
);
color_attachments[0].texture = texture.get();
device.create_render_pass(color_attachments, {}, true)
.bind_render_pipeline(device, pipeline)
.draw(device, 3)
.one_shot_submit(device);
surface.present(device);
} catch(stylizer::api::surface::texture_acquisition_failed fail) {
std::cerr << fail.what() << std::endl;
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}- A modern C++26 compiler
- magic_enum
- std::math
- signals
- SLCross (Slang, Tint, GLSLang)
- Dawn (if building for WebGPU)
MIT License. See LICENSE for details.