Install
$ agentstack add skill-nebulavenus-forge-gpu-dev-gpu-lesson ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Create a new GPU lesson for the forge-gpu project. Every GPU lesson uses forge_scene.h for the rendering baseline (shadow map, Blinn-Phong lighting, grid floor, sky gradient, FPS camera, UI). The lesson focuses entirely on its subject matter, not rendering plumbing.
The user will provide:
- Number: two-digit lesson number (e.g. 02)
- Name: short kebab-case name (e.g. first-triangle)
- Description: what the lesson teaches
If any of these are missing, ask the user before proceeding.
Steps
- Start from a clean main branch:
Before creating any files, ensure we're working from the latest main:
``bash git checkout main git pull origin main ``
This avoids conflicts from stale branches and ensures the new lesson builds on top of the latest project state.
- Determine what math is needed:
- Will this lesson use vectors (positions, colors, directions)?
- Will it use matrices (transformations, rotations)?
- Check if the math library (
common/math/forge_math.h) has what you need - If new math operations are needed, use
/dev-math-lessonto add them first
- Create the lesson directory:
lessons/gpu/$ARGUMENTS[0]-$ARGUMENTS[1]/
- Create main.c using the SDL callback architecture:
#define SDL_MAIN_USE_CALLBACKS 1before includes- Always use
forge_scene.hfor the rendering baseline. See the
forge-scene-renderer skill for the full API.
- Include required headers:
```c #include #include #include / offsetof / #include "math/forge_math.h"
#define FORGESCENEIMPLEMENTATION #include "scene/forge_scene.h" ```
SDL_AppInit— create GPU device, window, claim swapchain, allocate app_stateSDL_AppEvent— handle SDLEVENTQUIT (return SDLAPPSUCCESS)SDL_AppIterate— per-frame GPU workSDL_AppQuit— cleanup in reverse order, SDLfree the appstate- Use
SDL_calloc/SDL_freefor app_state (not malloc/free) - Every SDL GPU call gets error handling with
SDL_Logand descriptive messages - Check every SDL function that returns
bool—SDL_SubmitGPUCommandBuffer,
SDL_SetGPUSwapchainParameters, SDL_AcquireGPUSwapchainTexture, etc. all return false on failure. Log a descriptive error (include the function name) and clean up or early-return. Never ignore a bool return value.
- Use
#define WINDOW_WIDTH 1280and#define WINDOW_HEIGHT 720(16:9).
All lessons use this standard size for consistent screenshots.
- No magic numbers in production/library code —
#defineorenum
everything. In lesson files, inline numeric literals are acceptable when one-off demonstration values improve readability (e.g. vertex positions, color components, sample coordinates)
- Extensive comments explaining why and purpose, not just what —
every pipeline setting, resource binding, and API call should have a brief comment stating why that choice was made (e.g. why CULLMODE_NONE, why TRIANGLELIST, why we push uniforms each frame). This is a recurring PR review requirement.
- Use C99, matching SDL's own style
- Use math library types for all math operations (see "Using the Math Library" below)
- Create CMakeLists.txt:
```cmake addexecutable(NN-name WIN32 main.c) targetincludedirectories(NN-name PRIVATE ${FORGECOMMONDIR}) targetlinklibraries(NN-name PRIVATE SDL3::SDL3) forgetarget_assets(NN-name)
if(TARGET SDL3::SDL3-shared) addcustomcommand(TARGET NN-name POSTBUILD COMMAND ${CMAKECOMMAND} -E copyifdifferent $ $ VERBATIM ) endif() ```
Create forge-assets.toml next to CMakeLists.txt declaring which processed assets the lesson needs:
``toml [assets] dirs = [ "fonts/liberation_mono", "models/ModelName = ModelName", ] ``
See [pipeline/README.md](../../../pipeline/README.md#build-integration) for the full manifest reference.
- Create README.md following this structure:
# Lesson NN — Title## What you'll learn— bullet list of concepts## Result— screenshot/GIF first (captured in step 11), then describe what the reader will see## Key concepts— explain each new API concept introduced## Math— if the lesson uses math operations, link to relevant math lessons## Building— standard cmake build instructions## AI skill— mention the matching skill created in step 10, with a
relative link to .claude/skills//SKILL.md, the /skill-name invocation, and a note that users can copy it into their own projects
## Exercises— 3-4 exercises that extend the lesson
- Update the root CMakeLists.txt: add
add_subdirectory(lessons/gpu/NN-name)under "GPU Lessons"
- Update PLAN.md: check off the lesson if it was listed, or add it
- Build and test: run
cmake --build build --config Debugand verify it runs
- Capture a screenshot: Use the
/dev-add-screenshotskill to capture a screenshot
and embed it in the lesson README. Every lesson must have a visual in the "Result" section so readers can see what they're building before diving into code.
``bash python scripts/capture_lesson.py lessons/gpu/NN-name ``
Verify the image is in lessons/gpu/NN-name/assets/ and the README references it with ``.
- Create a matching skill: add
.claude/skills//SKILL.mdthat
distills the lesson into a reusable pattern with YAML frontmatter
- Run markdown linting: Use the
/dev-markdown-lintskill to verify all markdown files pass linting:
``bash npx markdownlint-cli2 "**/*.md" ``
If errors found, auto-fix first then manually fix remaining issues (especially MD040 language tags)
Using the Math Library
CRITICAL: GPU lessons must use the math library (common/math/forge_math.h) for all math operations. Never write bespoke math in GPU lessons.
Vertex data structures
Always use math library types for vertex attributes:
typedef struct Vertex {
vec2 position; /* NOT float x, y */
vec3 color; /* NOT float r, g, b */
} Vertex;
HLSL mapping:
vec2in C →float2in HLSL shadervec3in C →float3in HLSL shadervec4in C →float4in HLSL shader- Memory layout is identical — no conversion needed
Vertex attribute setup
vertex_attributes[0].offset = offsetof(Vertex, position); /* NOT offsetof(Vertex, x) */
vertex_attributes[1].offset = offsetof(Vertex, color); /* NOT offsetof(Vertex, r) */
Initializing vertex data
Use designated initializers with math library types:
static const Vertex vertices[] = {
{ .position = { 0.0f, 0.5f }, .color = { 1.0f, 0.0f, 0.0f } },
/* ... */
};
Or use constructor functions explicitly:
Vertex v;
v.position = vec2_create(0.0f, 0.5f);
v.color = vec3_create(1.0f, 0.0f, 0.0f);
Common math operations
Transformations:
mat4 rotation = mat4_rotate_z(angle);
mat4 translation = mat4_translate(vec3_create(x, y, z));
mat4 scale = mat4_scale(vec3_create(sx, sy, sz));
Vector operations:
vec3 sum = vec3_add(a, b);
vec3 normalized = vec3_normalize(v);
float distance = vec3_length(vec3_sub(target, position));
When you need new math
If the math library doesn't have an operation you need:
- Check
common/math/forge_math.h— might already exist - Check
lessons/math/— might have a lesson teaching it - Use
/dev-math-lessonto add it:
``bash /dev-math-lesson 02 quaternions "Quaternion rotations" ``
- This creates: math lesson + library update + documentation
Cross-referencing math lessons
In the lesson README, add a "Math" section linking to relevant math lessons:
## Math
This lesson uses:
- **Vectors** — [Math Lesson 01](../math/01-vectors/) for positions and colors
- **Matrices** — [Math Lesson 05](../math/05-matrices/) for rotations
Diagrams and Formulas
Find opportunities to create compelling diagrams and visualizations via the matplotlib scripts — they increase reader engagement and help learners understand the topics being taught. Use the /dev-create-diagram skill to add diagrams following the project's visual identity and quality standards.
Matplotlib diagrams
For geometric or visual diagrams (UV mapping, filtering comparison), add a diagram function to scripts/forge_diagrams/gpu/lesson_NN.py (create the file if it doesn't exist):
- Write a function following the existing pattern (shared
setup_axes,
draw_vector, save helpers from _common.py)
- Re-export from
scripts/forge_diagrams/gpu/__init__.py - Import and register in the
DIAGRAMSdict in__main__.pywith the lesson key (e.g."gpu/04") - Run
python scripts/forge_diagrams --lesson gpu/NNto generate the PNG - Reference in the README: ``
Mermaid diagrams
For flow/pipeline diagrams (texture upload flow, MVP pipeline), use inline mermaid blocks — GitHub renders them natively:
````markdown
flowchart LR
A[Step 1] -->|transform| B[Step 2] --> C[Step 3]
````
Use mermaid for sequential flows.
KaTeX math
For formulas, use inline $...$ and display $$...$$ math notation:
- Inline:
$\text{MVP} = P \times V \times M$ - Display math blocks must be split across three lines (CI enforces this):
$$
x_{\text{screen}} = \frac{x \cdot n}{-z}
$$
Keep worked examples (step-by-step with numbers) in `text blocks.
MANDATORY: Chunked writes for main.c
ALL GPU lesson main.c files MUST use the chunked-write pattern. Task agents have a 32K output token limit per Write call. A single Write over ~800 lines fails silently — the file is never created and all work is lost. This is a fatal error that wastes hours of work.
Required workflow:
- Create a
PLAN.mdin the lesson directory (lessons/gpu/NN-name/PLAN.md)
with a "main.c Decomposition" section before any coding agent starts writing. Specify what goes in each chunk. This is the lesson-local plan, NOT the root PLAN.md.
- Split into 3-4 parts (~400-600 lines each). Write each to
/tmp/, then
concatenate with cat.
- Agent A (header + helpers + structs) runs first. Agents B and C run in
parallel after A completes.
Recovery rule — if a coding agent fails with a token limit error:
- NEVER write a fallback or simplified
main.c. This destroys all the
planning and coding work.
- STOP immediately and report the failure to the user.
- Re-plan using the chunked approach and re-run with decomposed agents.
See [.claude/large-file-strategy.md](../../../.claude/large-file-strategy.md) for the full strategy and decomposition template.
Asset Pipeline Mandate (GPU Lessons 39+)
All GPU lessons numbered 39 and above must use pipeline-processed assets. No bespoke asset handling is allowed — all assets flow through the pipeline and are declared via forge-assets.toml manifests.
- All geometry MUST come from
forge_shapes_*()(procedural) or
forge_pipeline_load_mesh() on pipeline-processed assets.
- NEVER define inline vertex arrays for 3D objects.
- NEVER load raw unprocessed assets — use
forge_pipeline_load_mesh()/
forge_pipeline_load_texture() which load from assets/processed/.
- Individual textures are BC7 (albedo) or BC5 (normal maps) — shaders must
reconstruct normal Z from BC5 two-channel data. Texture atlases that combine albedo and normal maps into a single image use BC7 for both; the BC5 two-channel rule does not apply to atlas textures.
- If a lesson needs a new model, add it to
assets/models/, run
uv run python -m pipeline, and load the processed output.
- Reference
lessons/assets/when first introducing an asset. - Purely procedural shader lessons (fullscreen effects) are exempt.
- CMake: use
forge_target_assets(lesson_XX)— this reads the
forge-assets.toml manifest and handles the forge-assets dependency and all post-build copies automatically.
- NEVER write bespoke CMake asset logic — no
add_custom_commandfor
copying fonts, models, or textures. No file(GLOB) for textures. No direct invocations of forge_mesh_tool or forge_scene_tool. All of this is handled by the pipeline and the manifest.
- **NEVER copy assets from
${FORGE_ASSETS_DIR}or
${CMAKE_CURRENT_SOURCE_DIR}/assets** — all runtime assets come from ${FORGE_PROCESSED_DIR} via the manifest. Lesson-local assets/ directories hold only screenshots and diagrams for the README.
Code style reminders
- Naming:
PascalCasefor typedefs (e.g.Vertex,GpuPrimitive),
lowercase_snake_case for local variables and functions (e.g. app_state), UPPER_SNAKE_CASE for #define constants, Prefix_PascalCase for public API types (e.g. ForgeCapture) and prefix_snake_case for public API functions (e.g. forge_capture_init)
- The
app_statestruct holds all state passed between callbacks - Build on previous lessons — reference what was introduced before
- Each lesson should introduce ONE new concept at a time
- Always use the math library — no bespoke math in GPU lessons
- Link to math lessons when explaining concepts
- Never extract assets from glTFs à la carte — for lessons 01–38 that
use raw glTF models, copy the complete model (.gltf, .bin, and all referenced textures) into the lesson's assets/ directory and load it with forge_gltf_load(). For lessons 39+, see the Asset Pipeline Mandate above — use forge_pipeline_load_mesh() instead of raw glTF loading.
- Always check SDL return values — every SDL GPU function that returns
bool must be checked. Log the function name and SDL_GetError() on failure, then clean up resources and early-return. This includes SDL_SubmitGPUCommandBuffer, SDL_SetGPUSwapchainParameters, SDL_ClaimWindowForGPUDevice, SDL_Init, and others. This is a recurring PR review item — get it right the first time.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Nebulavenus
- Source: Nebulavenus/forge-gpu
- License: Zlib
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.