wgsl.runWGSL Öğren

Interaktif ders / Anatomi

WGSL Anatomi

Bu seri boş modülden çalışan shader modülüne doğru gider. Amaç WGSL dosyasının nasıl kurulduğunu, hangi declaration türlerinin nerede yaşayacağını ve entry point eklenince pipeline şeklinin nasıl değiştiğini görmektir.

01 / comment · whitespace

Yorumlar

Studio'da aç

WGSL iki tür yorum tanır: // satır sonuna kadar ve /* blok */. Blok yorumlar iç içe de olabilir — C/C++/JS'in aksine bu WGSL'in özelliği. Parser bunları görmezden gelir, sadece blankspace olarak sayar. Boş bir modül de geçerlidir; derler ama hiçbir şey çizmez.

Dene: blok yorumun içine başka bir /* … */ yerleştir — hâlâ derler. const X satırını sil; yine derler (modülde hiçbir şey olmak zorunda değil).
anatomi-01-yorumlar.wgslcomment · whitespace
// Bu bir line comment — parser görmez.
//
//   const X = 1;        ← yorum içindeki kod hâlâ yorum
//

/* Bu bir blok yorum, çoklu satır.
   /* WGSL blok yorumları İÇ İÇE olabilir — sayılır */
   parser yine görmez.
*/

// Aşağıda tek bir deklarasyon var:
const TEMP: f32 = 273.15;

02 / literal · suffix

Sayı literal'leri

Studio'da aç

WGSL sayıların tipini suffix'le belirtmene izin verir. 42 abstract int (bağlama göre i32 veya u32), 42u kesin u32, 3.14 abstract float, 3.14f kesin f32, 0x1Fu hex unsigned, 1.5e2 bilimsel gösterim. 0.5h f16 — ama önce enable f16; direktifi gerekir.

Dene: negatif literal — -1 aslında pozitif 1 + unary minus. 0xFF hex int dene. 0.5h'i aç → "f16 not enabled" hatası.
anatomi-02-sayi-literal-leri.wgslliteral · suffix
// WGSL sayı literal'leri — tip eki belirleyici:

const A: i32 = 42;          // int (whole numbers için varsayılan)
const B: u32 = 42u;         // unsigned int (suffix u)
const C: f32 = 3.14;        // float
const D: f32 = 3.14f;       // float (açık suffix)
const E: u32 = 0x1Fu;       // hex unsigned (= 31)
const F: f32 = 1.5e2;       // bilimsel (= 150.0)

// const G: f16 = 0.5h;     // f16 — enable f16; gerekir

03 / naming · reserved

Identifier kuralları

Studio'da aç

Identifier'lar harf veya _ ile başlamalı, sonrasında harf/rakam/_ gelebilir. $ izinli değil. İki ya da daha fazla underscore ile başlayan isimler (__foo) ya da tek underscore'la biten birkaç pattern reserved'dır — compiler hata atar. Tek _ ise özel: unused result ifadesi.

Dene: yorumlanmış geçersiz örneklerden birini aç ve hata mesajını oku.
anatomi-03-identifier-kurallari.wgslnaming · reserved
// Geçerli identifier'lar:
const myValue:  f32 = 1.0;
const my_value: f32 = 2.0;
const x1:       f32 = 3.0;
const _hidden:  f32 = 4.0;     // tek underscore başı OK

// Geçersiz olanları dene (yorumu kaldır):
// const __internal: f32 = 5.0;  // çift underscore RESERVED
// const $bad:       f32 = 1.0;  // $ karakteri yasak
// const 1bad:       f32 = 1.0;  // rakamla başlayamaz
// const my-name:    f32 = 1.0;  // tire yasak

04 / keyword · reserved

Anahtar kelime çakışması

Studio'da aç

WGSL ~30 keyword (anahtar kelime) ve onlarca reserved word (gelecek için ayrılmış) tanımlar. Bunları identifier olarak kullanırsan parser kafayı yer. let, var, const, fn, struct, if, else, for, while, loop, return, true, false, switch, override... hepsi rezerve.

Dene: yorumlu satırlardan birini aç — "expected identifier" ya da "unexpected keyword" hatası gelir. Bu, parser'ın o noktada bir isim beklemesinden.
anatomi-04-anahtar-kelime-cakismasi.wgslkeyword · reserved
// WGSL'de ayrılmış kelimeler identifier olamaz.

const value: f32 = 1.0;     // OK — 'value' ayrılmış değil

// Aşağıdakiler error verir (yorumu kaldır, gör):
// const let:    f32 = 1.0;    // 'let' anahtar kelime
// const fn:     f32 = 1.0;    // 'fn' anahtar kelime
// const struct: f32 = 1.0;    // 'struct' anahtar kelime
// const return: f32 = 1.0;    // 'return' anahtar kelime

05 / module scope · address space

const · var · override

Studio'da aç

