작업 기록으로

JavaScript 배열을 바꿔도 GPU buffer는 그대로다

buffer 생성과 좌표 전달을 구분하고, 배열만 변경한 뒤와 다시 전달한 뒤의 실제 GPU buffer 값을 비교했다.

WebGPU 장치 준비에서 얻은 device로 데이터 저장 공간을 만드는 단계로 이어갔다. 이번 질문은 JavaScript에서 좌표를 만들거나 바꾸면 GPU 쪽 값도 자동으로 바뀌는지였다.

좌표 배열과 buffer 만들기

삼각형의 세 꼭짓점을 JavaScript 배열에 담았다. 각 줄은 한 꼭짓점의 (x, y)다.

const vertices = new Float32Array([
   0.0,  0.6,
  -0.6, -0.6,
   0.6, -0.6,
]);

배열 선언만으로 GPU buffer에 좌표가 자동으로 들어가지는 않는다고 예측했다. 실제로 전달하는 과정이 따로 필요하다는 이유도 설명했다.

다음은 앞서 얻은 device를 사용하는 buffer 생성 코드다.

const vertexBuffer = device.createBuffer({
  size: vertices.byteLength,
  usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});

Float32Array의 숫자 6개는 각각 4바이트이므로 vertices.byteLength는 24다. VERTEX는 꼭짓점 데이터로 사용할 용도, COPY_DST는 데이터를 복사해 넣을 대상이라는 용도다. |로 둘을 함께 지정한다.

createBuffer()는 크기와 허용 용도를 지정해 저장 공간을 만든다. 이 코드에는 원본 배열을 전달하는 인자가 없으므로 앞의 좌표는 아직 전달하지 않은 상태다.

좌표를 전달하고 배열만 바꾸기

device.queue.writeBuffer(vertexBuffer, 0, vertices);
vertices[0] = 0.4;

writeBuffer()의 세 인자는 대상 buffer, 대상의 시작 위치, 원본 데이터다. 여기서 0은 buffer의 처음부터 쓰겠다는 바이트 단위 위치다.

그 뒤 JavaScript 배열의 첫 x좌표만 바꾸면 GPU buffer에도 자동 반영될지 물었다. 확신은 없었지만, 배열을 계속 연결하는 대신 호출 시점의 좌표 데이터를 복사할 것이므로 GPU 쪽에는 이전 값인 0.0이 남는다고 예측했다.

여기서 기억할 것

이 writeBuffer() 호출은 데이터 복사다. 이후 JavaScript 배열만 바꿔도 GPU buffer가 자동으로 갱신되지는 않는다.

변경된 좌표를 반영하려면 데이터를 다시 전달한다.

device.queue.writeBuffer(vertexBuffer, 0, vertices);

실제 buffer에서 확인한 값

실습 화면에서 첫 전달, 배열만 변경, 재전달을 순서대로 실행했다. GPU 쪽 표시는 실제 buffer를 읽은 값이다.

  • 첫 전달 뒤: JavaScript와 GPU의 첫 x좌표가 모두 0.0이었다.
  • 배열만 변경한 뒤: JavaScript는 0.4, GPU buffer는 0.0으로 표시됐다. 직접 이 두 값을 보고했다.
  • 다시 전달한 뒤: GPU buffer도 0.4로 표시됐다고 보고했다.

검증 화면은 vertex buffer에 읽기 검증을 위한 COPY_SRC 용도를 추가하고, 내용을 별도의 읽기용 buffer로 복사한 뒤 mapAsync(READ)로 확인했다. 화면에 표시한 값은 소수 첫째 자리로 정리했다. 이 읽기 구현은 실습 도구가 수행한 것이며, 해당 API를 직접 구현하거나 설명한 학습 결과로 기록하지 않는다.

재전달을 영어로 표현하기

첫 시도는 다음과 같았다.

To update GPU buffer after changes JavaScript array, we have to ship data.

목적을 나타내는 To update와 필요를 나타내는 we have to는 맞게 썼다. after changes를 after changing으로 다듬고, 데이터를 다시 전달한다는 의미를 transfer the data again으로 명확히 했다. 앞서 사용한 buffer·배열·데이터에는 the를 붙였다.

To update the GPU buffer after changing the JavaScript array, we have to transfer the data again.

참고 문장을 보며 전체 문장을 다시 썼다. 재작성의 JavaScrip은 JavaScript의 철자 오타로 정정했다. 독립 회상이나 장기 숙달을 확인한 것은 아니다.

데이터 전달 다음에는 그리기

이번에는 배열과 buffer, buffer 생성과 데이터 전달, 배열 변경과 재전달을 구분하고 실제 값까지 확인했다. buffer 읽기 코드를 독립적으로 작성하거나 삼각형을 그린 것은 아니다.

좌표를 전달하는 것만으로 화면에 삼각형이 나타나지는 않는다. 다음에는 이 데이터를 화면에 그리는 데 필요한 canvas 설정, shader, pipeline, 그리기 명령을 작은 단위로 이어간다.

참고 자료