Skip to main content

dev-gpu-lesson

Scaffold a new GPU lesson using forge_scene.h for the rendering baseline

설치로 이동

소스 정보

저장소
Nebulavenus/forge-gpu
최근 소스 활동
2026년 3월 27일 20:55
감지된 SKILL.md 언어
영어
스타
38
포크
7

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
dev-gpu-lesson
description
Scaffold a new GPU lesson using forge_scene.h for the rendering baseline
argument-hint
[number] [name] [description]
disable-model-invocation
true
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 1. **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. 2. **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-lesson` to add them first 3. **Create the lesson directory**: `lessons/gpu/$ARGUMENTS[0]-$ARGUMENTS[1]/` 4. **Create main.c** using the SDL callback architecture: - `#define SDL_MAIN_USE_CALLBACKS 1` before includes - **Always use `forge_scene.h`** for the rendering baseline. See the `forge-scene-renderer` skill for the full API. - Include required headers: ```c #include <SDL3/SDL.h> #include <SDL3/SDL_main.h> #include <stddef.h> /* offsetof */ #include "math/forge_math.h" #define FORGE_SCENE_IMPLEMENTATION #include "scene/forge_scene.h" ``` - `SDL_AppInit` — create GPU device, window, claim swapchain, allocate app_state - `SDL_AppEvent` — handle SDL_EVENT_QUIT (return SDL_APP_SUCCESS) - `SDL_AppIterate` — per-frame GPU work - `SDL_AppQuit` — cleanup in reverse order, SDL_free the app_state - Use `SDL_calloc` / `SDL_free` for app_state (not malloc/free) - Every SDL GPU call gets error handling with `SDL_Log` and 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 1280` and `#define WINDOW_HEIGHT 720` (16:9). All lessons use this standard size for consistent screenshots. - No magic numbers in production/library code — `#define` or `enum` 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) 5. **Create CMakeLists.txt**: ```cmake add_executable(NN-name WIN32 main.c) target_include_directories(NN-name PRIVATE ${FORGE_COMMON_DIR}) target_link_libraries(NN-name PRIVATE SDL3::SDL3) forge_target_assets(NN-name) if(TARGET SDL3::SDL3-shared) add_custom_command(TARGET NN-name POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:SDL3::SDL3-shared> $<TARGET_FILE_DIR:NN-name> 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. 6. **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/<topic>/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 7. **Update the root CMakeLists.txt**: add `add_subdirectory(lessons/gpu/NN-name)` under "GPU Lessons" 8. **Update PLAN.md**: check off the lesson if it was listed, or add it 9. **Build and test**: run `cmake --build build --config Debug` and verify it runs 10. **Capture a screenshot**: Use the `/dev-add-screenshot` skill 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 `![Lesson NN screenshot](assets/screenshot.png)`. 11. **Create a matching skill**: add `.claude/skills/<topic>/SKILL.md` that distills the lesson into a reusable pattern with YAML frontmatter 12. **Run markdown linting**: Use the `/dev-markdown-lint` skill 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:** ```c typedef struct Vertex { vec2 position; /* NOT float x, y */ vec3 color; /* NOT float r, g, b */ } Vertex; ``` **HLSL mapping:** - `vec2` in C → `float2` in HLSL shader - `vec3` in C → `float3` in HLSL shader - `vec4` in C → `float4` in HLSL shader - Memory layout is identical — no conversion needed ### Vertex attribute setup ```c 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: ```c static const Vertex vertices[] = { { .position = { 0.0f, 0.5f }, .color = { 1.0f, 0.0f, 0.0f } }, /* ... */ }; ``` Or use constructor functions explicitly: ```c Vertex v; v.position = vec2_create(0.0f, 0.5f); v.color = vec3_create(1.0f, 0.0f, 0.0f); ``` ### Common math operations **Transformations:** ```c 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:** ```c 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: 1. Check `common/math/forge_math.h` — might already exist 2. Check `lessons/math/` — might have a lesson teaching it 3. Use `/dev-math-lesson` to add it: ```bash /dev-math-lesson 02 quaternions "Quaternion rotations" ``` 4. This creates: math lesson + library update + documentation ### Cross-referencing math lessons In the lesson README, add a "Math" section linking to relevant math lessons: ```markdown ## 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): 1. Write a function following the existing pattern (shared `setup_axes`, `draw_vector`, `save` helpers from `_common.py`) 2. Re-export from `scripts/forge_diagrams/gpu/__init__.py` 3. Import and register in the `DIAGRAMS` dict in `__main__.py` with the lesson key (e.g. `"gpu/04"`) 4. Run `python scripts/forge_diagrams --lesson gpu/NN` to generate the PNG 5. Reference in the README: `![Description](assets/diagram_name.png)` ### Mermaid diagrams For **flow/pipeline diagrams** (texture upload flow, MVP pipeline), use inline mermaid blocks — GitHub renders them natively: ````markdown ```mermaid 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): ```text $$ 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:** 1. Create a `PLAN.md` in 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`. 2. Split into 3-4 parts (~400-600 lines each). Write each to `/tmp/`, then concatenate with `cat`. 3. 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_command` for 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: `PascalCase` for 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_state` struct 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`,
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기