Module scope'ta üç bildirim formu var: const (derleme zamanı sabit, tip otomatik veya açık), override (pipeline create sırasında JS'ten geçersiz kılınabilir), ve var<address_space> (yazılabilir, address space zorunlu — örn. private, workgroup). let sadece function scope'tadır — modülde yazarsan error.

Dene: en alttaki // let X = 1.0;'ı aç — "let declaration is not allowed at module scope" hatası gelir. override'ı JS'ten override etmek için pipeline create'te { constants: { BLUR: 2.5 } }.
anatomi-05-const-var-override.wgslmodule scope · address space
// Module scope: 3 bildirim formu

const PI: f32 = 3.14159;             // sabit, derleme zamanı
override BLUR: f32 = 1.0;            // pipeline anında set edilebilir
var<private> counter: i32 = 0;       // yazılabilir, address space lazım

// Kısa form (tip inferred):
const TAU = 6.28318;                 // tip f32 olarak çıkarılır

// Address space örnekleri:
// var<private>   counter: i32   — her invocation'a özel
// var<workgroup> shared:  array<f32, 64>  — workgroup paylaşımlı
// var<storage>   data:    array<f32>      — buffer'a bağlı

// 'let' module scope'ta YASAK — yorumu aç, hatayı gör:
// let X: f32 = 1.0;

06 / composite · attributes

Struct deklarasyonu

Studio'da aç

struct ad verilmiş alanlardan oluşan kompozit tip. Üye'ler @attribute taşıyabilir — örn. @location(0) vertex input'u, @align(16) hizalama. Constructor şeklinde çağırarak instance oluşturursun: Color(1.0, 0.0, 0.0).

Dene: Color'a a: f32 alanı ekle, RED constructor'ı 4 argümanlı yap. Tipler eşleşmezse parser hata verir.
anatomi-06-struct-deklarasyonu.wgslcomposite · attributes
// Struct: ad verilmiş alanlardan oluşan kompozit tip

struct Color {
  r: f32,
  g: f32,
  b: f32,
}

struct Vertex {
  @location(0) pos: vec3<f32>,
  @location(1) uv:  vec2<f32>,
}

// Constructor çağrısı:
const RED:  Color = Color(1.0, 0.0, 0.0);
const CYAN: Color = Color(0.13, 0.83, 0.93);

// Struct alanı '.' ile erişilir (sadece function scope'ta):
// fn foo() { let r = RED.r; }

07 / function · let · var

Function & yerel scope

Studio'da aç

Function scope'ta let (immutable) ve scope-yerel var (mutable, address space ZORUNLU değil — varsayılan function) izinli. Module scope'taki const/struct/var'lar buradan görünür. Function içindeki bildirimler dışarıdan görünmez — scope'lar tek yönlü.

Dene: area içindeki let r2'yi var r2 yap, sonra r2 = r2 * 2.0; ile yeniden ata. let ile yapamazsın.
anatomi-07-function-yerel-scope.wgslfunction · let · var
// Function scope: let ve var burada serbest

const PI: f32 = 3.14159;     // module scope

fn area(r: f32) -> f32 {
  let r2 = r * r;            // function scope, IMMUTABLE
  var temp: f32 = 0.0;       // function scope, mutable
  temp = PI * r2;            // module scope const'a erişim OK
  return temp;
}

// area() içindeki 'r2' DIŞARIDAN görünmez:
// const X = r2;  ← error: undeclared identifier 'r2'

// Henüz vs/fs entry point'i yok — canvas hâlâ blank.

08 / render pipeline · entry point

Tam shader: vs + fs

Studio'da aç

Burada modül "renderable" oluyor. @vertex fn vs(...) ve @fragment fn fs(...) eklenince WebGPU bir render pipeline kurabiliyor — canvas birden açılıyor. Bu, anatomi'nin son halkası: literal → identifier → const/var → struct → function → entry points. Geri kalan her şey (UV, SDF, raymarching) bu iskelet üstünde inşa edilir.

Dene: cos'u sin yap, renkler kayar. u.timeu.time * 4.0 yap, hızlanır. Daha derinine inmek için 12 aşamalık playground etüdüne geç.
anatomi-08-tam-shader-vs-fs.wgslrender pipeline · entry point
// İSKELET TAMAM. vs + fs eklendi → canvas açıldı.

struct U {
  resolution: vec2<f32>,
  time: f32,
}
@group(0) @binding(0) var<uniform> u: U;

@vertex
fn vs(@builtin(vertex_index) vi: u32) -> @builtin(position) vec4<f32> {
  // Tek üçgenle ekranı kapla
  let p = vec2<f32>(f32((vi << 1u) & 2u), f32(vi & 2u));
  return vec4<f32>(p * 2.0 - 1.0, 0.0, 1.0);
}

@fragment
fn fs(@builtin(position) frag: vec4<f32>) -> @location(0) vec4<f32> {
  let uv = frag.xy / u.resolution;
  let c  = 0.5 + 0.5 * cos(u.time + uv.xyx + vec3<f32>(0.0, 2.0, 4.0));
  return vec4<f32>(c, 1.0);
}