Skip to main content

dev-gpu-lesson

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

الانتقال إلى التثبيت

معلومات المصدر

المستودع
Nebulavenus/forge-gpu
آخر نشاط في المصدر
٢٧ مارس ٢٠٢٦ في ٢٠:٥٥
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٣٨
التفرعات
٧

خيارات التثبيت

يُحدَّد 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