WebGPU란?
웹 어플리케이션에서 GPU의 기능에 액세스 하기 위한 최신 기술이다.
기존에는 WebGL이 있었지만, 성능적인 제약이 많았다.
벌컨, 메탈, Direct3D 12가 제공하는 API를 기반으로 모방리 및 데스크톱 플랫폼에 고성능을 제공하는 것이 목적이며, 애플, 모질라, 마이크로소프트, 구글 등의 엔지니어들과 함께 개발 되어가고 있다.
한 때, canvas를 이용하여 이것저것 해본 경험들이 있었는데 WebGPU 기술을 이용하여서 뭔가 쪼물쪼물 만들어 봐야겠다. 일단 그를 위해서 튜토리얼 먼저 진행을 해 보는 것으로!
첫 번째 WebGPU 앱을 통한 튜토리얼 시작. node + ts로 환경 세팅
https://codelabs.developers.google.com/your-first-webgpu-app
일단, 위 글을 토대로 튜토리얼을 진행해 보려고 한다.
typscript를 완벽하게 지원하고, 사용하려면 다음을 참고해서 사용해 주어야 한다.
https://github.com/gpuweb/types
실제로 사용하려면 ts를 이용해야 하고 모듈 형태로 개발 해 두는게 좋으니 테스트 할 환경을 구축해 보도록 하자!
먼저 프로젝트를 하나 만들어 주도록 하자.
npm init
이후, typescript를 사용할 것이기 때문에, webgpu type을 설치해 주자.
npm install --save @webgpu/types
tsconfig.json을 아래와 같이 작성해 주었다.
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"outDir": "dist",
"typeRoots": [ "./node_modules/@webgpu/types", "./node_modules/@types"]
},
"include": [
"src/**/*"
]
}
이후, src 폴더 하위에, canvas.ts 파일을 생성하고 여기서 부터 작업을 진행해 보기로 했다.
캔버스 생성 및 WebGPU 초기화
1. HTML 파일 생성
<html>
<head>
<meta charset="utf-8">
<title>WebGPU Life</title>
</head>
<body>
<canvas width="512" height="512" id="test-canvas"></canvas>
<script type="module" src="./test.js"></script>
</body>
</html>
먼저, 테스트 대상 캔버스를 생성해 줘야 하기 때문에 적당한 곳에 index.html 파일을 생성하고 위와 같이 작성해 주었다.
다음은 test.js 파일 전문.
import {Canvas} from "../dist/canvas.js"
const canvas = Canvas.getInstance()
await canvas.init(document.getElementById('test-canvas'))
canvas.clearCanvas()
ts로 작성한 파일을 호출하고, canvas Element를 넘겨주게끔 만들어 주었다.
2. canvas.ts 파일 작성
export class Canvas {
static #instance;
static getInstance() {
if (!Canvas.#instance) {
Canvas.#instance = new Canvas();
}
return Canvas.#instance;
}
canvas: HTMLCanvasElement; // HTML Canvas Element를 저장하는 곳
adapter:GPUAdapter; // GPUAdapter를 지정. 어댑터는 기기의 특정 GPU 하드웨어를 WebGPU가 표현한 것
device: GPUDevice; // GPU Device와 상호작용하는 인터페이스
context: GPUCanvasContext; // GPU Canvas Context
canvasFormat: GPUTextureFormat; // WebGPU에서 캔버스에서 사용할 형식 (기기 유형에 따라 텍스처 형식에 따라 성능 이슈가 있다.)
encoder: GPUCommandEncoder; // GPU 명령어를 기록하기 위한 인터페이스
pass: GPURenderPassEncoder;
// 어댑터 연결 + 디바이스 연결 + 캔버스 구성
async init(canvas) {
this.canvas = canvas
if(!navigator.gpu) {
throw new Error("WebGPU not supported on this browser.")
}
this.adapter = await navigator.gpu.requestAdapter() // GPU adapter 요청
if(!this.adapter) {
throw new Error("No appropriate GPUAdapter found.");
}
this.device = await this.adapter.requestDevice() // GPU device 요청
this.context = this.canvas.getContext("webgpu")
this.canvasFormat = navigator.gpu.getPreferredCanvasFormat() // 적합한 캔버스 포맷을 gpu에서 알려주기 때문에, 텍스처 형식에 따른 성능 이슈를 없앰
// context에서 사용할 device, format을 설정
this.context.configure({
device: this.device,
format: this.canvasFormat
})
// encoder 세팅
this.encoder = this.device.createCommandEncoder();
}
clearCanvas() {
// context.getCurrentTexture => 현재 캔버스 컨텍스트에서 텍스처를 가져옴. width, height, format 등등
// loadOp :: 랜더패스가 시작 되기 전 작업
// storeOp :: 랜더 패스 완료 후 작업.
// beginRenderPass :: 랜더 패스 시작
this.pass = this.encoder.beginRenderPass({
colorAttachments: [{
view: this.context.getCurrentTexture().createView(),
loadOp: "clear",
clearValue:[0,0,0.4,1],
storeOp: "store",
}]
})
this.pass.end()
// 명령 버퍼 제출
this.device.queue.submit([this.encoder.finish()])
}
}
3. 결과 확인
'JAVASCRIPT > vanilla' 카테고리의 다른 글
[javascript] DOM 변화를 관측하여 observer 패턴 사용 (0) | 2023.11.02 |
---|---|
WebGPU(4) - cell 색 지정 (1) | 2023.05.17 |
WebGPU(3) - bindGroup (0) | 2023.05.16 |
WebGPU(2) - draw rect (0) | 2023.05.16 |