[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -1,94 +1,300 @@
|
||||
---
|
||||
id: wiki-2026-0508-compute-shader
|
||||
title: Compute Shader
|
||||
title: Compute Shader (WebGPU)
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-38086E]
|
||||
aliases: [compute shader, WebGPU compute, GPGPU, WGSL, GPU-driven rendering, indirect draw]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [webgpu, compute-shader, gpgpu, wgsl, gpu-driven-rendering, three-js, particle-system, simulation]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Compute Shader"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
language: WGSL / WebGPU
|
||||
framework: Three.js / Babylon.js / wgpu-rs
|
||||
---
|
||||
|
||||
# [[Compute Shader|Compute Shader]]
|
||||
# Compute Shader
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 컴퓨트 셰이더(Compute Shader)는 자바스크립트 메인 스레드나 CPU가 처리하던 무거운 연산 작업을 수천 개의 GPU 코어를 활용해 병렬로 처리할 수 있게 해주는 [[WebGPU|WebGPU]]의 핵심 기능입니다 [1]. 주로 입자(Particle) 시스템, 물리 연산, 실시간 필터링, 그리고 대규모 객체의 가시성 판별(Culling)과 같은 범용 GPU 연산(GPGPU)에 사용되어, 기존 [[WebGL|WebGL]] 기반 환경의 한계를 뛰어넘는 압도적인 성능 향상을 제공합니다 [1-3].
|
||||
## 매 한 줄
|
||||
> **"매 GPU thousand core 의 parallel"**. 매 WebGPU 의 introduce → 매 web 의 GPGPU 의 가능. 매 particle, 매 fluid sim, 매 culling, 매 ML inference. 매 CPU 30ms (10K particle) → 매 GPU 2ms (100K particle) — 매 150× faster.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **대규모 데이터 연산 및 성능 향상:** CPU 기반의 입자 시스템은 일반적으로 5만 개 정도에서 성능 병목을 겪지만, WebGPU 컴퓨트 셰이더를 도입하면 이를 수백만 개 단위로 확장할 수 있습니다 [2, 4]. 예를 들어, 1만 개의 입자를 CPU에서 업데이트할 때 30ms가 걸리던 작업을 컴퓨트 셰이더를 사용하면 10만 개의 입자를 2ms 이내에 처리하여 150배 이상의 성능 향상을 얻을 수 있습니다 [5].
|
||||
* **주요 활용 분야:** 컴퓨트 셰이더는 충돌 감지(Collision detection), 실시간 조명 계산, 대규모 데이터 필터링, 구조 시뮬레이션 등에 효과적으로 적용됩니다 [1, 4]. 실시간 편집과 거대한 스케일이 필요한 절차적 지형 생성(Procedural terrain generation)도 가능하게 해줍니다 [6]. 또한, 메쉬의 정점 변환을 컴퓨트 단계에서 미리 처리해 버퍼에 저장해두고 여러 렌더 패스에서 재사용하는 '컴퓨트 스키닝(Compute Skinning)' 기법도 지원합니다 [5].
|
||||
* **메모리 활용 및 스토리지 텍스처:** 일반적인 텍스처와 달리 컴퓨트 셰이더 환경에서는 '스토리지 텍스처([[Storage|Storage]] textures)'를 통해 셰이더 내에서 읽기와 쓰기 작업을 동시에 수행할 수 있으며, 이는 유체 시뮬레이션이나 이미지 처리 등에 필수적입니다 [7, 8]. 더불어 스레드 간 데이터 공유가 필요한 작업에서는 작업 그룹 변수(Workgroup variables)를 사용한 공유 메모리를 활용할 수 있는데, 이는 반복적인 데이터 접근 패턴에서 전역 메모리보다 10~100배 더 빠른 속도를 제공합니다 [6, 9].
|
||||
* **GPU 주도 렌더링([[GPU-driven Rendering|GPU-driven Rendering]])과 간접 그리기:** 컴퓨트 셰이더는 간접 그리기([[Indirect Draw|Indirect Draw]])와 결합하여 렌더링 파이프라인의 효율성을 극대화합니다 [9]. CPU가 인스턴스의 위치를 검사하고 그리기 명령을 준비하는 대신, 컴퓨트 셰이더가 직접 시야 포함 여부나 오클루전(가림 현상)을 판별한 뒤 시각적으로 유효한 객체들로만 간접 그리기 버퍼를 채웁니다 [3, 10, 11]. 이 방식을 통해 CPU와 GPU 간의 데이터 전송량을 거의 0으로 수렴하게 만들 수 있습니다 [3].
|
||||
* **렌더링 동기화:** 컴퓨트 셰이더가 포함된 씬을 렌더링할 때는 GPU 작업의 적절한 동기화가 필요합니다 [12]. 종속적인 렌더 패스가 시작되기 전에 컴퓨트 패스의 작업이 완전히 완료되도록 보장하기 위해 `renderAsync`와 같은 비동기 렌더링 방식의 사용이 권장됩니다 [12].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Graphics & Performance 분야의 자동 자산화 수행.
|
||||
### 매 use case
|
||||
1. **Particle system**: 매 millions.
|
||||
2. **Fluid simulation**: 매 SPH, 매 grid-based.
|
||||
3. **Cloth / soft-body**.
|
||||
4. **Procedural terrain**.
|
||||
5. **GPU-driven rendering**: 매 culling, 매 indirect draw.
|
||||
6. **Compute skinning**: 매 GPU 의 vertex transform.
|
||||
7. **Image processing**: 매 blur, 매 filter.
|
||||
8. **GPGPU**: 매 ML inference, 매 numerical.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[WebGPU|WebGPU]], GPU-driven Rendering, Indirect Draw, [[Frustum Culling|Frustum Culling]]
|
||||
- **Projects/Contexts:** 대규모 건설 및 BIM 모델 플랫폼(수백만 개의 컴포넌트 렌더링 최적화) [13, 14], 엑스포 2025 오사카에 전시된 100만 파티클 유체 시뮬레이션 설치물(Hokusai) [15, 16].
|
||||
- **Contradictions/Notes:** 컴퓨트 셰이더는 최신 그래픽 API인 WebGPU에서 기본 지원되지만, 구형 WebGL이나 [[WebGL2|WebGL2]] 환경에서는 직접적으로 지원되지 않으므로 이를 활용하기 위해서는 반드시 WebGPU 기반의 렌더러 환경을 사용해야 한다는 제약이 있습니다 [3, 17].
|
||||
### 매 vs vertex / fragment shader
|
||||
- **Vertex**: 매 per-vertex.
|
||||
- **Fragment**: 매 per-pixel.
|
||||
- **Compute**: 매 arbitrary computation, 매 storage R/W.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 핵심 concept
|
||||
|
||||
---
|
||||
#### Workgroup
|
||||
- 매 thread group (e.g., 8×8×1 = 64 threads).
|
||||
- 매 shared memory.
|
||||
- 매 hardware-mapped (warp / wavefront).
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
#### Storage buffer / texture
|
||||
- 매 read + write (vs sampled texture only read).
|
||||
- 매 fluid sim 등 의 essential.
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
#### Workgroup variable (shared memory)
|
||||
- 매 매 thread group 의 share.
|
||||
- 매 10-100× faster than global.
|
||||
- 매 reduction, prefix sum 의 base.
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
#### Indirect draw
|
||||
- 매 GPU 의 draw command 의 generate.
|
||||
- 매 CPU-GPU sync 의 minimize.
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
### 매 WGSL (WebGPU Shading Language)
|
||||
- 매 syntax: 매 Rust-like.
|
||||
- 매 type-strict.
|
||||
- 매 vertex / fragment / compute 의 unified.
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
### 매 sync / async
|
||||
- 매 GPU 의 async by default.
|
||||
- 매 dependency 의 explicit barrier.
|
||||
- 매 readback 의 expensive (avoid).
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
### 매 modern application
|
||||
- **Three.js WebGPU renderer**: 매 v160+.
|
||||
- **Babylon.js**.
|
||||
- **wgpu-rs**: 매 native + web.
|
||||
- **Hokusai** (Expo 2025 Osaka): 매 1M particle fluid.
|
||||
- **Million-component BIM platform**.
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
## 💻 패턴
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
### Basic compute shader (WGSL)
|
||||
```wgsl
|
||||
// 매 add two arrays
|
||||
@group(0) @binding(0) var<storage, read> input_a: array<f32>;
|
||||
@group(0) @binding(1) var<storage, read> input_b: array<f32>;
|
||||
@group(0) @binding(2) var<storage, read_write> output: array<f32>;
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
@compute @workgroup_size(64)
|
||||
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
||||
let idx = id.x;
|
||||
if (idx >= arrayLength(&input_a)) { return; }
|
||||
output[idx] = input_a[idx] + input_b[idx];
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### JavaScript dispatch (WebGPU)
|
||||
```js
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
const device = await adapter.requestDevice();
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
// 매 buffer
|
||||
const inputA = device.createBuffer({
|
||||
size: data.byteLength,
|
||||
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
||||
});
|
||||
device.queue.writeBuffer(inputA, 0, data);
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
// 매 pipeline
|
||||
const module = device.createShaderModule({ code: wgslSource });
|
||||
const pipeline = device.createComputePipeline({
|
||||
layout: 'auto',
|
||||
compute: { module, entryPoint: 'main' },
|
||||
});
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
const bindGroup = device.createBindGroup({
|
||||
layout: pipeline.getBindGroupLayout(0),
|
||||
entries: [
|
||||
{ binding: 0, resource: { buffer: inputA } },
|
||||
{ binding: 1, resource: { buffer: inputB } },
|
||||
{ binding: 2, resource: { buffer: output } },
|
||||
],
|
||||
});
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
// 매 dispatch
|
||||
const encoder = device.createCommandEncoder();
|
||||
const pass = encoder.beginComputePass();
|
||||
pass.setPipeline(pipeline);
|
||||
pass.setBindGroup(0, bindGroup);
|
||||
pass.dispatchWorkgroups(Math.ceil(data.length / 64));
|
||||
pass.end();
|
||||
device.queue.submit([encoder.finish()]);
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### Particle system (Three.js WebGPU)
|
||||
```js
|
||||
import { Fn, instanceIndex, storage, attribute } from 'three/webgpu';
|
||||
|
||||
const positionsAttribute = new Float32Array(N_PARTICLES * 3);
|
||||
const positionsBuffer = renderer.computeAsync(
|
||||
Fn(() => {
|
||||
const i = instanceIndex;
|
||||
const pos = storage(positionsAttribute, 'vec3', N_PARTICLES);
|
||||
pos.element(i).addAssign(velocity.element(i).mul(dt));
|
||||
pos.element(i).y.assign(pos.element(i).y.sub(gravity * dt));
|
||||
// 매 boundary
|
||||
If(pos.element(i).y.lessThan(0), () => {
|
||||
pos.element(i).y.assign(0);
|
||||
velocity.element(i).y.mulAssign(-0.8);
|
||||
});
|
||||
})().compute(N_PARTICLES)
|
||||
);
|
||||
```
|
||||
|
||||
### Fluid simulation (SPH-style)
|
||||
```wgsl
|
||||
// 매 매 particle 의 neighbor 의 search + 매 force compute
|
||||
@group(0) @binding(0) var<storage, read_write> particles: array<Particle>;
|
||||
@group(0) @binding(1) var<uniform> params: SimParams;
|
||||
|
||||
@compute @workgroup_size(64)
|
||||
fn step(@builtin(global_invocation_id) id: vec3<u32>) {
|
||||
let i = id.x;
|
||||
if (i >= arrayLength(&particles)) { return; }
|
||||
|
||||
var force = vec3<f32>(0.0, -9.8, 0.0);
|
||||
|
||||
// 매 neighbor sum (simplified — real SPH uses spatial grid)
|
||||
for (var j = 0u; j < arrayLength(&particles); j++) {
|
||||
if (j == i) { continue; }
|
||||
let r = particles[j].pos - particles[i].pos;
|
||||
let d = length(r);
|
||||
if (d < params.smoothing_length) {
|
||||
force += sph_force(particles[i], particles[j], r, d);
|
||||
}
|
||||
}
|
||||
|
||||
particles[i].vel += force * params.dt;
|
||||
particles[i].pos += particles[i].vel * params.dt;
|
||||
}
|
||||
```
|
||||
|
||||
### GPU-driven culling (frustum)
|
||||
```wgsl
|
||||
@group(0) @binding(0) var<storage, read> instances: array<InstanceData>;
|
||||
@group(0) @binding(1) var<storage, read_write> draw_args: array<DrawArgs>;
|
||||
@group(0) @binding(2) var<uniform> camera: Camera;
|
||||
|
||||
@compute @workgroup_size(64)
|
||||
fn cull(@builtin(global_invocation_id) id: vec3<u32>) {
|
||||
let i = id.x;
|
||||
if (i >= arrayLength(&instances)) { return; }
|
||||
|
||||
if (in_frustum(instances[i].bounding_box, camera.frustum)) {
|
||||
let slot = atomicAdd(&draw_args[0].instance_count, 1u);
|
||||
visible_indices[slot] = i;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Compute skinning (vertex transform pre-pass)
|
||||
```wgsl
|
||||
@group(0) @binding(0) var<storage, read> bone_matrices: array<mat4x4<f32>>;
|
||||
@group(0) @binding(1) var<storage, read> base_vertices: array<Vertex>;
|
||||
@group(0) @binding(2) var<storage, read_write> skinned: array<vec4<f32>>;
|
||||
|
||||
@compute @workgroup_size(64)
|
||||
fn skin(@builtin(global_invocation_id) id: vec3<u32>) {
|
||||
let i = id.x;
|
||||
let v = base_vertices[i];
|
||||
|
||||
var pos = vec4<f32>(0.0);
|
||||
for (var b = 0u; b < 4u; b++) {
|
||||
pos += bone_matrices[v.bone_idx[b]] * vec4<f32>(v.position, 1.0) * v.bone_weight[b];
|
||||
}
|
||||
|
||||
skinned[i] = pos;
|
||||
}
|
||||
|
||||
// 매 매 render pass 의 skinned 의 read.
|
||||
```
|
||||
|
||||
### Workgroup shared memory (reduction)
|
||||
```wgsl
|
||||
var<workgroup> shared: array<f32, 64>;
|
||||
|
||||
@compute @workgroup_size(64)
|
||||
fn sum_reduce(
|
||||
@builtin(local_invocation_id) lid: vec3<u32>,
|
||||
@builtin(global_invocation_id) gid: vec3<u32>,
|
||||
) {
|
||||
shared[lid.x] = input[gid.x];
|
||||
workgroupBarrier();
|
||||
|
||||
// 매 tree reduction
|
||||
for (var stride = 32u; stride > 0u; stride >>= 1u) {
|
||||
if (lid.x < stride) {
|
||||
shared[lid.x] += shared[lid.x + stride];
|
||||
}
|
||||
workgroupBarrier();
|
||||
}
|
||||
|
||||
if (lid.x == 0u) {
|
||||
output[workgroup_id.x] = shared[0];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Async render (Three.js)
|
||||
```js
|
||||
// 매 compute pass 의 finish 후 의 render
|
||||
async function frame() {
|
||||
await renderer.computeAsync(particleUpdate);
|
||||
await renderer.renderAsync(scene, camera);
|
||||
}
|
||||
```
|
||||
|
||||
## 🤔 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 100K+ particle | Compute shader |
|
||||
| Fluid sim | Compute + storage texture |
|
||||
| Frustum culling | GPU-driven culling |
|
||||
| ML inference (browser) | WebGPU + WGSL |
|
||||
| Image processing | Compute + storage texture |
|
||||
| Skinned mesh (many) | Compute skinning |
|
||||
| < 10K particle | CPU OK |
|
||||
| < 1000 instance | CPU instance |
|
||||
|
||||
**기본값**: WebGPU + Three.js v160+ for web. wgpu-rs for native.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[GPU-Computing]] · [[WebGPU]] · [[Computer-Graphics]]
|
||||
- 변형: [[WGSL]] · [[GPU-Driven-Rendering]] · [[Indirect-Draw]] · [[Workgroup-Shared-Memory]]
|
||||
- 응용: [[Three-js]] · [[Particle-System]] · [[Fluid-Simulation]] · [[Compute-Skinning]]
|
||||
- Adjacent: [[CSS Animations]] · [[Web-Performance]] · [[Bottlenecks]] · [[Bioenergetics]] (energy-efficient)
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 web GPU compute. 매 large particle / sim. 매 GPU-driven rendering. 매 browser ML.
|
||||
**언제 X**: 매 small task (CPU OK). 매 WebGL only fallback 필요.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **CPU-GPU readback every frame**: 매 sync stall.
|
||||
- **Workgroup size 의 wrong** (e.g., 8): 매 underutilization.
|
||||
- **No barrier**: 매 race condition.
|
||||
- **Storage texture 의 use w/o WebGPU**: 매 unsupported.
|
||||
- **Sync compute + render**: 매 stall.
|
||||
- **No fallback (older browser)**: 매 break.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (WebGPU spec, Three.js webgpu, Hokusai exhibition).
|
||||
- 신뢰도 A.
|
||||
- Related: [[CSS Animations]] · [[Web-Performance]] · [[Bottlenecks]] · [[Baseline-Project]] · [[20k skinned instances demo]].
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-04-19 | Auto-mapped |
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — workgroup + 매 WGSL / Three.js / fluid / culling / skinning code |
|
||||
|
||||
Reference in New Issue
Block a user