WebGPU

W3C 후보 권고안 초안,

이 문서에 대한 추가 정보
이 버전:
https://www.w3.org/TR/2025/CRD-webgpu-20250820/
최신 게시 버전:
https://www.w3.org/TR/webgpu/
편집자 초안:
https://gpuweb.github.io/gpuweb/
이전 버전:
히스토리:
https://www.w3.org/standards/history/webgpu/
피드백:
public-gpu@w3.org 제목 줄에 “[webgpu] … 메시지 주제 …” 포함 (아카이브)
GitHub
편집자:
(Google)
(Google)
(Mozilla)
이전 편집자:
(Apple Inc.)
(Mozilla)
(Apple Inc.)
참여:
이슈 등록 (열린 이슈)
테스트 스위트:
WebGPU CTS

요약

WebGPU는 그래픽 처리 장치(GPU)에서 렌더링 및 연산과 같은 작업을 수행할 수 있는 API를 제공합니다.

이 문서의 상태

이 섹션은 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록 및 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.

이 명세에 대한 피드백과 의견을 환영합니다. 이 명세에 대한 논의는 GitHub 이슈를 통해 진행하는 것이 좋습니다. 또는 GPU for the Web 워킹 그룹의 메일링 리스트 public-gpu@w3.org (아카이브)로 의견을 보낼 수 있습니다. 이 초안에는 워킹 그룹에서 논의 중인 미해결 이슈들이 일부 강조되어 있습니다. 이러한 이슈가 유효한지 여부를 포함하여 결과에 대한 결정은 아직 내려지지 않았습니다.

이 문서는 GPU for the Web 워킹 그룹에 의해 권고안 경로를 통해 후보 권고안 초안으로 발행되었습니다. 이 문서는 최소 까지 후보 권고안 상태를 유지합니다.

그룹은 모든 기능이 최신 GPU 시스템 API를 기반으로 최소 두 개의 배포 브라우저에서 구현됨을 입증할 것으로 기대합니다. 테스트 스위트는 구현 보고서를 작성하는 데 사용됩니다.

후보 권고안으로 발행되었다고 해서 W3C 및 회원의 지지를 의미하지 않습니다. 후보 권고안 초안은 워킹 그룹이 이후 후보 권고안 스냅샷에 포함하려는 이전 후보 권고안의 변경 사항을 통합합니다.

이 문서는 언제든지 유지 및 업데이트됩니다. 일부 내용은 진행 중인 작업입니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성되었습니다. W3C는 그룹 산출물과 관련하여 공개된 특허 공개 목록을 관리하며, 해당 페이지에는 특허 공개 방법도 포함되어 있습니다. 개인이 필수적 청구항이 포함된 특허를 실제로 알고 있다고 생각하는 경우, W3C 특허 정책의 6절에 따라 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C 프로세스 문서에 의해 관리됩니다.

1. 소개

이 섹션은 규범적이지 않습니다.

그래픽 처리 장치(GPU)는 개인 컴퓨팅에서 풍부한 렌더링 및 연산 응용 프로그램을 가능하게 하는 데 필수적이었습니다. WebGPU는 웹에서 GPU 하드웨어의 기능을 노출하는 API입니다. 이 API는 (2014년 이후) 네이티브 GPU API에 효율적으로 매핑되도록 처음부터 설계되었습니다. WebGPU는 WebGL과 관련이 없으며 OpenGL ES를 명시적으로 대상으로 하지 않습니다.

WebGPU는 물리적 GPU 하드웨어를 GPUAdapter로 봅니다. 어댑터와의 연결은 GPUDevice를 통해 제공되며, 이는 리소스를 관리하고 디바이스의 GPUQueue에서 명령을 실행합니다. GPUDevice는 자체 메모리를 가지고 있을 수 있으며, 처리 장치에 고속으로 접근할 수 있습니다. GPUBufferGPUTexture는 GPU 메모리에 의해 지원되는 물리적 리소스입니다. GPUCommandBufferGPURenderBundle는 사용자 기록 명령을 담는 컨테이너입니다. GPUShaderModule에는 셰이더 코드가 들어 있습니다. 그 외의 리소스들(예: GPUSampler 또는 GPUBindGroup)은 GPU에서 물리적 리소스가 사용되는 방식을 구성합니다.

GPU는 GPUCommandBuffer에 인코딩된 명령을 실행하며, 데이터를 파이프라인을 통해 처리합니다. 파이프라인은 고정 기능 및 프로그래머블 단계가 혼합된 구조입니다. 프로그래머블 단계는 셰이더를 실행하는데, 셰이더는 GPU 하드웨어에서 실행되도록 설계된 특별한 프로그램입니다. 파이프라인의 대부분 상태는 GPURenderPipeline 또는 GPUComputePipeline 객체로 정의됩니다. 이 파이프라인 객체에 포함되지 않은 상태는 beginRenderPass()setBlendConstant()와 같은 명령 인코딩 시에 설정됩니다.

2. 악의적 사용 고려사항

이 섹션은 규범적이지 않습니다. 이 섹션은 이 API를 웹에 노출할 때 발생할 수 있는 위험을 설명합니다.

2.1. 보안 고려사항

WebGPU의 보안 요구 사항은 웹의 기존 보안 요구와 동일하며, 협상 대상이 아닙니다. 일반적인 접근 방식은 모든 명령을 GPU에 전달하기 전에 엄격하게 검증하여 페이지가 자신의 데이터만 다룰 수 있도록 하는 것입니다.

2.1.1. CPU 기반 정의되지 않은 동작

WebGPU 구현은 사용자가 발행한 작업을 대상 플랫폼에 특화된 API 명령으로 변환합니다. 네이티브 API는 명령의 올바른 사용법을 지정하며 (예: vkCreateDescriptorSetLayout) 유효한 사용 규칙을 따르지 않으면 어떤 결과도 보장하지 않습니다. 이를 "정의되지 않은 동작"이라 하며, 공격자가 이를 악용하여 자신이 소유하지 않은 메모리에 접근하거나 드라이버가 임의의 코드를 실행하도록 할 수 있습니다.

안전하지 않은 사용을 막기 위해, 허용되는 WebGPU 동작의 범위는 모든 입력에 대해 정의됩니다. 구현체는 사용자의 모든 입력을 검증하고, 유효한 작업만 드라이버로 전달해야 합니다. 이 문서에서는 모든 오류 조건과 처리 의미론을 명시합니다. 예를 들어, copyBufferToBuffer()의 "source"와 "destination"에 겹치는 범위로 동일 버퍼를 지정하면 GPUCommandEncoder가 오류를 발생시키고 다른 작업은 수행되지 않습니다.

오류 처리에 대한 자세한 내용은 § 22 오류 및 디버깅을 참고하세요.

2.1.2. GPU 기반 정의되지 않은 동작

WebGPU 셰이더는 GPU 하드웨어 내의 연산 장치에서 실행됩니다. 네이티브 API에서는 일부 셰이더 명령이 GPU에서 정의되지 않은 동작을 일으킬 수 있습니다. 이를 해결하기 위해, 셰이더 명령 집합과 그 동작은 WebGPU에서 엄격하게 정의됩니다. 셰이더가 createShaderModule()에 제공될 때, WebGPU 구현체는 번역(플랫폼별 셰이더로)이나 변환 패스 전에 셰이더를 검증해야 합니다.

2.1.3. 초기화되지 않은 데이터

일반적으로, 새 메모리를 할당하면 시스템에서 실행 중인 다른 응용 프로그램의 남은 데이터가 노출될 수 있습니다. 이를 해결하기 위해, WebGPU는 모든 리소스를 개념적으로 0으로 초기화합니다. 하지만 실제로는 개발자가 내용을 직접 초기화하는 경우 이 단계를 생략할 수 있습니다. 여기에는 셰이더 내 변수 및 공유 워크그룹 메모리도 포함됩니다.

워크그룹 메모리 초기화 메커니즘은 플랫폼마다 다를 수 있습니다. 네이티브 API에 이를 초기화하는 기능이 없다면, WebGPU 구현체는 연산 셰이더를 변환하여 모든 호출에서 먼저 초기화, 동기화 후 개발자 코드를 실행하게 합니다.

참고:
큐 작업에서 사용되는 리소스의 초기화 상태는 작업이 큐에 등록될 때만 알 수 있습니다(예를 들어, 커맨드 버퍼에 인코딩될 때는 알 수 없음). 따라서, 일부 구현체는 큐 등록 시점에 비최적화된 늦은 초기화(예: 텍스처 클리어)를 요구할 수 있습니다(GPULoadOp "load" 대신 "clear"를 사용하는 등).

결과적으로, 모든 구현체는 비록 실제 페널티가 없더라도 이러한 잠재적 성능 저하에 대해 개발자 콘솔 경고를 권장합니다.

2.1.4. 셰이더에서의 범위 초과 접근

셰이더물리적 리소스에 직접 접근하거나 ("uniform" GPUBufferBinding 등), 또는 텍스처 유닛을 통해 접근할 수 있습니다. 텍스처 유닛은 텍스처 좌표 변환을 처리하는 고정 기능 하드웨어 블록입니다. WebGPU API의 검증은 셰이더에 전달되는 모든 입력 값이 제공되고 올바른 사용법과 타입임을 보장할 수 있습니다. 하지만 텍스처 유닛이 관여하지 않는 한, 데이터가 범위 내에서 접근되는 것은 API가 보장할 수 없습니다.

셰이더가 애플리케이션이 소유하지 않은 GPU 메모리에 접근하는 것을 막기 위해, WebGPU 구현체는 드라이버에서 "견고한 버퍼 접근(robust buffer access)" 모드를 활성화하여 접근이 버퍼의 경계 내로 제한되도록 할 수 있습니다.

또는, 구현체가 셰이더 코드를 변환하여 수동 경계 검사를 삽입할 수도 있습니다. 이 방식에서는 범위 초과 검사가 배열 인덱싱에만 적용됩니다. 호스트 측의 minBindingSize 검증 덕분에 셰이더 구조체의 단순 필드 접근에는 필요하지 않습니다.

셰이더가 물리적 리소스 경계 밖의 데이터를 읽으려 할 경우, 구현체는 다음 중 하나를 허용합니다:

  1. 리소스 경계 내의 다른 위치의 값을 반환

  2. "(0, 0, 0, X)" 형식의 값 벡터 반환(X는 임의값)

  3. 드로우 또는 디스패치 호출을 부분적으로 폐기

셰이더가 물리적 리소스 경계 밖에 데이터를 쓰려 할 경우, 구현체는 다음 중 하나를 허용합니다:

  1. 리소스 경계 내의 다른 위치에 값을 씀

  2. 쓰기 작업 폐기

  3. 드로우 또는 디스패치 호출을 부분적으로 폐기

2.1.5. 잘못된 데이터

CPU에서 GPU로 부동소수점 데이터를 업로드하거나 GPU에서 생성할 때, 값이 무한대나 NaN(Not-a-Number)와 같은 유효하지 않은 숫자 이진 표현이 될 수 있습니다. 이 경우 GPU의 동작은 IEEE-754 표준의 구현 정확도에 달려 있습니다. WebGPU는 잘못된 부동소수점을 도입해도 산술 계산 결과에만 영향을 주며, 다른 부작용은 없음을 보장합니다.

2.1.6. 드라이버 버그

GPU 드라이버도 다른 소프트웨어처럼 버그가 있을 수 있습니다. 버그가 발생할 경우, 공격자가 드라이버의 잘못된 동작을 악용하여 권한 없는 데이터에 접근할 수 있습니다. 위험을 줄이기 위해 WebGPU 워킹 그룹은 GPU 벤더와 협력하여 WebGPU 적합성 테스트 스위트(CTS)를 드라이버 테스트 프로세스에 통합할 예정입니다(WebGL처럼). WebGPU 구현체는 발견된 일부 버그에 대해 우회 방법을 갖추고, 우회할 수 없는 알려진 버그가 있는 드라이버에서는 WebGPU를 비활성화하는 것이 기대됩니다.

2.1.7. 타이밍 공격

2.1.7.1. 콘텐츠-타임라인 타이밍

WebGPU는 JavaScript에 콘텐츠 타임라인과 같은 새로운 상태를 노출하지 않습니다. 이러한 상태는 에이전트 간에 에이전트 클러스터 내에서 공유됩니다. 콘텐츠 타임라인 상태([[mapping]] 등)는 명시적 콘텐츠 타임라인 작업(일반 JavaScript처럼)에서만 변경됩니다.

2.1.7.2. 디바이스/큐-타임라인 타이밍

쓰기 가능한 저장 버퍼 및 기타 교차 호출 통신은 큐 타임라인에서 고정밀 타이머를 구성하는 데 사용될 수 있습니다.

선택적 "timestamp-query" 기능 역시 GPU 작업의 고정밀 타이밍을 제공합니다. 보안 및 프라이버시 문제를 완화하기 위해, 타이밍 쿼리 값은 더 낮은 정밀도로 맞춰집니다: current queue timestamp 참고. 특히:

2.1.8. Row hammer 공격

Row hammer는 DRAM 셀 상태 누출을 악용하는 공격의 한 종류입니다. GPU에서도 사용될 수 있습니다. WebGPU는 이에 대한 특정 대응책을 갖추고 있지 않으며, 메모리 리프레시 주기 단축 등 플랫폼 수준의 솔루션에 의존합니다.

2.1.9. 서비스 거부

WebGPU 응용 프로그램은 GPU 메모리 및 연산 장치에 접근할 수 있습니다. WebGPU 구현체는 다른 응용 프로그램의 응답성을 보장하기 위해 애플리케이션이 사용할 수 있는 GPU 메모리를 제한할 수 있습니다. GPU 처리 시간에 대해서는, WebGPU 구현체가 "감시견(watchdog)" 타이머를 설정하여 애플리케이션이 GPU를 몇 초 이상 응답하지 않게 하는 것을 방지할 수 있습니다. 이러한 조치는 WebGL에서 사용되는 것과 유사합니다.

2.1.10. 작업 부하 식별

WebGPU는 동일한 머신에서 실행되는 여러 프로그램(웹 페이지 포함)이 공유하는 제한된 글로벌 리소스에 접근합니다. 애플리케이션은 이러한 공유 리소스 사용 패턴을 기반으로 다른 열린 웹 페이지가 수행하는 작업 부하를 간접적으로 탐지하려고 시도할 수 있습니다. 이러한 문제는 Javascript의 시스템 메모리와 CPU 실행 처리량과 유사합니다. WebGPU는 이와 관련하여 추가적인 대응책을 제공하지 않습니다.

2.1.11. 메모리 자원

WebGPU는 VRAM과 같은 머신 전역 메모리 힙에서 실패할 수 있는 할당을 노출합니다. 이를 통해 할당을 시도하고 실패를 감지함으로써(힙 유형별로) 시스템의 남은 사용 가능 메모리 크기를 추론할 수 있습니다.

GPU는 내부적으로 하나 또는 여러 개(대개 두 개)의 메모리 힙을 모든 실행 중인 응용 프로그램이 공유합니다. 힙이 소진되면 WebGPU는 리소스 생성에 실패합니다. 이는 관찰 가능하므로, 악의적인 애플리케이션이 다른 애플리케이션이 어떤 힙을 사용하고 얼마를 할당하는지 추측할 수 있습니다.

2.1.12. 연산 자원

한 사이트가 다른 사이트와 동시에 WebGPU를 사용할 경우, 작업 처리 시간이 증가하는 현상을 관찰할 수 있습니다. 예를 들어, 한 사이트가 연산 작업을 지속적으로 제출하고 큐에서 작업 완료를 추적하면, GPU를 다른 곳에서 사용하기 시작했음을 감지할 수 있습니다.

GPU에는 산술 장치, 텍스처 샘플링 장치, 원자적 장치 등 독립적으로 테스트할 수 있는 여러 부분이 있습니다. 악의적인 애플리케이션은 이들 장치가 과부하되는 시점을 감지하여 다른 애플리케이션의 작업 부하를 추론할 수 있습니다. 이는 JavaScript의 CPU 실행 현실과 유사합니다.

2.1.13. 기능 오용

악의적인 사이트는 WebGPU가 제공하는 기능을 남용하여 사용자에게 도움이 되지 않는 계산(예: 숨겨진 암호화폐 채굴, 비밀번호 크래킹, 레인보우 테이블 연산 등)을 수행할 수 있습니다.

브라우저가 유효한 작업과 악용 작업을 구별할 수 없으므로, 이러한 형태의 API 오용을 방지할 방법은 없습니다. 이는 JavaScript, WebAssembly, WebGL 등 웹의 모든 범용 연산 기능에 공통적인 문제입니다. WebGPU는 일부 작업을 구현하기 쉬워지고, WebGL보다 약간 더 효율적으로 수행할 수 있을 뿐입니다.

이러한 오용을 완화하기 위해, 브라우저는 백그라운드 탭의 작업을 제한하거나, 탭이 많은 리소스를 사용하고 있음을 경고하거나, WebGPU 사용을 허용할 수 있는 컨텍스트를 제한할 수 있습니다.

사용자 에이전트는 잠재적으로 악의적인 사용으로 인한 높은 전력 사용에 대해 휴리스틱 기반 경고를 사용자에게 알릴 수 있습니다. 만약 사용자 에이전트가 이러한 경고를 구현한다면, WebGPU 사용도 JavaScript, WebAssembly, WebGL 등과 함께 휴리스틱에 포함해야 합니다.

2.2. 프라이버시 고려사항

There is a tracking vector here. WebGPU의 프라이버시 고려사항은 WebGL과 유사합니다. GPU API는 복잡하며, 개발자가 해당 기능을 효과적으로 활용할 수 있도록 기기 기능의 다양한 측면을 반드시 노출해야 합니다. 일반적인 완화 방법은 잠재적으로 식별 가능한 정보를 정규화하거나 구획화하고, 가능한 한 균일한 동작을 강제하는 것입니다.

사용자 에이전트는 32개를 초과하는 구분 가능한 구성 또는 버킷을 공개해서는 안 됩니다.

2.2.1. 기기별 기능 및 한계

WebGPU는 기반이 되는 GPU 아키텍처와 기기 구조에 대한 많은 세부사항을 노출할 수 있습니다. 여기에는 사용 가능한 물리적 어댑터, GPU 및 CPU 리소스에 대한 다양한 한계(예: 최대 텍스처 크기), 그리고 사용 가능한 하드웨어별 선택적 기능 등이 포함됩니다.

사용자 에이전트는 실제 하드웨어 한계를 반드시 노출할 필요가 없으며, 기기별 정보를 얼마나 노출할지 완전히 제어할 수 있습니다. 지문 채취를 줄이는 한 가지 전략은 모든 대상 플랫폼을 소수의 구획으로 묶는 것입니다. 일반적으로 하드웨어 한계 노출의 프라이버시 영향은 WebGL과 일치합니다.

기본 한계는 대부분의 애플리케이션이 더 높은 한계를 요청하지 않아도 작동할 수 있도록 의도적으로 충분히 높게 설정되어 있습니다. API 사용은 요청된 한계에 따라 검증되기 때문에, 실제 하드웨어 기능이 실수로 사용자에게 노출되는 일은 없습니다.

2.2.2. 기기별 아티팩트

WebGL에서와 마찬가지로 기기별 래스터화/정밀도 아티팩트와 성능 차이를 관찰할 수 있습니다. 이는 래스터화 커버리지 및 패턴, 셰이더 단계 간 보간 정밀도, 연산 장치 스케줄링 등 실행의 여러 측면에 해당됩니다.

일반적으로, 래스터화 및 정밀도 지문은 각 벤더의 대부분 또는 모든 기기에서 동일합니다. 성능 차이는 상대적으로 판별이 어렵지만 신호가 약합니다(JS 실행 성능과 유사).

프라이버시가 중요한 애플리케이션 및 사용자 에이전트는 이러한 아티팩트를 제거하기 위해 소프트웨어 구현을 활용해야 합니다.

2.2.3. 기기별 성능

사용자를 구분하는 또 다른 요인은 GPU에서 특정 작업의 성능을 측정하는 것입니다. 낮은 정밀도의 타이밍만으로도, 반복적으로 작업을 실행하면 사용자의 기기가 특정 작업에 빠른지 확인할 수 있습니다. 이는 WebGL과 Javascript 모두에서 흔히 볼 수 있는 벡터이지만, 신호가 약하고 실제로 정규화하기 어렵습니다.

WebGPU 연산 파이프라인은 고정 기능 하드웨어에 의해 방해받지 않는 GPU 접근을 제공합니다. 이는 고유한 기기 지문 채취 위험을 추가로 유발할 수 있습니다. 사용자 에이전트는 논리적 GPU 호출을 실제 연산 장치와 분리하여 이러한 위험을 줄일 수 있습니다.

2.2.4. User Agent 상태

이 명세는 오리진에 대한 추가적인 사용자 에이전트 상태를 정의하지 않습니다. 하지만 사용자 에이전트는 GPUShaderModule, GPURenderPipelineGPUComputePipeline과 같이 비용이 많이 드는 컴파일 결과에 대한 캐시를 보유할 것으로 예상됩니다. 이러한 캐시는 WebGPU 애플리케이션을 처음 방문한 이후 로딩 시간을 개선하는 데 중요합니다.

이 명세에서는 이러한 캐시가 매우 빠른 컴파일과 구분되지 않지만, 애플리케이션에서는 createComputePipelineAsync()가 해결되는 데 걸리는 시간을 쉽게 측정할 수 있습니다. 이는 오리진 간 정보(예: "사용자가 이 특정 셰이더를 사용하는 사이트에 접속했는가")를 누출할 수 있으므로, 사용자 에이전트는 스토리지 파티셔닝의 모범 사례를 따라야 합니다.

시스템의 GPU 드라이버 역시 자체적으로 컴파일된 셰이더 및 파이프라인 캐시를 보유할 수 있습니다. 사용자 에이전트는 가능하다면 이를 비활성화하거나, 셰이더에 파티션별 데이터를 추가하여 GPU 드라이버가 서로 다르게 인식하도록 할 수 있습니다.

2.2.5. 드라이버 버그

보안 고려사항에서 설명한 우려사항에 더해, 드라이버 버그는 사용자를 구분할 수 있는 동작 차이를 유발할 수 있습니다. 보안 고려사항에서 언급된 완화책(예: GPU 벤더와의 협력 및 사용자 에이전트의 알려진 문제 우회 구현)이 여기에도 적용됩니다.

2.2.6. 어댑터 식별자

WebGL의 과거 경험에 따르면, 개발자는 코드가 실행되는 GPU를 식별할 수 있어야 강건한 GPU 기반 콘텐츠를 만들고 유지할 수 있습니다. 예를 들어, 알려진 드라이버 버그가 있는 어댑터를 식별하여 이를 우회하거나, 특정 하드웨어에서 기대보다 성능이 낮은 기능을 피할 수 있습니다.

하지만 어댑터 식별자를 노출하면 지문 채취 정보가 자연스럽게 늘어나므로, 어댑터 식별의 정밀도를 제한하고자 하는 요구가 있습니다.

강건한 콘텐츠 구현과 프라이버시 보호의 균형을 맞추기 위해 여러 완화책을 적용할 수 있습니다. 우선, 사용자 에이전트는 알려진 드라이버 이슈를 식별하고 우회함으로써(브라우저가 GPU를 사용하기 시작한 이후로 해오던 것처럼) 개발자의 부담을 줄일 수 있습니다.

어댑터 식별자를 기본적으로 노출할 때는, 실제 사용 중인 어댑터를 식별하지 않으면서도 유용할 수 있도록 최대한 넓게(예: 어댑터의 벤더 및 일반 아키텍처) 식별해야 합니다. 때로는 실제 어댑터의 합리적인 대리로 간주되는 어댑터 식별자를 보고할 수도 있습니다.

어댑터에 대한 전체 상세 정보가 유용한 경우(예: 버그 리포트 제출 시)에는, 사용자가 자신의 하드웨어 정보를 페이지에 추가로 공개하도록 동의할 수 있습니다.

마지막으로, 사용자 에이전트는 필요하다고 판단될 경우(예: 강화된 프라이버시 모드) 어댑터 식별자를 전혀 보고하지 않을 수 있습니다.

3. 기초

3.1. 관례

3.1.1. 구문 단축

이 명세에서는 다음과 같은 구문 단축 표현을 사용합니다:

. ("점") 구문, 프로그래밍 언어에서 일반적임.

"Foo.Bar"는 "값(또는 인터페이스) FooBar 멤버"를 의미합니다. Fooordered map이며 Bar존재하지 않을 때undefined를 반환합니다.

"Foo.Bar제공됨"은 "Bar 멤버가 존재함을 의미합니다. (mapFoo에서)"

?. ("옵셔널 체이닝") 구문, JavaScript에서 차용.

"Foo?.Bar"는 "Foonull 또는 undefined이거나 Bar존재하지 않을 때 undefined; 그렇지 않으면 Foo.Bar"를 의미합니다.

예를 들어 bufferGPUBuffer일 때, buffer?.\[[device]].\[[adapter]]는 "buffernull 또는 undefinedundefined; 그렇지 않으면, buffer\[[device]] 내부 슬롯의 \[[adapter]] 내부 슬롯"을 의미.

?? ("널 병합") 구문, JavaScript에서 차용.

"x ?? y"는 "x가 null 또는 undefined가 아니면 x, 그렇지 않으면 y"입니다.

슬롯 기반 속성

동일한 이름의 내부 슬롯에 의해 지원되는 WebIDL 속성입니다. 변경 가능할 수도, 불가능할 수도 있습니다.

3.1.2. WebGPU 객체

WebGPU 객체WebGPU 인터페이스내부 객체로 이루어집니다.

WebGPU 인터페이스WebGPU 객체의 공개 인터페이스와 상태를 정의합니다. 이는 객체가 생성된 콘텐츠 타임라인(JavaScript에서 노출되는 WebIDL 인터페이스)에서 사용할 수 있습니다.

GPUObjectBase를 포함하는 모든 인터페이스는 WebGPU 인터페이스입니다.

내부 객체WebGPU 객체의 상태를 디바이스 타임라인에서 추적합니다. 내부 객체의 변경 가능한 상태에 대한 모든 읽기/쓰기는 하나의 잘 정렬된 디바이스 타임라인에서 실행되는 단계에서만 발생합니다.

다음과 같은 특별한 속성 유형이 WebGPU 객체에 정의될 수 있습니다:

불변 속성

객체 초기화 시 설정되는 읽기 전용 슬롯입니다. 모든 타임라인에서 접근할 수 있습니다.

참고: 슬롯이 불변이므로 구현체는 필요에 따라 여러 타임라인에 복사본을 둘 수 있습니다. 불변 속성은 이 명세에서 여러 복사본을 설명하지 않기 위해 이렇게 정의됩니다.

[[대괄호]]로 명명되면 내부 슬롯입니다.
대괄호없이로 명명되면 슬롯 기반 속성WebGPU 인터페이스입니다.

콘텐츠 타임라인 속성

객체가 생성된 콘텐츠 타임라인에서만 접근할 수 있는 속성입니다.

[[대괄호]]로 명명되면 내부 슬롯입니다.
대괄호없이로 명명되면 슬롯 기반 속성WebGPU 인터페이스입니다.

디바이스 타임라인 속성

내부 객체의 상태를 추적하는 속성이며, 객체가 생성된 디바이스 타임라인에서만 접근할 수 있습니다. 디바이스 타임라인 속성은 변경 가능할 수 있습니다.

디바이스 타임라인 속성[[대괄호]]로 명명되며, 내부 슬롯입니다.

큐 타임라인 속성

내부 객체의 상태를 추적하며, 객체가 생성된 큐 타임라인에서만 접근할 수 있습니다. 큐 타임라인 속성은 변경 가능할 수 있습니다.

큐 타임라인 속성[[대괄호]]로 명명되며, 내부 슬롯입니다.

interface mixin GPUObjectBase {
    attribute USVString label;
};
새로운 WebGPU 객체를 생성(GPUObjectBase parent, 인터페이스 T, GPUObjectDescriptorBase descriptor) (TGPUObjectBase를 확장함), 다음 콘텐츠 타임라인 단계 실행:
  1. deviceparent.[[device]]로 둡니다.

  2. objectT의 새 인스턴스로 둡니다.

  3. object.[[device]]device를 설정합니다.

  4. object.labeldescriptor.label을 설정합니다.

  5. object를 반환합니다.

GPUObjectBase 에는 다음 불변 속성이 있습니다:

[[device]], 타입 device, 읽기 전용

이 객체의 내부 객체를 소유하는 디바이스입니다.

이 객체의 컨텐츠에 대한 작업은 항상 assert디바이스 타임라인에서 실행되며, 디바이스가 유효함을 보장합니다.

GPUObjectBase 에는 다음 콘텐츠 타임라인 속성이 있습니다:

label, 타입 USVString

개발자가 제공하는 레이블로, 구현체 정의 방식으로 사용됩니다. 브라우저, OS 또는 기타 도구에서 개발자가 해당 내부 객체를 식별하는 데 사용할 수 있습니다. 예를 들어 GPUError 메시지, 콘솔 경고, 브라우저 개발자 도구, 플랫폼 디버깅 유틸리티 등에 레이블을 표시할 수 있습니다.

참고:
구현체는 WebGPU 객체 식별을 위해 오류 메시지에 레이블을 활용하는 것이 권장됩니다.

그러나 객체 식별 방식이 반드시 레이블만을 의미하지는 않습니다: 구현체는 레이블이 없는 경우에도 사용 가능한 다른 정보를 활용해야 합니다. 예시:

참고:
labelGPUObjectBase의 속성입니다. 두 GPUObjectBase "래퍼" 객체는 같은 기반 객체를 참조하더라도 완전히 별도의 레이블 상태를 가집니다 (예: getBindGroupLayout() 반환 객체). label 속성은 JavaScript에서 설정되는 경우를 제외하고는 변경되지 않습니다.

즉, 하나의 기반 객체에 여러 개의 레이블이 연결될 수 있습니다. 이 명세는 레이블이 디바이스 타임라인에 어떻게 전달되는지 정의하지 않습니다. 레이블 사용 방식은 완전히 구현체 정의입니다: 오류 메시지에 가장 최근 레이블, 모든 레이블, 또는 레이블을 전혀 표시하지 않을 수 있습니다.

타입을 USVString으로 정의한 이유는, 일부 사용자 에이전트가 이를 기반 네이티브 API의 디버그 기능에 제공할 수 있기 때문입니다.

GPUObjectBase 에는 다음 디바이스 타임라인 속성이 있습니다:

[[valid]], 타입 boolean, 초기값 true.

true내부 객체가 사용 가능함을 의미합니다.

참고:
이상적으로는 WebGPU 인터페이스가 부모 객체(예: 이 인터페이스를 소유한 [[device]])의 가비지 컬렉션을 방해하지 않아야 합니다. 하지만 일부 구현체에서는 부모 객체에 강한 참조를 유지해야 할 수 있어 이를 보장할 수 없습니다.

따라서 개발자는 WebGPU 인터페이스의 모든 자식 객체가 가비지 컬렉션될 때까지 해당 인터페이스가 수거되지 않을 수 있음을 염두에 두어야 합니다. 이는 일부 리소스가 예상보다 오래 할당된 상태로 남아 있을 수 있음을 의미합니다.

할당된 리소스를 예측 가능하게 해제하려면, destroy 메서드(WebGPU 인터페이스의 예: GPUDevice.destroy() 또는 GPUBuffer.destroy())를 가비지 컬렉션에 의존하기보다 적극적으로 호출하는 것이 좋습니다.

3.1.3. 객체 디스크립터

객체 디스크립터는 객체를 생성하는 데 필요한 정보를 담고 있으며, 일반적으로 create* 메서드(예: GPUDevice의 메서드)를 통해 생성됩니다.

dictionary GPUObjectDescriptorBase {
    USVString label = "";
};

GPUObjectDescriptorBase 에는 다음 멤버가 있습니다:

label, 타입 USVString, 기본값 ""

GPUObjectBase.label의 초기값입니다.

3.2. 비동기성

3.2.1. 잘못된 내부 객체 및 전염성 무효화

WebGPU의 객체 생성 작업은 프라미스를 반환하지 않지만, 내부적으로는 비동기적으로 동작합니다. 반환된 객체는 내부 객체를 참조하며, 디바이스 타임라인에서 조작됩니다. 예외나 거부로 실패하는 대신, 대부분의 디바이스 타임라인에서 발생하는 오류는 해당 디바이스에서 생성된 GPUError를 통해 전달됩니다.

내부 객체유효하거나 무효입니다. 무효 객체는 이후에 유효 상태가 될 수 없지만, 유효 객체는 무효화될 수 있습니다.

객체는 생성 시 무효일 수 있으며, 예를 들어 객체 디스크립터가 유효한 객체를 나타내지 않거나, 리소스 할당에 필요한 메모리가 부족할 때 발생할 수 있습니다. 또한, 다른 무효 객체로부터 객체를 생성할 때도 발생하는데 (예: 무효 GPUTexture에 대해 createView()를 호출하는 경우), 이를 전염성 무효화라고 합니다.

내부 객체대부분의 타입에서 생성 후 무효가 될 수 없지만, 소유 디바이스가 손실되거나, destroyed 상태, 혹은 버퍼 상태가 "destroyed" 등 특수 내부 상태일 때 사용 불가능해질 수 있습니다.

일부 타입의 내부 객체는 생성 후에도 무효가 될 수 있는데, 대표적으로 디바이스, 어댑터, GPUCommandBuffer, 그리고 커맨드/패스/번들 인코더 등이 해당됩니다.

주어진 GPUObjectBase object유효하려면 object.[[valid]] 값이 true여야 합니다.
주어진 GPUObjectBase object무효가 되려면 object.[[valid]] 값이 false여야 합니다.
주어진 GPUObjectBase objecttargetObject함께 사용에 유효하려면 아래 디바이스 타임라인 요구사항을 모두 충족해야 합니다:
GPUObjectBase object무효화하려면 아래 디바이스 타임라인 단계를 실행합니다:
  1. object.[[valid]] 값을 false로 설정합니다.

3.2.2. 프라미스 순서

WebGPU의 여러 작업은 프라미스를 반환합니다.

WebGPU는 이 프라미스들이 해결(성공 또는 실패)되는 순서에 대해 다음의 경우를 제외하고 어떠한 보장도 하지 않습니다:

애플리케이션은 그 외의 프라미스 해결 순서에 의존해서는 안 됩니다.

3.3. 좌표계

렌더링 작업에서는 다음과 같은 좌표계를 사용합니다:

참고: WebGPU의 좌표계는 그래픽 파이프라인에서 DirectX의 좌표계와 일치합니다.

3.4. 프로그래밍 모델

3.4.1. 타임라인

WebGPU의 동작은 "타임라인"으로 설명됩니다. 각 작업(알고리즘으로 정의됨)은 타임라인에서 발생합니다. 타임라인은 작업의 순서뿐만 아니라 어떤 상태가 어떤 작업에 사용 가능한지도 명확히 정의합니다.

참고: 이 "타임라인" 모델은 브라우저 엔진의 멀티 프로세스 모델(일반적으로 "콘텐츠 프로세스"와 "GPU 프로세스")의 제약을 기술하며, 많은 구현에서 GPU 자체도 별도의 실행 단위로 작동합니다. WebGPU 구현은 타임라인이 병렬 실행되어야 할 필요가 없으므로, 복수 프로세스나 복수 스레드가 필요하지 않습니다. (단, get a copy of the image contents of a context와 같이 다른 타임라인이 완료될 때까지 동기적으로 대기해야 하는 경우에는 동시성이 필요합니다.)

콘텐츠 타임라인

웹 스크립트 실행과 연관되어 있습니다. 본 명세에서 기술한 모든 메서드 호출이 이에 포함됩니다.

GPUDevice device에서 작업을 콘텐츠 타임라인에 전달하려면, 해당 단계로 queue a global task for GPUDevice device를 실행합니다.

디바이스 타임라인

사용자 에이전트가 발행하는 GPU 디바이스 작업과 연관되어 있습니다. 어댑터, 디바이스, GPU 리소스 및 상태 객체의 생성이 포함되며, 이는 사용자 에이전트가 GPU를 제어하는 관점에서 일반적으로 동기적으로 동작하지만, 별도의 OS 프로세스에서 실행될 수 있습니다.

큐 타임라인

GPU의 연산 장치에서 작업이 실제로 실행되는 것과 연관되어 있습니다. 실제 드로우, 복사, 연산 작업이 GPU에서 실행됩니다.

타임라인 비특정

위의 어느 타임라인과도 연관될 수 있습니다.

단계가 불변 속성이나 호출 단계에서 전달된 인자만 다룬다면 어떤 타임라인에서도 실행될 수 있습니다.

다음은 각 타임라인과 연관된 단계와 값의 스타일링 예시입니다. 이 스타일링은 규범적이지 않으며, 명세 본문이 항상 연관성을 설명합니다.
불변 값 예시 용어 정의

모든 타임라인에서 사용될 수 있습니다.

콘텐츠 타임라인 예시 용어 정의

오직 콘텐츠 타임라인에서만 사용될 수 있습니다.

디바이스 타임라인 예시 용어 정의

오직 디바이스 타임라인에서만 사용될 수 있습니다.

큐 타임라인 예시 용어 정의

오직 큐 타임라인에서만 사용될 수 있습니다.

타임라인 비특정 단계는 다음과 같습니다.

불변 값 예시 용어 사용.

콘텐츠 타임라인에서 실행되는 단계는 다음과 같습니다.

불변 값 예시 용어 사용. 콘텐츠 타임라인 예시 용어 사용.

디바이스 타임라인에서 실행되는 단계는 다음과 같습니다.

불변 값 예시 용어 사용. 디바이스 타임라인 예시 용어 사용.

큐 타임라인에서 실행되는 단계는 다음과 같습니다.

불변 값 예시 용어 사용. 큐 타임라인 예시 용어 사용.

본 명세에서 비동기 작업은 반환값이 콘텐츠 타임라인 이외의 타임라인에서 발생하는 작업에 따라 결정될 때 사용됩니다. 비동기 작업은 API에서 프라미스와 이벤트로 표시됩니다.

GPUComputePassEncoder.dispatchWorkgroups():
  1. 사용자가 dispatchWorkgroups 명령을 GPUComputePassEncoder의 메서드로 호출하여, 콘텐츠 타임라인에서 실행합니다.

  2. 사용자가 GPUQueue.submit()를 호출하여 GPUCommandBuffer 를 사용자 에이전트에 전달하면, 에이전트가 OS 드라이버에 저수준 제출을 요청하여 디바이스 타임라인에서 처리합니다.

  3. 제출된 작업은 GPU 호출 스케줄러가 실제 연산 장치에 분배하여 실행하며, 이는 큐 타임라인에서 발생합니다.

GPUDevice.createBuffer():
  1. 사용자가 GPUBufferDescriptor를 작성하고, 이를 이용해 GPUBuffer를 생성하는데, 이는 콘텐츠 타임라인에서 실행됩니다.

  2. 사용자 에이전트가 디바이스 타임라인에서 저수준 버퍼를 생성합니다.

GPUBuffer.mapAsync():
  1. 사용자가 콘텐츠 타임라인에서 GPUBuffer를 매핑 요청하고, 프라미스를 반환받습니다.

  2. 사용자 에이전트는 버퍼가 현재 GPU에 의해 사용 중인지 확인하고, 사용이 끝나면 다시 확인하도록 자체적으로 알림을 설정합니다.

  3. GPU가 큐 타임라인에서 버퍼 사용을 마치면, 사용자 에이전트가 버퍼를 메모리에 매핑하고 프라미스를 resolve합니다.

3.4.2. 메모리 모델

이 섹션은 규범적이지 않습니다.

애플리케이션 초기화 루틴에서 GPUDevice를 얻은 후, WebGPU 플랫폼은 다음과 같은 계층으로 구성되어 있다고 볼 수 있습니다:

  1. 명세를 구현하는 사용자 에이전트.

  2. 이 장치용 저수준 네이티브 API 드라이버가 있는 운영체제.

  3. 실제 CPU 및 GPU 하드웨어.

WebGPU 플랫폼 계층은 명세를 구현할 때 사용자 에이전트가 고려해야 할 다양한 메모리 유형을 가질 수 있습니다:

대부분의 물리적 리소스는 GPU가 계산이나 렌더링에 효율적인 타입의 메모리에 할당됩니다. 사용자가 GPU로 새로운 데이터를 제공해야 할 때, 데이터는 먼저 프로세스 경계를 넘어 GPU 드라이버와 통신하는 사용자 에이전트 부분에 도달해야 할 수 있습니다. 이후 드라이버가 데이터를 볼 수 있도록 만들어야 하는데, 때로는 드라이버가 할당한 스테이징 메모리로 복사해야 합니다. 마지막으로, 전용 GPU 메모리로 데이터를 전송해야 할 수 있으며, 내부 레이아웃도 GPU가 효율적으로 처리할 수 있도록 변경될 수 있습니다.

이러한 모든 전환은 사용자 에이전트의 WebGPU 구현이 처리합니다.

참고: 이 예시는 최악의 경우를 설명합니다. 실제로는 프로세스 경계를 넘지 않아도 되거나, 사용자에게 ArrayBuffer 뒤에 드라이버가 관리하는 메모리를 직접 노출하여 데이터 복사를 피할 수 있는 경우도 있습니다.

3.4.3. 자원 사용

물리적 리소스내부 사용 형태로 GPU 명령에서 사용할 수 있습니다:

입력

드로우 또는 디스패치 호출에 대한 입력 데이터를 가진 버퍼. 내용 보존. buffer INDEX, buffer VERTEX, 또는 buffer INDIRECT에 의해 허용됨.

상수

셰이더 관점에서 상수로 간주되는 리소스 바인딩. 내용 보존. buffer UNIFORM 또는 texture TEXTURE_BINDING에 의해 허용됨.

저장소

읽기/쓰기 저장 리소스 바인딩. buffer STORAGE 또는 texture STORAGE_BINDING에 의해 허용됨.

저장소-읽기

읽기 전용 저장 리소스 바인딩. 내용 보존. buffer STORAGE 또는 texture STORAGE_BINDING에 의해 허용됨.

어태치먼트

렌더 패스에서 읽기/쓰기 출력 어태치먼트 또는 쓰기 전용 리졸브 타깃으로 사용되는 텍스처. texture RENDER_ATTACHMENT에 의해 허용됨.

어태치먼트-읽기

렌더 패스에서 읽기 전용 어태치먼트로 사용되는 텍스처. 내용 보존. texture RENDER_ATTACHMENT에 의해 허용됨.

서브리소스는 전체 버퍼 또는 텍스처 서브리소스를 의미합니다.

일부 내부 사용은 서로 호환됩니다. 서브리소스는 여러 사용을 조합한 상태가 될 수 있습니다. U 리스트가 아래 규칙 중 하나라도 만족하면 호환 사용 리스트라고 간주합니다:

사용을 호환 사용 리스트로만 결합하도록 강제하면, 메모리 작업에서 데이터 경쟁(race)이 발생할 수 있는 시점을 API가 제한할 수 있습니다. 이 특성은 WebGPU 기반 애플리케이션이 다른 플랫폼에서 수정 없이 잘 동작할 가능성을 높여줍니다.

EXAMPLE:
동일한 버퍼를 저장소입력으로 같은 GPURenderPassEncoder에서 바인딩하면, 해당 버퍼에 대해 호환 사용 리스트가 아닙니다.
EXAMPLE:
이 규칙을 통해 읽기 전용 깊이-스텐실이 가능합니다: 하나의 깊이/스텐실 텍스처를 렌더 패스에서 두 가지 읽기 전용 사용으로 동시에 활용할 수 있습니다:
EXAMPLE:
사용 범위 저장소 예외는 아래 두 가지 경우를 허용합니다:
EXAMPLE:
사용 범위 어태치먼트 예외는 텍스처 서브리소스를 어태치먼트로 여러 번 사용하는 것을 허용합니다. 이는 3D 텍스처의 분리된 슬라이스들을 단일 렌더 패스에서 서로 다른 어태치먼트로 바인딩할 수 있도록 필요합니다.

한 슬라이스를 두 개의 다른 어태치먼트에 바인딩하는 것은 허용되지 않습니다; 이는 beginRenderPass()에서 검사합니다.

3.4.4. 동기화

사용 범위map 형식으로, 서브리소스에서 list<내부 사용>>로 연결됩니다. 각 사용 범위는 서로 동시 실행될 수 있는 작업의 범위를 포함하며, 따라서 서브리소스는 범위 내에서 호환 사용 리스트로만 사용할 수 있습니다.

사용 범위 scope사용 범위 검증을 통과하려면, scope의 각 [subresource, usageList]에 대해 usageList호환 사용 리스트여야 합니다.
사용 범위 usageScope서브리소스 subresource를 사용(내부 사용 또는 내부 사용 집합) usage추가하려면:
  1. usageScope[subresource]가 존재하지 않으면 []로 설정합니다.

  2. 추가 usageusageScope[subresource]에 추가합니다.

사용 범위 A사용 범위 B병합하려면:
  1. A의 각 [subresource, usage]에 대해:

    1. 추가 subresourceBusage로 추가합니다.

사용 범위는 인코딩 과정에서 생성 및 검증됩니다:

사용 범위는 다음과 같습니다:

참고: 복사 명령은 독립 실행 작업이므로 검증에 사용 범위를 사용하지 않습니다. 자체적으로 self-race를 방지하는 검증을 구현합니다.

EXAMPLE:
아래 예시 자원 사용은 사용 범위에 포함됩니다:

3.5. 핵심 내부 객체

3.5.1. 어댑터

어댑터는 시스템에서 WebGPU 구현을 식별합니다: 브라우저 기반 플랫폼의 연산/렌더링 기능 인스턴스와, 그 기능 위에 구현된 브라우저의 WebGPU 인스턴스 모두를 포함합니다.

어댑터GPUAdapter를 통해 노출됩니다.

어댑터는 기반 구현을 고유하게 대표하지 않습니다: requestAdapter()를 여러 번 호출하면 매번 다른 어댑터 객체가 반환됩니다.

어댑터 객체는 오직 하나의 디바이스만 생성할 수 있습니다: requestDevice()가 성공적으로 호출되면 어댑터의 [[state]]"consumed"로 변경됩니다. 추가로 어댑터 객체는 언제든지 만료될 수 있습니다.

참고: 이는 디바이스 생성 시 어댑터 선택에서 최신 시스템 상태를 사용할 수 있도록 보장합니다. 또한 첫 초기화, 어댑터 분리로 인한 재초기화, 테스트용 GPUDevice.destroy() 호출 등 여러 시나리오를 일관되게 처리할 수 있게 해줍니다.

어댑터는 성능에 중대한 제한이 있지만, 더 넓은 호환성, 예측 가능한 동작, 또는 향상된 프라이버시와 같은 조합을 위해 폴백 어댑터로 간주될 수 있습니다. 모든 시스템에서 폴백 어댑터가 반드시 제공될 필요는 없습니다.

어댑터는 다음 불변 속성을 가집니다:

[[features]], 타입 ordered set<GPUFeatureName>, 읽기 전용

이 어댑터에서 디바이스를 생성할 때 사용할 수 있는 기능들입니다.

[[limits]], 타입 지원 한계, 읽기 전용

이 어댑터에서 디바이스를 생성할 때 사용할 수 있는 최상 한계입니다.

각 어댑터 한계는 지원 한계의 기본값과 같거나 더 나은 값이어야 합니다.

[[fallback]], 타입 boolean, 읽기 전용

true일 때 어댑터가 폴백 어댑터임을 나타냅니다.

[[xrCompatible]], 타입 boolean

true일 때, 어댑터가 WebXR 세션과 호환되도록 요청되었음을 나타냅니다.

어댑터는 다음 디바이스 타임라인 속성을 가집니다:

[[state]], 초기값 "valid"
"valid"

어댑터를 사용해 디바이스를 생성할 수 있습니다.

"consumed"

어댑터가 이미 디바이스 생성에 사용되었으므로 다시 사용할 수 없습니다.

"expired"

어댑터가 다른 이유로 만료되었습니다.

GPUAdapter adapter만료하려면, 다음 디바이스 타임라인 단계 실행:
  1. adapter.[[adapter]].[[state]] 값을 "expired"로 설정합니다.

3.5.2. 디바이스

디바이스어댑터의 논리적 인스턴스화로, 내부 객체가 이 디바이스를 통해 생성됩니다.

디바이스GPUDevice로 노출됩니다.

디바이스는 자신으로부터 생성된 모든 내부 객체의 독점 소유자입니다: 디바이스무효가 될 때 (손실되거나 destroyed일 때), 해당 디바이스 및 그 위에서 생성된 모든 객체(직접적으로 예: createTexture(), 간접적으로 예: createView()) 는 암묵적으로 사용 불가 상태가 됩니다.

디바이스는 다음 불변 속성을 가집니다:

[[adapter]], 타입 어댑터, 읽기 전용

이 디바이스가 생성된 어댑터입니다.

[[features]], 타입 ordered set<GPUFeatureName>, 읽기 전용

이 디바이스에서 사용할 수 있는 기능이며, 생성 시에 결정됩니다. 기반 어댑터가 더 많은 기능을 지원하더라도, 추가 기능을 사용할 수 없습니다.

[[limits]], 타입 지원 한계, 읽기 전용

이 디바이스에서 사용할 수 있는 한계이며, 생성 시에 결정됩니다. 기반 어댑터가 더 나은 한계를 지원하더라도, 더 나은 한계를 사용할 수 없습니다.

디바이스는 다음 콘텐츠 타임라인 속성을 가집니다:

[[content device]], 타입 GPUDevice, 읽기 전용

이 디바이스와 연관된 콘텐츠 타임라인 GPUDevice 인터페이스입니다.

어댑터 adapter에서 GPUDeviceDescriptor descriptor새 디바이스를 생성하려면, 다음 디바이스 타임라인 단계 실행:
  1. featuresdescriptor.requiredFeatures의 값을 set으로 둡니다.

  2. features"texture-formats-tier2"가 포함되어 있다면:

    1. Append "texture-formats-tier1"features에 추가

  3. features"texture-formats-tier1"가 포함되어 있다면:

    1. Append "rg11b10ufloat-renderable"features에 추가

  4. Append "core-features-and-limits"features에 추가.

  5. limits에 모든 값을 기본값으로 둔 지원 한계 객체를 둡니다.

  6. descriptor.requiredLimits의 각 (key, value)에 대해:

    1. valueundefined가 아니고, valuelimits[key]보다 더 나으면:

      1. limits[key]를 value로 설정

  7. device디바이스 객체를 둡니다.

  8. device.[[adapter]]adapter로 설정.

  9. device.[[features]]features로 설정.

  10. device.[[limits]]limits로 설정.

  11. device를 반환.

사용자 에이전트가 디바이스 접근을 취소해야 할 때마다, 디바이스 손실(device, "unknown") 을 해당 디바이스의 디바이스 타임라인에서 호출합니다. 이는 해당 타임라인에 대기 중이던 다른 작업보다 먼저 발생할 수 있습니다.

작업 실패로 인해 디바이스의 객체 상태가 관찰될 만큼 변하거나 내부 구현/드라이버 상태가 손상될 위험이 있다면, 이런 변화가 관찰되지 않도록 디바이스를 손실해야 합니다.

참고: 앱이 직접 destroy()로 디바이스 손실을 유발하지 않은 모든 경우에, 사용자 에이전트는 lost 프라미스를 핸들링하더라도 무조건 개발자 가시 경고를 고려해야 합니다. 이런 시나리오는 드물어야 하며, 신호는 중요합니다. 왜냐하면 WebGPU API 대부분은 앱의 런타임 흐름을 방해하지 않기 위해 문제가 없는 것처럼 동작하기 때문입니다: 검증 오류가 발생하지 않고, 대부분의 프라미스가 정상적으로 resolve되는 등.

device손실(device, reason) 처리하려면, 다음 디바이스 타임라인 단계 실행:
  1. 무효화 device.

  2. device.[[content device]]콘텐츠 타임라인에서 다음 단계 실행:

    1. device.lost 를 새 GPUDeviceLostInfo로 resolve하며, reasonreason으로, message구현체 정의 값으로 설정.

      참고: message는 불필요한 사용자/시스템 정보를 노출하지 않아야 하며, 앱에서 절대 파싱하지 않아야 합니다.

  3. device손실 상태가 됨을 기다리는 모든 대기 단계 완료.

참고: 손실된 디바이스에서는 오류가 발생하지 않습니다. § 22 오류 및 디버깅 참고.

디바이스 device에서 event에 대해 timeline에서 steps타임라인 이벤트 대기하려면:

그때 timeline에서 steps를 실행합니다.

3.6. 선택적 기능

WebGPU 어댑터디바이스에는 기능(capabilities)이 있으며, 이는 WebGPU 기능이 구현마다 다르게 동작하는 부분을 설명합니다. 주로 하드웨어 또는 시스템 소프트웨어의 제약 때문입니다. 기능기능(feature) 또는 한계(limit)입니다.

사용자 에이전트는 32개를 초과하는 구분 가능한 구성이나 버킷을 공개해서는 안 됩니다.

어댑터의 기능은 반드시 § 4.2.1 어댑터 기능 보장을 따라야 합니다.

requestDevice()에서 지원되는 기능만 요청할 수 있습니다; 지원되지 않는 기능을 요청하면 실패합니다.

디바이스의 기능은 "새 디바이스"에서 어댑터의 기본값(기능 없음 및 지원 한계의 기본값)에서 시작해, requestDevice()에서 요청한 기능을 추가하여 결정됩니다. 이러한 기능은 어댑터의 기능과 관계없이 적용됩니다.

There is a tracking vector here. 프라이버시 관련 내용은 § 2.2.1 기기별 기능 및 한계를 참고하세요.

3.6.1. 기능

기능(feature)은 모든 구현에서 지원되지 않는 WebGPU의 선택적 기능 집합입니다. 일반적으로 하드웨어 또는 시스템 소프트웨어의 제약 때문입니다.

모든 기능은 선택적이지만, 어댑터는 그 가용성을 보장합니다 (§ 4.2.1 어댑터 기능 보장 참조).

디바이스는 생성 시 결정된 정확한 기능 집합만 지원합니다(§ 3.6 선택적 기능 참조). API 호출은 이 디바이스의 기능에 따라 검증을 수행합니다(어댑터의 기능이 아님):

GPUFeatureName featureGPUObjectBase object활성화됨이란, object.[[device]].[[features]] 에 포함될 때만 해당 feature가 활성화됩니다.

각 기능이 어떤 역할을 하는지에 대한 설명은 기능 색인을 참고하세요.

참고: 기능을 활성화하는 것이 항상 바람직한 것은 아니며, 성능에 영향을 줄 수 있습니다. 이를 감안해, 그리고 다양한 디바이스 및 구현에서 이식성을 높이기 위해, 실제로 필요한 기능만 요청하는 것이 좋습니다.

3.6.2. 한계

한계(limit)는 디바이스에서 WebGPU 사용에 대한 수치적 한계입니다.

참고: "더 나은" 한계를 설정하는 것이 항상 바람직한 것은 아니며, 성능에 영향을 줄 수 있습니다. 이를 감안해, 그리고 다양한 디바이스 및 구현에서 이식성을 높이기 위해, 실제로 필요한 경우에만 기본값보다 더 나은 한계를 요청하는 것이 좋습니다.

각 한계에는 기본값이 있습니다.

어댑터는 항상 기본값 또는 더 나은 값을 지원합니다 (§ 4.2.1 어댑터 기능 보장 참고).

디바이스는 생성 시 결정된 정확한 한계 집합만 지원합니다(§ 3.6 선택적 기능 참조). API 호출은 이 디바이스의 한계에 따라 검증을 수행합니다(어댑터의 한계가 아님), 더 나은 값도, 더 낮은 값도 사용할 수 없습니다.

각 한계에 대해 어떤 값이 더 나은 값인지 정의됩니다. 더 나은 한계 값은 항상 검증을 완화하여, 더 많은 프로그램이 유효해집니다. 각 한계 클래스마다 "더 나은"의 정의가 다릅니다.

한계마다 서로 다른 한계 클래스가 있습니다:

최대값

해당 한계는 API에 전달되는 어떤 값의 최대값을 제한합니다.

더 높은 값이 더 나은 값입니다.

기본값 이상(≥)만 설정할 수 있습니다. 더 낮은 값은 기본값으로 강제됩니다.

정렬값

해당 한계는 API에 전달되는 어떤 값의 최소 정렬값을 제한합니다. 즉, 값은 해당 한계의 배수여야 합니다.

더 낮은 값이 더 나은 값입니다.

기본값 이하(≤)의 2의 거듭제곱만 설정할 수 있습니다. 2의 거듭제곱이 아닌 값은 유효하지 않습니다. 더 높은 거듭제곱은 기본값으로 강제됩니다.

지원 한계 객체는 WebGPU에서 정의된 모든 한계에 대한 값을 가집니다:

한계 이름 타입 한계 클래스 기본값
maxTextureDimension1D GPUSize32 최대값 8192
size.width 값의 최대 허용치 (1D 텍스처에서 dimension "1d" 사용).
maxTextureDimension2D GPUSize32 최대값 8192
size.widthsize.height 값의 최대 허용치 (2D 텍스처에서 dimension "2d" 사용).
maxTextureDimension3D GPUSize32 최대값 2048
size.width, size.heightsize.depthOrArrayLayers 값의 최대 허용치 (3D 텍스처에서 dimension "3d" 사용).
maxTextureArrayLayers GPUSize32 최대값 256
size.depthOrArrayLayers 값의 최대 허용치 (2D 텍스처에서 dimension "2d" 사용).
maxBindGroups GPUSize32 최대값 4
GPUBindGroupLayouts 최대 갯수 (bindGroupLayouts 사용 시 GPUPipelineLayout 생성).
maxBindGroupsPlusVertexBuffers GPUSize32 최대값 24
동시에 사용되는 바인드 그룹 및 버텍스 버퍼 슬롯의 최대 갯수 (빈 슬롯 포함). createRenderPipeline()드로우 호출에서 검증.
maxBindingsPerBindGroup GPUSize32 최대값 1000
GPUBindGroupLayout 생성 시 사용 가능한 binding 인덱스 최대 갯수.

참고: 이 한계는 규범적이지만 임의적입니다. 기본 binding slot limits에서는 하나의 바인드 그룹에 1000개 바인딩을 사용하는 것은 불가능하지만, GPUBindGroupLayoutEntry.binding 값을 999까지 허용합니다. 이 한계는 구현체가 바인딩 공간을 합리적인 메모리 내에서 배열로 처리할 수 있도록 합니다.

maxDynamicUniformBuffersPerPipelineLayout GPUSize32 최대값 8
GPUBindGroupLayoutEntry 중 동적 오프셋이 있는 uniform buffer의 최대 갯수 (GPUPipelineLayout 기준). binding slot 한계 초과 참고.
maxDynamicStorageBuffersPerPipelineLayout GPUSize32 최대값 4
GPUBindGroupLayoutEntry 중 동적 오프셋이 있는 storage buffer의 최대 갯수 (GPUPipelineLayout 기준). binding slot 한계 초과 참고.
maxSampledTexturesPerShaderStage GPUSize32 최대값 16
GPUShaderStage stageGPUBindGroupLayoutEntry 중 샘플링 텍스처의 최대 갯수 (GPUPipelineLayout 기준). binding slot 한계 초과 참고.
maxSamplersPerShaderStage GPUSize32 최대값 16
GPUShaderStage stageGPUBindGroupLayoutEntry 중 샘플러의 최대 갯수 (GPUPipelineLayout 기준). binding slot 한계 초과 참고.
maxStorageBuffersPerShaderStage GPUSize32 최대값 8
GPUShaderStage stageGPUBindGroupLayoutEntry 중 storage buffer의 최대 갯수 (GPUPipelineLayout 기준). binding slot 한계 초과 참고.
maxStorageTexturesPerShaderStage GPUSize32 최대값 4
GPUShaderStage stageGPUBindGroupLayoutEntry 중 storage texture의 최대 갯수 (GPUPipelineLayout 기준). binding slot 한계 초과 참고.
maxUniformBuffersPerShaderStage GPUSize32 최대값 12
GPUShaderStage stageGPUBindGroupLayoutEntry 중 uniform buffer의 최대 갯수 (GPUPipelineLayout 기준). binding slot 한계 초과 참고.
maxUniformBufferBindingSize GPUSize64 최대값 65536 bytes
GPUBufferBinding.size 값의 최대치 (바인딩 타입이 "uniform"일 때).
maxStorageBufferBindingSize GPUSize64 최대값 134217728 bytes (128 MiB)
GPUBufferBinding.size 값의 최대치 (바인딩 타입이 "storage" 또는 "read-only-storage"일 때).
minUniformBufferOffsetAlignment GPUSize32 정렬값 256 bytes
GPUBufferBinding.offset 및 setBindGroup()에서 제공되는 동적 오프셋의 정렬값 (GPUBindGroupLayoutEntry 타입이 "uniform"일 때).
minStorageBufferOffsetAlignment GPUSize32 정렬값 256 bytes
GPUBufferBinding.offset 및 setBindGroup()에서 제공되는 동적 오프셋의 정렬값 (GPUBindGroupLayoutEntry 타입이 "storage" 또는 "read-only-storage"일 때).
maxVertexBuffers GPUSize32 최대값 8
buffers 최대 갯수 (GPURenderPipeline 생성 시).
maxBufferSize GPUSize64 최대값 268435456 bytes (256 MiB)
size 최대값 (GPUBuffer 생성 시).
maxVertexAttributes GPUSize32 최대값 16
attributes 최대 갯수 (buffers 전체 합계, GPURenderPipeline 생성 시).
maxVertexBufferArrayStride GPUSize32 최대값 2048 bytes
arrayStride 최대 허용값 (GPURenderPipeline 생성 시).
maxInterStageShaderVariables GPUSize32 최대값 16
입력/출력 변수의 최대 허용 갯수 (버텍스 출력, 프래그먼트 입력 등 스테이지 간 통신).
maxColorAttachments GPUSize32 최대값 8
GPURenderPipelineDescriptor.fragment.targets, GPURenderPassDescriptor.colorAttachments, GPURenderPassLayout.colorFormats 값의 최대 갯수.
maxColorAttachmentBytesPerSample GPUSize32 최대값 32
모든 컬러 어태치먼트에서 렌더 파이프라인 출력 데이터의 한 샘플(픽셀 또는 서브픽셀)을 저장하는 데 필요한 최대 바이트 수.
maxComputeWorkgroupStorageSize GPUSize32 최대값 16384 bytes
컴퓨트 스테이지 GPUShaderModule 엔트리 포인트에서 사용되는 workgroup 스토리지의 최대 바이트 수.
maxComputeInvocationsPerWorkgroup GPUSize32 최대값 256
컴퓨트 스테이지 GPUShaderModule 엔트리 포인트의 workgroup_size 차원의 곱의 최대값.
maxComputeWorkgroupSizeX GPUSize32 최대값 256
컴퓨트 스테이지 GPUShaderModule 엔트리 포인트의 workgroup_size X 차원의 최대값.
maxComputeWorkgroupSizeY GPUSize32 최대값 256
컴퓨트 스테이지 GPUShaderModule 엔트리 포인트의 workgroup_size Y 차원의 최대값.
maxComputeWorkgroupSizeZ GPUSize32 최대값 64
컴퓨트 스테이지 GPUShaderModule 엔트리 포인트의 workgroup_size Z 차원의 최대값.
maxComputeWorkgroupsPerDimension GPUSize32 최대값 65535
dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ) 인자별 최대값.
3.6.2.1. GPUSupportedLimits

GPUSupportedLimits 는 어댑터 또는 디바이스의 지원 한계를 노출합니다. GPUAdapter.limitsGPUDevice.limits 참고.

[Exposed=(Window, Worker), SecureContext]
interface GPUSupportedLimits {
    readonly attribute unsigned long maxTextureDimension1D;
    readonly attribute unsigned long maxTextureDimension2D;
    readonly attribute unsigned long maxTextureDimension3D;
    readonly attribute unsigned long maxTextureArrayLayers;
    readonly attribute unsigned long maxBindGroups;
    readonly attribute unsigned long maxBindGroupsPlusVertexBuffers;
    readonly attribute unsigned long maxBindingsPerBindGroup;
    readonly attribute unsigned long maxDynamicUniformBuffersPerPipelineLayout;
    readonly attribute unsigned long maxDynamicStorageBuffersPerPipelineLayout;
    readonly attribute unsigned long maxSampledTexturesPerShaderStage;
    readonly attribute unsigned long maxSamplersPerShaderStage;
    readonly attribute unsigned long maxStorageBuffersPerShaderStage;
    readonly attribute unsigned long maxStorageTexturesPerShaderStage;
    readonly attribute unsigned long maxUniformBuffersPerShaderStage;
    readonly attribute unsigned long long maxUniformBufferBindingSize;
    readonly attribute unsigned long long maxStorageBufferBindingSize;
    readonly attribute unsigned long minUniformBufferOffsetAlignment;
    readonly attribute unsigned long minStorageBufferOffsetAlignment;
    readonly attribute unsigned long maxVertexBuffers;
    readonly attribute unsigned long long maxBufferSize;
    readonly attribute unsigned long maxVertexAttributes;
    readonly attribute unsigned long maxVertexBufferArrayStride;
    readonly attribute unsigned long maxInterStageShaderVariables;
    readonly attribute unsigned long maxColorAttachments;
    readonly attribute unsigned long maxColorAttachmentBytesPerSample;
    readonly attribute unsigned long maxComputeWorkgroupStorageSize;
    readonly attribute unsigned long maxComputeInvocationsPerWorkgroup;
    readonly attribute unsigned long maxComputeWorkgroupSizeX;
    readonly attribute unsigned long maxComputeWorkgroupSizeY;
    readonly attribute unsigned long maxComputeWorkgroupSizeZ;
    readonly attribute unsigned long maxComputeWorkgroupsPerDimension;
};
3.6.2.2. GPUSupportedFeatures

GPUSupportedFeaturessetlike 인터페이스입니다. set entries는 어댑터 또는 디바이스가 지원하는 GPUFeatureName 값(기능)입니다. 반드시 GPUFeatureName enum의 문자열만 포함해야 합니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUSupportedFeatures {
    readonly setlike<DOMString>;
};
참고:
GPUSupportedFeatures set entries의 타입은 DOMString입니다. 이렇게 하면 사용자 에이전트가 명세의 후속 버전에 추가된 새로운 GPUFeatureName을 인식하지 못해도 원활하게 처리할 수 있습니다. 만약 set entries의 타입이 GPUFeatureName이라면, 아래 코드에서 false를 반환하는 대신 TypeError가 발생합니다:
인식되지 않은 기능 지원 여부 확인:
if (adapter.features.has('unknown-feature')) {
    // Use unknown-feature
} else {
    console.warn('unknown-feature is not supported by this adapter.');
}
3.6.2.3. WGSLLanguageFeatures

WGSLLanguageFeaturesnavigator.gpu.wgslLanguageFeaturessetlike 인터페이스입니다. set entries는 해당 구현이 지원하는 WGSL 언어 확장의 문자열 이름입니다(어댑터, 디바이스와 관계없이).

[Exposed=(Window, Worker), SecureContext]
interface WGSLLanguageFeatures {
    readonly setlike<DOMString>;
};
3.6.2.4. GPUAdapterInfo

GPUAdapterInfo 는 어댑터에 대한 다양한 식별 정보를 노출합니다.

GPUAdapterInfo 의 멤버들은 특정 값이 반드시 채워진다는 보장이 없습니다. 값이 제공되지 않으면 속성은 빈 문자열 ""을 반환합니다. 어떤 값을 노출할지 결정하는 것은 사용자 에이전트의 재량이며, 일부 디바이스에서는 값이 전혀 채워지지 않을 수 있습니다. 따라서 애플리케이션은 모든 GPUAdapterInfo 값(값 없음 포함)을 처리할 수 있어야 합니다.

어댑터의 GPUAdapterInfoGPUAdapter.infoGPUDevice.adapterInfo를 통해 노출됩니다. 이 정보는 불변(immutable)입니다: 동일 어댑터에 대해 각 GPUAdapterInfo 속성은 접근할 때마다 같은 값을 반환합니다.

참고: GPUAdapterInfo 속성은 한 번 접근하면 불변이지만, 각 속성에 대해 노출할 값을 언제 결정할지 구현체가 지연할 수 있습니다.

참고: 동일한 물리 어댑터를 나타내더라도 다른 GPUAdapter 인스턴스는 GPUAdapterInfo에서 다른 값을 노출할 수 있습니다. 그래도 특별한 이벤트로 페이지의 식별 정보 접근 권한이 늘어난 경우가 아니라면(이 명세에서는 그런 이벤트 정의 없음) 동일한 값을 노출해야 합니다.

There is a tracking vector here. 프라이버시 관련 내용은 § 2.2.6 어댑터 식별자를 참고하세요.

[Exposed=(Window, Worker), SecureContext]
interface GPUAdapterInfo {
    readonly attribute DOMString vendor;
    readonly attribute DOMString architecture;
    readonly attribute DOMString device;
    readonly attribute DOMString description;
    readonly attribute unsigned long subgroupMinSize;
    readonly attribute unsigned long subgroupMaxSize;
    readonly attribute boolean isFallbackAdapter;
};

GPUAdapterInfo 는 다음 속성을 가집니다:

vendor, 타입 DOMString, 읽기 전용

어댑터의 벤더 이름(가능한 경우). 없으면 빈 문자열.

architecture, 타입 DOMString, 읽기 전용

어댑터가 속한 GPU 계열/클래스 이름(가능한 경우). 없으면 빈 문자열.

device, 타입 DOMString, 읽기 전용

어댑터에 대한 벤더별 식별자(가능한 경우). 없으면 빈 문자열.

참고: 해당 어댑터의 종류를 나타내는 값입니다. 예를 들어 PCI device ID일 수 있습니다. 특정 하드웨어(시리얼번호 등)를 고유하게 식별하지 않습니다.

description, 타입 DOMString, 읽기 전용

드라이버가 보고한 어댑터 설명(가능한 경우, 사람이 읽을 수 있는 문자열). 없으면 빈 문자열.

참고: description에는 별도의 포맷이 적용되지 않으므로 파싱 권장하지 않습니다. 드라이버 이슈 등으로 동작을 달리하는 앱은 가능하면 다른 필드를 활용해야 합니다.

subgroupMinSize, 타입 unsigned long, 읽기 전용

"subgroups" 기능이 지원된다면, subgroup size의 최소값(해당 어댑터 기준).

subgroupMaxSize, 타입 unsigned long, 읽기 전용

"subgroups" 기능이 지원된다면, subgroup size의 최대값(해당 어댑터 기준).

isFallbackAdapter, 타입 boolean, 읽기 전용

어댑터폴백 어댑터인지 여부.

주어진 어댑터 adapter에 대해 새 adapter info를 생성하려면, 아래 콘텐츠 타임라인 단계 실행:
  1. adapterInfoGPUAdapterInfo 새 인스턴스 할당.

  2. 벤더가 알려져 있으면 adapterInfo.vendoradapter 벤더 이름(정규화 식별자 문자열)을 설정. 프라이버시 보호를 위해 빈 문자열 또는 유사 벤더명을 사용할 수 있음.

  3. 아키텍처가 알려져 있으면 adapterInfo.architectureadapter가 속한 계열/클래스(정규화 식별자 문자열)를 설정. 프라이버시 보호를 위해 빈 문자열 또는 유사 아키텍처명을 사용할 수 있음.

  4. 디바이스가 알려져 있으면 adapterInfo.deviceadapter 벤더별 식별자(정규화 식별자 문자열)를 설정. 프라이버시 보호를 위해 빈 문자열 또는 유사 식별자를 사용할 수 있음.

  5. 설명이 알려져 있으면 adapterInfo.description 에 드라이버가 보고한 설명을 설정. 프라이버시 보호를 위해 빈 문자열 또는 유사 설명을 사용할 수 있음.

  6. "subgroups" 기능이 지원되면 subgroupMinSize 에 지원하는 최소 subgroup size를 설정. 아니면 4로 설정.

    참고: 프라이버시 보호를 위해 일부 기능 미지원 또는 식별 불가능한 값을 사용할 수 있음(예: 모든 디바이스에 4 사용).

  7. "subgroups" 기능이 지원되면 subgroupMaxSize 에 지원하는 최대 subgroup size를 설정. 아니면 128로 설정.

    참고: 프라이버시 보호를 위해 일부 기능 미지원 또는 식별 불가능한 값을 사용할 수 있음(예: 모든 디바이스에 128 사용).

  8. adapterInfo.isFallbackAdapter 값을 adapter.[[fallback]]로 설정.

  9. adapterInfo 반환.

정규화 식별자 문자열은 아래 규칙을 따릅니다:

[a-z0-9]+(-[a-z0-9]+)*

a-z 0-9 -
정규화 식별자 문자열 예시:
  • gpu

  • 3d

  • 0x3b2f

  • next-gen

  • series-x20-ultra

3.7. 확장 문서

"확장 문서"는 새로운 기능을 설명하는 추가 문서로, 이는 비규범적이며 WebGPU/WGSL 명세의 일부가 아닙니다. 이러한 문서는 현행 표준을 기반으로 새로운 기능을 설명하며, 종종 하나 이상의 새로운 API 기능 플래그 및/또는 WGSL enable 지시문, 또는 다른 웹 초안 명세와의 상호작용을 포함합니다.

WebGPU 구현체는 확장 기능을 노출해서는 안 됩니다; 그렇게 하면 명세 위반입니다. 새로운 기능은 WebGPU 표준(이 문서) 및/또는 WGSL 명세에 통합될 때까지 WebGPU 표준의 일부가 아닙니다.

3.8. 오리진 제한

WebGPU는 이미지, 비디오, 캔버스에 저장된 이미지 데이터를 접근할 수 있도록 허용합니다. 셰이더를 통해 GPU에 업로드된 텍스처의 내용을 간접적으로 추론할 수 있기 때문에, 교차 도메인 미디어 사용에는 제한이 있습니다.

WebGPU는 이미지 소스가 오리진-클린하지 않은 경우 업로드를 허용하지 않습니다.

이로 인해 WebGPU로 렌더링된 캔버스의 origin-clean 플래그는 결코 false로 설정되지 않습니다.

이미지 및 비디오 요소에 대해 CORS 요청 발행에 대한 자세한 내용은 다음을 참고하세요:

3.9. 태스크 소스

3.9.1. WebGPU 태스크 소스

WebGPU는 태스크 소스라는 새로운 WebGPU 태스크 소스를 정의합니다. 이는 uncapturederror 이벤트 및 GPUDevice.lost에 사용됩니다.

GPUDevice device에 대해, 콘텐츠 타임라인에서 일련의 단계 steps글로벌 태스크로 큐잉 하려면:
  1. 글로벌 태스크 큐잉WebGPU 태스크 소스에 대해, device를 생성한 글로벌 객체와 steps를 전달해 실행합니다.

3.9.2. 자동 만료 태스크 소스

WebGPU는 태스크 소스라는 새로운 자동 만료 태스크 소스를 정의합니다. 특정 객체의 자동, 시간 기반 만료(파괴)에 사용됩니다:

GPUDevice device콘텐츠 타임라인의 단계 steps자동 만료 태스크로 큐잉 하려면:
  1. 글로벌 태스크 큐잉자동 만료 태스크 소스에 대해, device를 생성한 글로벌 객체와 steps를 전달해 실행합니다.

자동 만료 태스크 소스의 태스크는 높은 우선순위로 처리되어야 하며, 큐잉 후에는 사용자 정의(JavaScript) 태스크보다 먼저 실행되어야 합니다.

참고:
이러한 동작은 더 예측 가능하며, 엄격함을 통해 개발자가 암묵적 수명에 대한 잘못된 가정을 빠르게 감지할 수 있어 이식성 높은 앱 개발에 도움이 됩니다. 개발자는 다양한 구현체에서 반드시 테스트할 것을 강력히 권장합니다.

구현 참고: 높은 우선순위 만료 "태스크"는 실제 태스크를 실행하는 대신 이벤트 루프 처리 모델의 고정 지점에 추가 단계 삽입으로 구현해도 무방합니다.

3.10. 색 공간 및 인코딩

WebGPU는 색상 관리(color management)를 제공하지 않습니다. WebGPU 내부의 모든 값(예: 텍스처 요소)은 색상 관리가 적용된 값이 아니라, 순수 숫자 값입니다.

WebGPU는 색상 관리가 적용된 출력(GPUCanvasConfiguration) 및 입력 (copyExternalImageToTexture()importExternalTexture())과 인터페이스합니다. 따라서 WebGPU의 숫자 값과 외부 색상 값 사이에는 색상 변환이 필요합니다. 이러한 인터페이스 지점마다 인코딩(색 공간, 전송 함수, 알파 프리멀티플리케이션)이 개별적으로 정의되어 WebGPU의 숫자 값이 해석됩니다.

WebGPU는 PredefinedColorSpace enum의 모든 색 공간을 허용합니다. 각 색 공간은 참조된 CSS 정의에 따라 확장 범위로 정의되므로, 색 공간 밖의 색상 값(색도 및 휘도 모두)을 표현할 수 있습니다.

가뮤트 초과 프리멀티플라이드 RGBA 값은 R/G/B 채널 값 중 하나라도 알파 채널 값을 초과하는 경우입니다. 예를 들어 프리멀티플라이드 sRGB RGBA 값 [1.0, 0, 0, 0.5]는 (비프리멀티플라이드) 색상 [2, 0, 0]에 50% 알파를 적용한 것으로, CSS에서는 rgb(srgb 2 0 0 / 50%)로 표현됩니다. sRGB 색 공간을 벗어난 색상 값과 마찬가지로, 이는 확장된 색 공간 내에서 잘 정의된 점입니다(알파가 0이면 색상 없음). 하지만 이러한 값이 눈에 보이는 캔버스에 출력될 경우 결과는 정의되지 않습니다 (GPUCanvasAlphaMode "premultiplied" 참고).

3.10.1. 색 공간 변환

색상은 한 공간에서 다른 공간으로 변환할 때 위 정의에 따라 표현을 변환합니다.

소스 값에 RGBA 채널이 4개 미만일 경우, 부족한 green/blue/alpha 채널을 각각 0, 0, 1로 설정한 뒤 색 공간/인코딩 및 알파 프리멀티플라이드 변환을 수행합니다. 변환 후 목적지에서 채널이 4개 미만일 경우, 추가 채널은 무시됩니다.

참고: 그레이스케일 이미지는 일반적으로 RGB 값 (V, V, V) 또는 RGBA 값 (V, V, V, A)로 색 공간 내에서 표현됩니다.

색상 변환 과정에서 값이 소실(clamp)되지 않습니다: 한 색 공간에서 다른 색 공간으로 변환할 때, 소스 색 값이 목적지 색 공간의 가뮤트 범위를 벗어나면 [0, 1] 범위를 벗어난 값이 나올 수 있습니다. 예를 들어, sRGB 목적지의 경우 소스가 rgba16float이거나 더 넓은 색 공간(Display-P3 등)이거나, 프리멀티플라이드 값이 가뮤트 초과 값을 포함하는 경우 발생할 수 있습니다.

마찬가지로 소스 값이 고비트뎁스(PNG 16비트 등) 또는 확장 범위(canvas의 float16 저장 등)일 경우, 색 공간 변환을 통해 이러한 색상 값이 보존되며, 중간 계산은 소스와 동일한 정밀도를 가져야 합니다.

3.10.2. 색 공간 변환 생략

색 공간/인코딩 변환의 소스와 목적지가 동일하면 변환이 필요하지 않습니다. 일반적으로 변환 단계 중 어떤 단계가 항등 함수(no-op)라면, 구현체는 성능을 위해 이를 생략해야 합니다.

최적의 성능을 위해, 앱은 전체 과정에서 필요한 변환 횟수를 최소화할 수 있도록 색 공간 및 인코딩 옵션을 설정하는 것이 권장됩니다. 다양한 이미지 소스(GPUCopyExternalImageSourceInfo)의 경우:

참고: 이러한 기능에 의존하기 전에 브라우저 구현 지원 여부를 확인하세요.

3.11. JavaScript에서 WGSL로의 숫자 변환

WebGPU API의 여러 부분(pipeline-overridable constants 및 렌더 패스 clear 값)은 WebIDL(double 또는 float) 타입의 숫자 값을 받아 WGSL 값(bool, i32, u32, f32, f16)으로 변환합니다.

IDL 값 idlValuedouble 또는 float일 때, WGSL 타입 T로 변환하려면, TypeError가 발생할 수 있으며, 아래 디바이스 타임라인 단계를 실행합니다:

참고:TypeError디바이스 타임라인에서 생성되며, JavaScript에는 전달되지 않습니다.

  1. assert idlValue가 유한한 값인지 확인합니다. 이는 unrestricted double 또는 unrestricted float가 아니기 때문입니다.

  2. v! idlValueECMAScript 값으로 변환한 결과의 ECMAScript Number입니다.

  3. 만약 Tbool이면

    ! v를 타입 boolean의 IDL 값으로 변환한 결과에 해당하는 WGSL bool 값을 반환합니다.

    참고: 이 알고리즘은 ECMAScript 값을 IDL double 또는 float로 변환한 뒤 호출됩니다. 만약 원래 ECMAScript 값이 숫자나 불리언이 아닌 [] 또는 {}였다면, WGSL bool 결과는 ECMAScript 값을 직접 boolean으로 변환한 결과와 다를 수 있습니다.

    만약 Ti32이면

    ? v를 [EnforceRange] long 타입의 IDL 값으로 변환한 결과에 해당하는 WGSL i32 값을 반환합니다.

    만약 Tu32이면

    ? v를 [EnforceRange] unsigned long 타입의 IDL 값으로 변환한 결과에 해당하는 WGSL u32 값을 반환합니다.

    만약 Tf32이면

    ? vfloat 타입의 IDL 값으로 변환한 결과에 해당하는 WGSL f32 값을 반환합니다.

    만약 Tf16이면
    1. wgslF32? vfloat 타입의 IDL 값으로 변환한 결과에 해당하는 WGSL f32 값으로 둡니다.

    2. f16(wgslF32)를 반환합니다. 이는 WGSL f32 값을 f16으로 변환하는 규칙(WGSL 부동소수점 변환)을 따릅니다.

    참고: 값이 f32 범위 내라면 오류가 발생하지 않으며, f16 범위를 벗어나도 오류 없이 변환됩니다.

GPUColor 타입의 color텍스처 포맷의 텍셀 값 format으로 변환하려면, TypeError가 발생할 수 있으며, 아래 디바이스 타임라인 단계를 실행합니다:

참고:TypeError디바이스 타임라인에서 생성되며, JavaScript에는 전달되지 않습니다.

  1. format의 컴포넌트 타입이(assert로 모두 같은 타입임을 보장):

    부동소수점 또는 정규화 타입

    Tf32로 둡니다.

    부호 있는 정수 타입

    Ti32로 둡니다.

    부호 없는 정수 타입

    Tu32로 둡니다.

  2. wgslColor를 타입 vec4<T>의 WGSL 값으로, RGBA 채널 각각을 ? 변환(WGSL 타입 T 변환)한 값으로 설정합니다.

  3. wgslColorformat에 맞게 § 23.2.7 출력 머지(Output Merging) 단계와 동일한 변환 규칙을 적용해 변환 후 반환합니다.

    참고: 정수 타입이 아니라면, 구체적인 값 선택은 구현체 정의입니다. 정규화 타입의 경우 값은 타입의 범위로 강제(clamp)됩니다.

참고: 즉, 작성되는 값은 WGSL 셰이더가 vec4f32, i32, u32로 출력한 것과 동일하게 동작합니다.

4. 초기화

GPU 객체는 WindowWorkerGlobalScope 컨텍스트에서 NavigatorWorkerNavigator 인터페이스를 통해 노출되며 navigator.gpu로 접근할 수 있습니다:

interface mixin NavigatorGPU {
    [SameObject, SecureContext] readonly attribute GPU gpu;
};
Navigator includes NavigatorGPU;
WorkerNavigator includes NavigatorGPU;

NavigatorGPU 는 다음 속성을 가집니다:

gpu, 타입 GPU, 읽기 전용

글로벌 싱글톤 객체로, requestAdapter() 등 최상위 진입점을 제공합니다.

4.2. GPU

GPU는 WebGPU의 진입점입니다.

[Exposed=(Window, Worker), SecureContext]
interface GPU {
    Promise<GPUAdapter?> requestAdapter(optional GPURequestAdapterOptions options = {});
    GPUTextureFormat getPreferredCanvasFormat();
    [SameObject] readonly attribute WGSLLanguageFeatures wgslLanguageFeatures;
};

GPU는 다음 메서드를 가집니다:

requestAdapter(options)

사용자 에이전트에서 어댑터를 요청합니다. 사용자 에이전트는 어댑터를 반환할지, 반환한다면 옵션에 따라 선택합니다.

호출 대상: GPU this.

인자:

GPU.requestAdapter(options) 메서드 인자.
파라미터 타입 Nullable Optional 설명
options GPURequestAdapterOptions 어댑터 선택 기준.

반환값: Promise<GPUAdapter?>

콘텐츠 타임라인 단계:

  1. contentTimeline을 현재 콘텐츠 타임라인으로 둡니다.

  2. promise새 promise로 둡니다.

  3. initialization stepsthis디바이스 타임라인에서 실행합니다.

  4. promise를 반환합니다.

디바이스 타임라인 initialization steps:
  1. 아래 단계의 모든 요구사항을 반드시 만족해야 합니다.

    1. options.featureLevel 반드시 feature level string이어야 합니다.

    만족하고 사용자 에이전트가 어댑터를 반환하기로 결정한 경우:

    1. adapter어댑터로 설정하며, § 4.2.2 어댑터 선택 규칙과 options 기준에 따라 선택. § 4.2.1 어댑터 기능 보장 준수. adapter의 속성은 정의에 따라 초기화:

      1. adapter.[[limits]]adapter.[[features]] 를 해당 어댑터의 지원 기능으로 설정. adapter.[[features]]"core-features-and-limits"를 포함해야 함.

      2. adapter폴백 어댑터 기준을 만족하면 adapter.[[fallback]]true로, 아니면 false로 설정.

      3. adapter.[[xrCompatible]] 값을 options.xrCompatible 로 설정.

    그렇지 않으면:

    1. adapternull로 둡니다.

  2. 이후 단계는 contentTimeline에서 실행.

콘텐츠 타임라인 단계:
  1. adapternull이 아니면:

    1. resolve promiseGPUAdapter 새 객체(내부적으로 adapter 캡슐화)로 설정.

  2. 그렇지 않으면 resolve promisenull로 설정.

getPreferredCanvasFormat()

이 시스템에서 8비트 깊이, 표준 다이나믹 레인지 콘텐츠를 표시하기에 최적의 GPUTextureFormat을 반환합니다. 반드시 "rgba8unorm" 또는 "bgra8unorm"만 반환해야 합니다.

반환된 값은 format 으로 configure() 호출 시 전달하여, 연관된 GPUCanvasContext 캔버스가 효율적으로 내용을 표시할 수 있도록 할 수 있습니다.

참고: 화면에 표시되지 않는 캔버스는 이 포맷을 사용해도 이점이 없을 수 있습니다.

호출 대상: GPU this.

반환값: GPUTextureFormat

콘텐츠 타임라인 단계:

  1. WebGPU 캔버스 표시에 최적인 포맷을 선택하여 "rgba8unorm" 또는 "bgra8unorm" 반환.

GPU는 다음 속성을 가집니다:

wgslLanguageFeatures, 타입 WGSLLanguageFeatures, 읽기 전용

지원되는 WGSL 언어 확장 이름. 지원되는 언어 확장은 자동으로 활성화됩니다.

어댑터언제든지 만료될 수 있습니다. 시스템 상태가 변경되어 requestAdapter() 호출 결과에 영향을 줄 수 있을 때, 사용자 에이전트는 이전에 반환된 어댑터만료해야 합니다. 예:

참고: 사용자 에이전트는 시스템 상태가 변경되지 않아도 어댑터를 자주 만료할 수 있습니다(예: 생성 후 몇 초 또는 몇 분 후). 이는 실제 시스템 상태 변화를 감추고, requestAdapter() 를 다시 호출하는 것이 항상 필요하다는 점을 개발자에게 더 잘 인식시키는 데 도움이 됩니다. 만약 애플리케이션에서 이런 상황을 만나면, 표준 디바이스 손실 복구 처리를 통해 회복할 수 있습니다.

GPUAdapter 힌트 없이 요청하기 예시:
const gpuAdapter = await navigator.gpu.requestAdapter();

4.2.1. 어댑터 기능 보장

GPUAdapter 객체가 requestAdapter() 로 반환될 때는 아래 보장을 제공해야 합니다:

4.2.2. 어댑터 선택

GPURequestAdapterOptions 는 사용자 에이전트에게 앱에 적합한 구성을 힌트로 제공합니다.

dictionary GPURequestAdapterOptions {
    DOMString featureLevel = "core";
    GPUPowerPreference powerPreference;
    boolean forceFallbackAdapter = false;
    boolean xrCompatible = false;
};
enum GPUPowerPreference {
    "low-power",
    "high-performance",
};

GPURequestAdapterOptions 는 아래 멤버를 가집니다:

featureLevel, 타입 DOMString, 기본값 "core"

어댑터 요청의 "feature level"입니다.

허용되는 feature level string 값:

"core"

영향 없음.

"compatibility"

영향 없음.

참고: 이 값은 향후 추가 검증 제한을 선택적으로 적용하기 위한 예약 값입니다. 현재는 사용하지 않아야 합니다.

powerPreference, 타입 GPUPowerPreference

시스템의 사용 가능한 어댑터 중 어떤 클래스가 선택되어야 하는지 힌트를 제공합니다.

이 힌트 값은 어떤 어댑터가 선택되는지에 영향을 줄 수 있지만, 어댑터가 반환되는지 여부에는 영향을 주지 않습니다.

참고: 이 힌트의 주요 용도는 멀티 GPU 시스템에서 어떤 GPU를 사용할지 결정하는 것입니다. 예를 들어, 일부 노트북에는 저전력 내장 GPU와 고성능 외장 GPU가 있습니다. 이 힌트는 선택된 GPU의 전원 구성에도 영향을 줄 수 있습니다.

참고: 배터리 상태, 연결된 디스플레이, 착탈식 GPU 등 하드웨어 구성에 따라 동일한 powerPreference여도 다른 어댑터가 선택될 수 있습니다. 일반적으로 동일한 하드웨어 구성 및 상태, powerPreference라면 동일 어댑터가 선택될 가능성이 높습니다.

다음 값 중 하나여야 합니다:

undefined (또는 미지정)

사용자 에이전트에 힌트를 제공하지 않습니다.

"low-power"

성능보다 전력 절약을 우선하도록 요청합니다.

참고: 일반적으로 초당 1프레임만 렌더링하거나, 단순한 지오메트리/셰이더만 사용하는 콘텐츠, 작은 HTML 캔버스 등을 사용할 경우 이에 적합합니다. 가능하면 이 값을 사용하면 휴대기기의 배터리 수명에 큰 도움이 될 수 있습니다.

"high-performance"

전력 소모보다 성능을 우선하도록 요청합니다.

참고: 이 값을 선택하면, 해당 어댑터에서 생성한 디바이스가 전력 절약을 위해 저전력 어댑터로 전환되면서 강제로 디바이스 손실(device loss)이 발생할 수 있습니다. 정말 필요하다고 판단될 때만 이 값을 지정해야 하며, 휴대기기에서 배터리 수명이 크게 감소할 수 있습니다.

forceFallbackAdapter, 타입 boolean, 기본값 false

true이면 폴백 어댑터만 반환될 수 있습니다. 사용자 에이전트가 폴백 어댑터를 지원하지 않으면 requestAdapter()null로 resolve됩니다.

참고: requestAdapter()forceFallbackAdapterfalse일 때도, 적합한 어댑터가 없거나 사용자 에이전트가 폴백 어댑터 반환을 선택하면 폴백 어댑터를 반환할 수 있습니다. 폴백 어댑터에서 실행을 막으려면 info.isFallbackAdapter 속성을 확인한 후 GPUDevice 를 요청해야 합니다.

xrCompatible, 타입 boolean, 기본값 false

true로 설정하면 WebXR 세션 렌더링에 가장 적합한 어댑터를 반환해야 함을 의미합니다. 사용자 에이전트나 시스템이 WebXR 세션을 지원하지 않는 경우, 어댑터 선택 시 이 값을 무시할 수 있습니다.

참고: 어댑터를 요청할 때 xrCompatibletrue로 설정되지 않으면, 해당 어댑터에서 생성한 GPUDeviceWebXR 세션 렌더링에 사용할 수 없습니다.

"high-performance" GPUAdapter를 요청하는 예시:
const gpuAdapter = await navigator.gpu.requestAdapter({
    powerPreference: 'high-performance'
});

4.3. GPUAdapter

GPUAdapter어댑터를 캡슐화하며, 해당 기능한계 등 기능을 설명합니다.

GPUAdapter 를 얻으려면 requestAdapter() 를 사용하세요.

[Exposed=(Window, Worker), SecureContext]
interface GPUAdapter {
    [SameObject] readonly attribute GPUSupportedFeatures features;
    [SameObject] readonly attribute GPUSupportedLimits limits;
    [SameObject] readonly attribute GPUAdapterInfo info;

    Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
};

GPUAdapter 는 다음 불변 속성을 가집니다.

features, 타입 GPUSupportedFeatures, 읽기 전용

this.[[adapter]].[[features]] 값의 집합입니다.

limits, 타입 GPUSupportedLimits, 읽기 전용

this.[[adapter]].[[limits]] 값입니다.

info, 타입 GPUAdapterInfo, 읽기 전용

GPUAdapter가 참조하는 물리적 어댑터 정보입니다.

동일한 GPUAdapter 에 대해 GPUAdapterInfo 값은 시간이 지나도 변하지 않습니다.

항상 동일 객체를 반환합니다. 처음 객체를 만들 때:

호출 대상: GPUAdapter this.

반환값: GPUAdapterInfo

콘텐츠 타임라인 단계:

  1. this.[[adapter]] 에 대해 새 adapter info를 반환합니다.

[[adapter]], 타입 adapter, 읽기 전용

GPUAdapter가 참조하는 어댑터입니다.

GPUAdapter 는 다음 메서드를 가집니다:

requestDevice(descriptor)

어댑터에서 디바이스를 요청합니다.

이 작업은 1회성입니다: 디바이스가 성공적으로 반환되면 어댑터는 "consumed" 상태가 됩니다.

호출 대상: GPUAdapter this.

인자:

GPUAdapter.requestDevice(descriptor) 메서드 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUDeviceDescriptor 요청할 GPUDevice의 설명.

반환값: Promise<GPUDevice>

콘텐츠 타임라인 단계:

  1. contentTimeline을 현재 콘텐츠 타임라인으로 둡니다.

  2. promise새 promise로 둡니다.

  3. adapterthis.[[adapter]]로 둡니다.

  4. initialization stepsthis디바이스 타임라인에서 실행합니다.

  5. promise를 반환합니다.

디바이스 타임라인 initialization steps:
  1. 아래 요구사항 중 하나라도 만족하지 않으면:

    만족하지 않으면 contentTimeline에서 아래 단계 실행 후 반환:

    콘텐츠 타임라인 단계:
    1. promiseTypeError로 reject.

    참고: 브라우저에서 해당 기능명을 전혀 모를 때도 동일 오류가 발생합니다(GPUFeatureName 정의에 없음). 브라우저가 기능을 지원하지 않는 경우와 특정 어댑터가 지원하지 않는 경우의 동작을 일치시킵니다.

  2. 아래 단계 요구사항을 반드시 만족해야 합니다.

    1. adapter.[[state]] 값이 "consumed"가 아니어야 합니다.

    2. descriptor.requiredLimits의 각 [key, value] 쌍에서 valueundefined가 아닌 경우:

      1. key지원 한계의 멤버 이름이어야 합니다.

      2. valueadapter.[[limits]][key]보다 더 나은 값이 아니어야 합니다.

      3. key클래스정렬이라면, value는 2의 거듭제곱이며 232보다 작아야 합니다.

      참고: key가 인식되지 않더라도 valueundefined면 개발자 가시 경고를 주는 것이 좋습니다.

    만족하지 않으면 contentTimeline에서 아래 단계 실행 후 반환:

  3. adapter.[[state]] 값이 "expired"이거나 사용자 에이전트가 요청을 처리할 수 없는 경우:

    1. 디바이스device로 둡니다.

    2. 디바이스 손실 처리(device, "unknown").

    3. assert adapter.[[state]] 값이 "expired"임을 확인.

      참고: 이런 경우 개발자 가시 경고를 대부분(또는 모든 경우) 주는 것이 좋습니다. 앱은 requestAdapter()로부터 재초기화 로직을 수행해야 합니다.

    그렇지 않으면:

    1. descriptor에서 기술한 기능으로 새 디바이스device로 둡니다.

    2. 어댑터 만료 처리(adapter).

  4. 이후 단계는 contentTimeline에서 실행.

콘텐츠 타임라인 단계:
  1. GPUDevice 인스턴스를 gpuDevice로 둡니다.

  2. gpuDevice.[[device]] 값을 device로 설정.

  3. device.[[content device]] 값을 gpuDevice로 설정.

  4. gpuDevice.label 값을 descriptor.label로 설정.

  5. resolve promisegpuDevice로 설정.

    참고: 어댑터가 요청을 처리할 수 없어 이미 디바이스가 손실된 경우, device.lostpromise가 resolve되기 전에 이미 resolve됩니다.

기본 기능과 한계로 GPUDevice 요청 예시:
const gpuAdapter = await navigator.gpu.requestAdapter();
const gpuDevice = await gpuAdapter.requestDevice();

4.3.1. GPUDeviceDescriptor

GPUDeviceDescriptor 는 디바이스 요청을 기술합니다.

dictionary GPUDeviceDescriptor
         : GPUObjectDescriptorBase {
    sequence<GPUFeatureName> requiredFeatures = [];
    record<DOMString, (GPUSize64 or undefined)> requiredLimits = {};
    GPUQueueDescriptor defaultQueue = {};
};

GPUDeviceDescriptor 는 다음 멤버를 가집니다:

requiredFeatures, 타입 sequence<GPUFeatureName>, 기본값 []

디바이스 요청에 반드시 필요한 기능을 지정합니다. 어댑터가 해당 기능을 제공할 수 없으면 요청은 실패합니다.

API 호출 검증 시 결과 디바이스에 대해 정확히 명시된 기능 집합만 허용되며, 그 외는 허용되지 않습니다.

requiredLimits, 타입 record<DOMString, (GPUSize64 or undefined)>, 기본값 {}

디바이스 요청에 반드시 필요한 한계를 지정합니다. 어댑터가 해당 한계를 제공할 수 없으면 요청은 실패합니다.

값이 undefined가 아닌 각 키는 지원 한계의 멤버 이름이어야 합니다.

결과 디바이스에서의 API 호출은 어댑터가 아니라 디바이스의 정확한 한계에 따라 검증됩니다(§ 3.6.2 한계 참고).

defaultQueue, 타입 GPUQueueDescriptor, 기본값 {}

기본 GPUQueue의 디스크립터.

"texture-compression-astc" 기능을 지원하는 경우, 해당 기능을 포함해 GPUDevice를 요청하는 예시:
const gpuAdapter = await navigator.gpu.requestAdapter();

const requiredFeatures = [];
if (gpuAdapter.features.has('texture-compression-astc')) {
    requiredFeatures.push('texture-compression-astc')
}

const gpuDevice = await gpuAdapter.requestDevice({
    requiredFeatures
});
더 높은 maxColorAttachmentBytesPerSample 한계를 지정해 GPUDevice를 요청하는 예시:
const gpuAdapter = await navigator.gpu.requestAdapter();

if (gpuAdapter.limits.maxColorAttachmentBytesPerSample < 64) {
    // 원하는 한계가 지원되지 않을 경우, 더 높은 한계를 요구하지 않는 코드 경로로 대체하거나
    // 최소 요구사항에 미달하는 디바이스임을 사용자에게 안내하는 등의 처리를 할 수 있습니다.
}

// max color attachments bytes per sample 한계 상향 요청.
const gpuDevice = await gpuAdapter.requestDevice({
    requiredLimits: { maxColorAttachmentBytesPerSample: 64 },
});
4.3.1.1. GPUFeatureName

GPUFeatureName 은 특정 기능 집합을 식별하며, 해당 기능이 지원될 경우 기존 WebGPU에서 불가능한 추가 사용이 가능합니다.

enum GPUFeatureName {
    "core-features-and-limits",
    "depth-clip-control",
    "depth32float-stencil8",
    "texture-compression-bc",
    "texture-compression-bc-sliced-3d",
    "texture-compression-etc2",
    "texture-compression-astc",
    "texture-compression-astc-sliced-3d",
    "timestamp-query",
    "indirect-first-instance",
    "shader-f16",
    "rg11b10ufloat-renderable",
    "bgra8unorm-storage",
    "float32-filterable",
    "float32-blendable",
    "clip-distances",
    "dual-source-blending",
    "subgroups",
    "texture-formats-tier1",
    "texture-formats-tier2",
    "primitive-index",
};

4.4. GPUDevice

GPUDevice디바이스를 캡슐화하며, 해당 디바이스의 기능을 노출합니다.

GPUDeviceWebGPU 인터페이스가 생성되는 최상위 인터페이스입니다.

GPUDevice를 얻으려면 requestDevice() 를 사용하세요.

[Exposed=(Window, Worker), SecureContext]
interface GPUDevice : EventTarget {
    [SameObject] readonly attribute GPUSupportedFeatures features;
    [SameObject] readonly attribute GPUSupportedLimits limits;
    [SameObject] readonly attribute GPUAdapterInfo adapterInfo;

    [SameObject] readonly attribute GPUQueue queue;

    undefined destroy();

    GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
    GPUTexture createTexture(GPUTextureDescriptor descriptor);
    GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
    GPUExternalTexture importExternalTexture(GPUExternalTextureDescriptor descriptor);

    GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
    GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
    GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);

    GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
    GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
    GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
    Promise<GPUComputePipeline> createComputePipelineAsync(GPUComputePipelineDescriptor descriptor);
    Promise<GPURenderPipeline> createRenderPipelineAsync(GPURenderPipelineDescriptor descriptor);

    GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
    GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor);

    GPUQuerySet createQuerySet(GPUQuerySetDescriptor descriptor);
};
GPUDevice includes GPUObjectBase;

GPUDevice는 다음 불변 속성을 가집니다:

features, 타입 GPUSupportedFeatures, 읽기 전용

이 디바이스가 지원하는 GPUFeatureName 값의 집합 ([[device]].[[features]]).

limits, 타입 GPUSupportedLimits, 읽기 전용

이 디바이스가 지원하는 한계 ([[device]].[[limits]]).

queue, 타입 GPUQueue, 읽기 전용

이 디바이스의 기본 GPUQueue입니다.

adapterInfo, 타입 GPUAdapterInfo, 읽기 전용

GPUDevice가 참조하는 디바이스를 생성한 물리 어댑터 정보입니다.

동일 GPUDevice에 대해, GPUAdapterInfo 값은 시간이 지나도 변하지 않습니다.

항상 동일 객체를 반환합니다. 처음 객체를 만들 때:

호출 대상: GPUDevice this.

반환값: GPUAdapterInfo

콘텐츠 타임라인 단계:

  1. this.[[device]].[[adapter]]에 대해 새 adapter info를 반환합니다.

[[device]]GPUDevice가 참조하는 디바이스입니다.

GPUDevice는 다음 메서드를 가집니다:

destroy()

디바이스를 파괴하여 더 이상 작업할 수 없게 합니다. 남아있는 비동기 작업은 모두 실패합니다.

참고: 디바이스를 여러 번 파괴해도 문제가 없습니다.

호출 대상: GPUDevice this.

콘텐츠 타임라인 단계:

  1. 이 디바이스의 모든 GPUBuffer에 대해 unmap() 호출.

  2. 이후 단계는 this디바이스 타임라인에서 실행.

  1. 디바이스 손실 처리(this.[[device]], "destroyed").

참고: 더 이상 작업을 큐잉할 수 없으므로, 구현체는 남아있는 비동기 작업을 즉시 중단하고, 매핑 해제된 메모리를 포함하여 자원을 해제할 수 있습니다.

GPUDevice허용된 버퍼 용도는 아래와 같습니다:
GPUDevice허용된 텍스처 용도는 아래와 같습니다:

4.5. 예시

오류 처리를 포함한 GPUAdapterGPUDevice 요청의 좀 더 견고한 예시:
let gpuDevice = null;

async function initializeWebGPU() {
    // 사용자 에이전트가 WebGPU를 지원하는지 확인.
    if (!('gpu' in navigator)) {
        console.error("사용자 에이전트가 WebGPU를 지원하지 않습니다.");
        return false;
    }

    // 어댑터 요청.
    const gpuAdapter = await navigator.gpu.requestAdapter();

    // requestAdapter는 적합한 어댑터가 없으면 null로 resolve될 수 있음.
    if (!gpuAdapter) {
        console.error('WebGPU 어댑터를 찾을 수 없습니다.');
        return false;
    }

    // 디바이스 요청.
    // 옵션 딕셔너리에 잘못된 값이 들어가면 promise가 reject될 수 있음.
    // 항상 어댑터의 feature와 limit을 확인한 후 requestDevice()를 호출하면 reject를 피할 수 있음.
    gpuDevice = await gpuAdapter.requestDevice();

    // requestDevice는 절대 null을 반환하지 않지만, 유효한 디바이스 요청을 충족할 수 없으면 이미 손실된 디바이스가 반환될 수 있음.
    // 또한 디바이스는 생성 후 여러 이유(브라우저 리소스 관리, 드라이버 업데이트 등)로 언제든 손실될 수 있으므로
    // 디바이스 손실을 항상 우아하게 처리하는 것이 좋음.
    gpuDevice.lost.then((info) => {
        console.error(`WebGPU 디바이스가 손실됨: ${info.message}`);

        gpuDevice = null;

        // 디바이스 손실의 많은 원인은 일시적이므로, 앱은 이전 디바이스가 손실되면 새 디바이스를 다시 요청해야 함.
        // 단, 손실 이유가 앱에서 디바이스를 직접 destroy한 경우는 제외. 이전 디바이스로 생성한 모든 WebGPU 리소스(버퍼, 텍스처 등)는
        // 새 디바이스로 재생성해야 함.
        if (info.reason != 'destroyed') {
            initializeWebGPU();
        }
    });

    onWebGPUInitialized();

    return true;
}

function onWebGPUInitialized() {
    // 여기서 WebGPU 리소스 생성 시작...
}

initializeWebGPU();

5. 버퍼

5.1. GPUBuffer

GPUBuffer 는 GPU 연산에 사용할 수 있는 메모리 블록을 나타냅니다. 데이터는 선형 레이아웃으로 저장되며, 할당된 각 바이트는 GPUBuffer의 시작 오프셋 기준으로 접근할 수 있습니다. 연산에 따라 정렬 제한이 있을 수 있습니다. 일부 GPUBuffers는 매핑되어 해당 메모리 블록을 ArrayBuffer (매핑)로 접근할 수 있습니다.

GPUBuffercreateBuffer() 로 생성합니다. 버퍼는 mappedAtCreation 으로 생성할 수 있습니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUBuffer {
    readonly attribute GPUSize64Out size;
    readonly attribute GPUFlagsConstant usage;

    readonly attribute GPUBufferMapState mapState;

    Promise<undefined> mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size);
    ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size);
    undefined unmap();

    undefined destroy();
};
GPUBuffer includes GPUObjectBase;

enum GPUBufferMapState {
    "unmapped",
    "pending",
    "mapped",
};

GPUBuffer는 다음 불변 속성을 가집니다:

size, 타입 GPUSize64Out, 읽기 전용

GPUBuffer에 할당된 바이트 단위 길이입니다.

usage, 타입 GPUFlagsConstant, 읽기 전용

GPUBuffer에서 허용된 용도.

GPUBuffer는 다음 콘텐츠 타임라인 속성을 가집니다:

mapState, 타입 GPUBufferMapState, 읽기 전용

버퍼의 현재 GPUBufferMapState 상태:

"unmapped"

버퍼가 this.getMappedRange()로 매핑되어 있지 않음.

"pending"

버퍼 매핑이 요청되었으나 대기 중. mapAsync()에서 검증에 성공하거나 실패할 수 있음.

"mapped"

버퍼가 매핑되어 this.getMappedRange()를 사용할 수 있음.

getter 단계는 아래와 같습니다:

콘텐츠 타임라인 단계:
  1. this.[[mapping]]null이 아니면 "mapped" 반환.

  2. this.[[pending_map]]null이 아니면 "pending" 반환.

  3. "unmapped" 반환.

[[pending_map]], 타입 Promise<void> 또는 null, 초기값 null

현재 대기 중인 Promise, mapAsync()의 반환값.

항상 pending map은 하나만 있을 수 있습니다. 이미 요청이 진행 중이면 mapAsync()는 즉시 거부됩니다.

[[mapping]], 타입 active buffer mapping 또는 null, 초기값 null

버퍼가 getMappedRange()로 매핑되어 있을 때만 설정됨. 그렇지 않으면 null([[pending_map]]가 있어도).

active buffer mapping은 다음 필드가 있는 구조체입니다:

data, 타입 Data Block

GPUBuffer의 매핑 데이터. ArrayBuffer 뷰로 접근하며, getMappedRange()로 반환되고, views에 저장됩니다.

mode, 타입 GPUMapModeFlags

매핑 모드(GPUMapModeFlags), mapAsync() 또는 createBuffer() 호출 시 지정.

range, 타입 튜플 [unsigned long long, unsigned long long]

매핑된 GPUBuffer 범위.

views, 타입 list<ArrayBuffer>

API에서 ArrayBuffer로 반환된 매핑 데이터. getMappedRange()로 반환됨. unmap() 호출 시 분리(detach)됨.

active buffer mapping 초기화를 mode mode와 range range로 하려면, 아래 콘텐츠 타임라인 단계 실행:
  1. sizerange[1] - range[0]로 둡니다.

  2. data? CreateByteDataBlock(size)로 둡니다.

    참고:
    이 할당은 RangeError를 발생시킬 수 있습니다. 일관성/예측성을 위해:
    • 어떤 size에서 new ArrayBuffer()가 성공한다면, 이 할당도 그때 성공해야 합니다.

    • 어떤 size에서 new ArrayBuffer()RangeError결정적으로 던지면, 이 할당도 동일하게 던져야 합니다.

  3. 아래 값으로 active buffer mapping 반환:

버퍼 매핑 및 unmap 과정.
버퍼 매핑 실패.

GPUBuffer는 다음 디바이스 타임라인 속성을 가집니다:

[[internal state]]

버퍼의 현재 내부 상태:

"available"

버퍼를 큐 연산에서 사용할 수 있음(invalid 상태가 아니라면).

"unavailable"

버퍼가 매핑되어 큐 연산에서 사용할 수 없음.

"destroyed"

버퍼가 destroy()로 파괴되어 어떤 연산도 할 수 없음.

5.1.1. GPUBufferDescriptor

dictionary GPUBufferDescriptor
         : GPUObjectDescriptorBase {
    required GPUSize64 size;
    required GPUBufferUsageFlags usage;
    boolean mappedAtCreation = false;
};

GPUBufferDescriptor 는 다음 멤버를 가집니다:

size, 타입 GPUSize64

버퍼의 크기(바이트 단위).

usage, 타입 GPUBufferUsageFlags

버퍼의 허용된 용도.

mappedAtCreation, 타입 boolean, 기본값 false

true로 설정하면 버퍼가 생성 즉시 매핑된 상태로 생성되어, getMappedRange() 를 바로 호출할 수 있습니다. usageMAP_READ 또는 MAP_WRITE 가 없어도 mappedAtCreationtrue로 설정할 수 있습니다. 이는 버퍼의 초기 데이터를 설정할 때 사용할 수 있습니다.

버퍼 생성이 결국 실패하더라도, unmapped될 때까지는 매핑된 범위에 읽기/쓰기가 가능한 것처럼 동작함을 보장합니다.

5.1.2. 버퍼 용도

typedef [EnforceRange] unsigned long GPUBufferUsageFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUBufferUsage {
    const GPUFlagsConstant MAP_READ      = 0x0001;
    const GPUFlagsConstant MAP_WRITE     = 0x0002;
    const GPUFlagsConstant COPY_SRC      = 0x0004;
    const GPUFlagsConstant COPY_DST      = 0x0008;
    const GPUFlagsConstant INDEX         = 0x0010;
    const GPUFlagsConstant VERTEX        = 0x0020;
    const GPUFlagsConstant UNIFORM       = 0x0040;
    const GPUFlagsConstant STORAGE       = 0x0080;
    const GPUFlagsConstant INDIRECT      = 0x0100;
    const GPUFlagsConstant QUERY_RESOLVE = 0x0200;
};

GPUBufferUsage 플래그는 GPUBuffer가 생성 후 어떻게 사용될 수 있는지 결정합니다:

MAP_READ

버퍼를 읽기용으로 매핑할 수 있음. (예: mapAsync()GPUMapMode.READ와 함께 호출)

COPY_DST와만 결합 가능.

MAP_WRITE

버퍼를 쓰기용으로 매핑할 수 있음. (예: mapAsync()GPUMapMode.WRITE와 함께 호출)

COPY_SRC와만 결합 가능.

COPY_SRC

버퍼를 복사 연산의 소스로 사용 가능. (예: copyBufferToBuffer()copyBufferToTexture() 호출 시 source로 사용)

COPY_DST

버퍼를 복사/쓰기 연산의 대상으로 사용 가능. (예: copyBufferToBuffer()copyTextureToBuffer() 호출 시 destination으로 사용, 또는 writeBuffer()의 대상 등)

INDEX

버퍼를 인덱스 버퍼로 사용 가능. (예: setIndexBuffer()에 전달)

VERTEX

버퍼를 버텍스 버퍼로 사용 가능. (예: setVertexBuffer()에 전달)

UNIFORM

버퍼를 유니폼 버퍼로 사용 가능. (예: GPUBufferBindingLayoutbuffer.type 값이 "uniform"인 경우 등)

STORAGE

버퍼를 스토리지 버퍼로 사용 가능. (예: GPUBufferBindingLayoutbuffer.type 값이 "storage" 또는 "read-only-storage"인 경우 등)

INDIRECT

버퍼를 간접 명령 인자 저장 용도로 사용 가능. (예: indirectBuffer 인자로 drawIndirect()dispatchWorkgroupsIndirect()에 전달)

QUERY_RESOLVE

버퍼를 쿼리 결과 캡처 용도로 사용 가능. (예: destination 인자로 resolveQuerySet()에 전달)

5.1.3. 버퍼 생성

createBuffer(descriptor)

GPUBuffer를 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createBuffer(descriptor) 메서드 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUBufferDescriptor 생성할 GPUBuffer의 설명.

반환값: GPUBuffer

콘텐츠 타임라인 단계:

  1. b! 새 WebGPU 객체 생성(this, GPUBuffer, descriptor)로 둡니다.

  2. b.size 값을 descriptor.size로 설정.

  3. b.usage 값을 descriptor.usage로 설정.

  4. 만약 descriptor.mappedAtCreationtrue라면:

    1. descriptor.size 가 4의 배수가 아니면 RangeError를 throw.

    2. b.[[mapping]] 값을 ? active buffer mapping 초기화(mode WRITE, range [0, descriptor.size])로 설정.

  5. initialization stepsthis디바이스 타임라인에서 실행.

  6. b를 반환.

디바이스 타임라인 initialization steps:
  1. 아래 요구사항 중 하나라도 만족하지 않으면, 검증 오류 생성, b를 무효화하고 반환.

참고: 버퍼 생성이 실패하고 descriptor.mappedAtCreation 값이 false인 경우, mapAsync() 호출은 거부됩니다. 매핑을 위한 리소스는 할당 취소 또는 재활용될 수 있습니다.

  1. descriptor.mappedAtCreation 값이 true면:

    1. b.[[internal state]] 값을 "unavailable"로 설정.

    그 외에는:

    1. b.[[internal state]] 값을 "available"로 설정.

  2. b에 대해 각 바이트가 0인 디바이스 할당 생성.

    할당이 부작용 없이 실패하면, out-of-memory 오류 생성, b를 무효화하고 반환.

128 바이트 크기의 쓰기 가능한 유니폼 버퍼 생성 예시:
const buffer = gpuDevice.createBuffer({
    size: 128,
    usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
});

5.1.4. 버퍼 파괴

앱에서 GPUBuffer가 더 이상 필요하지 않을 때, destroy()를 호출해 가비지 컬렉션 전에 접근 권한을 잃게 할 수 있습니다. 버퍼를 파괴하면 매핑도 해제되어 할당된 매핑 메모리가 해제됩니다.

참고: 이렇게 하면 사용자 에이전트가 해당 GPUBuffer와 연결된 GPU 메모리를 해당 버퍼를 사용하는 모든 제출된 작업이 완료된 뒤 회수할 수 있습니다.

GPUBuffer는 다음 메서드를 가집니다:

destroy()

GPUBuffer를 파괴합니다.

참고: 버퍼를 여러 번 파괴해도 문제가 없습니다.

호출 대상: GPUBuffer this.

반환값: undefined

콘텐츠 타임라인 단계:

  1. this.unmap() 호출.

  2. 이후 단계는 this.[[device]]디바이스 타임라인에서 실행.

디바이스 타임라인 단계:
  1. this.[[internal state]] 값을 "destroyed"로 설정.

참고: 이 버퍼로 더 이상 작업을 큐잉할 수 없으므로, 구현체는 매핑 해제된 메모리를 포함한 자원 할당을 해제할 수 있습니다.

5.2. 버퍼 매핑

애플리케이션은 GPUBuffer를 매핑(map) 요청하여 ArrayBuffer로 해당 버퍼의 일부 할당 영역에 접근할 수 있습니다. GPUBuffer 매핑은 mapAsync()로 비동기 요청하며, 사용자 에이전트가 GPU가 해당 버퍼를 사용 중임을 확인한 뒤 애플리케이션이 내용을 접근할 수 있게 합니다. 매핑된 GPUBuffer는 GPU가 사용할 수 없으며, unmap()을 통해 unmap한 뒤에야 Queue 타임라인에서 해당 버퍼를 사용하는 작업을 제출할 수 있습니다.

GPUBuffer가 매핑된 뒤에는, getMappedRange()로 동기적으로 해당 콘텐츠의 범위에 접근할 수 있습니다. 반환되는 ArrayBuffer는 오직 unmap() (직접 호출하거나 GPUBuffer.destroy(), GPUDevice.destroy()로 간접 호출)로만 detach될 수 있습니다. transferred될 수 없으며, 다른 연산에서 시도하면 TypeError가 발생합니다.

typedef [EnforceRange] unsigned long GPUMapModeFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUMapMode {
    const GPUFlagsConstant READ  = 0x0001;
    const GPUFlagsConstant WRITE = 0x0002;
};

GPUMapMode 플래그는 GPUBuffermapAsync()로 호출할 때 어떻게 매핑할지 결정합니다:

READ

MAP_READ 용도로 생성한 버퍼에서만 유효합니다.

버퍼가 매핑되면 getMappedRange() 호출 시 버퍼의 현재 값이 들어있는 ArrayBuffer를 반환합니다. 반환된 ArrayBuffer의 변경 내용은 unmap() 호출 후 버려집니다.

WRITE

MAP_WRITE 용도로 생성한 버퍼에서만 유효합니다.

버퍼가 매핑되면 getMappedRange() 호출 시 버퍼의 현재 값이 들어있는 ArrayBuffer를 반환합니다. 반환된 ArrayBuffer의 변경 내용은 GPUBufferunmap() 호출 후 저장됩니다.

참고: MAP_WRITE 용도 버퍼는 COPY_SRC와만 결합할 수 있으므로, 쓰기 매핑 시 GPU에서 생성된 값을 반환할 수 없고, 반환된 ArrayBuffer는 항상 기본 초기화 데이터(0)나 이전 매핑에서 웹페이지가 기록한 데이터만 포함합니다.

GPUBuffer는 다음 메서드를 가집니다:

mapAsync(mode, offset, size)

지정한 GPUBuffer의 범위를 매핑(map)하며, 반환된 PromiseGPUBuffer의 내용을 getMappedRange()로 접근할 준비가 완료되면 resolve됩니다.

반환된 Promise의 resolve는 오직 버퍼가 매핑됐음을 나타냅니다. 콘텐츠 타임라인에서 볼 수 있는 다른 작업의 완료를 보장하지 않으며, 특히 다른 Promise (onSubmittedWorkDone()mapAsync()가 다른 GPUBuffer에 대해 반환한 Promise)들의 완료도 의미하지 않습니다.

onSubmittedWorkDone()로 반환된 Promise의 resolve는 해당 호출 전에 큐에서 독점적으로 사용된 GPUBuffer에 대해 mapAsync()가 완료됨을 의미합니다.

호출 대상: GPUBuffer this.

인자:

GPUBuffer.mapAsync(mode, offset, size) 메서드 인자.
파라미터 타입 Nullable Optional 설명
mode GPUMapModeFlags 버퍼를 읽기/쓰기로 매핑할지 여부.
offset GPUSize64 매핑 시작 위치(바이트 단위).
size GPUSize64 매핑 범위 크기(바이트 단위).

반환값: Promise<undefined>

콘텐츠 타임라인 단계:

  1. contentTimeline을 현재 콘텐츠 타임라인으로 둡니다.

  2. 만약 this.mapState"unmapped"가 아니면:

    1. this.[[device]]디바이스 타임라인에서 early-reject steps를 실행합니다.

    2. OperationError로 reject된 promise를 반환합니다.

  3. p를 새로운 Promise로 둡니다.

  4. this.[[pending_map]]p를 설정합니다.

  5. this.[[device]]디바이스 타임라인에서 validation steps를 실행합니다.

  6. p를 반환합니다.

디바이스 타임라인 early-reject steps:
  1. 검증 오류를 생성한다.

  2. 반환.

디바이스 타임라인 validation steps:
  1. sizeundefined이면:

    1. rangeSize를 max(0, this.size - offset)로 둔다.

    그 외에는:

    1. rangeSizesize로 둔다.

  2. 아래 조건 중 하나라도 만족하지 않으면:

    1. deviceLosttrue로 둔다.

    2. map failure stepscontentTimeline에서 실행한다.

    3. 반환.

  3. 아래 조건 중 하나라도 만족하지 않으면:

    그 후:

    1. deviceLostfalse로 둔다.

    2. map failure stepscontentTimeline에서 실행한다.

    3. 검증 오류를 생성한다.

    4. 반환.

  4. this.[[internal state]] 값을 "unavailable"로 설정한다.

    참고: 버퍼가 매핑된 상태라 이 단계와 unmap() 사이에는 내용이 변경될 수 없다.

  5. 아래 이벤트 중 하나라도 발생하면(혹은 이미 발생한 경우):

    이후 단계는 this.[[device]]디바이스 타임라인에서 실행한다.

디바이스 타임라인 단계:
  1. this.[[device]]손실(lost)이면 deviceLosttrue로, 아니면 false로 둔다.

    참고: 디바이스가 바로 앞 단계와 이 단계 사이에 손실될 수 있음.

  2. deviceLosttrue라면:

    1. map failure stepscontentTimeline에서 실행한다.

    그 외에는:

    1. internalStateAtCompletionthis.[[internal state]]로 둔다.

      참고: 이 시점에 unmap() 호출로 버퍼가 다시 "available" 상태가 되었다면 [[pending_map]] != 아래의 p이므로 아래 단계에서 매핑 성공할 수 없음.

    2. dataForMappedRegionthisoffset부터 rangeSize 바이트만큼의 내용으로 둔다.

    3. map success stepscontentTimeline에서 실행한다.

콘텐츠 타임라인 매핑 성공 단계:
  1. 만약 this.[[pending_map]]p와 다르다면:

    참고: unmap()에 의해 매핑이 취소됨.

    1. Assert p는 reject 상태여야 한다.

    2. 반환.

  2. Assert p는 pending 상태여야 한다.

  3. Assert internalStateAtCompletion이 "unavailable"이다.

  4. mappingactive buffer mapping 초기화(mode mode, range [offset, offset + rangeSize])로 둔다.

    이 할당이 실패하면:

    1. this.[[pending_map]]null로 설정하고, RangeErrorp를 reject 한다.

    2. 반환.

  5. mapping.data의 내용을 dataForMappedRegion으로 설정.

  6. this.[[mapping]]mapping으로 설정.

  7. this.[[pending_map]]null로 설정하고, resolve p.

콘텐츠 타임라인 매핑 실패 단계:
  1. 만약 this.[[pending_map]]p와 다르다면:

    참고: unmap()에 의해 매핑이 취소됨.

    1. Assert p는 이미 reject 상태여야 한다.

    2. 반환.

  2. Assert p는 아직 pending 상태여야 한다.

  3. this.[[pending_map]]null로 설정.

  4. deviceLost가 true라면:

    1. AbortErrorp를 reject 한다.

      참고: unmap()으로 매핑을 취소할 때 발생하는 오류와 동일한 타입.

    그 외에는:

    1. OperationErrorp를 reject 한다.

getMappedRange(offset, size)

지정된 매핑 범위의 ArrayBuffer를 반환합니다. 반환된 GPUBuffer의 내용을 포함합니다.

호출 대상: GPUBuffer this.

인자:

GPUBuffer.getMappedRange(offset, size) 메서드 인자.
파라미터 타입 Nullable Optional 설명
offset GPUSize64 버퍼에서 반환할 내용의 바이트 단위 오프셋.
size GPUSize64 반환할 ArrayBuffer의 크기(바이트 단위).

반환값: ArrayBuffer

콘텐츠 타임라인 단계:

  1. size가 없으면:

    1. rangeSize를 max(0, this.size - offset)로 둔다.

    그 외에는 rangeSizesize로 둔다.

  2. 아래 조건 중 하나라도 만족하지 않으면 OperationError를 throw하고 반환한다.

    참고: GPUBuffermappedAtCreation으로 생성된 경우, invalid 상태여도 항상 매핑 범위를 가져올 수 있음. 이는 콘텐츠 타임라인이 invalid 상태를 모를 수 있기 때문임.

  3. datathis.[[mapping]].data로 둔다.

  4. view! ArrayBuffer 생성(크기 rangeSize)로 둔다. 단, 포인터는 data의 (offset - [[mapping]].range[0]) 오프셋부터의 내용에 mutably reference함.

    참고: RangeError는 발생하지 않음. data는 이미 mapAsync() 또는 createBuffer()에서 할당됨.

  5. view.[[ArrayBufferDetachKey]] 를 "WebGPUBufferMapping"으로 설정함.

    참고: TypeErrorunmap()이외의 방법으로 DetachArrayBuffer를 시도할 때 발생함.

  6. Append viewthis.[[mapping]].views에 추가한다.

  7. view를 반환한다.

참고: getMappedRange()가 매핑 상태를 확인하지 않고 성공한 경우, mapAsync() 성공, mapState"mapped"인지 확인, 또는 onSubmittedWorkDone() 성공 등 상태 확인에 대한 경고를 개발자에게 표시할 수 있음.

unmap()

매핑된 GPUBuffer 범위를 해제(unmap)하여 GPU가 다시 해당 내용을 사용할 수 있도록 합니다.

호출 대상: GPUBuffer this.

반환값: undefined

콘텐츠 타임라인 단계:

  1. this.[[pending_map]]null이 아니면:

    1. Reject this.[[pending_map]]AbortError로 reject한다.

    2. this.[[pending_map]]null로 설정한다.

  2. this.[[mapping]]null이면:

    1. 반환.

  3. this.ArrayBuffer abthis.[[mapping]].views에서 각각에 대해:

    1. DetachArrayBuffer(ab, "WebGPUBufferMapping")를 실행한다.

  4. bufferUpdatenull로 둔다.

  5. this.[[mapping]].modeWRITE를 포함하면:

    1. bufferUpdate를 { data: this.[[mapping]].data, offset: this.[[mapping]].range[0] }로 둔다.

    참고: WRITE 모드 없이 매핑된 버퍼는 unmap시 애플리케이션이 매핑 범위에 로컬에서 수정한 내용이 모두 폐기되며 이후 매핑에 영향을 주지 않는다.

  6. this.[[mapping]]null로 둔다.

  7. 이후 단계는 this.[[device]]디바이스 타임라인에서 실행한다.

디바이스 타임라인 단계:
  1. 아래 조건 중 하나라도 만족하지 않으면 반환한다.

  2. Assert this.[[internal state]] 값이 "unavailable"임을 확인.

  3. bufferUpdatenull이 아니면:

    1. this.[[device]].queue큐 타임라인 단계로 이동:

      큐 타임라인 단계:
      1. thisbufferUpdate.offset에서 bufferUpdate.data의 내용으로 버퍼 내용을 갱신함.

  4. this.[[internal state]] 을 "available"로 둔다.

6. 텍스처와 텍스처 뷰

6.1. GPUTexture

텍스처1d, 2d, 또는 3d 데이터 배열로 구성되며, 각 요소에는 여러 값을 포함할 수 있어 색상과 같은 정보를 표현합니다. 텍스처는 생성 시 지정된 GPUTextureUsage에 따라 다양한 방법으로 읽고 쓸 수 있습니다. 예를 들어, 텍스처는 렌더 및 컴퓨트 파이프라인 셰이더에서 샘플링, 읽기, 쓰기할 수 있고, 렌더 패스 출력으로 쓰기도 가능합니다. 내부적으로 텍스처는 GPU 메모리에 다차원 접근에 최적화된 레이아웃으로 저장되는 경우가 많습니다(선형 접근이 아닌).

하나의 텍스처는 하나 이상의 텍스처 서브리소스로 구성되며, 각각은 mipmap 레벨2d 텍스처의 경우 array layeraspect로 고유하게 식별됩니다.

텍스처 서브리소스서브리소스로, 각각은 하나의 사용 범위 내에서 서로 다른 내부 용도로 사용될 수 있습니다.

mipmap 레벨의 각 서브리소스는 공간 차원마다 바로 이전 레벨의 리소스 크기보다 약 절반 크기입니다 (자세한 내용은 논리적 miplevel별 텍스처 크기 참고). 레벨 0의 서브리소스는 텍스처 자체의 크기를 가집니다. 작은 레벨은 일반적으로 동일 이미지의 저해상도 버전을 저장하는 데 사용됩니다. GPUSampler와 WGSL은 상세도 레벨 선택 및 보간을 명시적 또는 자동으로 지원합니다.

"2d" 텍스처는 array layer 배열일 수 있습니다. 각 array layer의 서브리소스는 다른 layer의 동일한 리소스와 크기가 같습니다. 2d가 아닌 텍스처는 모든 서브리소스의 array layer 인덱스가 0입니다.

각 서브리소스에는 aspect가 있습니다. 컬러 텍스처는 하나의 aspect(color)만 가집니다. 깊이 또는 스텐실 포맷 텍스처는 여러 aspect를 가질 수 있습니다: 깊이 aspect, 스텐실 aspect, 또는 둘 다 가질 수 있으며, depthStencilAttachment"depth" 바인딩 등 특수 용도로 사용될 수 있습니다.

"3d" 텍스처는 여러 slice를 가질 수 있으며, 각 slice는 텍스처의 특정 z 값에 해당하는 2차원 이미지입니다. slice는 별도의 서브리소스가 아닙니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUTexture {
    GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});

    undefined destroy();

    readonly attribute GPUIntegerCoordinateOut width;
    readonly attribute GPUIntegerCoordinateOut height;
    readonly attribute GPUIntegerCoordinateOut depthOrArrayLayers;
    readonly attribute GPUIntegerCoordinateOut mipLevelCount;
    readonly attribute GPUSize32Out sampleCount;
    readonly attribute GPUTextureDimension dimension;
    readonly attribute GPUTextureFormat format;
    readonly attribute GPUFlagsConstant usage;
};
GPUTexture includes GPUObjectBase;

GPUTexture 는 다음 불변 속성을 가집니다:

width, 타입 GPUIntegerCoordinateOut, 읽기 전용

GPUTexture의 너비입니다.

height, 타입 GPUIntegerCoordinateOut, 읽기 전용

GPUTexture의 높이입니다.

depthOrArrayLayers, 타입 GPUIntegerCoordinateOut, 읽기 전용

GPUTexture의 깊이 또는 레이어 개수입니다.

mipLevelCount, 타입 GPUIntegerCoordinateOut, 읽기 전용

GPUTexture의 mip 레벨 개수입니다.

sampleCount, 타입 GPUSize32Out, 읽기 전용

GPUTexture의 샘플 개수입니다.

dimension, 타입 GPUTextureDimension, 읽기 전용

GPUTexture의 서브리소스별 텍셀 집합의 차원입니다.

format, 타입 GPUTextureFormat, 읽기 전용

GPUTexture의 포맷입니다.

usage, 타입 GPUFlagsConstant, 읽기 전용

GPUTexture의 허용된 용도입니다.

[[viewFormats]], 타입 sequence<GPUTextureFormat>

GPUTexture에 대한 뷰 생성 시 GPUTextureViewDescriptor.format으로 사용할 수 있는 GPUTextureFormat들의 집합입니다.

GPUTexture 는 다음 디바이스 타임라인 속성을 가집니다:

[[destroyed]], 타입 boolean, 초기값 false

텍스처가 destroy되면, 어떤 작업에도 더 이상 사용할 수 없으며, 하부 메모리가 해제될 수 있습니다.

compute render extent(baseSize, mipLevel)

인자:

반환값: GPUExtent3DDict

디바이스 타임라인 단계:

  1. extent를 새로운 GPUExtent3DDict 객체로 둔다.

  2. extent.width 를 max(1, baseSize.widthmipLevel)로 설정한다.

  3. extent.height 를 max(1, baseSize.heightmipLevel)로 설정한다.

  4. extent.depthOrArrayLayers 를 1로 설정한다.

  5. extent를 반환한다.

논리적 miplevel별 텍스처 크기는 특정 miplevel에서 텍스처의 텍셀 단위 크기입니다. 다음 절차로 계산됩니다:

Logical miplevel-specific texture extent(descriptor, mipLevel)

인자:

반환값: GPUExtent3DDict

  1. extent를 새로운 GPUExtent3DDict 객체로 둔다.

  2. descriptor.dimension 값이 다음 중 하나일 때:

    "1d"
    "2d"
    "3d"
  3. extent를 반환한다.

물리적 miplevel별 텍스처 크기는 특정 miplevel에서 텍스처의 텍셀 단위 크기로, 텍셀 블록을 완성하기 위한 추가 패딩이 포함될 수 있습니다. 다음 절차로 계산됩니다:

Physical miplevel-specific texture extent(descriptor, mipLevel)

인자:

반환값: GPUExtent3DDict

  1. extent를 새로운 GPUExtent3DDict 객체로 둔다.

  2. logicalExtent논리적 miplevel별 텍스처 크기(descriptor, mipLevel)로 둔다.

  3. descriptor.dimension 값이 다음 중 하나일 때:

    "1d"
    "2d"
    "3d"
  4. extent를 반환한다.

6.1.1. GPUTextureDescriptor

dictionary GPUTextureDescriptor
         : GPUObjectDescriptorBase {
    required GPUExtent3D size;
    GPUIntegerCoordinate mipLevelCount = 1;
    GPUSize32 sampleCount = 1;
    GPUTextureDimension dimension = "2d";
    required GPUTextureFormat format;
    required GPUTextureUsageFlags usage;
    sequence<GPUTextureFormat> viewFormats = [];
};

GPUTextureDescriptor 는 다음 멤버를 가집니다:

size, 타입 GPUExtent3D

텍스처의 너비, 높이, 깊이 또는 레이어 개수입니다.

mipLevelCount, 타입 GPUIntegerCoordinate, 기본값 1

텍스처가 포함할 mip 레벨 개수입니다.

sampleCount, 타입 GPUSize32, 기본값 1

텍스처의 샘플 개수입니다. sampleCount > 1이면 다중 샘플 텍스처임을 나타냅니다.

dimension, 타입 GPUTextureDimension, 기본값 "2d"

텍스처가 1차원, 2차원 레이어 배열, 또는 3차원인지 여부입니다.

format, 타입 GPUTextureFormat

텍스처의 포맷입니다.

usage, 타입 GPUTextureUsageFlags

텍스처의 허용되는 용도입니다.

viewFormats, 타입 sequence<GPUTextureFormat>, 기본값 []

이 텍스처에 대해 format 값을 사용하여 createView() 를 호출할 때 허용되는 뷰 포맷을 지정합니다(텍스처의 실제 format 포함).

참고:
이 목록에 포맷을 추가하면 성능에 큰 영향을 줄 수 있으므로 불필요하게 포맷을 추가하지 않는 것이 좋습니다.

실제 성능 영향은 대상 시스템에 따라 매우 다르므로 개발자는 다양한 시스템에서 테스트하여 애플리케이션에 대한 영향을 확인해야 합니다. 예를 들어, 일부 시스템에서는 format 또는 viewFormats 항목에 "rgba8unorm-srgb"가 포함된 경우, "rgba8unorm"만 사용하는 텍스처보다 성능이 저하될 수 있습니다. 비슷한 주의사항이 다른 포맷, 포맷 쌍에도 적용됩니다.

이 목록의 포맷들은 텍스처 포맷과 텍스처 뷰 포맷 호환이어야 합니다.

GPUTextureFormat formatviewFormat텍스처 뷰 포맷 호환이 되려면:
  • formatviewFormat과 같거나,

  • formatviewFormatsrgb 포맷(-srgb 접미사 유무)만 다르면

enum GPUTextureDimension {
    "1d",
    "2d",
    "3d",
};
"1d"

너비만 있는 1차원 텍스처를 지정합니다. "1d" 텍스처는 mipmap을 가질 수 없으며, 다중 샘플, 압축 또는 깊이/스텐실 포맷을 사용할 수 없고, 렌더 타겟으로도 사용할 수 없습니다.

"2d"

너비와 높이가 있으며, 레이어를 가질 수 있는 텍스처를 지정합니다.

"3d"

너비, 높이, 깊이를 가지는 텍스처를 지정합니다. "3d" 텍스처는 다중 샘플을 지원하지 않으며, 해당 포맷이 3d 텍스처를 지원해야 합니다 (모든 일반 컬러 포맷과 일부 packed/압축 포맷).

6.1.2. 텍스처 용도

typedef [EnforceRange] unsigned long GPUTextureUsageFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUTextureUsage {
    const GPUFlagsConstant COPY_SRC          = 0x01;
    const GPUFlagsConstant COPY_DST          = 0x02;
    const GPUFlagsConstant TEXTURE_BINDING   = 0x04;
    const GPUFlagsConstant STORAGE_BINDING   = 0x08;
    const GPUFlagsConstant RENDER_ATTACHMENT = 0x10;
};

GPUTextureUsage 플래그는 GPUTexture 생성 후 어떻게 사용할 수 있는지 결정합니다:

COPY_SRC

텍스처를 복사 작업의 소스로 사용할 수 있습니다. (예: source 인자로 copyTextureToTexture() 또는 copyTextureToBuffer() 호출 시.)

COPY_DST

텍스처를 복사 또는 쓰기 작업의 대상으로 사용할 수 있습니다. (예: destination 인자로 copyTextureToTexture() 또는 copyBufferToTexture() 호출 시, 혹은 writeTexture() 호출의 대상.)

TEXTURE_BINDING

텍스처를 셰이더에서 샘플링 텍스처로 바인딩할 수 있습니다(예: GPUTextureBindingLayout의 바인드 그룹 항목).

STORAGE_BINDING

텍스처를 셰이더에서 storage 텍스처로 바인딩할 수 있습니다(예: GPUStorageTextureBindingLayout의 바인드 그룹 항목).

RENDER_ATTACHMENT

텍스처를 렌더 패스에서 컬러 또는 깊이/스텐실 attachment로 사용할 수 있습니다. (예: GPURenderPassColorAttachment.view 또는 GPURenderPassDepthStencilAttachment.view로 사용.)

maximum mipLevel count(dimension, size)

인자:

  1. 최대 차원 값 m을 계산합니다:

  2. floor(log2(m)) + 1을 반환합니다.

6.1.3. 텍스처 생성

createTexture(descriptor)

GPUTexture를 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createTexture(descriptor) 메서드 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUTextureDescriptor 생성할 GPUTexture의 설명.

반환값: GPUTexture

콘텐츠 타임라인 단계:

  1. ? GPUExtent3D 형태 검증(descriptor.size).

  2. ? 텍스처 포맷 필수 기능 검증(descriptor.format, this.[[device]]).

  3. ? 텍스처 포맷 필수 기능 검증descriptor.viewFormats의 각각의 요소와 this.[[device]]에 대해 수행한다.

  4. t! 새 WebGPU 객체 생성(this, GPUTexture, descriptor)로 둔다.

  5. t.widthdescriptor.size.width로 설정.

  6. t.heightdescriptor.size.height로 설정.

  7. t.depthOrArrayLayersdescriptor.size.depthOrArrayLayers로 설정.

  8. t.mipLevelCountdescriptor.mipLevelCount로 설정.

  9. t.sampleCountdescriptor.sampleCount로 설정.

  10. t.dimensiondescriptor.dimension로 설정.

  11. t.formatdescriptor.format로 설정.

  12. t.usagedescriptor.usage로 설정.

  13. this디바이스 타임라인에서 초기화 단계를 실행합니다.

  14. t를 반환합니다.

디바이스 타임라인 초기화 단계:
  1. 아래 조건 중 하나라도 만족하지 않으면 검증 오류를 생성하고, t를 무효화하고 반환합니다.

  2. t.[[viewFormats]]descriptor.viewFormats로 설정.

  3. t에 대해 각 블록이 0비트 표현의 블록과 동등 텍셀 표현을 가지도록 디바이스 할당을 생성합니다.

    할당이 부작용 없이 실패하면, 메모리 부족 오류 생성, t를 무효화하고 반환합니다.

GPUTextureDescriptor 유효성 검증(this, descriptor):

인자:

디바이스 타임라인 단계:

  1. limitsthis.[[limits]]로 둔다.

  2. 아래 요구사항을 모두 만족하면 true 반환, 아니면 false 반환:

16x16, RGBA, 2D 텍스처(배열 레이어 1개, mip 레벨 1개) 생성 예시:
const texture = gpuDevice.createTexture({
    size: { width: 16, height: 16 },
    format: 'rgba8unorm',
    usage: GPUTextureUsage.TEXTURE_BINDING,
});

6.1.4. 텍스처 소멸

애플리케이션에서 더 이상 GPUTexture가 필요하지 않은 경우, 가비지 컬렉션 전에 destroy()를 호출하여 접근 권한을 미리 잃도록 선택할 수 있습니다.

참고: 이렇게 하면 사용자 에이전트가 GPUTexture와 관련된 GPU 메모리를 해당 텍스처를 사용하는 모든 이전 제출 작업이 완료된 후 회수할 수 있습니다.

GPUTexture 는 다음 메서드를 가집니다:

destroy()

GPUTexture를 소멸시킵니다.

호출 대상: GPUTexture this.

반환값: undefined

콘텐츠 타임라인 단계:

  1. 이후 단계는 디바이스 타임라인에서 실행합니다.

디바이스 타임라인 단계:
  1. this.[[destroyed]] 를 true로 설정합니다.

6.2. GPUTextureView

GPUTextureView는 특정 GPUTexture에 대해 텍스처 서브리소스의 일부 집합을 참조하는 뷰입니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUTextureView {
};
GPUTextureView includes GPUObjectBase;

GPUTextureView 는 다음 불변 속성을 가집니다:

[[texture]], 읽기 전용

이 뷰가 참조하는 GPUTexture입니다.

[[descriptor]], 읽기 전용

이 텍스처 뷰를 설명하는 GPUTextureViewDescriptor입니다.

모든 선택적 GPUTextureViewDescriptor 필드는 정의되어 있습니다.

[[renderExtent]], 읽기 전용

렌더링 가능한 뷰일 경우, 렌더링에 사용되는 실질적인 GPUExtent3DDict입니다.

참고: 이 크기는 baseMipLevel에 따라 달라집니다.

텍스처 뷰 view서브리소스 집합은 [[descriptor]] desc를 기준으로, view.[[texture]]의 서브리소스 중 각각의 서브리소스 s가 아래 조건을 만족하는 부분집합입니다:

GPUTextureView 객체는 서브리소스 집합이 겹칠 때에만 텍스처 뷰 aliasing 관계입니다.

6.2.1. 텍스처 뷰 생성

dictionary GPUTextureViewDescriptor
         : GPUObjectDescriptorBase {
    GPUTextureFormat format;
    GPUTextureViewDimension dimension;
    GPUTextureUsageFlags usage = 0;
    GPUTextureAspect aspect = "all";
    GPUIntegerCoordinate baseMipLevel = 0;
    GPUIntegerCoordinate mipLevelCount;
    GPUIntegerCoordinate baseArrayLayer = 0;
    GPUIntegerCoordinate arrayLayerCount;
};

GPUTextureViewDescriptor 는 다음 멤버를 가집니다:

format, 타입 GPUTextureFormat

텍스처 뷰의 포맷입니다. 반드시 해당 텍스처의 format 또는 생성 시 지정된 viewFormats 중 하나여야 합니다.

dimension, 타입 GPUTextureViewDimension

텍스처를 어떤 차원으로 볼지 지정합니다.

usage, 타입 GPUTextureUsageFlags, 기본값 0

텍스처 뷰의 허용된 usage입니다. 반드시 텍스처의 usage 플래그의 부분집합이어야 합니다. 0일 경우, 기본값은 텍스처의 모든 usage 플래그입니다.

참고: 뷰의 format이 텍스처의 모든 usage를 지원하지 않으면, 기본값이 실패하며 뷰의 usage를 명시적으로 지정해야 합니다.

aspect, 타입 GPUTextureAspect, 기본값 "all"

텍스처의 어느 aspect가 텍스처 뷰에서 접근 가능한지 지정합니다.

baseMipLevel, 타입 GPUIntegerCoordinate, 기본값 0

텍스처 뷰에서 접근 가능한 첫 번째(가장 상세한) mipmap 레벨입니다.

mipLevelCount, 타입 GPUIntegerCoordinate

baseMipLevel부터 몇 개의 mipmap 레벨이 텍스처 뷰에서 접근 가능한지 지정합니다.

baseArrayLayer, 타입 GPUIntegerCoordinate, 기본값 0

텍스처 뷰에서 접근 가능한 첫 번째 배열 레이어의 인덱스입니다.

arrayLayerCount, 타입 GPUIntegerCoordinate

baseArrayLayer부터 몇 개의 배열 레이어가 텍스처 뷰에서 접근 가능한지 지정합니다.

enum GPUTextureViewDimension {
    "1d",
    "2d",
    "2d-array",
    "cube",
    "cube-array",
    "3d",
};
"1d"

텍스처를 1차원 이미지로 봅니다.

해당 WGSL 타입:

  • texture_1d

  • texture_storage_1d

"2d"

텍스처를 단일 2차원 이미지로 봅니다.

해당 WGSL 타입:

  • texture_2d

  • texture_storage_2d

  • texture_multisampled_2d

  • texture_depth_2d

  • texture_depth_multisampled_2d

"2d-array"

텍스처 뷰를 2차원 이미지 배열로 봅니다.

해당 WGSL 타입:

  • texture_2d_array

  • texture_storage_2d_array

  • texture_depth_2d_array

"cube"

텍스처를 큐브맵으로 봅니다.

뷰에는 6개의 배열 레이어가 있으며, 각각은 큐브의 면에 해당합니다. 순서는 [+X, -X, +Y, -Y, +Z, -Z]이고 방향은 다음과 같습니다:

큐브맵 면들. +U/+V 축은 각 면의 텍스처 좌표를 나타내며, 각 면의 texel copy 메모리 레이아웃도 의미합니다.

참고: 내부에서 보면 오른손 좌표계가 아닌 왼손 좌표계가 되며, +X는 오른쪽, +Y는 위, +Z는 앞쪽이 됩니다.

샘플링은 큐브맵의 모든 면에 걸쳐 매끄럽게 처리됩니다.

해당 WGSL 타입:

  • texture_cube

  • texture_depth_cube

"cube-array"

텍스처를 n개의 큐브맵 묶음 배열로 봅니다. 각각은 6개의 배열 레이어로 하나의 "cube" 뷰처럼 동작하며, 전체 배열 레이어 수는 6n입니다.

해당 WGSL 타입:

  • texture_cube_array

  • texture_depth_cube_array

"3d"

텍스처를 3차원 이미지로 봅니다.

해당 WGSL 타입:

  • texture_3d

  • texture_storage_3d

GPUTextureAspect 값은 aspect 집합에 대응합니다. 아래 각 값에 대한 aspect 집합은 다음과 같이 정의됩니다.

enum GPUTextureAspect {
    "all",
    "stencil-only",
    "depth-only",
};
"all"

텍스처 포맷의 모든 사용 가능한 aspect가 텍스처 뷰에서 접근 가능합니다. 컬러 포맷의 경우 color aspect가 접근 가능하며, depth-stencil 결합 포맷은 depth와 stencil aspect 모두 접근 가능합니다. depth 또는 stencil 포맷 중 aspect가 하나뿐인 경우 해당 aspect만 접근 가능합니다.

aspect 집합은 [color, depth, stencil] 입니다.

"stencil-only"

depth 또는 stencil 포맷에서 stencil aspect만 텍스처 뷰에서 접근 가능합니다.

aspect 집합은 [stencil] 입니다.

"depth-only"

depth 또는 stencil 포맷에서 depth aspect만 텍스처 뷰에서 접근 가능합니다.

aspect 집합은 [depth] 입니다.

createView(descriptor)

GPUTextureView를 생성합니다.

참고:
기본적으로 createView()는 텍스처 전체를 표현할 수 있는 차원의 뷰를 생성합니다. 예를 들어, createView() 호출 시 dimension을 지정하지 않고 여러 레이어가 있는 "2d" 텍스처에 대해 호출하면, "2d-array" GPUTextureView가 생성됩니다. arrayLayerCount가 1이어도 마찬가지입니다.

레이어 개수를 개발 시점에 알 수 없는 소스로 생성된 텍스처의 경우 셰이더 호환성을 위해 createView() 호출에 명시적으로 dimension을 지정하는 것이 권장됩니다.

호출 대상: GPUTexture this.

인자:

GPUTexture.createView(descriptor) 메서드 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUTextureViewDescriptor 생성할 GPUTextureView의 설명.

반환값: view, 타입 GPUTextureView.

콘텐츠 타임라인 단계:

  1. ? 텍스처 포맷 필수 기능 검증(descriptor.format, this.[[device]]).

  2. view! 새 WebGPU 객체 생성(this, GPUTextureView, descriptor)로 둔다.

  3. this디바이스 타임라인에서 초기화 단계를 실행합니다.

  4. view를 반환합니다.

디바이스 타임라인 초기화 단계:
  1. descriptorGPUTextureViewDescriptor 기본값 해석의 결과로 설정합니다 (thisdescriptor 사용).

  2. 아래 조건 중 하나라도 만족하지 않으면 검증 오류를 생성, view를 무효화하고 반환합니다.

  3. view를 새로운 GPUTextureView 객체로 둔다.

  4. view.[[texture]] 값을 this로 설정.

  5. view.[[descriptor]] 값을 descriptor로 설정.

  6. descriptor.usageRENDER_ATTACHMENT가 포함된 경우:

    1. renderExtentcompute render extent([this.width, this.height, this.depthOrArrayLayers], descriptor.baseMipLevel)로 둔다.

    2. view.[[renderExtent]] 값을 renderExtent로 설정.

GPUTextureViewDescriptor 기본값을 해결할 때 GPUTextureView textureGPUTextureViewDescriptor descriptor를 대상으로 할 때, 아래 디바이스 타임라인 단계들을 실행한다:
  1. resolveddescriptor의 복사본으로 둔다.

  2. resolved.format 값이 제공되지 않은 경우:

    1. formatGPUTextureAspect 해석의 결과로 둔다( format, descriptor.aspect).

    2. formatnull이면:

      그 외에는:

      • resolved.format 값을 format으로 설정.

  3. resolved.mipLevelCount 값이 제공되지 않은 경우: resolved.mipLevelCounttexture.mipLevelCountresolved.baseMipLevel로 설정.

  4. resolved.dimension 값이 제공되지 않은 경우이고, texture.dimension 이 다음 중 하나일 때:

    "1d"

    resolved.dimension"1d"로 설정.

    "2d"

    array layer counttexture에서 1인 경우:

    그 외에는:

    "3d"

    resolved.dimension"3d"로 설정.

  5. resolved.arrayLayerCount 값이 제공되지 않은 경우이고, resolved.dimension 값이 다음 중 하나일 때:

    "1d", "2d", 또는 "3d"

    resolved.arrayLayerCount1로 설정.

    "cube"

    resolved.arrayLayerCount6으로 설정.

    "2d-array" 또는 "cube-array"

    resolved.arrayLayerCounttexturearray layer countresolved.baseArrayLayer로 설정.

  6. resolved.usage 값이 0이면: resolved.usagetexture.usage로 설정.

  7. resolved를 반환.

GPUTexture texturearray layer count를 결정하려면 아래 단계를 수행합니다:
  1. texture.dimension 값이 다음 중 하나일 때:

    "1d" 또는 "3d"

    1 반환.

    "2d"

    texture.depthOrArrayLayers 반환.

6.3. 텍스처 포맷

포맷의 이름은 컴포넌트의 순서, 컴포넌트당 비트 수, 그리고 컴포넌트의 데이터 타입을 지정합니다.

포맷에 -srgb 접미사가 있으면, 셰이더에서 색상 값을 읽고 쓸 때 sRGB 변환(감마와 선형 변환)이 적용됩니다. 압축 텍스처 포맷은 기능으로 제공됩니다. 명명 규칙은 여기의 관례를 따라야 하며, 텍스처 이름을 접두사로 사용합니다. 예시: etc2-rgba8unorm.

텍셀 블록은 픽셀 기반 GPUTextureFormat 텍스처의 단일 주소 지정 가능한 요소이자, 블록 기반 압축 GPUTextureFormat 텍스처의 단일 압축 블록입니다.

텍셀 블록 너비텍셀 블록 높이는 하나의 텍셀 블록의 가로, 세로 차원을 지정합니다.

텍셀 블록 복사 풋프린트aspectGPUTextureFormat 에 대해, 텍셀 복사 시 하나의 텍셀 블록이 차지하는 바이트 수입니다(해당 시).

참고: 텍셀 블록 메모리 비용GPUTextureFormat 별로 하나의 텍셀 블록을 저장하는 데 필요한 바이트 수입니다. 모든 포맷에 대해 완전히 정의된 값은 아닙니다. 이 값은 안내용이며, 표준적인 값이 아닙니다.

enum GPUTextureFormat {
    // 8비트 포맷
    "r8unorm",
    "r8snorm",
    "r8uint",
    "r8sint",

    // 16비트 포맷
    "r16unorm",
    "r16snorm",
    "r16uint",
    "r16sint",
    "r16float",
    "rg8unorm",
    "rg8snorm",
    "rg8uint",
    "rg8sint",

    // 32비트 포맷
    "r32uint",
    "r32sint",
    "r32float",
    "rg16unorm",
    "rg16snorm",
    "rg16uint",
    "rg16sint",
    "rg16float",
    "rgba8unorm",
    "rgba8unorm-srgb",
    "rgba8snorm",
    "rgba8uint",
    "rgba8sint",
    "bgra8unorm",
    "bgra8unorm-srgb",
    // Packed 32비트 포맷
    "rgb9e5ufloat",
    "rgb10a2uint",
    "rgb10a2unorm",
    "rg11b10ufloat",

    // 64비트 포맷
    "rg32uint",
    "rg32sint",
    "rg32float",
    "rgba16unorm",
    "rgba16snorm",
    "rgba16uint",
    "rgba16sint",
    "rgba16float",

    // 128비트 포맷
    "rgba32uint",
    "rgba32sint",
    "rgba32float",

    // 깊이/스텐실 포맷
    "stencil8",
    "depth16unorm",
    "depth24plus",
    "depth24plus-stencil8",
    "depth32float",

    // "depth32float-stencil8" 기능
    "depth32float-stencil8",

    // 디바이스/사용자 에이전트가 "texture-compression-bc"를 지원 & requestDevice에서 활성화된 경우 사용 가능한 BC 압축 포맷
    "bc1-rgba-unorm",
    "bc1-rgba-unorm-srgb",
    "bc2-rgba-unorm",
    "bc2-rgba-unorm-srgb",
    "bc3-rgba-unorm",
    "bc3-rgba-unorm-srgb",
    "bc4-r-unorm",
    "bc4-r-snorm",
    "bc5-rg-unorm",
    "bc5-rg-snorm",
    "bc6h-rgb-ufloat",
    "bc6h-rgb-float",
    "bc7-rgba-unorm",
    "bc7-rgba-unorm-srgb",

    // 디바이스/사용자 에이전트가 "texture-compression-etc2"를 지원 & requestDevice에서 활성화된 경우 사용 가능한 ETC2 압축 포맷
    "etc2-rgb8unorm",
    "etc2-rgb8unorm-srgb",
    "etc2-rgb8a1unorm",
    "etc2-rgb8a1unorm-srgb",
    "etc2-rgba8unorm",
    "etc2-rgba8unorm-srgb",
    "eac-r11unorm",
    "eac-r11snorm",
    "eac-rg11unorm",
    "eac-rg11snorm",

    // 디바이스/사용자 에이전트가 "texture-compression-astc"를 지원 & requestDevice에서 활성화된 경우 사용 가능한 ASTC 압축 포맷
    "astc-4x4-unorm",
    "astc-4x4-unorm-srgb",
    "astc-5x4-unorm",
    "astc-5x4-unorm-srgb",
    "astc-5x5-unorm",
    "astc-5x5-unorm-srgb",
    "astc-6x5-unorm",
    "astc-6x5-unorm-srgb",
    "astc-6x6-unorm",
    "astc-6x6-unorm-srgb",
    "astc-8x5-unorm",
    "astc-8x5-unorm-srgb",
    "astc-8x6-unorm",
    "astc-8x6-unorm-srgb",
    "astc-8x8-unorm",
    "astc-8x8-unorm-srgb",
    "astc-10x5-unorm",
    "astc-10x5-unorm-srgb",
    "astc-10x6-unorm",
    "astc-10x6-unorm-srgb",
    "astc-10x8-unorm",
    "astc-10x8-unorm-srgb",
    "astc-10x10-unorm",
    "astc-10x10-unorm-srgb",
    "astc-12x10-unorm",
    "astc-12x10-unorm-srgb",
    "astc-12x12-unorm",
    "astc-12x12-unorm-srgb",
};

"depth24plus""depth24plus-stencil8" 포맷의 깊이 컴포넌트는 24비트 깊이 값 또는 "depth32float" 값으로 구현될 수 있습니다.

stencil8 포맷은 실제 "stencil8" 또는 "depth24stencil8"로 구현될 수 있으며, 이 경우 깊이 aspect는 숨겨지고 접근할 수 없습니다.

참고:
depth32float 채널의 정밀도는 24비트 깊이 채널의 정밀도보다 해당 표현 범위(0.0~1.0) 내 모든 값에서 엄격히 높지만, 표현 가능한 값의 집합이 정확히 상위 집합인 것은 아닙니다.

포맷이 렌더링 가능하려면 컬러 렌더링 포맷이거나 깊이/스텐실 포맷이어야 합니다. 만약 해당 포맷이 § 26.1.1 일반 컬러 포맷RENDER_ATTACHMENT 기능으로 나열되어 있다면, 컬러 렌더링 포맷입니다. 그렇지 않은 포맷은 컬러 렌더링 포맷이 아닙니다. 모든 깊이/스텐실 포맷은 렌더링 가능합니다.

렌더링 가능 포맷블렌딩 가능 포맷이기도 하며, 렌더 파이프라인 블렌딩에 사용할 수 있습니다. 자세한 내용은 § 26.1 텍스처 포맷 지원을 참고하세요.

포맷이 필터링 가능하려면, GPUTextureSampleType "float" (단순 "unfilterable-float"만이 아니라) 를 지원해야 하며, "filtering" GPUSampler에 사용할 수 있어야 합니다. 자세한 내용은 § 26.1 텍스처 포맷 지원을 참고하세요.

GPUTextureAspect 해석(format, aspect)

인자:

반환값: GPUTextureFormat 또는 null

  1. aspect가 다음 중 하나일 때:

    "all"

    format 반환.

    "depth-only"
    "stencil-only"

    format이 깊이-스텐실 포맷이면: aspect별 포맷§ 26.1.2 깊이-스텐실 포맷에 따라 반환하거나, 해당 aspect가 format에 없으면 null 반환.

  2. null 반환.

일부 텍스처 포맷을 사용하려면 GPUDevice 에서 기능을 활성화해야 합니다. 새로운 포맷이 명세에 추가될 수 있으므로, 해당 enum 값이 구현체에 알려지지 않을 수 있습니다. 모든 구현에서 동작을 일관성 있게 만들기 위해, 기능이 필요한 포맷을 기능을 활성화하지 않은 디바이스에서 사용하려 하면 예외가 발생합니다. 이는 포맷이 구현체에 알려지지 않았을 때와 같은 동작을 보장합니다.

어떤 GPUTextureFormat이 기능을 필요로 하는지는 § 26.1 텍스처 포맷 지원을 참고하세요.

텍스처 포맷 필수 기능 검증(GPUTextureFormat format,
논리적 device device):
  1. format이 기능을 필요로 하는데 device.[[features]] 에 해당 기능이 포함되지 않은 경우:

    1. TypeError를 throw합니다.

6.4. GPUExternalTexture

GPUExternalTexture 는 외부 비디오 프레임을 래핑한 샘플링 가능한 2D 텍스처입니다. 이는 불변 스냅샷으로, WebGPU 내부에서(샘플링만 가능)든 외부에서(예: 비디오 프레임 진행 등)든 시간이 지나도 내용이 변하지 않습니다.

GPUExternalTextureexternalTexture 바인드 그룹 레이아웃 엔트리 멤버를 통해 바인드 그룹에 바인딩할 수 있습니다. 해당 멤버는 여러 바인딩 슬롯을 사용하니 주의하세요.

참고:
GPUExternalTexture 는 임포트된 소스의 복사본을 생성하지 않고도 구현될 있지만, 이는 구현의 정의에 따라 달라집니다. 내부 표현의 소유권은 단독일 수도 있고(예: 비디오 디코더 등) 다른 소유자와 공유될 수도 있지만, 애플리케이션에서는 볼 수 없습니다.

외부 텍스처의 내부 표현은(정밀 샘플링 동작을 제외하면) 관측할 수 없으나, 일반적으로 다음을 포함할 수 있습니다:

구현체 내부의 구성 방식은 시간, 시스템, 사용자 에이전트, 미디어 소스, 심지어 단일 비디오 소스의 각 프레임마다 일관되지 않을 수 있습니다. 다양한 표현에 대응하기 위해, 각 외부 텍스처마다 아래와 같이 보수적으로 바인딩합니다:

[Exposed=(Window, Worker), SecureContext]
interface GPUExternalTexture {
};
GPUExternalTexture includes GPUObjectBase;

GPUExternalTexture 는 다음 불변 속성을 가집니다:

[[descriptor]], 타입 GPUExternalTextureDescriptor, 읽기 전용

텍스처 생성에 사용된 descriptor입니다.

GPUExternalTexture 는 다음 불변 속성을 가집니다:

[[expired]], 타입 boolean, 초기값 false

객체가 만료되어 더 이상 사용할 수 없는지 여부를 나타냅니다.

참고: [[destroyed]] 슬롯과 유사하지만, 이 값은 true에서 false로 다시 바뀔 수 있습니다.

6.4.1. 외부 텍스처 가져오기

외부 텍스처는 외부 비디오 객체에서 importExternalTexture()를 사용해 생성됩니다.

HTMLVideoElement에서 생성된 외부 텍스처는 가져온 후 작업에서 자동으로 만료(소멸)되며, 다른 리소스처럼 수동이나 가비지 컬렉션 시 소멸되지 않습니다. 외부 텍스처가 만료되면 [[expired]] 슬롯이 true로 바뀝니다.

VideoFrame에서 생성된 외부 텍스처는, 소스 VideoFrame닫혔을 때(명시적으로 close()로, 또는 다른 방법으로)만 만료(소멸)됩니다.

참고: decode()에 설명된 대로, 작성자는 디코더 정지를 피하기 위해 출력 VideoFrame에 대해 반드시 close()를 호출해야 합니다. 가져온 VideoFrame이 닫히지 않고 버려지면, 가져온 GPUExternalTexture 객체가 VideoFrame을 살아있게 유지합니다. 두 객체 모두 버려질 때까지 VideoFrame은 가비지 컬렉션되지 않습니다. 가비지 컬렉션은 예측 불가능하므로, 이것이 비디오 디코더를 지연시킬 수 있습니다.

GPUExternalTexture 가 만료되면 importExternalTexture()를 다시 호출해야 합니다. 하지만 사용자 에이전트가 만료 상태를 해제하고 새로운 객체를 만들지 않고 같은 GPUExternalTexture를 다시 반환할 수 있습니다. 이는 일반적으로 애플리케이션 실행이 비디오 프레임률과 맞춰 스케줄되지 않는 경우(예: requestVideoFrameCallback() 사용 등)에 발생합니다. 같은 객체가 다시 반환되면 이전 객체와 동등 비교가 가능하며, GPUBindGroup, GPURenderBundle 등에서 이전 객체를 계속 사용할 수 있습니다.

dictionary GPUExternalTextureDescriptor
         : GPUObjectDescriptorBase {
    required (HTMLVideoElement or VideoFrame) source;
    PredefinedColorSpace colorSpace = "srgb";
};

GPUExternalTextureDescriptor 딕셔너리는 다음 멤버를 가집니다:

source, 타입 (HTMLVideoElement or VideoFrame)

외부 텍스처를 가져올 비디오 소스입니다. 소스 크기는 외부 소스 크기 표에 따라 결정됩니다.

colorSpace, 타입 PredefinedColorSpace, 기본값 "srgb"

source의 이미지 내용을 읽을 때 변환할 색 공간입니다.

importExternalTexture(descriptor)

제공된 이미지 소스를 래핑하는 GPUExternalTexture를 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.importExternalTexture(descriptor) 메서드 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUExternalTextureDescriptor 외부 이미지 소스 객체(및 생성 옵션)를 제공합니다.

반환값: GPUExternalTexture

콘텐츠 타임라인 단계:

  1. sourcedescriptor.source로 둔다.

  2. 현재 source의 이미지 내용이 같은 descriptor(label 제외)로 가장 최근에 importExternalTexture()를 호출한 결과와 동일하고, 사용자 에이전트가 재사용을 선택한 경우:

    1. previousResult를 이전에 반환된 GPUExternalTexture로 둔다.

    2. previousResult.[[expired]]false로 설정하여, 하부 리소스 소유권을 갱신한다.

    3. resultpreviousResult로 둔다.

    참고: 이는 애플리케이션이 중복 import를 감지하고 종속 객체(GPUBindGroup 등)를 다시 생성하지 않을 수 있게 해줍니다. 구현은 동일 프레임이 여러 GPUExternalTexture로 래핑되는 경우도 처리해야 하며, import 메타데이터(colorSpace 등)는 동일 프레임에도 달라질 수 있습니다.

    그 외에는:

    1. sourceorigin-clean하지 않으면, SecurityError를 throw하고 반환.

    2. usability? 이미지 인자 사용 가능 여부 확인(source)로 둔다.

    3. usabilitygood이 아니면:

      1. 검증 오류 생성.

      2. 무효화된 GPUExternalTexture를 반환.

    4. datasource의 현재 이미지 내용을 descriptor.colorSpace 색 공간으로, unpremultiplied alpha로 변환한 결과로 둔다.

      이는 범위 [0, 1]을 벗어날 수 있습니다. 클램핑이 필요하다면 샘플링 후 별도로 수행할 수 있습니다.

      참고: 복사처럼 서술되었지만, 읽기 전용 하부 데이터 참조와 변환용 메타데이터로 구현될 수도 있습니다.

    5. resultdata를 래핑하는 새로운 GPUExternalTexture 객체로 둔다.

  3. sourceHTMLVideoElement이면, 자동 만료 작업 큐잉(디바이스 this 및 다음 단계 포함):

    1. result.[[expired]]true로 설정하여 하부 리소스 소유권 해제.

    참고: HTMLVideoElement는 텍스처 샘플링과 같은 작업 내에서 import되어야 하며 (일반적으로 requestVideoFrameCallback 또는 애플리케이션에 따라 requestAnimationFrame() 사용), 그렇지 않으면 텍스처가 애플리케이션에서 사용되기 전에 소멸될 수 있습니다.

  4. sourceVideoFrame이면, source닫힐 때 다음 단계를 실행:

    1. result.[[expired]]true로 설정.

  5. result.label 값을 descriptor.label로 설정.

  6. result를 반환.

페이지 애니메이션 프레임 속도에 맞춰 비디오 요소 외부 텍스처로 렌더링:
const videoElement = document.createElement('video');
// ... videoElement를 설정하고, 준비될 때까지 대기 ...

function frame() {
    requestAnimationFrame(frame);

    // 매 애니메이션 프레임마다 항상 비디오를 다시 import해야 함(import가 만료되었을 수 있음)
    // 브라우저가 이전 프레임을 캐시 및 재사용할 수 있고, 이 경우 동일한 GPUExternalTexture 객체를 다시 반환할 수 있음
    // 이 경우 기존 바인드 그룹도 여전히 유효함
    const externalTexture = gpuDevice.importExternalTexture({
        source: videoElement
    });

    // ... externalTexture를 사용해 렌더링 ...
}
requestAnimationFrame(frame);
requestVideoFrameCallback이 사용 가능하면 비디오 프레임 속도에 맞춰 비디오 요소 외부 텍스처로 렌더링:
const videoElement = document.createElement('video');
// ... videoElement 설정 ...

function frame() {
    videoElement.requestVideoFrameCallback(frame);

    // 프레임이 진행된 것을 알기 때문에 항상 재-import
    const externalTexture = gpuDevice.importExternalTexture({
        source: videoElement
    });

    // ... externalTexture를 사용해 렌더링 ...
}
videoElement.requestVideoFrameCallback(frame);

6.5. 외부 텍스처 바인딩 샘플링

externalTexture 바인딩 포인트는 GPUExternalTexture 객체(비디오 등 동적 이미지 소스)를 바인딩할 수 있습니다. 또한 GPUTextureGPUTextureView도 지원합니다.

참고: GPUTexture 또는 GPUTextureViewexternalTexture 바인딩에 바인딩하면, crop/회전/색상 변환 없이 단일 RGBA 평면을 가진 GPUExternalTexture처럼 동작합니다.

외부 텍스처는 WGSL에서 texture_external로 표현되며, textureLoadtextureSampleBaseClampToEdge로 읽을 수 있습니다.

textureSampleBaseClampToEdge에 제공된 sampler는 하부 텍스처 샘플링에 사용됩니다.

바인딩 리소스 타입GPUExternalTexture일 경우, 결과는 colorSpace로 설정된 색 공간에 있습니다. 샘플러(및 필터링)가 하부 값에서 지정된 색 공간으로 변환되기 전 또는 후에 적용되는지는 구현에 따라 다릅니다.

참고: 내부 표현이 RGBA 평면이면 샘플링은 일반 2D 텍스처처럼 동작합니다. 여러 하부 평면(Y+UV 등)이 있으면, 샘플러가 각 하부 텍스처를 개별적으로 샘플링한 뒤 YUV→색 공간 변환이 진행됩니다.

7. 샘플러

7.1. GPUSampler

GPUSampler 는 셰이더에서 텍스처 리소스 데이터를 해석하는 데 사용할 변환 및 필터링 정보를 인코딩합니다.

GPUSamplercreateSampler()로 생성합니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUSampler {
};
GPUSampler includes GPUObjectBase;

GPUSampler 는 다음 불변 속성을 가집니다:

[[descriptor]], 타입 GPUSamplerDescriptor, 읽기 전용

GPUSamplerDescriptorGPUSampler 를 생성했습니다.

[[isComparison]], 타입 boolean, 읽기 전용

GPUSampler 가 비교 샘플러로 사용되는지 여부입니다.

[[isFiltering]], 타입 boolean, 읽기 전용

GPUSampler 가 텍스처의 여러 샘플에 가중치를 두는지 여부입니다.

7.1.1. GPUSamplerDescriptor

GPUSamplerDescriptorGPUSampler 생성 시 사용할 옵션을 지정합니다.

dictionary GPUSamplerDescriptor
         : GPUObjectDescriptorBase {
    GPUAddressMode addressModeU = "clamp-to-edge";
    GPUAddressMode addressModeV = "clamp-to-edge";
    GPUAddressMode addressModeW = "clamp-to-edge";
    GPUFilterMode magFilter = "nearest";
    GPUFilterMode minFilter = "nearest";
    GPUMipmapFilterMode mipmapFilter = "nearest";
    float lodMinClamp = 0;
    float lodMaxClamp = 32;
    GPUCompareFunction compare;
    [Clamp] unsigned short maxAnisotropy = 1;
};
addressModeU, 타입 GPUAddressMode, 기본값 "clamp-to-edge"
addressModeV, 타입 GPUAddressMode, 기본값 "clamp-to-edge"
addressModeW, 타입 GPUAddressMode, 기본값 "clamp-to-edge"

텍스처의 너비, 높이, 깊이 좌표 각각에 대한 address mode를 지정합니다.

magFilter, 타입 GPUFilterMode, 기본값 "nearest"

샘플링 영역이 텍셀 하나보다 작거나 같을 때의 샘플링 동작을 지정합니다.

minFilter, 타입 GPUFilterMode, 기본값 "nearest"

샘플링 영역이 텍셀 하나보다 클 때의 샘플링 동작을 지정합니다.

mipmapFilter, 타입 GPUMipmapFilterMode, 기본값 "nearest"

mipmap 레벨 간 샘플링 동작을 지정합니다.

lodMinClamp, 타입 float, 기본값 0
lodMaxClamp, 타입 float, 기본값 32

텍스처 샘플링 시 내부적으로 사용되는 상세 레벨(LOD)의 최소/최대값을 지정합니다.

compare, 타입 GPUCompareFunction

지정 시 해당 GPUCompareFunction을 사용하는 비교 샘플러가 됩니다.

참고: 비교 샘플러도 필터링을 사용할 수 있지만, 샘플링 결과는 구현에 따라 달라지며 일반 필터링 규칙과 다를 수 있습니다.

maxAnisotropy, 타입 unsigned short, 기본값 1

샘플러에서 사용할 최대 이방성값 클램프를 지정합니다. maxAnisotropy가 1보다 크고 구현이 지원하는 경우 이방성 필터링이 활성화됩니다.

이방성 필터링은 비스듬히 보는 텍스처의 이미지 품질을 향상시킵니다. maxAnisotropy가 클수록 필터링 시 지원되는 최대 이방성 비율을 의미합니다.

참고:
대부분의 구현은 maxAnisotropy 값으로 1~16 범위를 지원합니다. 실제로 사용되는 maxAnisotropy 값은 플랫폼이 지원하는 최대값으로 클램프됩니다.

정확한 필터링 동작은 구현에 따라 다릅니다.

상세 레벨(Level of detail, LOD)은 텍스처 샘플링 시 어떤 mip 레벨을 선택하는지 나타내며, 셰이더의 textureSampleLevel 등으로 명시하거나 텍스처 좌표 미분값으로 암시적으로 결정될 수 있습니다.

참고: 암시적 LOD 계산 예시는 Vulkan 1.3: Scale Factor Operation, LOD Operation and Image Level Selection을 참고하세요.

GPUAddressMode 는 샘플링한 텍셀이 텍스처 경계를 벗어났을 때의 샘플러 동작을 지정합니다.

enum GPUAddressMode {
    "clamp-to-edge",
    "repeat",
    "mirror-repeat",
};
"clamp-to-edge"

텍스처 좌표를 0.0~1.0 사이로 클램프합니다.

"repeat"

텍스처 좌표가 텍스처 반대편으로 래핑됩니다.

"mirror-repeat"

텍스처 좌표가 텍스처 반대편으로 래핑되지만, 좌표의 정수 부분이 홀수일 때 텍스처가 뒤집힙니다.

GPUFilterModeGPUMipmapFilterMode 는 샘플링 영역이 정확히 한 텍셀만을 포함하지 않을 때의 동작을 지정합니다.

참고: 각 필터링 모드에서 어떤 텍셀이 샘플링되는지에 대한 예시는 Vulkan 1.3: Texel Filtering을 참고하세요.

enum GPUFilterMode {
    "nearest",
    "linear",
};

enum GPUMipmapFilterMode {
    "nearest",
    "linear",
};
"nearest"

텍스처 좌표에 가장 가까운 텍셀의 값을 반환합니다.

"linear"

각 차원마다 두 텍셀을 선택하고 값의 선형 보간을 반환합니다.

GPUCompareFunction 은 비교 샘플러의 동작을 지정합니다. 셰이더에서 비교 샘플러를 사용하면 depth_ref가 가져온 텍셀 값과 비교되어, 비교 결과(1.0f는 통과, 0.0f는 실패)가 생성됩니다.

비교 후 텍스처 필터링이 활성화된 경우, 필터링 단계에서 비교 결과가 혼합되어 [0, 1] 범위의 값이 생성됩니다. 필터링은 일반적으로 평소와 동일하게 동작하지만, 구현에 따라 정밀도가 낮거나 아예 혼합이 없을 수도 있습니다.

enum GPUCompareFunction {
    "never",
    "less",
    "equal",
    "less-equal",
    "greater",
    "not-equal",
    "greater-equal",
    "always",
};
"never"

비교 테스트가 절대 통과하지 않습니다.

"less"

제공된 값이 샘플링된 값보다 작으면 비교 테스트를 통과합니다.

"equal"

제공된 값이 샘플링된 값과 같으면 비교 테스트를 통과합니다.

"less-equal"

제공된 값이 샘플링된 값 이하이면 비교 테스트를 통과합니다.

"greater"

제공된 값이 샘플링된 값보다 크면 비교 테스트를 통과합니다.

"not-equal"

제공된 값이 샘플링된 값과 다르면 비교 테스트를 통과합니다.

"greater-equal"

제공된 값이 샘플링된 값 이상이면 비교 테스트를 통과합니다.

"always"

비교 테스트가 항상 통과합니다.

7.1.2. 샘플러 생성

createSampler(descriptor)

GPUSampler를 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createSampler(descriptor) 메서드 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUSamplerDescriptor 생성할 GPUSampler의 설명.

반환값: GPUSampler

콘텐츠 타임라인 단계:

  1. s! 새 WebGPU 객체 생성(this, GPUSampler, descriptor)로 둔다.

  2. this디바이스 타임라인에서 초기화 단계를 실행합니다.

  3. s를 반환합니다.

디바이스 타임라인 초기화 단계:
  1. 다음 조건 중 하나라도 만족하지 않으면 검증 오류 생성, s를 무효화하고 반환합니다.

  2. s.[[descriptor]]descriptor로 설정합니다.

  3. s.[[isComparison]]s.[[descriptor]]compare 속성이 null 또는 undefined이면 false, 아니면 true로 설정합니다.

  4. s.[[isFiltering]]minFilter, magFilter, mipmapFilter 중 어느 것도 "linear" 값이 없으면 false로, 있으면 true로 설정합니다.

trilinear 필터링과 좌표 반복을 하는 GPUSampler 생성 예시:
const sampler = gpuDevice.createSampler({
    addressModeU: 'repeat',
    addressModeV: 'repeat',
    magFilter: 'linear',
    minFilter: 'linear',
    mipmapFilter: 'linear',
});

8. 리소스 바인딩

8.1. GPUBindGroupLayout

GPUBindGroupLayoutGPUBindGroup에 바인딩되는 리소스 집합과 셰이더 단계에서의 접근성 사이의 인터페이스를 정의합니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUBindGroupLayout {
};
GPUBindGroupLayout includes GPUObjectBase;

GPUBindGroupLayout 은 다음 불변 속성을 가집니다:

[[descriptor]], 타입 GPUBindGroupLayoutDescriptor, 읽기 전용

8.1.1. 바인드 그룹 레이아웃 생성

GPUBindGroupLayoutGPUDevice.createBindGroupLayout()로 생성됩니다.

dictionary GPUBindGroupLayoutDescriptor
         : GPUObjectDescriptorBase {
    required sequence<GPUBindGroupLayoutEntry> entries;
};

GPUBindGroupLayoutDescriptor 딕셔너리는 다음 멤버를 가집니다:

entries, 타입 sequence<GPUBindGroupLayoutEntry>

바인드 그룹의 셰이더 리소스 바인딩을 기술하는 엔트리 목록입니다.

GPUBindGroupLayoutEntryGPUBindGroupLayout에 포함되는 단일 셰이더 리소스 바인딩을 설명합니다.

dictionary GPUBindGroupLayoutEntry {
    required GPUIndex32 binding;
    required GPUShaderStageFlags visibility;

    GPUBufferBindingLayout buffer;
    GPUSamplerBindingLayout sampler;
    GPUTextureBindingLayout texture;
    GPUStorageTextureBindingLayout storageTexture;
    GPUExternalTextureBindingLayout externalTexture;
};

GPUBindGroupLayoutEntry 딕셔너리는 다음 멤버를 가집니다:

binding, 타입 GPUIndex32

해당 GPUBindGroupLayout 내 리소스 바인딩의 고유 식별자이며, GPUBindGroupEntry.binding@binding 속성과 대응됩니다.

visibility, 타입 GPUShaderStageFlags

GPUShaderStage 멤버들의 비트셋입니다. 각 설정된 비트는 GPUBindGroupLayoutEntry의 리소스가 해당 셰이더 단계에서 접근 가능함을 나타냅니다.

buffer, 타입 GPUBufferBindingLayout
sampler, 타입 GPUSamplerBindingLayout
texture, 타입 GPUTextureBindingLayout
storageTexture, 타입 GPUStorageTextureBindingLayout
externalTexture, 타입 GPUExternalTextureBindingLayout

이 멤버 중 반드시 하나만 설정해야 하며, 바인딩 타입을 나타냅니다. 해당 멤버의 내용은 타입별 옵션을 지정합니다.

createBindGroup()의 해당 리소스는 이 바인딩에 대해 바인딩 리소스 타입을 가져야 합니다.

typedef [EnforceRange] unsigned long GPUShaderStageFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUShaderStage {
    const GPUFlagsConstant VERTEX   = 0x1;
    const GPUFlagsConstant FRAGMENT = 0x2;
    const GPUFlagsConstant COMPUTE  = 0x4;
};

GPUShaderStage 에는 해당 GPUBindGroupEntry가 이 GPUBindGroupLayoutEntry에 대해 어느 셰이더 단계에서 보이는지 설명하는 다음 플래그가 포함되어 있습니다:

VERTEX

바인드 그룹 엔트리가 버텍스 셰이더에서 접근할 수 있습니다.

FRAGMENT

바인드 그룹 엔트리가 프래그먼트 셰이더에서 접근할 수 있습니다.

COMPUTE

바인드 그룹 엔트리가 컴퓨트 셰이더에서 접근할 수 있습니다.

GPUBindGroupLayoutEntrybinding memberGPUBindGroupLayoutEntry의 어떤 멤버가 정의되었는지에 따라 결정됩니다: buffer, sampler, texture, storageTexture, 또는 externalTexture. 하나의 GPUBindGroupLayoutEntry에는 반드시 하나만 정의될 수 있습니다. 각 멤버는 관련 GPUBindingResource 타입을 가지며, 각 binding type은 관련 internal usage를 가지며, 아래 표에 정리되어 있습니다:

바인딩 멤버 리소스 타입 바인딩 타입
바인딩 사용 용도
buffer GPUBufferBinding
(또는 GPUBuffer 약어로)
"uniform" 상수(constant)
"storage" 저장(storage)
"read-only-storage" 저장읽기(storage-read)
sampler GPUSampler "filtering" 상수(constant)
"non-filtering"
"comparison"
texture GPUTextureView
(또는 GPUTexture 약어로)
"float" 상수(constant)
"unfilterable-float"
"depth"
"sint"
"uint"
storageTexture GPUTextureView
(또는 GPUTexture 약어로)
"write-only" 저장(storage)
"read-write"
"read-only" 저장읽기(storage-read)
externalTexture GPUExternalTexture
또는 GPUTextureView
(또는 GPUTexture 약어로)
상수(constant)
list 타입의 GPUBindGroupLayoutEntryentries바인딩 슬롯 한도 초과한 경우는 지원 한도 limits에서 해당 한도를 초과하여 슬롯이 사용된 경우입니다. 각 entry는 여러 한도에 대해 여러 슬롯을 사용할 수 있습니다.

디바이스 타임라인 단계:

  1. entries의 각 entry에 대해, 만약:

    entry.buffer?.type 값이 "uniform" 이고, entry.buffer?.hasDynamicOffset 값이 true이면

    1개의 maxDynamicUniformBuffersPerPipelineLayout 슬롯을 사용한 것으로 간주.

    entry.buffer?.type 값이 "storage" 이고, entry.buffer?.hasDynamicOffset 값이 true이면

    1개의 maxDynamicStorageBuffersPerPipelineLayout 슬롯을 사용한 것으로 간주.

  2. 각 셰이더 단계 stage in « VERTEX, FRAGMENT, COMPUTE »:

    1. entries의 각 entryentry.visibility 값에 stage가 포함된 경우, 만약:

      entry.buffer?.type 값이 "uniform"이면

      1개의 maxUniformBuffersPerShaderStage 슬롯을 사용한 것으로 간주.

      entry.buffer?.type 값이 "storage" 또는 "read-only-storage"이면

      1개의 maxStorageBuffersPerShaderStage 슬롯을 사용한 것으로 간주.

      entry.sampler 값이 제공됨이면

      1개의 maxSamplersPerShaderStage 슬롯을 사용한 것으로 간주.

      entry.texture 값이 제공됨이면

      1개의 maxSampledTexturesPerShaderStage 슬롯을 사용한 것으로 간주.

      entry.storageTexture 값이 제공됨이면

      1개의 maxStorageTexturesPerShaderStage 슬롯을 사용한 것으로 간주.

      entry.externalTexture 값이 제공됨이면

      4개의 maxSampledTexturesPerShaderStage 슬롯, 1개의 maxSamplersPerShaderStage 슬롯, 1개의 maxUniformBuffersPerShaderStage 슬롯을 사용한 것으로 간주.

      참고: 이 동작의 설명은 GPUExternalTexture 를 참고.

enum GPUBufferBindingType {
    "uniform",
    "storage",
    "read-only-storage",
};

dictionary GPUBufferBindingLayout {
    GPUBufferBindingType type = "uniform";
    boolean hasDynamicOffset = false;
    GPUSize64 minBindingSize = 0;
};

GPUBufferBindingLayout 딕셔너리는 다음 멤버를 가집니다:

type, 타입 GPUBufferBindingType, 기본값 "uniform"

이 바인딩에 연결되는 버퍼가 요구하는 타입을 나타냅니다.

hasDynamicOffset, 타입 boolean, 기본값 false

이 바인딩이 동적 오프셋을 요구하는지 여부를 나타냅니다.

minBindingSize, 타입 GPUSize64, 기본값 0

이 바인딩 포인트에서 사용되는 버퍼 바인딩의 최소 size를 나타냅니다.

바인딩은 createBindGroup()에서 항상 이 크기에 대해 검증됩니다.

이 값이 0이 아니면 파이프라인 생성 시 추가로 검증되며, 해당 값이 변수의 최소 버퍼 바인딩 크기 이상이어야 합니다.

이 값이 0이면 파이프라인 생성에서는 무시되고, draw/dispatch 명령에서 바인드 그룹 검증 시 각 바인딩이 변수의 최소 버퍼 바인딩 크기를 만족하는지 확인합니다.

참고: 실행 시점 검증은 이른 검증이 요구되는 다른 바인딩 관련 필드(예: sampleTypeformat)에도 이론적으로 적용 가능하지만, 현재는 파이프라인 생성에서만 검증됩니다. 이러한 실행 시점 검증은 비용이 크거나 불필요하게 복잡할 수 있으므로, 가장 실용적 영향이 큰 minBindingSize에만 적용됩니다.

enum GPUSamplerBindingType {
    "filtering",
    "non-filtering",
    "comparison",
};

dictionary GPUSamplerBindingLayout {
    GPUSamplerBindingType type = "filtering";
};

GPUSamplerBindingLayout 딕셔너리는 다음 멤버를 가집니다:

type, 타입 GPUSamplerBindingType, 기본값 "filtering"

이 바인딩에 연결되는 샘플러가 요구하는 타입을 나타냅니다.

enum GPUTextureSampleType {
    "float",
    "unfilterable-float",
    "depth",
    "sint",
    "uint",
};

dictionary GPUTextureBindingLayout {
    GPUTextureSampleType sampleType = "float";
    GPUTextureViewDimension viewDimension = "2d";
    boolean multisampled = false;
};

GPUTextureBindingLayout 딕셔너리는 다음 멤버를 가집니다:

sampleType, 타입 GPUTextureSampleType, 기본값 "float"

이 바인딩에 연결되는 텍스처 뷰가 요구하는 타입을 나타냅니다.

viewDimension, 타입 GPUTextureViewDimension, 기본값 "2d"

이 바인딩에 연결되는 텍스처 뷰가 요구하는 dimension을 나타냅니다.

multisampled, 타입 boolean, 기본값 false

이 바인딩에 연결되는 텍스처 뷰가 멀티샘플링이어야 하는지 여부를 나타냅니다.

enum GPUStorageTextureAccess {
    "write-only",
    "read-only",
    "read-write",
};

dictionary GPUStorageTextureBindingLayout {
    GPUStorageTextureAccess access = "write-only";
    required GPUTextureFormat format;
    GPUTextureViewDimension viewDimension = "2d";
};

GPUStorageTextureBindingLayout 딕셔너리는 다음 멤버를 가집니다:

access, 타입 GPUStorageTextureAccess, 기본값 "write-only"

이 바인딩의 접근 모드(읽기, 쓰기 가능 여부 등)를 나타냅니다.

format, 타입 GPUTextureFormat

이 바인딩에 연결되는 텍스처 뷰가 요구하는 format을 나타냅니다.

viewDimension, 타입 GPUTextureViewDimension, 기본값 "2d"

이 바인딩에 연결되는 텍스처 뷰가 요구하는 dimension을 나타냅니다.

dictionary GPUExternalTextureBindingLayout {
};

GPUBindGroupLayout 객체는 다음 디바이스 타임라인 속성을 가집니다:

[[entryMap]], 타입 ordered map<GPUSize32, GPUBindGroupLayoutEntry>, 읽기 전용

GPUBindGroupLayout 이 설명하는 GPUBindGroupLayoutEntry들을 가리키는 바인딩 인덱스 맵입니다.

[[dynamicOffsetCount]], 타입 GPUSize32, 읽기 전용

GPUBindGroupLayout 내 동적 오프셋을 가진 버퍼 바인딩 수입니다.

[[exclusivePipeline]], 타입 GPUPipelineBase?, 읽기 전용

GPUBindGroupLayout기본 파이프라인 레이아웃의 일부로 생성된 경우 생성한 파이프라인입니다. null이 아니면 이 GPUBindGroup로 생성한 바인드 그룹은 해당 GPUPipelineBase에서만 사용할 수 있습니다.

createBindGroupLayout(descriptor)

GPUBindGroupLayout를 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createBindGroupLayout(descriptor) 메서드 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUBindGroupLayoutDescriptor 생성할 GPUBindGroupLayout의 설명.

반환값: GPUBindGroupLayout

콘텐츠 타임라인 단계:

  1. descriptor.entries의 각 GPUBindGroupLayoutEntry entry에 대해:

    1. entry.storageTexture 값이 제공됨이라면:

      1. ? 텍스처 포맷 필수 기능 검증entry.storageTexture.formatthis.[[device]]에 대해 수행.

  2. layout! 새 WebGPU 객체 생성(this, GPUBindGroupLayout, descriptor)로 둔다.

  3. this디바이스 타임라인에서 초기화 단계를 실행합니다.

  4. layout을 반환합니다.

디바이스 타임라인 초기화 단계:
  1. 아래 조건 중 하나라도 만족하지 않으면 검증 오류 생성, layout을 무효화하고 반환.

  2. layout.[[descriptor]] 값을 descriptor로 설정합니다.

  3. layout.[[dynamicOffsetCount]] 값을 descriptor에서 buffer제공됨이고, buffer.hasDynamicOffset 값이 true인 entry 수로 설정합니다.

  4. layout.[[exclusivePipeline]] 값을 null로 설정합니다.

  5. descriptor.entries의 각 GPUBindGroupLayoutEntry entry에 대해:

    1. entrylayout.[[entryMap]]entry.binding 키로 삽입합니다.

8.1.2. 호환성

GPUBindGroupLayout 객체 ab는 아래 모든 조건을 만족할 때 그룹 등가(group-equivalent)로 간주합니다.

바인드 그룹 레이아웃이 그룹 등가(group-equivalent)이면 모든 컨텐츠에서 서로 대체하여 사용할 수 있습니다.

8.2. GPUBindGroup

GPUBindGroup 는 리소스 집합을 하나의 그룹으로 묶어서 바인딩하고, 셰이더 단계에서 리소스가 어떻게 사용되는지 정의합니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUBindGroup {
};
GPUBindGroup includes GPUObjectBase;

GPUBindGroup 는 다음 디바이스 타임라인 속성을 가집니다:

[[layout]], 타입 GPUBindGroupLayout, 읽기 전용

GPUBindGroup와 연결된 GPUBindGroupLayout입니다.

[[entries]], 타입 sequence<GPUBindGroupEntry>, 읽기 전용

GPUBindGroup가 기술하는 GPUBindGroupEntry의 집합입니다.

[[usedResources]], 타입 사용 범위(usage scope), 읽기 전용

이 바인드 그룹이 사용하는 버퍼 및 텍스처 서브리소스(subresource)의 집합이며, 각 내부 용도(internal usage) 플래그 리스트와 연결되어 있습니다.

GPUBindGroup bindGroup바인드된 버퍼 범위(bound buffer ranges)list<GPUBufferDynamicOffset> dynamicOffsets가 주어졌을 때 다음과 같이 계산합니다:
  1. result를 새로운 set<(GPUBindGroupLayoutEntry, GPUBufferBinding)>로 둔다.

  2. dynamicOffsetIndex를 0으로 둔다.

  3. bindGroup.[[entries]]에 있는 각 GPUBindGroupEntry bindGroupEntrybindGroupEntry.binding 순으로 정렬하여 반복:

    1. bindGroupLayoutEntrybindGroup.[[layout]].[[entryMap]][bindGroupEntry.binding]로 둔다.

    2. bindGroupLayoutEntry.buffer 값이 제공되지 않았다면, continue.

    3. bound버퍼 바인딩으로 변환(get as buffer binding)(bindGroupEntry.resource)로 둔다.

    4. bindGroupLayoutEntry.buffer.hasDynamicOffset 값이 true이면:

      1. bound.offset 값을 dynamicOffsets[dynamicOffsetIndex]만큼 증가시킨다.

      2. dynamicOffsetIndex를 1 증가시킨다.

    5. 추가 (bindGroupLayoutEntry, bound)를 result에 수행한다.

  4. result를 반환한다.

8.2.1. 바인드 그룹 생성

GPUBindGroupGPUDevice.createBindGroup()로 생성합니다.

dictionary GPUBindGroupDescriptor
         : GPUObjectDescriptorBase {
    required GPUBindGroupLayout layout;
    required sequence<GPUBindGroupEntry> entries;
};

GPUBindGroupDescriptor 딕셔너리는 다음 멤버를 가집니다:

layout, 타입 GPUBindGroupLayout

이 바인드 그룹의 엔트리가 따를 GPUBindGroupLayout입니다.

entries, 타입 sequence<GPUBindGroupEntry>

layout로 기술된 바인딩에 대해 셰이더에 노출할 리소스를 기술하는 엔트리 목록입니다.

typedef (GPUSampler or
         GPUTexture or
         GPUTextureView or
         GPUBuffer or
         GPUBufferBinding or
         GPUExternalTexture) GPUBindingResource;

dictionary GPUBindGroupEntry {
    required GPUIndex32 binding;
    required GPUBindingResource resource;
};

GPUBindGroupEntryGPUBindGroup에 바인딩될 단일 리소스를 기술하며, 다음 멤버를 가집니다:

binding, 타입 GPUIndex32

해당 GPUBindGroup 내 리소스 바인딩의 고유 식별자이며, GPUBindGroupLayoutEntry.binding@binding 속성과 대응됩니다.

resource, 타입 GPUBindingResource

바인딩할 리소스이며, GPUSampler, GPUTexture, GPUTextureView, GPUBuffer, GPUBufferBinding, 또는 GPUExternalTexture일 수 있습니다.

GPUBindGroupEntry 는 다음 디바이스 타임라인 속성을 가집니다:

[[prevalidatedSize]], 타입 boolean

이 바인딩 엔트리가 생성 시점에 버퍼 크기 검증을 거쳤는지 여부입니다.

dictionary GPUBufferBinding {
    required GPUBuffer buffer;
    GPUSize64 offset = 0;
    GPUSize64 size;
};

GPUBufferBinding 은 바인드할 버퍼 및 선택적 범위를 기술하는 리소스이며, 다음 멤버를 가집니다:

buffer, 타입 GPUBuffer

바인드할 GPUBuffer입니다.

offset, 타입 GPUSize64, 기본값 0

buffer 시작점에서부터 바인딩되는 범위의 시작까지의 오프셋(바이트 단위)입니다.

size, 타입 GPUSize64

버퍼 바인딩의 크기(바이트 단위)입니다. 제공되지 않을 경우, offset에서 buffer 끝까지의 범위를 지정합니다.

createBindGroup(descriptor)

GPUBindGroup를 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createBindGroup(descriptor) 메서드 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUBindGroupDescriptor 생성할 GPUBindGroup의 설명.

반환값: GPUBindGroup

콘텐츠 타임라인 단계:

  1. bindGroup! 새 WebGPU 객체 생성(this, GPUBindGroup, descriptor)로 둔다.

  2. this디바이스 타임라인에서 초기화 단계를 실행합니다.

  3. bindGroup을 반환합니다.

디바이스 타임라인 초기화 단계:
  1. limitsthis.[[device]].[[limits]]로 둔다.

  2. 아래 조건 중 하나라도 만족하지 않으면 검증 오류 생성, bindGroup을 무효화하고 반환.

    descriptor.entries의 각 GPUBindGroupEntry bindingDescriptor에 대해:

  3. bindGroup.[[layout]] = descriptor.layout로 설정합니다.

  4. bindGroup.[[entries]] = descriptor.entries로 설정합니다.

  5. bindGroup.[[usedResources]] = {}로 설정합니다.

  6. descriptor.entries의 각 GPUBindGroupEntry bindingDescriptor에 대해:

    1. internalUsagelayoutBinding에 대한 binding usage로 둡니다.

    2. resource가 참조하는 모든 subresource[[usedResources]]internalUsage로 추가합니다.

    3. bindingDescriptor.[[prevalidatedSize]] 값을, layoutBinding에 대해 정의된 binding memberbuffer이고, layoutBinding.buffer.minBindingSize 값이 0이면 false, 아니면 true로 설정합니다.

텍스처 뷰로 변환(get as texture view)(resource)

인자:

반환값: GPUTextureView

  1. Assert resourceGPUTexture 또는 GPUTextureView여야 합니다.

  2. resource가 아래 중 하나라면:

    GPUTexture
    1. resource.createView()를 반환합니다.

    GPUTextureView
    1. resource를 반환합니다.

버퍼 바인딩으로 변환(get as buffer binding)(resource)

인자:

반환값: GPUBufferBinding

  1. Assert resourceGPUBuffer 또는 GPUBufferBinding여야 합니다.

  2. resource가 아래 중 하나라면:

    GPUBuffer
    1. bufferBinding을 새로운 GPUBufferBinding으로 둔다.

    2. bufferBinding.buffer 값을 resource로 설정합니다.

    3. bufferBinding을 반환합니다.

    GPUBufferBinding
    1. resource를 반환합니다.

실질 버퍼 바인딩 크기(effective buffer binding size)(binding)

인자:

반환값: GPUSize64

  1. binding.size 값이 제공되지 않았다면:

    1. max(0, binding.buffer.size - binding.offset)를 반환합니다.

  2. binding.size를 반환합니다.

GPUBufferBinding 객체 ab버퍼 바인딩 메모리 중복(buffer-binding-aliasing)으로 간주되는 경우는 아래 모두가 true일 때입니다:

참고: 이 계산을 할 때, 모든 동적 오프셋은 이미 범위에 적용된 상태입니다.

8.3. GPUPipelineLayout

GPUPipelineLayoutsetBindGroup()을 통해 커맨드 인코딩 시 설정된 모든 GPUBindGroup 객체의 리소스와, GPURenderCommandsMixin.setPipeline 또는 GPUComputePassEncoder.setPipeline으로 설정된 파이프라인의 셰이더 사이의 매핑을 정의합니다.

리소스의 전체 바인딩 주소는 다음 세 가지로 구성됩니다:

  1. 해당 리소스가 보이는 셰이더 단계 마스크

  2. 바인드 그룹 인덱스

  3. 바인딩 번호

이 주소의 구성 요소는 파이프라인의 바인딩 공간으로도 볼 수 있습니다. GPUBindGroup (해당 GPUBindGroupLayout 포함) 는 고정된 바인드 그룹 인덱스에 대한 공간을 담당합니다. 포함된 바인딩은 해당 인덱스에서 셰이더가 사용하는 리소스의 상위 집합이어야 합니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUPipelineLayout {
};
GPUPipelineLayout includes GPUObjectBase;

GPUPipelineLayout 는 다음 디바이스 타임라인 속성을 가집니다:

[[bindGroupLayouts]], 타입 list<GPUBindGroupLayout>, 읽기 전용

생성 시 GPUPipelineLayoutDescriptor.bindGroupLayouts에 지정된 GPUBindGroupLayout 객체들입니다.

참고: 동일한 GPUPipelineLayout을 여러 GPURenderPipeline 또는 GPUComputePipeline 파이프라인에 사용하면, 이들 사이를 전환할 때 UA가 내부적으로 리소스를 재바인딩할 필요가 없음을 보장합니다.

GPUComputePipeline 객체 X는 GPUPipelineLayout.bindGroupLayouts A, B, C로 생성되었습니다. GPUComputePipeline 객체 Y는 GPUPipelineLayout.bindGroupLayouts A, D, C로 생성되었습니다. 커맨드 인코딩 시퀀스에 두 번의 dispatch가 있다고 가정할 때:
  1. setBindGroup(0, ...)

  2. setBindGroup(1, ...)

  3. setBindGroup(2, ...)

  4. setPipeline(X)

  5. dispatchWorkgroups()

  6. setBindGroup(1, ...)

  7. setPipeline(Y)

  8. dispatchWorkgroups()

이 상황에서 두 번째 dispatch를 위해 그룹 슬롯 2를 UA가 다시 바인딩해야 합니다. 이는 GPUPipelineLayout.bindGroupLayouts의 2번 인덱스의 GPUBindGroupLayout 또는 슬롯 2의 GPUBindGroup이 변경되지 않더라도 발생합니다.

참고: GPUPipelineLayout의 권장 사용법은 가장 일반적이고 변경 빈도가 낮은 바인드 그룹을 레이아웃의 "하단"(즉 인덱스 0이나 1)에 배치하는 것입니다. 반대로 바인드 그룹이 draw 호출 사이에 자주 변경될수록 인덱스를 높게 두는 것이 좋습니다. 이 가이드라인은 UA가 draw 호출 사이의 상태 변경을 최소화하여 CPU 오버헤드를 낮출 수 있도록 돕습니다.

8.3.1. 파이프라인 레이아웃 생성

GPUPipelineLayoutGPUDevice.createPipelineLayout()로 생성됩니다.

dictionary GPUPipelineLayoutDescriptor
         : GPUObjectDescriptorBase {
    required sequence<GPUBindGroupLayout?> bindGroupLayouts;
};

GPUPipelineLayoutDescriptor 딕셔너리는 파이프라인에서 사용되는 모든 GPUBindGroupLayout을 정의하며, 다음 멤버를 가집니다:

bindGroupLayouts, 타입 sequence<GPUBindGroupLayout?>

파이프라인에서 사용할 수 있는 GPUBindGroupLayout의 옵션 목록입니다. 각 요소는 GPUShaderModule@group 어트리뷰트에 대응하며, N번째 요소는 @group(N)에 대응합니다.

createPipelineLayout(descriptor)

GPUPipelineLayout를 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createPipelineLayout(descriptor) 메서드 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUPipelineLayoutDescriptor 생성할 GPUPipelineLayout의 설명.

반환값: GPUPipelineLayout

콘텐츠 타임라인 단계:

  1. pl! 새 WebGPU 객체 생성(this, GPUPipelineLayout, descriptor)로 둔다.

  2. this디바이스 타임라인에서 초기화 단계를 실행합니다.

  3. pl을 반환합니다.

디바이스 타임라인 초기화 단계:
  1. limitsthis.[[device]].[[limits]]로 둔다.

  2. bindGroupLayoutslist of null GPUBindGroupLayout로, sizelimits.maxBindGroups와 같은 새 리스트로 둔다.

  3. bindGroupLayoutdescriptor.bindGroupLayouts의 인덱스 i에 대해:

    1. bindGroupLayoutnull이 아니고, bindGroupLayout.[[descriptor]].entries 값이 비어 있지 않으면:

      1. bindGroupLayouts[i]에 bindGroupLayout을 설정합니다.

  4. allEntriesbindGroupLayouts의 각 null이 아닌 bgl에 대해 bgl.[[descriptor]].entries를 연결한 결과로 둔다.

  5. 아래 조건 중 하나라도 만족하지 않으면 검증 오류 생성, pl을 무효화하고 반환.

  6. pl.[[bindGroupLayouts]] 값을 bindGroupLayouts로 설정합니다.

참고:GPUPipelineLayout 객체는 내부 [[bindGroupLayouts]] 시퀀스가 group-equivalentGPUBindGroupLayout 객체를 포함하면 모든 용도에서 등가로 간주됩니다.

8.4. 예시

유니폼 버퍼, 텍스처, 샘플러 바인딩을 기술하는 GPUBindGroupLayout 을 생성합니다. 그리고 GPUBindGroupGPUPipelineLayoutGPUBindGroupLayout을 활용해 생성합니다.
const bindGroupLayout = gpuDevice.createBindGroupLayout({
    entries: [{
        binding: 0,
        visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
        buffer: {}
    }, {
        binding: 1,
        visibility: GPUShaderStage.FRAGMENT,
        texture: {}
    }, {
        binding: 2,
        visibility: GPUShaderStage.FRAGMENT,
        sampler: {}
    }]
});

const bindGroup = gpuDevice.createBindGroup({
    layout: bindGroupLayout,
    entries: [{
        binding: 0,
        resource: { buffer: buffer },
    }, {
        binding: 1,
        resource: texture
    }, {
        binding: 2,
        resource: sampler
    }]
});

const pipelineLayout = gpuDevice.createPipelineLayout({
    bindGroupLayouts: [bindGroupLayout]
});

9. 셰이더 모듈

9.1. GPUShaderModule

[Exposed=(Window, Worker), SecureContext]
interface GPUShaderModule {
    Promise<GPUCompilationInfo> getCompilationInfo();
};
GPUShaderModule includes GPUObjectBase;

GPUShaderModule 은 내부 셰이더 모듈 객체에 대한 참조입니다.

9.1.1. 셰이더 모듈 생성

dictionary GPUShaderModuleDescriptor
         : GPUObjectDescriptorBase {
    required USVString code;
    sequence<GPUShaderModuleCompilationHint> compilationHints = [];
};
code, of type USVString

WGSL 셰이더 모듈을 위한 소스 코드입니다.

compilationHints, of type sequence<GPUShaderModuleCompilationHint>, defaulting to []

GPUShaderModuleCompilationHint들의 목록입니다.

애플리케이션에서 제공하는 모든 힌트는 파이프라인의 엔트리 포인트 하나에 관한 정보를 포함해야 합니다. 이 파이프라인은 결국 해당 엔트리 포인트로부터 생성됩니다.

구현체는 GPUShaderModuleCompilationHint에 포함된 정보를 최대한 활용하여 createShaderModule() 내에서 컴파일을 최대한 많이 수행해야 합니다.

타입 검사 외에는 이러한 힌트가 어떤 방식으로든 검증되지 않습니다.

NOTE:
compilationHints에 정보를 제공해도 성능을 제외한 관찰 가능한 효과는 없습니다. 생성되지 않는 파이프라인에 대한 힌트를 제공하면 성능에 악영향을 줄 수 있습니다.

하나의 셰이더 모듈은 여러 엔트리 포인트를 가질 수 있으며, 여러 파이프라인이 하나의 셰이더 모듈로부터 생성될 수 있기 때문에, 구현체가 createShaderModule()에서 한 번에 가능한 많은 컴파일을 수행하는 것이 createComputePipeline() 또는 createRenderPipeline()을 여러 번 호출하는 것보다 더 성능이 좋을 수 있습니다.

힌트는 명시적으로 이름이 지정된 엔트리 포인트에만 적용됩니다. GPUProgrammableStage.entryPoint와는 다르게, 모듈에 엔트리 포인트가 하나만 있더라도 기본값이 없습니다.

Note: 힌트는 관찰 가능한 방식으로 검증되지 않지만, 사용자 에이전트는 식별 가능한 오류(예: 알 수 없는 엔트리 포인트 이름이나 호환되지 않는 파이프라인 레이아웃 등)를 개발자에게 노출할 수 있습니다. 예를 들어 브라우저 개발자 콘솔에서 표시될 수 있습니다.

createShaderModule(descriptor)

GPUShaderModule을 생성합니다.

호출 대상: GPUDevice this.

인수:

GPUDevice.createShaderModule(descriptor) 메서드의 인수.
파라미터 타입 Nullable Optional 설명
descriptor GPUShaderModuleDescriptor 생성할 GPUShaderModule에 대한 설명입니다.

반환값: GPUShaderModule

콘텐츠 타임라인 단계:

  1. sm! 새로운 WebGPU 객체 생성(this, GPUShaderModule, descriptor)로 설정합니다.

  2. this디바이스 타임라인에서 초기화 단계를 수행합니다.

  3. sm을 반환합니다.

디바이스 타임라인 초기화 단계:
  1. error를 WGSL 소스 descriptor.code셰이더 모듈 생성에서 발생한 오류로 설정하거나, 오류가 없으면 null로 설정합니다.

  2. 다음 요구사항 중 하나라도 만족하지 않으면, 유효성 검사 오류 생성, 무효화 sm, 그리고 반환합니다.

    Note: 분류되지 않은 오류는 셰이더 모듈 생성에서 발생할 수 없습니다. 구현체가 셰이더 모듈 생성 중에 이러한 오류를 감지하면, 셰이더 모듈이 유효한 것처럼 동작해야 하며 오류는 파이프라인 생성 시까지 지연되어야 합니다.

NOTE:
사용자 에이전트는 여기서 발생한 유효성 검사 오류의 message 텍스트에 상세 컴파일러 오류 메시지나 셰이더 텍스트를 포함하지 않아야 합니다: 이러한 정보는 getCompilationInfo()를 통해 접근할 수 있습니다. 사용자 에이전트는 개발자가 더 쉽게 디버깅할 수 있도록 사람이 읽을 수 있는 형식의 오류 세부 정보를 제공해야 하며 (예: 브라우저 개발자 콘솔의 경고로, 전체 셰이더 소스를 펼쳐볼 수 있도록 표시).

셰이더 컴파일 오류는 현행 표준 애플리케이션에서는 드물어야 하므로, 사용자 에이전트는 오류 처리(GPU error scopeuncapturederror 이벤트 핸들러)에 관계없이 개발자에게 오류를 표시할 수 있습니다. 그렇지 않다면, 사람이 읽을 수 있는 오류 세부 정보를 액세스할 수 있는 별도의 방법을 제공하고 문서화해야 하며, 예를 들어 오류를 무조건적으로 표시하는 체크박스를 추가하거나, GPUCompilationInfo 객체를 콘솔에 로깅할 때 사람이 읽을 수 있는 세부 정보를 표시해야 합니다.

WGSL 코드에서 GPUShaderModule을 생성:
// 뷰포트 전체를 빨간색으로 채우는 간단한 버텍스 및 프래그먼트 셰이더 쌍 예시입니다.
const shaderSource = `
    var<private> pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
        vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));

    @vertex
    fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> @builtin(position) vec4<f32> {
        return vec4(pos[vertexIndex], 1.0, 1.0);
    }

    @fragment
    fn fragmentMain() -> @location(0) vec4<f32> {
        return vec4(1.0, 0.0, 0.0, 1.0);
    }
`;

const shaderModule = gpuDevice.createShaderModule({
    code: shaderSource,
});
9.1.1.1. 셰이더 모듈 컴파일 힌트

셰이더 모듈 컴파일 힌트는 선택적으로 제공하는 추가 정보로서, 특정 GPUShaderModule 엔트리 포인트가 향후 어떻게 사용될지에 대한 의도를 나타냅니다. 일부 구현체에서는 이 정보가 셰이더 모듈을 더 빨리 컴파일하는 데 도움이 되어, 성능이 향상될 수 있습니다.

dictionary GPUShaderModuleCompilationHint {
    required USVString entryPoint;
    (GPUPipelineLayout or GPUAutoLayoutMode) layout;
};
layout, 타입 (GPUPipelineLayout or GPUAutoLayoutMode)

GPUPipelineLayoutGPUShaderModule이 이후 createComputePipeline() 또는 createRenderPipeline() 호출에서 사용될 수 있는 파이프라인 레이아웃입니다. "auto"로 설정되면, 해당 힌트와 연관된 엔트리 포인트에 대해 기본 파이프라인 레이아웃이 사용됩니다.

NOTE:
가능하다면 작성자는 createShaderModule()createComputePipeline() / createRenderPipeline()에 동일한 정보를 제공하는 것이 좋습니다.

애플리케이션이 createShaderModule() 호출 시 힌트 정보를 제공할 수 없다면, 호출을 지연시키기보다는 compilationHints 시퀀스 또는 GPUShaderModuleCompilationHint의 멤버에서 알 수 없는 정보를 생략하는 것이 일반적으로 더 바람직합니다. 해당 정보를 생략하면 컴파일이 createComputePipeline() / createRenderPipeline()까지 지연될 수 있습니다.

작성자가 createShaderModule()에 전달한 힌트 정보가 이후 createComputePipeline() / createRenderPipeline()에 동일 모듈로 전달될 정보와 일치하지 않을 가능성이 있다면, 그 정보를 createShaderModule()에 전달하지 않는 것이 좋습니다. 일치하지 않는 정보를 전달하면 불필요한 컴파일이 발생할 수 있습니다.

9.1.2. 셰이더 모듈 컴파일 정보

enum GPUCompilationMessageType {
    "error",
    "warning",
    "info",
};

[Exposed=(Window, Worker), Serializable, SecureContext]
interface GPUCompilationMessage {
    readonly attribute DOMString message;
    readonly attribute GPUCompilationMessageType type;
    readonly attribute unsigned long long lineNum;
    readonly attribute unsigned long long linePos;
    readonly attribute unsigned long long offset;
    readonly attribute unsigned long long length;
};

[Exposed=(Window, Worker), Serializable, SecureContext]
interface GPUCompilationInfo {
    readonly attribute FrozenArray<GPUCompilationMessage> messages;
};

GPUCompilationMessageGPUShaderModule 컴파일러에서 생성한 정보성, 경고 또는 오류 메시지입니다. 메시지는 개발자가 셰이더 code 문제를 진단하는 데 도움이 되도록 사람이 읽을 수 있도록 작성됩니다. 각 메시지는 셰이더 코드 내의 한 지점, 코드의 부분 문자열, 또는 코드의 특정 지점과 연관되지 않을 수도 있습니다.

GPUCompilationMessage는 다음과 같은 속성을 가집니다:

message, 타입 DOMString, 읽기 전용

이 컴파일 메시지에 대한 사람이 읽을 수 있고 지역화 가능한 텍스트입니다.

Note: message언어 및 방향 정보에 대한 모범 사례를 따라야 합니다. 이는 향후 표준이 등장할 경우 해당 문자열의 언어 및 방향 메타데이터 보고 방식도 포함됩니다.

Editorial note: 현재로서는 레거시 API와 호환성 및 일관성을 제공하는 언어/방향 권고가 없으나, 향후 제공될 경우 공식적으로 도입하세요.

type, 타입 GPUCompilationMessageType, 읽기 전용

메시지의 심각도 수준입니다.

type"error"이면, 셰이더 생성 오류에 해당합니다.

lineNum, 타입 unsigned long long, 읽기 전용

메시지가 대응하는 셰이더 code의 줄 번호입니다. 1부터 시작하며, 1이면 셰이더 code의 첫 번째 줄을 의미합니다. 줄은 줄 바꿈으로 구분됩니다.

메시지가 부분 문자열에 대응하는 경우, 해당 부분 문자열이 시작되는 줄을 나타냅니다. 메시지가 셰이더 code의 특정 지점을 참조하지 않으면 0이 됩니다.

linePos, 타입 unsigned long long, 읽기 전용

셰이더 lineNum 줄의 시작부터 메시지가 대응하는 지점 또는 부분 문자열까지의 UTF-16 코드 유닛 오프셋입니다. 1부터 시작하며, linePos1이면 해당 줄의 첫 번째 코드 유닛을 의미합니다.

메시지가 부분 문자열에 대응하는 경우, 그 부분 문자열의 첫 번째 UTF-16 코드 유닛을 나타냅니다. 메시지가 셰이더 code의 특정 지점을 참조하지 않으면 0이 됩니다.

offset, 타입 unsigned long long, 읽기 전용

셰이더 code의 시작부터 메시지가 대응하는 지점 또는 부분 문자열까지의 UTF-16 코드 유닛 오프셋입니다. lineNumlinePos와 동일한 위치를 참조해야 합니다. 메시지가 셰이더 code의 특정 지점을 참조하지 않으면 0이 됩니다.

length, 타입 unsigned long long, 읽기 전용

메시지가 대응하는 부분 문자열의 UTF-16 코드 유닛 개수입니다. 메시지가 부분 문자열과 연관되지 않으면 length는 0이어야 합니다.

Note: GPUCompilationMessage.lineNumGPUCompilationMessage.linePos는 대부분의 경우 사람이 읽을 수 있는 메시지를 출력하여 많은 텍스트 에디터에서 표시되는 줄 및 열 번호와 일치시키는 용도로 사용되므로 1부터 시작합니다.

Note: GPUCompilationMessage.offsetGPUCompilationMessage.length는 셰이더 code의 부분 문자열을 substr()로 추출할 때 적합합니다. 메시지가 대응하는 부분 문자열을 얻을 수 있습니다.

getCompilationInfo()

GPUShaderModule의 컴파일 중에 생성된 모든 메시지를 반환합니다.

메시지의 위치, 순서 및 내용은 구현 정의입니다. 특히, 메시지는 lineNum 기준으로 정렬되어 있지 않을 수 있습니다.

호출 대상: GPUShaderModule this

반환값: Promise<GPUCompilationInfo>

콘텐츠 타임라인 단계:

  1. contentTimeline을 현재 콘텐츠 타임라인으로 설정합니다.

  2. promise새로운 promise로 설정합니다.

  3. this디바이스 타임라인에서 동기화 단계를 수행합니다.

  4. promise를 반환합니다.

디바이스 타임라인 동기화 단계:
  1. eventthis에 대한 셰이더 모듈 생성의 성공 또는 실패 시 발생하도록 설정합니다.

  2. 타임라인 이벤트 수신 eventthis.[[device]]에서 수행하며, 이후 단계는 contentTimeline에서 처리합니다.

콘텐츠 타임라인 단계:
  1. info를 새로운 GPUCompilationInfo로 설정합니다.

  2. messagesthis셰이더 모듈 생성 중에 생성된 오류, 경고 또는 정보 메시지의 목록으로 설정하거나, 디바이스가 손실된 경우 빈 목록 []로 설정합니다.

  3. messages의 각 message에 대해:

    1. m을 새로운 GPUCompilationMessage로 설정합니다.

    2. m.messagemessage의 텍스트를 설정합니다.

    3. 만약 message셰이더 생성 오류라면:

      m.type"error"로 설정합니다.

      경고라면:

      m.type"warning"로 설정합니다.

      그 외의 경우:

      m.type"info"로 설정합니다.

    4. 만약 message가 셰이더 code의 특정 부분 문자열이나 위치와 연관되어 있다면:
      1. m.lineNum을 메시지가 참조하는 첫 번째 줄의 1 기반 번호로 설정합니다.

      2. m.linePos를 메시지가 참조하는 m.lineNum의 첫 번째 UTF-16 코드 유닛의 1 기반 번호로 설정하거나, message가 전체 줄을 참조한다면 1로 설정합니다.

      3. m.offset을 셰이더의 시작부터 부분 문자열 또는 위치까지의 UTF-16 코드 유닛 수로 설정합니다.

      4. m.lengthmessage가 참조하는 부분 문자열의 UTF-16 코드 유닛 길이로 설정하거나, message가 위치만 참조한다면 0으로 설정합니다.

      그 외의 경우:
      1. m.lineNum0으로 설정합니다.

      2. m.linePos0으로 설정합니다.

      3. m.offset0으로 설정합니다.

      4. m.length0으로 설정합니다.

    5. info.messagesm을 추가합니다.

  4. promiseinfo로 resolve합니다.

10. 파이프라인

파이프라인GPUComputePipeline 또는 GPURenderPipeline이 될 수 있으며, 바인딩과 버텍스 버퍼 형태의 입력 데이터를 처리하여 출력 렌더 타깃의 색상 등과 같은 출력을 생성하는 GPU 하드웨어, 드라이버, 그리고 사용자 에이전트가 결합된 전체 기능을 나타냅니다.

구조적으로 파이프라인은 프로그래머블 스테이지(셰이더)와 블렌딩 모드 등과 같은 고정 기능 상태의 시퀀스로 구성됩니다.

Note: 내부적으로, 타깃 플랫폼에 따라 드라이버가 일부 고정 기능 상태를 셰이더 코드로 변환하여 사용자가 제공한 셰이더와 함께 연결할 수 있습니다. 이 연결이 객체가 전체로 생성되는 이유 중 하나입니다.

이 결합 상태는 하나의 객체로 생성됩니다 (GPUComputePipeline 또는 GPURenderPipeline) 그리고 하나의 명령으로 전환됩니다 (GPUComputePassEncoder.setPipeline() 또는 GPURenderCommandsMixin.setPipeline() 각각).

파이프라인을 생성하는 방법은 두 가지가 있습니다:

즉시 파이프라인 생성

createComputePipeline()createRenderPipeline() 은 바로 패스 인코더에서 사용할 수 있는 파이프라인 객체를 반환합니다.

이 과정이 실패하면 파이프라인 객체는 무효화되고 호출은 유효성 검사 오류 또는 내부 오류를 생성합니다.

Note: 핸들 객체가 즉시 반환되지만 실제 파이프라인 생성은 동기적이지 않습니다. 파이프라인 생성이 오래 걸릴 경우, 디바이스 타임라인에서 생성 호출과 최초 setPipeline() 실행 사이, 해당 GPUCommandEncoder 또는 GPURenderBundleEncoderfinish() 시점, 그리고 해당 GPUCommandBuffersubmit() 호출 시점 중 하나에서 스톨이 발생할 수 있습니다. 이 지점은 명시되지 않지만, 가장 가능성 높은 시점입니다.

비동기 파이프라인 생성

createComputePipelineAsync()createRenderPipelineAsync() 는 파이프라인 생성이 완료되면 파이프라인 객체로 resolve되는 Promise를 반환합니다.

실패 시 PromiseGPUPipelineError로 reject됩니다.

GPUPipelineError는 파이프라인 생성 실패를 설명합니다.

[Exposed=(Window, Worker), SecureContext, Serializable]
interface GPUPipelineError : DOMException {
    constructor(optional DOMString message = "", GPUPipelineErrorInit options);
    readonly attribute GPUPipelineErrorReason reason;
};

dictionary GPUPipelineErrorInit {
    required GPUPipelineErrorReason reason;
};

enum GPUPipelineErrorReason {
    "validation",
    "internal",
};

GPUPipelineError 생성자:

constructor()
인수:
GPUPipelineError.constructor() 메서드의 인수.
파라미터 타입 Nullable Optional 설명
message DOMString 기본 DOMException의 오류 메시지입니다.
options GPUPipelineErrorInit GPUPipelineError에 특화된 옵션입니다.

콘텐츠 타임라인 단계:

  1. this.name"GPUPipelineError"로 설정합니다.

  2. this.messagemessage로 설정합니다.

  3. this.reasonoptions.reason으로 설정합니다.

GPUPipelineError 는 다음과 같은 속성을 가집니다:

reason, 타입 GPUPipelineErrorReason, 읽기 전용

파이프라인 생성 중 발생한 오류의 종류를 슬롯 기반 attribute로 노출하는 읽기 전용 속성입니다. GPUPipelineErrorReason:

GPUPipelineError 객체는 직렬화 가능한 객체입니다.

valueserialized가 주어질 때, 직렬화 단계는 다음과 같습니다:
  1. DOMException직렬화 단계valueserialized를 인수로 실행합니다.

valueserialized가 주어질 때, 역직렬화 단계는 다음과 같습니다:
  1. DOMException역직렬화 단계valueserialized를 인수로 실행합니다.

10.1. 기본 파이프라인

enum GPUAutoLayoutMode {
    "auto",
};

dictionary GPUPipelineDescriptorBase
         : GPUObjectDescriptorBase {
    required (GPUPipelineLayout or GPUAutoLayoutMode) layout;
};
layout, 타입 (GPUPipelineLayout or GPUAutoLayoutMode)

이 파이프라인의 GPUPipelineLayout 또는 파이프라인 레이아웃을 자동으로 생성하려면 "auto"를 사용합니다.

Note: "auto"가 사용되면 해당 파이프라인은 다른 파이프라인과 GPUBindGroup을 공유할 수 없습니다.

interface mixin GPUPipelineBase {
    [NewObject] GPUBindGroupLayout getBindGroupLayout(unsigned long index);
};

GPUPipelineBase 는 다음 디바이스 타임라인 속성을 가집니다:

[[layout]], 타입 GPUPipelineLayout

this와 함께 사용할 수 있는 리소스의 레이아웃 정의입니다.

GPUPipelineBase 는 다음과 같은 메서드를 가집니다:

getBindGroupLayout(index)

index에 있는 GPUPipelineBaseGPUBindGroupLayout에 호환되는 GPUBindGroupLayout을 반환합니다.

호출 대상: GPUPipelineBase this

인수:

GPUPipelineBase.getBindGroupLayout(index) 메서드의 인수.
파라미터 타입 Nullable Optional 설명
index unsigned long 파이프라인 레이아웃의 [[bindGroupLayouts]] 시퀀스의 인덱스입니다.

반환값: GPUBindGroupLayout

콘텐츠 타임라인 단계:

  1. layout을 새로운 GPUBindGroupLayout 객체로 설정합니다.

  2. this디바이스 타임라인에서 초기화 단계를 수행합니다.

  3. layout을 반환합니다.

디바이스 타임라인 초기화 단계:
  1. limitsthis.[[device]].[[limits]]로 설정합니다.

  2. 다음 조건 중 하나라도 만족하지 않으면 유효성 검사 오류 생성, 무효화 layout 그리고 반환합니다.

  3. layoutthis.[[layout]].[[bindGroupLayouts]][index]의 복사본으로 초기화합니다.

    Note: GPUBindGroupLayout 은 항상 값으로만 사용되며, 참조로 사용되지 않으므로 이는 같은 내부 객체를 새로운 WebGPU 인터페이스로 반환하는 것과 동일합니다. 새로운 GPUBindGroupLayout WebGPU 인터페이스가 매번 반환되며, 이는 콘텐츠 타임라인디바이스 타임라인 간의 왕복을 피하기 위함입니다.

10.1.1. 기본 파이프라인 레이아웃

GPUPipelineBase 객체가 layout"auto"로 설정하여 생성된 경우, 기본 레이아웃이 생성되어 대신 사용됩니다.

Note: 기본 레이아웃은 단순한 파이프라인에 편의를 위해 제공되지만, 대부분의 경우 명시적 레이아웃 사용을 권장합니다. 기본 레이아웃에서 생성된 바인드 그룹은 다른 파이프라인과 함께 사용할 수 없으며, 셰이더를 변경하면 기본 레이아웃의 구조가 바뀌어 바인드 그룹 생성 오류가 발생할 수 있습니다.

GPUPipelineBase pipeline을 위한 기본 파이프라인 레이아웃을 생성하려면, 다음 디바이스 타임라인 단계를 실행하세요:

  1. groupCount를 0으로 설정합니다.

  2. groupDescsdevice.[[limits]].maxBindGroups 개의 새로운 GPUBindGroupLayoutDescriptor 객체 시퀀스로 설정합니다.

  3. groupDescs의 각 groupDesc에 대해:

    1. groupDesc.entries를 빈 시퀀스로 설정합니다.

  4. pipeline을 생성할 때 사용된 descriptor의 각 GPUProgrammableStage stageDesc에 대해:

    1. shaderStagepipeline에서 stageDesc가 사용되는 셰이더 스테이지의 GPUShaderStageFlags로 설정합니다.

    2. entryPointget the entry point(shaderStage, stageDesc)로 설정합니다. Assert entryPointnull이 아님을 확인합니다.

    3. entryPoint정적으로 사용하는 각 리소스 resource에 대해:

      1. groupresource의 "group" decoration으로 설정합니다.

      2. bindingresource의 "binding" decoration으로 설정합니다.

      3. entry를 새로운 GPUBindGroupLayoutEntry로 설정합니다.

      4. entry.bindingbinding으로 설정합니다.

      5. entry.visibilityshaderStage로 설정합니다.

      6. resource가 샘플러 바인딩이면:

        1. samplerLayout을 새로운 GPUSamplerBindingLayout로 설정합니다.

        2. entry.samplersamplerLayout으로 설정합니다.

      7. resource가 비교 샘플러 바인딩이면:

        1. samplerLayout을 새로운 GPUSamplerBindingLayout로 설정합니다.

        2. samplerLayout.type"comparison"으로 설정합니다.

        3. entry.samplersamplerLayout으로 설정합니다.

      8. resource가 버퍼 바인딩이면:

        1. bufferLayout을 새로운 GPUBufferBindingLayout로 설정합니다.

        2. bufferLayout.minBindingSizeresource최소 버퍼 바인딩 크기로 설정합니다.

        3. resource가 read-only storage buffer이면:

          1. bufferLayout.type"read-only-storage"로 설정합니다.

        4. resource가 storage buffer이면:

          1. bufferLayout.type"storage"로 설정합니다.

        5. entry.bufferbufferLayout으로 설정합니다.

      9. resource가 샘플링된 텍스처 바인딩이면:

        1. textureLayout을 새로운 GPUTextureBindingLayout로 설정합니다.

        2. resource가 깊이 텍스처 바인딩이면:

          그 외 resource의 샘플 타입이 다음과 같으면:

          f32stageDesc에서 샘플러를 함께 사용하는 texture builtin 함수 호출에 resource정적으로 사용되면

          textureLayout.sampleType"float"로 설정합니다.

          f32 그 외

          textureLayout.sampleType"unfilterable-float"로 설정합니다.

          i32

          textureLayout.sampleType"sint"로 설정합니다.

          u32

          textureLayout.sampleType"uint"로 설정합니다.

        3. textureLayout.viewDimensionresource의 dimension으로 설정합니다.

        4. resource가 멀티샘플 텍스처면:

          1. textureLayout.multisampledtrue로 설정합니다.

        5. entry.texturetextureLayout으로 설정합니다.

      10. resource가 storage texture 바인딩이면:

        1. storageTextureLayout을 새로운 GPUStorageTextureBindingLayout로 설정합니다.

        2. storageTextureLayout.formatresource의 format으로 설정합니다.

        3. storageTextureLayout.viewDimensionresource의 dimension으로 설정합니다.

        4. access 모드가 다음과 같으면:

          read

          textureLayout.access"read-only"로 설정합니다.

          write

          textureLayout.access"write-only"로 설정합니다.

          read_write

          textureLayout.access"read-write"로 설정합니다.

        5. entry.storageTexturestorageTextureLayout으로 설정합니다.

      11. groupCount를 max(groupCount, group + 1)로 설정합니다.

      12. groupDescs[group]에 binding 값이 bindingpreviousEntry가 있으면:

        1. entrypreviousEntryvisibility가 다르면:

          1. entry.visibility 에 설정된 비트를 previousEntry.visibility 에 추가합니다.

        2. resource가 버퍼 바인딩이고 entrypreviousEntry보다 더 큰 buffer.minBindingSize 값을 가지면:

          1. previousEntry.buffer.minBindingSizeentry.buffer.minBindingSize로 설정합니다.

        3. resource가 샘플링된 텍스처 바인딩이고 entrytexture.sampleTypepreviousEntry와 다르며, 두 entrypreviousEntry 모두 texture.sampleType"float" 또는 "unfilterable-float"이면:

          1. previousEntry.texture.sampleType"float"로 설정합니다.

        4. 그 외 entrypreviousEntry간에 다른 속성이 있으면:

          1. null을 반환합니다 (파이프라인 생성이 실패하게 됨).

        5. resource가 storage texture 바인딩이고, entry.storageTexture.access"read-write"이고, previousEntry.storageTexture.access"write-only"이며, previousEntry.storageTexture.formatSTORAGE_BINDING"read-write"와 호환된다면:

          1. previousEntry.storageTexture.access"read-write"로 설정합니다.

      13. 그 외의 경우

        1. entrygroupDescs[group]에 추가합니다.

  5. groupLayouts를 새로운 리스트로 설정합니다.

  6. 0부터 groupCount - 1까지의 각 i에 대해:

    1. groupDescgroupDescs[i]로 설정합니다.

    2. bindGroupLayoutdevice.createBindGroupLayout()(groupDesc) 호출 결과로 설정합니다.

    3. bindGroupLayout.[[exclusivePipeline]]pipeline으로 설정합니다.

    4. bindGroupLayoutgroupLayouts에 추가합니다.

  7. desc를 새로운 GPUPipelineLayoutDescriptor로 설정합니다.

  8. desc.bindGroupLayoutsgroupLayouts로 설정합니다.

  9. device.createPipelineLayout()(desc)를 반환합니다.

10.1.2. GPUProgrammableStage

GPUProgrammableStage는 사용자가 제공한 GPUShaderModule에서 파이프라인의 프로그래머블 스테이지 중 하나를 제어하는 진입점을 설명합니다. 엔트리 포인트 이름은 WGSL 식별자 비교 규칙을 따릅니다.

dictionary GPUProgrammableStage {
    required GPUShaderModule module;
    USVString entryPoint;
    record<USVString, GPUPipelineConstantValue> constants = {};
};

typedef double GPUPipelineConstantValue; // WGSL의 bool, f32, i32, u32, 그리고 f16(활성화된 경우)을 나타낼 수 있음.

GPUProgrammableStage는 다음 멤버를 가집니다:

module, 타입 GPUShaderModule

이 프로그래머블 스테이지가 실행할 코드를 포함하는 GPUShaderModule입니다.

entryPoint, 타입 USVString

이 스테이지가 작업을 수행할 때 사용할 module 내 함수의 이름입니다.

NOTE: entryPoint 딕셔너리 멤버는 필수가 아니기 때문에, GPUProgrammableStage를 사용하는 메서드는 어떤 엔트리 포인트를 참조하는지 결정하기 위해 "get the entry point" 알고리즘을 사용해야 합니다.

constants, 타입 record<USVString, GPUPipelineConstantValue>, 기본값은 {}

셰이더 모듈 module에 있는 파이프라인 오버라이드 가능 상수들의 값을 지정합니다.

파이프라인 오버라이드 가능 상수는 하나의 파이프라인 오버라이드 상수 식별자 문자열로 고유하게 식별되며, 선언 시 파이프라인 상수 ID를 명시했다면 그 값, 그렇지 않으면 상수의 식별자 이름을 사용합니다.

각 키-값 쌍의 키는 해당 상수의 식별자 문자열과 같아야 하며, 비교는 WGSL 식별자 비교 규칙에 따라 수행합니다. 파이프라인이 실행될 때 그 상수는 지정한 값을 갖게 됩니다.

값은 GPUPipelineConstantValue로 지정하며, double입니다. 파이프라인 오버라이드 가능 상수의 WGSL 타입(bool/i32/u32/f32/f16)로 변환됩니다. 변환에 실패하면 유효성 검사 오류가 발생합니다.

WGSL에서 정의된 파이프라인 오버라이드 가능 상수 예시:
@id(0)      override has_point_light: bool = true;  // 알고리즘 제어.
@id(1200)   override specular_param: f32 = 2.3;     // 숫자 제어.
@id(1300)   override gain: f32;                     // 반드시 오버라이드 필요.
            override width: f32 = 0.0;              // API 레벨에서 지정
                                                    //   이름 "width" 사용.
            override depth: f32;                    // API 레벨에서 지정
                                                    //   이름 "depth" 사용.
                                                    //   반드시 오버라이드 필요.
            override height = 2 * depth;            // 기본값은
                                                    // (API에서 지정하지 않으면),
                                                    // 다른 오버라이드 가능 상수에 따라 결정됨.

기본값이 없는 오버라이드 필수 상수만 제공한 JS 코드 예시:

{
    // ...
    constants: {
        1300: 2.0,  // "gain"
        depth: -1,  // "depth"
    }
}

모든 상수 오버라이드 JS 코드 예시:

{
    // ...
    constants: {
        0: false,   // "has_point_light"
        1200: 3.0,  // "specular_param"
        1300: 2.0,  // "gain"
        width: 20,  // "width"
        depth: -1,  // "depth"
        height: 15, // "height"
    }
}
GPUShaderStage stage, GPUProgrammableStage descriptor에 대해 엔트리 포인트 가져오기를 실행하려면, 다음 디바이스 타임라인 단계를 수행하세요:
  1. 만약 descriptor.entryPoint제공된 경우:

    1. descriptor.moduledescriptor.entryPoint와 이름이 같고, 셰이더 스테이지가 stage와 같은 엔트리 포인트가 있으면 그 엔트리 포인트를 반환합니다.

      그렇지 않으면 null을 반환합니다.

    그 외의 경우:

    1. descriptor.module에 셰이더 스테이지가 stage인 엔트리 포인트가 정확히 하나만 있으면 그 엔트리 포인트를 반환합니다.

      그렇지 않으면 null을 반환합니다.

GPUProgrammableStage 유효성 검사(stage, descriptor, layout, device)

인수:

아래 단계의 모든 요구사항을 반드시 만족해야 합니다. 하나라도 만족하지 않으면 false를 반환하고, 모두 만족하면 true를 반환합니다.

  1. descriptor.moduledevice사용 가능(valid to use with) 상태여야 합니다.

  2. entryPoint엔트리 포인트 가져오기(stage, descriptor)로 설정합니다.

  3. entryPointnull이 아니어야 합니다.

  4. entryPoint정적으로 사용하는 각 binding에 대해:

  5. 루트 entryPoint에 있는 셰이더 스테이지 내 함수들의 모든 texture 내장 함수 호출에 대해, 샘플링된 텍스처(sampled texture) 또는 depth texture 타입의 textureBinding과, sampler 타입(단, sampler_comparison 제외)의 samplerBinding을 함께 사용할 때:

    1. texturetextureBinding에 해당하는 GPUBindGroupLayoutEntry로 설정합니다.

    2. samplersamplerBinding에 해당하는 GPUBindGroupLayoutEntry로 설정합니다.

    3. sampler.type"filtering"인 경우, texture.sampleType은 반드시 "float"여야 합니다.

    Note: "comparison" 샘플러는 "depth" 텍스처와만 사용할 수 있습니다. WGSL texture_depth_* 바인딩에 연결할 수 있는 유일한 텍스처 타입입니다.

  6. descriptor.constants의 각 keyvalue에 대해:

    1. key는 반드시 셰이더 모듈 descriptor.module에 정의된 파이프라인 오버라이드 가능 상수 중 하나의 식별자 문자열과 같아야 하며, 비교는 WGSL 식별자 비교 규칙을 따릅니다. 파이프라인 오버라이드 가능 상수는 entryPoint정적으로 사용될 필요는 없습니다. 그 상수의 타입을 T라 합니다.

    2. IDL 값 valueWGSL 타입 T로 변환할 때 TypeError가 throw되면 안 됩니다.

  7. entryPoint파이프라인 오버라이드 상수 식별자 문자열 key정적으로 사용되는 모든 경우:

  8. 파이프라인 생성 프로그램 오류[WGSL] 명세의 규칙에 따라 발생하면 안 됩니다.

셰이더 바인딩 유효성 검사(variable, layout)

인수:

bindGroup을 바인드 그룹 인덱스로, bindIndex를 바인딩 인덱스로, 셰이더 바인딩 선언 variable에서 얻어옵니다.

아래 조건을 모두 만족하면 true를 반환합니다:

버퍼 바인딩 변수 var최소 버퍼 바인딩 크기는 다음과 같이 계산됩니다:
  1. T저장 타입으로 설정합니다.

  2. T런타임 크기 배열이거나, 런타임 크기 배열을 포함하고 있다면, 해당 array<E>array<E, 1>로 대체합니다.

    Note: 이렇게 하면 항상 한 개의 요소를 위한 메모리가 확보되어, 배열 인덱스를 배열 길이에 맞게 클램프하여 인-메모리 접근이 가능하게 됩니다.

  3. SizeOf(T)를 반환합니다.

Note: 이 하한을 강제하면 버퍼 변수로 읽고 쓸 때 항상 버퍼의 경계 내 메모리 위치만 접근하도록 보장합니다.

리소스 바인딩, 파이프라인 오버라이드 가능 상수, 셰이더 스테이지 입력 또는 셰이더 스테이지 출력은 엔트리 포인트에 대해 해당 셰이더 스테이지 인터페이스에 존재하면 정적으로 사용됨으로 간주합니다.

10.2. GPUComputePipeline

GPUComputePipeline파이프라인의 한 종류로서, 컴퓨트 셰이더 스테이지를 제어하며, GPUComputePassEncoder에서 사용할 수 있습니다.

컴퓨트 입력과 출력은 모두 지정된 GPUPipelineLayout에 따라 바인딩에 포함됩니다. 출력은 buffer 바인딩(타입 "storage"), storageTexture 바인딩(타입 "write-only" 또는 "read-write")에 해당합니다.

컴퓨트 파이프라인의 스테이지:

  1. 컴퓨트 셰이더

[Exposed=(Window, Worker), SecureContext]
interface GPUComputePipeline {
};
GPUComputePipeline includes GPUObjectBase;
GPUComputePipeline includes GPUPipelineBase;

10.2.1. 컴퓨트 파이프라인 생성

GPUComputePipelineDescriptor는 컴퓨트 파이프라인을 설명합니다. 자세한 내용은 § 23.1 컴퓨팅을 참고하세요.

dictionary GPUComputePipelineDescriptor
         : GPUPipelineDescriptorBase {
    required GPUProgrammableStage compute;
};

GPUComputePipelineDescriptor는 다음 멤버를 가집니다:

compute, 타입 GPUProgrammableStage

파이프라인의 컴퓨트 셰이더 엔트리 포인트를 설명합니다.

createComputePipeline(descriptor)

즉시 파이프라인 생성을 통해 GPUComputePipeline을 생성합니다.

호출 대상: GPUDevice this.

인수:

GPUDevice.createComputePipeline(descriptor) 메서드의 인수.
파라미터 타입 Nullable Optional 설명
descriptor GPUComputePipelineDescriptor 생성할 GPUComputePipeline에 대한 설명.

반환값: GPUComputePipeline

콘텐츠 타임라인 단계:

  1. pipeline! 새로운 WebGPU 객체 생성(this, GPUComputePipeline, descriptor)로 설정합니다.

  2. this디바이스 타임라인에서 초기화 단계를 수행합니다.

  3. pipeline을 반환합니다.

디바이스 타임라인 초기화 단계:
  1. layoutpipeline에 대해 기본 파이프라인 레이아웃으로 설정합니다. 단, descriptor.layout"auto"인 경우에만, 그렇지 않으면 descriptor.layout을 사용합니다.

  2. 아래 단계의 모든 요구사항을 반드시 만족해야 합니다. 하나라도 만족하지 않으면 유효성 검사 오류 생성, 무효화 pipeline 그리고 반환합니다.

    1. layoutthis사용 가능(valid to use with) 상태여야 합니다.

    2. GPUProgrammableStage 유효성 검사(COMPUTE, descriptor.compute, layout, this)가 반드시 성공해야 합니다.

    3. entryPoint엔트리 포인트 가져오기(COMPUTE, descriptor.compute)로 설정합니다.

      Assert entryPointnull이 아님을 확인합니다.

    4. workgroupStorageUsed를 루트 entryPointworkgroup 주소 공간을 가진 정적으로 사용되는 모든 변수의 타입 T에 대해 roundUp(16, SizeOf(T))의 합으로 설정합니다.

      workgroupStorageUsed는 반드시 device.limits.maxComputeWorkgroupStorageSize 이하여야 합니다.

    5. entryPoint는 반드시 device.limits.maxComputeInvocationsPerWorkgroup 이하의 workgroup 내 invocations만 사용해야 합니다.

    6. entryPointworkgroup_size 속성의 각 컴포넌트는 반드시 아래와 같은 대응하는 컴포넌트 값 이하여야 합니다: [device.limits.maxComputeWorkgroupSizeX, device.limits.maxComputeWorkgroupSizeY, device.limits.maxComputeWorkgroupSizeZ].

  3. 파이프라인 생성 구현에서 파이프라인 생성 분류되지 않은 오류가 발생하면, 내부 오류 생성, 무효화 pipeline 그리고 반환합니다.

    Note: 구현에서 셰이더 모듈 생성 시 분류되지 않은 오류를 감지했다면, 해당 오류는 이 단계에서 표면화됩니다.

  4. pipeline.[[layout]]layout으로 설정합니다.

createComputePipelineAsync(descriptor)

비동기 파이프라인 생성을 통해 GPUComputePipeline을 생성합니다. 반환된 Promise는 생성된 파이프라인이 추가 지연 없이 사용 가능해질 때 resolve됩니다.

파이프라인 생성이 실패하면 반환된 PromiseGPUPipelineError로 reject됩니다. (GPUError는 디바이스로 dispatch되지 않습니다.)

Note: 가능한 경우 이 메서드 사용을 권장합니다. 파이프라인 컴파일로 큐 타임라인 작업이 블록되는 것을 방지할 수 있습니다.

호출 대상: GPUDevice this.

인수:

GPUDevice.createComputePipelineAsync(descriptor) 메서드의 인수.
파라미터 타입 Nullable Optional 설명
descriptor GPUComputePipelineDescriptor 생성할 GPUComputePipeline에 대한 설명.

반환값: Promise<GPUComputePipeline>

콘텐츠 타임라인 단계:

  1. contentTimeline을 현재 콘텐츠 타임라인으로 설정합니다.

  2. promise새로운 promise로 설정합니다.

  3. this디바이스 타임라인에서 초기화 단계를 수행합니다.

  4. promise를 반환합니다.

디바이스 타임라인 초기화 단계:
  1. pipelinethis.createComputePipeline()descriptor로 호출한 것처럼 생성하되, 오류는 디바이스로 디스패치하지 않고 error로 캡처합니다.

  2. pipeline에 대한 파이프라인 생성이 성공 또는 실패할 때 event가 발생하도록 설정합니다.

  3. 타임라인 이벤트 수신 eventthis.[[device]]에서 수행하며, 이후 단계는 디바이스 타임라인에서 처리합니다.

디바이스 타임라인 단계:
  1. pipeline유효하거나 thislost 상태면:

    1. 아래 단계를 contentTimeline에서 실행합니다:

      콘텐츠 타임라인 단계:
      1. promisepipeline으로 resolve합니다.

    2. 반환합니다.

    Note: lost된 디바이스에서는 오류가 생성되지 않습니다. § 22 오류 및 디버깅 참고.

  2. pipeline무효이고 error내부 오류일 경우, 아래 단계를 contentTimeline에서 실행하고 반환합니다.

    콘텐츠 타임라인 단계:
    1. promiseGPUPipelineError 와 함께 reject합니다. reason 값은 "internal"입니다.

  3. pipeline무효이고 error유효성 검사 오류일 경우, 아래 단계를 contentTimeline에서 실행하고 반환합니다.

    콘텐츠 타임라인 단계:
    1. promiseGPUPipelineError 와 함께 reject합니다. reason 값은 "validation"입니다.

간단한 GPUComputePipeline 생성 예시:
const computePipeline = gpuDevice.createComputePipeline({
    layout: pipelineLayout,
    compute: {
        module: computeShaderModule,
        entryPoint: 'computeMain',
    }
});

10.3. GPURenderPipeline

GPURenderPipeline파이프라인의 한 종류로서, 버텍스 및 프래그먼트 셰이더 스테이지를 제어하며, GPURenderPassEncoderGPURenderBundleEncoder에서 사용할 수 있습니다.

렌더 파이프라인의 입력값:

렌더 파이프라인의 출력값:

렌더 파이프라인은 다음 렌더 스테이지들로 구성됩니다:

  1. 버텍스 fetch (GPUVertexState.buffers로 제어)

  2. 버텍스 셰이더 (GPUVertexState로 제어)

  3. 도형 조립 (GPUPrimitiveState로 제어)

  4. 래스터화 (GPUPrimitiveState, GPUDepthStencilState, GPUMultisampleState로 제어)

  5. 프래그먼트 셰이더 (GPUFragmentState로 제어)

  6. 스텐실 테스트 및 연산 (GPUDepthStencilState로 제어)

  7. 깊이 테스트 및 쓰기 (GPUDepthStencilState로 제어)

  8. 출력 머징 (GPUFragmentState.targets로 제어)

[Exposed=(Window, Worker), SecureContext]
interface GPURenderPipeline {
};
GPURenderPipeline includes GPUObjectBase;
GPURenderPipeline includes GPUPipelineBase;

GPURenderPipeline는 다음 디바이스 타임라인 속성을 가집니다:

[[descriptor]], 타입 GPURenderPipelineDescriptor, 읽기 전용

이 파이프라인을 기술하는 GPURenderPipelineDescriptor입니다.

모든 선택적 필드는 GPURenderPipelineDescriptor에서 정의됩니다.

[[writesDepth]], 타입 boolean, 읽기 전용

파이프라인이 깊이/스텐실 어태치먼트의 깊이 컴포넌트에 쓰는 경우 true

[[writesStencil]], 타입 boolean, 읽기 전용

파이프라인이 깊이/스텐실 어태치먼트의 스텐실 컴포넌트에 쓰는 경우 true

10.3.1. 렌더 파이프라인 생성

GPURenderPipelineDescriptor는 각 렌더 스테이지를 구성하여 렌더 파이프라인을 설명합니다. 자세한 내용은 § 23.2 렌더링을 참고하세요.

dictionary GPURenderPipelineDescriptor
         : GPUPipelineDescriptorBase {
    required GPUVertexState vertex;
    GPUPrimitiveState primitive = {};
    GPUDepthStencilState depthStencil;
    GPUMultisampleState multisample = {};
    GPUFragmentState fragment;
};

GPURenderPipelineDescriptor는 다음 멤버를 가집니다:

vertex, 타입 GPUVertexState

파이프라인의 버텍스 셰이더 엔트리 포인트와 입력 버퍼 레이아웃을 설명합니다.

primitive, 타입 GPUPrimitiveState, 기본값 {}

파이프라인의 도형 관련 속성을 설명합니다.

depthStencil, 타입 GPUDepthStencilState

테스트, 연산, 바이어스 등 선택적 깊이-스텐실 속성을 설명합니다.

multisample, 타입 GPUMultisampleState, 기본값 {}

파이프라인의 멀티샘플링 속성을 설명합니다.

fragment, 타입 GPUFragmentState

파이프라인의 프래그먼트 셰이더 엔트리 포인트와 출력 색상을 설명합니다. 제공되지 않은 경우 § 23.2.8 컬러 출력 없음 모드가 활성화됩니다.

createRenderPipeline(descriptor)

즉시 파이프라인 생성으로 GPURenderPipeline을 생성합니다.

호출 대상: GPUDevice this.

인수:

GPUDevice.createRenderPipeline(descriptor) 메서드의 인수.
파라미터 타입 Nullable Optional 설명
descriptor GPURenderPipelineDescriptor 생성할 GPURenderPipeline에 대한 설명.

반환값: GPURenderPipeline

콘텐츠 타임라인 단계:

  1. descriptor.fragment제공된 경우:

    1. 모든 non-null colorState에 대해 descriptor.fragment.targets:

      1. ? 텍스처 포맷 요구 기능 유효성 검사colorState.formatthis.[[device]]으로 수행합니다.

  2. descriptor.depthStencil제공된 경우:

    1. ? 텍스처 포맷 요구 기능 유효성 검사descriptor.depthStencil.formatthis.[[device]]으로 수행합니다.

  3. pipeline! 새로운 WebGPU 객체 생성(this, GPURenderPipeline, descriptor)로 설정합니다.

  4. this디바이스 타임라인에서 초기화 단계를 수행합니다.

  5. pipeline을 반환합니다.

디바이스 타임라인 초기화 단계:
  1. layoutpipeline에 대해 기본 파이프라인 레이아웃으로 설정합니다. 단, descriptor.layout"auto"인 경우에만, 그렇지 않으면 descriptor.layout을 사용합니다.

  2. 아래 단계의 모든 요구사항을 반드시 만족해야 합니다. 하나라도 만족하지 않으면 유효성 검사 오류 생성, 무효화 pipeline 그리고 반환합니다.

    1. layoutthis사용 가능(valid to use with) 상태여야 합니다.

    2. GPURenderPipelineDescriptor 유효성 검사(descriptor, layout, this)가 반드시 성공해야 합니다.

    3. vertexBufferCountdescriptor.vertex.buffers에서 마지막 non-null 항목의 인덱스 + 1로 설정하고, 항목이 없다면 0으로 설정합니다.

    4. layout.[[bindGroupLayouts]].size + vertexBufferCountthis.[[device]].[[limits]].maxBindGroupsPlusVertexBuffers 이하여야 합니다.

  3. 파이프라인 생성 구현에서 파이프라인 생성 분류되지 않은 오류가 발생하면, 내부 오류 생성, 무효화 pipeline 그리고 반환합니다.

    Note: 구현에서 셰이더 모듈 생성 시 분류되지 않은 오류를 감지했다면, 해당 오류는 이 단계에서 표면화됩니다.

  4. pipeline.[[descriptor]]descriptor로 설정합니다.

  5. pipeline.[[writesDepth]] 를 false로 설정합니다.

  6. pipeline.[[writesStencil]] 를 false로 설정합니다.

  7. depthStencildescriptor.depthStencil로 설정합니다.

  8. depthStencil가 null이 아니면:

    1. depthStencil.depthWriteEnabled제공된 경우:

      1. pipeline.[[writesDepth]]depthStencil.depthWriteEnabled 값으로 설정합니다.

    2. depthStencil.stencilWriteMask 가 0이 아니면:

      1. stencilFrontdepthStencil.stencilFront로 설정합니다.

      2. stencilBackdepthStencil.stencilBack로 설정합니다.

      3. cullModedescriptor.primitive.cullMode.

      4. cullMode"front"가 아니고, stencilFront.passOp, stencilFront.depthFailOp, 또는 stencilFront.failOp 중 하나라도 "keep"가 아니라면:

        1. pipeline.[[writesStencil]]을 true로 설정한다.

      5. cullMode"back"가 아니고, stencilBack.passOp, stencilBack.depthFailOp, 또는 stencilBack.failOp 중 하나라도 "keep"가 아니라면:

        1. pipeline.[[writesStencil]]을 true로 설정한다.

  9. pipeline.[[layout]]layout으로 설정한다.

createRenderPipelineAsync(descriptor)

GPURenderPipeline비동기 파이프라인 생성을 사용하여 생성한다. 반환되는 Promise는 생성된 파이프라인이 추가적인 지연 없이 사용할 준비가 되었을 때 resolve된다.

파이프라인 생성에 실패하면, 반환된 PromiseGPUPipelineError로 reject된다. (GPUError는 디바이스에 디스패치되지 않는다.)

참고: 가능한 경우 이 메서드의 사용이 권장된다. 파이프라인 컴파일 시 큐 타임라인 작업이 막히는 것을 방지하기 때문이다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createRenderPipelineAsync(descriptor) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPURenderPipelineDescriptor 생성할 GPURenderPipeline의 설명.

반환값: Promise<GPURenderPipeline>

콘텐츠 타임라인 단계:

  1. 현재 콘텐츠 타임라인contentTimeline으로 한다.

  2. promise새로운 Promise로 한다.

  3. this디바이스 타임라인에서 초기화 단계를 수행한다.

  4. promise를 반환한다.

디바이스 타임라인 초기화 단계:
  1. pipelineGPURenderPipeline의 새 인스턴스로 생성한다. 이 때 this.createRenderPipeline()descriptor로 호출한 것처럼 처리하되, 오류는 디바이스에 디스패치하지 않고 error로 캡처한다.

  2. pipeline파이프라인 생성이 완료(성공 또는 실패)될 때 event가 발생한다.

  3. 타임라인 이벤트 수신 eventthis.[[device]]에서 수신하고, 이후 단계는 this디바이스 타임라인에서 처리한다.

디바이스 타임라인 단계:
  1. pipeline유효하거나, thislost 상태라면:

    1. contentTimeline에서 다음 단계를 수행한다:

      콘텐츠 타임라인 단계:
      1. resolve promisepipeline을 전달한다.

    2. Return.

    참고: lost 상태의 디바이스에서는 오류가 발생하지 않는다. § 22 오류 및 디버깅 참고.

  2. pipeline무효이고, error내부 오류라면, contentTimeline에서 다음 단계를 수행하고 return한다.

    콘텐츠 타임라인 단계:
    1. reject promiseGPUPipelineErrorreason "internal"을 전달한다.

  3. pipeline무효이고, error검증 오류라면, contentTimeline에서 다음 단계를 수행하고 return한다.

    콘텐츠 타임라인 단계:
    1. reject promiseGPUPipelineErrorreason "validation"을 전달한다.

GPURenderPipelineDescriptor 유효성 검사(descriptor, layout, device)

인자:

디바이스 타임라인 단계:

  1. 다음 조건이 모두 만족되면 true를 반환한다:

인터스테이지 인터페이스 유효성 검사(device, descriptor)

인자:

반환값: boolean

디바이스 타임라인 단계:

  1. maxVertexShaderOutputVariablesdevice.limits.maxInterStageShaderVariables로 한다.

  2. maxVertexShaderOutputLocationdevice.limits.maxInterStageShaderVariables - 1로 한다.

  3. descriptor.primitive.topology"point-list"인 경우:

    1. maxVertexShaderOutputVariables를 1 감소시킨다.

  4. clip_distancesdescriptor.vertex 출력에 선언된 경우:

    1. clipDistancesSizeclip_distances 배열 크기로 한다.

    2. maxVertexShaderOutputVariables를 ceil(clipDistancesSize / 4)만큼 감소시킨다.

    3. maxVertexShaderOutputLocation을 ceil(clipDistancesSize / 4)만큼 감소시킨다.

  5. 다음 요구사항을 하나라도 만족하지 못하면 false를 반환한다:

    • descriptor.vertex의 사용자 정의 출력이 maxVertexShaderOutputVariables개 이하여야 한다.

    • descriptor.vertex의 각 사용자 정의 출력의 location 값이 ≤ maxVertexShaderOutputLocation이어야 한다.

  6. descriptor.fragment 가 제공된 경우:

    1. maxFragmentShaderInputVariablesdevice.limits.maxInterStageShaderVariables로 한다.

    2. front_facing, sample_index, sample_mask 내장값 중 하나라도 descriptor.fragment 입력이면:

      1. maxFragmentShaderInputVariables를 1 감소시킨다.

    3. 다음 요구사항을 하나라도 만족하지 못하면 false를 반환한다:

      • descriptor.fragment의 각 사용자 정의 입력에 대해, descriptor.vertex의 사용자 정의 출력이 해당 location, 타입, 보간 방식을 만족해야 한다.

        참고: 버텍스 전용 파이프라인은 사용자 정의 출력을 버텍스 단계에서 가질 수 있으며, 해당 값은 폐기된다.

      • descriptor.fragment의 사용자 정의 입력이 maxFragmentShaderInputVariables개 이하여야 한다.

    4. Assert: descriptor.fragment의 각 사용자 정의 입력의 location 값이 device.limits.maxInterStageShaderVariables보다 작아야 한다. (위 규칙에서 따라옴)

  7. true를 반환한다.

간단한 GPURenderPipeline 생성 예시:
const renderPipeline = gpuDevice.createRenderPipeline({
    layout: pipelineLayout,
    vertex: {
        module: shaderModule,
        entryPoint: 'vertexMain'
    },
    fragment: {
        module: shaderModule,
        entryPoint: 'fragmentMain',
        targets: [{
            format: 'bgra8unorm',
        }],
    }
});

10.3.2. 프리미티브 상태

dictionary GPUPrimitiveState {
    GPUPrimitiveTopology topology = "triangle-list";
    GPUIndexFormat stripIndexFormat;
    GPUFrontFace frontFace = "ccw";
    GPUCullMode cullMode = "none";

    // "depth-clip-control" 기능 필요.
    boolean unclippedDepth = false;
};

GPUPrimitiveState는 다음 멤버를 가지며, GPURenderPipeline이 버텍스 입력을 기반으로 프리미티브를 구성하고 래스터화하는 방식을 설명합니다:

topology, 타입 GPUPrimitiveTopology, 기본값 "triangle-list"

버텍스 입력으로부터 생성할 프리미티브의 유형입니다.

stripIndexFormat, 타입 GPUIndexFormat

스트립 토폴로지("line-strip" 또는 "triangle-strip") 파이프라인에서 인덱스 버퍼 포맷 및 프리미티브 리스타트 값을 결정합니다("uint16"/0xFFFF 또는 "uint32"/0xFFFFFFFF). 비스트립 토폴로지 파이프라인에서는 사용할 수 없습니다.

참고: 일부 구현은 파이프라인 상태 객체 컴파일 시 프리미티브 리스타트 값 정보를 필요로 합니다.

스트립 토폴로지 파이프라인에서 인덱스드 드로우 호출(drawIndexed() 또는 drawIndexedIndirect())을 사용할 때 반드시 설정해야 하며, 드로우 호출에서 사용하는 인덱스 버퍼 포맷(setIndexBuffer()에서 설정)을 일치시켜야 합니다.

자세한 내용은 § 23.2.3 프리미티브 조립을 참고하세요.

frontFace, 타입 GPUFrontFace, 기본값 "ccw"

어떤 폴리곤을 앞면으로 간주할지 정의합니다.

cullMode, 타입 GPUCullMode, 기본값 "none"

어떤 폴리곤 방향을 컬링(제거)할지 정의합니다.

unclippedDepth, 타입 boolean, 기본값 false

true인 경우 깊이 클리핑이 비활성화됨을 나타냅니다.

"depth-clip-control" 기능이 활성화되어 있어야 합니다.

GPUPrimitiveState 유효성 검사(descriptor, device) 인자:

디바이스 타임라인 단계:

  1. 다음 조건을 모두 만족하면 true를 반환한다:

enum GPUPrimitiveTopology {
    "point-list",
    "line-list",
    "line-strip",
    "triangle-list",
    "triangle-strip",
};

GPUPrimitiveTopologyGPURenderPipeline으로 드로우 호출 시 사용할 프리미티브 타입을 정의합니다. 자세한 내용은 § 23.2.5 래스터화를 참고하세요:

"point-list"

각 버텍스가 하나의 포인트 프리미티브를 정의합니다.

"line-list"

연속된 두 버텍스가 하나의 라인 프리미티브를 정의합니다.

"line-strip"

첫 번째 이후 각 버텍스가 이전 버텍스와 함께 하나의 라인 프리미티브를 정의합니다.

"triangle-list"

연속된 세 버텍스가 하나의 삼각형 프리미티브를 정의합니다.

"triangle-strip"

첫 두 버텍스 이후 각 버텍스가 앞의 두 버텍스와 함께 하나의 삼각형 프리미티브를 정의합니다.

enum GPUFrontFace {
    "ccw",
    "cw",
};

GPUFrontFaceGPURenderPipeline이 폴리곤을 앞면으로 간주하는 방식을 정의합니다. 자세한 내용은 § 23.2.5.4 폴리곤 래스터화를 참고하세요:

"ccw"

프레임버퍼 좌표가 반시계 방향으로 주어진 버텍스의 폴리곤은 앞면으로 간주됩니다.

"cw"

프레임버퍼 좌표가 시계 방향으로 주어진 버텍스의 폴리곤은 앞면으로 간주됩니다.

enum GPUCullMode {
    "none",
    "front",
    "back",
};

GPUPrimitiveTopologyGPURenderPipeline으로 드로우 호출 시 컬링될 폴리곤을 정의합니다. 자세한 내용은 § 23.2.5.4 폴리곤 래스터화를 참고하세요:

"none"

모든 폴리곤이 버려지지 않습니다.

"front"

앞면 폴리곤이 버려집니다.

"back"

뒷면 폴리곤이 버려집니다.

참고: GPUFrontFaceGPUCullMode"point-list", "line-list", "line-strip" 토폴로지에서는 효과가 없습니다.

10.3.3. 멀티샘플 상태

dictionary GPUMultisampleState {
    GPUSize32 count = 1;
    GPUSampleMask mask = 0xFFFFFFFF;
    boolean alphaToCoverageEnabled = false;
};

GPUMultisampleStateGPURenderPipeline이 렌더 패스의 멀티샘플링된 attachment와 상호작용하는 방식을 설명하는 다음 멤버들을 갖습니다.

count, 타입 GPUSize32, 기본값 1

픽셀 당 샘플 개수. 이 GPURenderPipelinecolorAttachmentsdepthStencilAttachment와 같이 sampleCount가 동일한 attachment 텍스처와만 호환됩니다.

mask, 타입 GPUSampleMask, 기본값 0xFFFFFFFF

샘플 중 어떤 샘플에 쓸지 결정하는 마스크입니다.

alphaToCoverageEnabled, 타입 boolean, 기본값 false

true인 경우, 프래그먼트의 알파 채널을 샘플 커버리지 마스크 생성에 사용함을 의미합니다.

GPUMultisampleState 유효성 검사(descriptor) 인자:

디바이스 타임라인 단계:

  1. 다음 조건을 모두 만족하면 true를 반환한다:

10.3.4. 프래그먼트 상태

dictionary GPUFragmentState
         : GPUProgrammableStage {
    required sequence<GPUColorTargetState?> targets;
};
targets, 타입 sequence<GPUColorTargetState?>

이 파이프라인이 기록하는 컬러 타겟의 포맷과 동작을 정의하는 GPUColorTargetState 리스트입니다.

GPUFragmentState 유효성 검사(device, descriptor, layout)

인자:

디바이스 타임라인 단계:

  1. 다음 요구사항을 모두 만족하면 true를 반환한다:

GPUFragmentState의 컬러 attachment 바이트/샘플 유효성 검사(device, targets)

인자:

디바이스 타임라인 단계:

  1. formatslist<GPUTextureFormat?>의 빈 리스트로 한다.

  2. targets의 각 target에 대해:

    1. targetundefined면, 넘어간다.

    2. Append target.formatformats에 추가한다.

  3. 컬러 attachment 바이트/샘플 계산(formats) 값이 device.[[limits]].maxColorAttachmentBytesPerSample 이하이어야 한다.

참고: 프래그먼트 셰이더는 파이프라인에서 사용하는 것보다 더 많은 값을 출력할 수 있습니다. 이 경우 해당 값은 무시됩니다.

GPUBlendComponent component가 논리적 device device에 대해 유효한 GPUBlendComponent이려면 아래 조건을 만족해야 합니다:

10.3.5. 컬러 타겟 상태

dictionary GPUColorTargetState {
    required GPUTextureFormat format;

    GPUBlendState blend;
    GPUColorWriteFlags writeMask = 0xF;  // GPUColorWrite.ALL
};
format, 타입 GPUTextureFormat

이 컬러 타겟의 GPUTextureFormat입니다. 파이프라인은 GPURenderPassEncoder가 해당 색상 attachment에 이 포맷의 GPUTextureView를 사용할 때만 호환됩니다.

blend, 타입 GPUBlendState

이 컬러 타겟의 블렌딩 동작입니다. 지정하지 않으면 블렌딩이 비활성화됩니다.

writeMask, 타입 GPUColorWriteFlags, 기본값 0xF

이 컬러 타겟에 드로잉할 때 어떤 채널에 쓸지 제어하는 비트마스크입니다.

dictionary GPUBlendState {
    required GPUBlendComponent color;
    required GPUBlendComponent alpha;
};
color, 타입 GPUBlendComponent

해당 렌더 타겟의 컬러 채널의 블렌딩 동작을 정의합니다.

alpha, 타입 GPUBlendComponent

해당 렌더 타겟의 알파 채널의 블렌딩 동작을 정의합니다.

typedef [EnforceRange] unsigned long GPUColorWriteFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUColorWrite {
    const GPUFlagsConstant RED   = 0x1;
    const GPUFlagsConstant GREEN = 0x2;
    const GPUFlagsConstant BLUE  = 0x4;
    const GPUFlagsConstant ALPHA = 0x8;
    const GPUFlagsConstant ALL   = 0xF;
};
10.3.5.1. 블렌드 상태
dictionary GPUBlendComponent {
    GPUBlendOperation operation = "add";
    GPUBlendFactor srcFactor = "one";
    GPUBlendFactor dstFactor = "zero";
};

GPUBlendComponent 는 프래그먼트의 컬러 또는 알파 컴포넌트가 어떻게 블렌딩되는지 설명하는 다음 멤버들을 갖습니다:

operation, 타입 GPUBlendOperation, 기본값 "add"

타겟 attachment 컴포넌트에 기록되는 값을 계산하는 데 사용하는 GPUBlendOperation을 정의합니다.

srcFactor, 타입 GPUBlendFactor, 기본값 "one"

프래그먼트 셰이더에서 나온 값에 대해 수행할 GPUBlendFactor 연산을 정의합니다.

dstFactor, 타입 GPUBlendFactor, 기본값 "zero"

타겟 attachment에서 나온 값에 대해 수행할 GPUBlendFactor 연산을 정의합니다.

다음 표들은 주어진 프래그먼트 위치에 대해 컬러 컴포넌트를 설명할 때 이 기호를 사용합니다:

RGBAsrc 컬러 attachment에 대해 프래그먼트 셰이더가 출력한 컬러. 셰이더가 알파 채널을 반환하지 않으면 src-alpha 블렌드 팩터는 사용할 수 없습니다.
RGBAsrc1 "@blend_src" 속성1인 컬러 attachment에 대해 프래그먼트 셰이더가 출력한 컬러. 셰이더가 알파 채널을 반환하지 않으면 src1-alpha 블렌드 팩터는 사용할 수 없습니다.
RGBAdst 컬러 attachment에 현재 있는 컬러. green/blue/alpha 채널이 없으면 각각 0, 0, 1로 기본값이 설정됩니다.
RGBAconst 현재 [[blendConstant]].
RGBAsrcFactor srcFactor에 의해 정의된 소스 블렌드 팩터 컴포넌트.
RGBAdstFactor dstFactor에 의해 정의된 대상 블렌드 팩터 컴포넌트.
enum GPUBlendFactor {
    "zero",
    "one",
    "src",
    "one-minus-src",
    "src-alpha",
    "one-minus-src-alpha",
    "dst",
    "one-minus-dst",
    "dst-alpha",
    "one-minus-dst-alpha",
    "src-alpha-saturated",
    "constant",
    "one-minus-constant",
    "src1",
    "one-minus-src1",
    "src1-alpha",
    "one-minus-src1-alpha",
};

GPUBlendFactor 는 소스 또는 대상 블렌드 팩터가 어떻게 계산되는지 정의합니다:

GPUBlendFactor 블렌드 팩터 RGBA 컴포넌트 기능
"zero" (0, 0, 0, 0)
"one" (1, 1, 1, 1)
"src" (Rsrc, Gsrc, Bsrc, Asrc)
"one-minus-src" (1 - Rsrc, 1 - Gsrc, 1 - Bsrc, 1 - Asrc)
"src-alpha" (Asrc, Asrc, Asrc, Asrc)
"one-minus-src-alpha" (1 - Asrc, 1 - Asrc, 1 - Asrc, 1 - Asrc)
"dst" (Rdst, Gdst, Bdst, Adst)
"one-minus-dst" (1 - Rdst, 1 - Gdst, 1 - Bdst, 1 - Adst)
"dst-alpha" (Adst, Adst, Adst, Adst)
"one-minus-dst-alpha" (1 - Adst, 1 - Adst, 1 - Adst, 1 - Adst)
"src-alpha-saturated" (min(Asrc, 1 - Adst), min(Asrc, 1 - Adst), min(Asrc, 1 - Adst), 1)
"constant" (Rconst, Gconst, Bconst, Aconst)
"one-minus-constant" (1 - Rconst, 1 - Gconst, 1 - Bconst, 1 - Aconst)
"src1" (Rsrc1, Gsrc1, Bsrc1, Asrc1) dual-source-blending
"one-minus-src1" (1 - Rsrc1, 1 - Gsrc1, 1 - Bsrc1, 1 - Asrc1)
"src1-alpha" (Asrc1, Asrc1, Asrc1, Asrc1)
"one-minus-src1-alpha" (1 - Asrc1, 1 - Asrc1, 1 - Asrc1, 1 - Asrc1)
enum GPUBlendOperation {
    "add",
    "subtract",
    "reverse-subtract",
    "min",
    "max",
};

GPUBlendOperation 은 소스와 대상 블렌드 팩터를 결합하는 알고리즘을 정의합니다:

GPUBlendOperation RGBA 컴포넌트
"add" RGBAsrc × RGBAsrcFactor + RGBAdst × RGBAdstFactor
"subtract" RGBAsrc × RGBAsrcFactor - RGBAdst × RGBAdstFactor
"reverse-subtract" RGBAdst × RGBAdstFactor - RGBAsrc × RGBAsrcFactor
"min" min(RGBAsrc, RGBAdst)
"max" max(RGBAsrc, RGBAdst)

10.3.6. 깊이/스텐실 상태

dictionary GPUDepthStencilState {
    required GPUTextureFormat format;

    boolean depthWriteEnabled;
    GPUCompareFunction depthCompare;

    GPUStencilFaceState stencilFront = {};
    GPUStencilFaceState stencilBack = {};

    GPUStencilValue stencilReadMask = 0xFFFFFFFF;
    GPUStencilValue stencilWriteMask = 0xFFFFFFFF;

    GPUDepthBias depthBias = 0;
    float depthBiasSlopeScale = 0;
    float depthBiasClamp = 0;
};

GPUDepthStencilStateGPURenderPipeline 이 렌더 패스의 depthStencilAttachment에 어떤 영향을 미치는지 설명하는 다음 멤버들을 갖습니다:

format, 타입 GPUTextureFormat

GPURenderPipeline이 호환되는 depthStencilAttachmentformat입니다.

depthWriteEnabled, 타입 boolean

GPURenderPipelinedepthStencilAttachment 의 깊이 값을 변경할 수 있는지 나타냅니다.

depthCompare, 타입 GPUCompareFunction

프래그먼트의 깊이 값과 depthStencilAttachment 깊이 값을 비교하는 데 사용되는 연산입니다.

stencilFront, 타입 GPUStencilFaceState, 기본값 {}

앞면 프리미티브에 대해 스텐실 비교 및 연산이 어떻게 수행되는지 정의합니다.

stencilBack, 타입 GPUStencilFaceState, 기본값 {}

뒷면 프리미티브에 대해 스텐실 비교 및 연산이 어떻게 수행되는지 정의합니다.

stencilReadMask, 타입 GPUStencilValue, 기본값 0xFFFFFFFF

스텐실 비교 테스트를 수행할 때 depthStencilAttachment 스텐실 값 비트 중 어느 비트를 읽을지 제어하는 비트마스크입니다.

stencilWriteMask, 타입 GPUStencilValue, 기본값 0xFFFFFFFF

스텐실 연산을 수행할 때 depthStencilAttachment 스텐실 값 비트 중 어느 비트를 쓸지 제어하는 비트마스크입니다.

depthBias, 타입 GPUDepthBias, 기본값 0

각 삼각형 프래그먼트에 더해지는 상수 깊이 바이어스입니다. 자세한 내용은 바이어스된 프래그먼트 깊이를 참고하세요.

depthBiasSlopeScale, 타입 float, 기본값 0

삼각형 프래그먼트의 기울기에 따라 스케일되는 깊이 바이어스입니다. 자세한 내용은 바이어스된 프래그먼트 깊이를 참고하세요.

depthBiasClamp, 타입 float, 기본값 0

삼각형 프래그먼트의 최대 깊이 바이어스입니다. 자세한 내용은 바이어스된 프래그먼트 깊이를 참고하세요.

참고: depthBias, depthBiasSlopeScale, 그리고 depthBiasClamp"point-list", "line-list", 그리고 "line-strip" 프리미티브에는 영향을 주지 않으며, 0이어야 합니다.

바이어스된 프래그먼트 깊이depthStencilAttachment attachment에 기록되는 프래그먼트에 대해 GPUDepthStencilState state를 사용할 때 다음 큐 타임라인 단계를 따라 계산됩니다:
  1. formatattachment.view.format으로 한다.

  2. rformat에서 32비트 float로 변환한 0보다 큰 최소 양의 표현값으로 한다.

  3. maxDepthSlope을 프래그먼트의 깊이 값의 수평 및 수직 기울기 중 최대값으로 한다.

  4. formatunorm 포맷인 경우:

    1. bias(float)state.depthBias * r + state.depthBiasSlopeScale * maxDepthSlope로 한다.

  5. 그 외에 formatfloat 포맷인 경우:

    1. bias(float)state.depthBias * 2^(exp(max depth in primitive) - r) + state.depthBiasSlopeScale * maxDepthSlope로 한다.

  6. state.depthBiasClamp > 0인 경우:

    1. biasmin(state.depthBiasClamp, bias)로 설정한다.

  7. 그 외에 state.depthBiasClamp < 0인 경우:

    1. biasmax(state.depthBiasClamp, bias)로 설정한다.

  8. state.depthBias0 또는 state.depthBiasSlopeScale0인 경우:

    1. 프래그먼트의 깊이 값을 fragment depth value + bias로 설정한다.

GPUDepthStencilState 유효성 검사(descriptor, topology)

인자:

디바이스 타임라인 단계:

  1. 다음 조건을 모두 만족할 때만 true를 반환한다:

dictionary GPUStencilFaceState {
    GPUCompareFunction compare = "always";
    GPUStencilOperation failOp = "keep";
    GPUStencilOperation depthFailOp = "keep";
    GPUStencilOperation passOp = "keep";
};

GPUStencilFaceState 는 스텐실 비교 및 연산이 어떻게 수행되는지 설명하는 다음 멤버들을 갖습니다:

compare, 타입 GPUCompareFunction, 기본값 "always"

프래그먼트의 [[stencilReference]] 값을 depthStencilAttachment 스텐실 값과 비교할 때 사용하는 GPUCompareFunction입니다.

failOp, 타입 GPUStencilOperation, 기본값 "keep"

compare 비교 테스트가 실패할 때 수행되는 GPUStencilOperation입니다.

depthFailOp, 타입 GPUStencilOperation, 기본값 "keep"

프래그먼트의 깊이 비교(depthCompare)가 실패할 때 수행되는 GPUStencilOperation입니다.

passOp, 타입 GPUStencilOperation, 기본값 "keep"

compare 비교 테스트가 성공할 때 수행되는 GPUStencilOperation입니다.

enum GPUStencilOperation {
    "keep",
    "zero",
    "replace",
    "invert",
    "increment-clamp",
    "decrement-clamp",
    "increment-wrap",
    "decrement-wrap",
};

GPUStencilOperation 은 다음 연산을 정의합니다:

"keep"

현재 스텐실 값을 유지합니다.

"zero"

스텐실 값을 0으로 설정합니다.

"replace"

스텐실 값을 [[stencilReference]]로 설정합니다.

"invert"

현재 스텐실 값을 비트 반전합니다.

"increment-clamp"

현재 스텐실 값을 증가시키되, depthStencilAttachment의 스텐실 aspect의 최댓값을 넘지 않도록 클램프합니다.

"decrement-clamp"

현재 스텐실 값을 감소시키되, 0보다 작아지지 않도록 클램프합니다.

"increment-wrap"

현재 스텐실 값을 증가시키되, 값이 depthStencilAttachment의 스텐실 aspect 최댓값을 넘으면 0으로 래핑합니다.

"decrement-wrap"

현재 스텐실 값을 감소시키되, 값이 0보다 작아지면 depthStencilAttachment의 스텐실 aspect 최댓값으로 래핑합니다.

10.3.7. 버텍스 상태

enum GPUIndexFormat {
    "uint16",
    "uint32",
};

인덱스 포맷은 버퍼 내 인덱스 값의 데이터 타입을 결정하며, 스트립 프리미티브 토폴로지("line-strip" 또는 "triangle-strip") 사용 시 프리미티브 리스타트 값도 지정합니다. 프리미티브 리스타트 값은 인덱스 값 중 새 프리미티브를 시작해야 하는 값이며, 이전 인덱스 버텍스들과 계속 스트립을 구성하는 대신, 새 프리미티브가 시작됨을 의미합니다.

GPUPrimitiveState에서 스트립 프리미티브 토폴로지를 지정할 경우 인덱스드 드로우에 사용되는 경우 stripIndexFormat 을 반드시 명시해야 하며, 프리미티브 리스타트 값이 파이프라인 생성 시점에 확정되어야 합니다. GPUPrimitiveState가 리스트 프리미티브 토폴로지를 지정할 경우 인덱스드 렌더링 시 setIndexBuffer()에 전달된 인덱스 포맷을 사용합니다.

인덱스 포맷 바이트 크기 프리미티브 리스타트 값
"uint16" 2 0xFFFF
"uint32" 4 0xFFFFFFFF
10.3.7.1. 버텍스 포맷

GPUVertexFormat 은 버텍스 속성이 버텍스 버퍼에서 어떻게 해석되고 셰이더에 노출되는지 나타냅니다. 포맷 이름은 컴포넌트의 순서, 컴포넌트 당 비트 수, 그리고 각 컴포넌트의 버텍스 데이터 타입을 지정합니다.

버텍스 데이터 타입은 동일한 기본 타입의 WGSL 스칼라 타입과 비트 수에 관계없이 매핑될 수 있습니다:

버텍스 포맷 접두사 버텍스 데이터 타입 호환 WGSL 타입
uint 부호 없는 정수 u32
sint 부호 있는 정수 i32
unorm 부호 없는 정규화 f16, f32
snorm 부호 있는 정규화
float 부동소수점

다중 컴포넌트 포맷은 "x" 뒤의 숫자로 컴포넌트 수를 지정합니다. 버텍스 포맷과 셰이더 타입 간 컴포넌트 수가 불일치할 수 있으며, 부족한 컴포넌트는 기본값으로 채워지고, 초과하는 컴포넌트는 버려질 수 있습니다.

"unorm8x2" 포맷의 버텍스 속성에서 바이트 값 [0x7F, 0xFF]를 사용할 때 셰이더에서 다음 타입으로 접근할 수 있습니다:
셰이더 타입 셰이더 값
f16 0.5h
f32 0.5f
vec2<f16> vec2(0.5h, 1.0h)
vec2<f32> vec2(0.5f, 1.0f)
vec3<f16> vec2(0.5h, 1.0h, 0.0h)
vec3<f32> vec2(0.5f, 1.0f, 0.0f)
vec4<f16> vec2(0.5h, 1.0h, 0.0h, 1.0h)
vec4<f32> vec2(0.5f, 1.0f, 0.0f, 1.0f)

버텍스 포맷이 셰이더에 어떻게 노출되는지 더 자세한 내용은 § 23.2.2 버텍스 처리를 참고하세요.

enum GPUVertexFormat {
    "uint8",
    "uint8x2",
    "uint8x4",
    "sint8",
    "sint8x2",
    "sint8x4",
    "unorm8",
    "unorm8x2",
    "unorm8x4",
    "snorm8",
    "snorm8x2",
    "snorm8x4",
    "uint16",
    "uint16x2",
    "uint16x4",
    "sint16",
    "sint16x2",
    "sint16x4",
    "unorm16",
    "unorm16x2",
    "unorm16x4",
    "snorm16",
    "snorm16x2",
    "snorm16x4",
    "float16",
    "float16x2",
    "float16x4",
    "float32",
    "float32x2",
    "float32x3",
    "float32x4",
    "uint32",
    "uint32x2",
    "uint32x3",
    "uint32x4",
    "sint32",
    "sint32x2",
    "sint32x3",
    "sint32x4",
    "unorm10-10-10-2",
    "unorm8x4-bgra",
};
버텍스 포맷 데이터 타입 컴포넌트 수 바이트 크기 예시 WGSL 타입
"uint8" 부호 없는 정수 1 1 u32
"uint8x2" 부호 없는 정수 2 2 vec2<u32>
"uint8x4" 부호 없는 정수 4 4 vec4<u32>
"sint8" 부호 있는 정수 1 1 i32
"sint8x2" 부호 있는 정수 2 2 vec2<i32>
"sint8x4" 부호 있는 정수 4 4 vec4<i32>
"unorm8" 부호 없는 정규화 1 1 f32
"unorm8x2" 부호 없는 정규화 2 2 vec2<f32>
"unorm8x4" 부호 없는 정규화 4 4 vec4<f32>
"snorm8" 부호 있는 정규화 1 1 f32
"snorm8x2" 부호 있는 정규화 2 2 vec2<f32>
"snorm8x4" 부호 있는 정규화 4 4 vec4<f32>
"uint16" 부호 없는 정수 1 2 u32
"uint16x2" 부호 없는 정수 2 4 vec2<u32>
"uint16x4" 부호 없는 정수 4 8 vec4<u32>
"sint16" 부호 있는 정수 1 2 i32
"sint16x2" 부호 있는 정수 2 4 vec2<i32>
"sint16x4" 부호 있는 정수 4 8 vec4<i32>
"unorm16" 부호 없는 정규화 1 2 f32
"unorm16x2" 부호 없는 정규화 2 4 vec2<f32>
"unorm16x4" 부호 없는 정규화 4 8 vec4<f32>
"snorm16" 부호 있는 정규화 1 2 f32
"snorm16x2" 부호 있는 정규화 2 4 vec2<f32>
"snorm16x4" 부호 있는 정규화 4 8 vec4<f32>
"float16" 부동소수점 1 2 f32
"float16x2" 부동소수점 2 4 vec2<f16>
"float16x4" 부동소수점 4 8 vec4<f16>
"float32" 부동소수점 1 4 f32
"float32x2" 부동소수점 2 8 vec2<f32>
"float32x3" 부동소수점 3 12 vec3<f32>
"float32x4" 부동소수점 4 16 vec4<f32>
"uint32" 부호 없는 정수 1 4 u32
"uint32x2" 부호 없는 정수 2 8 vec2<u32>
"uint32x3" 부호 없는 정수 3 12 vec3<u32>
"uint32x4" 부호 없는 정수 4 16 vec4<u32>
"sint32" 부호 있는 정수 1 4 i32
"sint32x2" 부호 있는 정수 2 8 vec2<i32>
"sint32x3" 부호 있는 정수 3 12 vec3<i32>
"sint32x4" 부호 있는 정수 4 16 vec4<i32>
"unorm10-10-10-2" 부호 없는 정규화 4 4 vec4<f32>
"unorm8x4-bgra" 부호 없는 정규화 4 4 vec4<f32>
enum GPUVertexStepMode {
    "vertex",
    "instance",
};

단계 모드는 현재 버텍스 또는 인스턴스 인덱스를 기준으로 버텍스 버퍼 데이터의 주소가 어떻게 계산되는지 설정합니다:

"vertex"

각 버텍스마다 arrayStride 만큼 주소가 증가하며, 인스턴스마다 초기화됩니다.

"instance"

각 인스턴스마다 arrayStride 만큼 주소가 증가합니다.

dictionary GPUVertexState
         : GPUProgrammableStage {
    sequence<GPUVertexBufferLayout?> buffers = [];
};
buffers, 타입 sequence<GPUVertexBufferLayout?>, 기본값 []

이 파이프라인에서 사용하는 각 버텍스 버퍼의 버텍스 속성 데이터 레이아웃을 정의하는 GPUVertexBufferLayout 리스트입니다.

버텍스 버퍼는 개념적으로 구조체 배열로서의 버퍼 메모리 뷰입니다. arrayStride 는 해당 배열의 요소 간의 바이트 단위 간격입니다. 버텍스 버퍼의 각 요소는 구조체와 유사하며, attributes에 정의된 메모리 레이아웃을 따릅니다. 멤버는 구조체 내 속성에 해당합니다.

GPUVertexAttribute 는 자신의 format 과 구조체 내에서의 offset (바이트 단위)를 정의합니다.

각 속성은 버텍스 셰이더에서 개별 입력으로 나타나며, 각 입력은 숫자 location에 바인딩됩니다. 이 위치는 shaderLocation로 지정합니다. GPUVertexState 내 모든 location은 고유해야 합니다.

dictionary GPUVertexBufferLayout {
    required GPUSize64 arrayStride;
    GPUVertexStepMode stepMode = "vertex";
    required sequence<GPUVertexAttribute> attributes;
};
arrayStride, 타입 GPUSize64

이 배열의 요소 간 바이트 간격입니다.

stepMode, 타입 GPUVertexStepMode, 기본값 "vertex"

배열의 각 요소가 버텍스 데이터인지 인스턴스 데이터인지 여부입니다.

attributes, 타입 sequence<GPUVertexAttribute>

각 요소 내 버텍스 속성의 레이아웃을 정의하는 배열입니다.

dictionary GPUVertexAttribute {
    required GPUVertexFormat format;
    required GPUSize64 offset;

    required GPUIndex32 shaderLocation;
};
format, 타입 GPUVertexFormat

속성의 GPUVertexFormat입니다.

offset, 타입 GPUSize64

속성 데이터가 요소 시작점에서 몇 바이트 떨어져 있는지 나타내는 오프셋입니다.

shaderLocation, 타입 GPUIndex32

이 속성과 연관된 숫자 위치로, "@location" 속성 으로 셰이더에서 선언합니다. vertex.module에 해당합니다.

GPUVertexBufferLayout 유효성 검사(device, descriptor)

인자:

디바이스 타임라인 단계:

  1. 다음 조건을 모두 만족할 때만 true를 반환한다:

GPUVertexState 유효성 검사(device, descriptor, layout)

인자:

디바이스 타임라인 단계:

  1. entryPointget the entry point(VERTEX, descriptor)로 한다.

  2. Assert entryPointnull이 아니어야 함.

  3. 다음 단계에서 모든 요구사항이 충족되어야 합니다.

    1. GPUProgrammableStage 유효성 검사(VERTEX, descriptor, layout, device) 성공해야 함.

    2. descriptor.buffers.size 값이 device.[[device]].[[limits]].maxVertexBuffers 이하이어야 함.

    3. 리스트 descriptor.buffers의 각 vertexBuffer 레이아웃 디스크립터가 GPUVertexBufferLayout 유효성 검사(device, vertexBuffer)를 통과해야 함.

    4. 모든 vertexBuffer.attributes.size의 합이 descriptor.buffers의 모든 vertexBuffer에 대해, device.[[device]].[[limits]].maxVertexAttributes 이하이어야 함.

    5. entryPoint에서 정적으로 사용되는(타입 T의 location location에서 선언된) 모든 버텍스 속성 선언에 대해, 반드시 descriptor.buffers[i]?.attributes[j].shaderLocation == location인 쌍이 정확히 하나 존재해야 함.

      이때 attrib는 해당 GPUVertexAttribute입니다.

    6. Tattrib.format버텍스 데이터 타입과 호환되어야 함:

      "unorm", "snorm", 또는 "float"

      Tf32 또는 vecN<f32>여야 함.

      "uint"

      Tu32 또는 vecN<u32>여야 함.

      "sint"

      Ti32 또는 vecN<i32>여야 함.

11. 복사

11.1. 버퍼 복사

버퍼 복사 연산은 원시 바이트 단위로 동작합니다.

WebGPU는 "버퍼링된" GPUCommandEncoder 명령을 제공합니다:

그리고 "즉시" GPUQueue 연산:

11.2. 텍셀 복사

텍셀 복사 연산은 바이트가 아닌 텍스처/"이미지" 데이터에 대해 동작합니다.

WebGPU는 "버퍼링된" GPUCommandEncoder 명령을 제공합니다:

그리고 "즉시" GPUQueue 연산:

텍셀 복사 중에는 동등한 텍셀 표현으로 복사됩니다. 텍셀 복사는 소스의 유효한 정상 숫자 값이 목적지에 동일한 숫자 값으로 보장될 뿐, 아래 값들의 비트 표현을 반드시 보존하지는 않습니다:

참고: 복사는 WGSL 셰이더로 수행될 수 있으므로, WGSL 부동소수점 동작이 관찰될 수 있습니다.

다음 정의들은 이 메서드들에서 사용됩니다:

11.2.1. GPUTexelCopyBufferLayout

"GPUTexelCopyBufferLayout" 은 바이트 버퍼(GPUBuffer 또는 AllowSharedBufferSource)에서 "텍셀"의 "레이아웃"을 "텍셀 복사" 연산에서 설명합니다.

dictionary GPUTexelCopyBufferLayout {
    GPUSize64 offset = 0;
    GPUSize32 bytesPerRow;
    GPUSize32 rowsPerImage;
};

텍셀 이미지는 하나 이상의 텍셀 블록 행으로 구성됩니다(여기서는 텍셀 블록 행이라 함). 텍셀 이미지의 각 텍셀 블록 행에는 같은 수의 텍셀 블록이 있어야 하며, 하나의 텍셀 이미지 내 모든 텍셀 블록은 같은 GPUTextureFormat입니다.

GPUTexelCopyBufferLayout 은 선형 메모리 내 텍셀 이미지의 레이아웃입니다. 텍스처와 GPUBuffer 간에 데이터를 복사하거나, GPUQueue에서 텍스처로 쓰기를 예약할 때 사용됩니다.

바이트 배열과 텍스처 간 복사 연산은 항상 전체 텍셀 블록 단위로 동작합니다. 텍셀 블록의 일부만 업데이트하는 것은 불가능합니다.

텍셀 블록텍셀 복사의 선형 메모리 레이아웃에서 각 텍셀 블록 행 내에 꽉 채워져 있으며, 각 텍셀 블록은 바로 앞 텍셀 블록 다음에 바로 이어집니다. 패딩은 없습니다. 복사를 포함하여 깊이·스텐실 포맷 텍스처의 특정 aspect에 대해: 스텐실 값은 바이트 배열에 꽉 채워지고, 깊이 값은 해당 타입("depth16unorm" 또는 "depth32float") 배열에 꽉 채워집니다.

offset, 타입 GPUSize64, 기본값 0

텍셀 데이터 소스(GPUTexelCopyBufferInfo.buffer 등)의 시작점부터 해당 소스 내 텍셀 데이터의 시작까지 바이트 단위 오프셋입니다.

bytesPerRow, 타입 GPUSize32

텍셀 블록 행의 시작점과 그 다음 텍셀 블록 행의 시작점 사이의 바이트 단위 간격입니다.

복사 높이/깊이가 블록 1개를 초과하여 여러 텍셀 블록 행이 있는 경우 필수입니다.

rowsPerImage, 타입 GPUSize32

해당 텍스처의 단일 텍셀 이미지텍셀 블록 행의 개수. rowsPerImage × bytesPerRow 는 데이터의 각 텍셀 이미지 시작점 간 바이트 단위 간격입니다.

복사 깊이가 블록 1개를 초과하여 여러 텍셀 이미지가 있는 경우 필수입니다.

11.2.2. GPUTexelCopyBufferInfo

"GPUTexelCopyBufferInfo" 는 "버퍼" 소스 또는 목적지에 대한 "정보"(GPUBufferGPUTexelCopyBufferLayout) 를 "텍셀 복사" 연산에서 설명합니다. copySize와 함께 GPUBuffer 내 텍셀 영역의 footprint를 설명합니다.

dictionary GPUTexelCopyBufferInfo
         : GPUTexelCopyBufferLayout {
    required GPUBuffer buffer;
};
buffer, 타입 GPUBuffer

복사되는 텍셀 데이터를 포함하거나 복사된 텍셀 데이터를 저장할 버퍼(사용되는 메서드에 따라 다름)입니다.

GPUTexelCopyBufferInfo 유효성 검사

인자:

반환값: boolean

디바이스 타임라인 단계:

  1. 다음 조건을 모두 만족할 때만 true를 반환한다:

11.2.3. GPUTexelCopyTextureInfo

"GPUTexelCopyTextureInfo" 는 "텍스처" 복사 연산의 "정보"(GPUTexture 등)를 설명합니다. copySize와 함께, 텍스처의 서브영역(동일한 mip-map 레벨 내에서 하나 이상의 연속 텍스처 서브리소스를 포함)을 설명합니다.

dictionary GPUTexelCopyTextureInfo {
    required GPUTexture texture;
    GPUIntegerCoordinate mipLevel = 0;
    GPUOrigin3D origin = {};
    GPUTextureAspect aspect = "all";
};
texture, 타입 GPUTexture

복사할 텍스처입니다.

mipLevel, 타입 GPUIntegerCoordinate, 기본값 0

복사할 texture의 mip-map 레벨입니다.

origin, 타입 GPUOrigin3D, 기본값 {}

복사할 서브영역의 원점(최소 좌표)입니다. copySize와 함께, 전체 복사 서브영역을 정의합니다.

aspect, 타입 GPUTextureAspect, 기본값 "all"

복사할 texture의 aspect를 지정합니다.

텍스처 복사 서브영역GPUTexelCopyTextureInfo copyTexture의 depth slice 또는 array layer index에 대해 다음 절차로 결정됩니다:
  1. texturecopyTexture.texture로 한다.

  2. texture.dimension이 다음 중 무엇인지에 따라:

    1d
    1. Assert index0

    2. depthSliceOrLayertexture로 한다

    2d

    depthSliceOrLayertexture의 array layer index로 한다

    3d

    depthSliceOrLayertexture의 depth slice index로 한다

  3. textureMipdepthSliceOrLayer의 mip level copyTexture.mipLevel로 한다.

  4. textureMip의 aspect copyTexture.aspect를 반환한다.

텍셀 블록 바이트 오프셋GPUTexelCopyBufferLayout bufferLayout에서 텍셀 블록 x, y, depth slice 또는 array layer z에 해당하는 GPUTexture texture 데이터에 대해 다음 절차로 결정됩니다:
  1. blockBytestexture.format텍셀 블록 복사 footprint로 한다.

  2. imageOffset을 (z × bufferLayout.rowsPerImage × bufferLayout.bytesPerRow) + bufferLayout.offset로 한다.

  3. rowOffset을 (y × bufferLayout.bytesPerRow) + imageOffset로 한다.

  4. blockOffset을 (x × blockBytes) + rowOffset로 한다.

  5. blockOffset을 반환한다.

GPUTexelCopyTextureInfo 유효성 검사(texelCopyTextureInfo, copySize)

인자:

반환값: boolean

디바이스 타임라인 단계:

  1. blockWidthtexelCopyTextureInfo.texture.format텍셀 블록 너비로 한다.

  2. blockHeighttexelCopyTextureInfo.texture.format텍셀 블록 높이로 한다.

  3. 다음 조건을 모두 만족할 때만 true를 반환한다:

텍스처 버퍼 복사 유효성 검사(texelCopyTextureInfo, bufferLayout, dataLength, copySize, textureUsage, aligned)

인자:

반환값: boolean

디바이스 타임라인 단계:

  1. texturetexelCopyTextureInfo.texture로 한다

  2. aspectSpecificFormat = texture.format로 한다.

  3. offsetAlignment = texture.format텍셀 블록 복사 footprint로 한다.

  4. 다음 조건을 모두 만족할 때만 true를 반환한다:

    1. GPUTexelCopyTextureInfo 유효성 검사(texelCopyTextureInfo, copySize)가 true를 반환함.

    2. texture.sampleCount 값이 1임.

    3. texture.usage 값에 textureUsage가 포함되어 있음.

    4. texture.format 값이 깊이·스텐실 포맷인 경우:

      1. texelCopyTextureInfo.aspect 값이 texture.format의 단일 aspect를 참조해야 함.

      2. textureUsage가 다음 중 하나인 경우:

        COPY_SRC

        그 aspect는 텍셀 복사 소스여야 하며, § 26.1.2 깊이-스텐실 포맷에 따름.

        COPY_DST

        그 aspect는 텍셀 복사 목적지여야 하며, § 26.1.2 깊이-스텐실 포맷에 따름.

      3. aspectSpecificFormat측면별 포맷으로 설정하며, § 26.1.2 깊이-스텐실 포맷에 따름.

      4. offsetAlignment을 4로 설정함.

    5. alignedtrue인 경우:

      1. bufferLayout.offset 값이 offsetAlignment의 배수여야 함.

    6. 직렬 텍스처 데이터 유효성 검사(bufferLayout, dataLength, aspectSpecificFormat, copySize)가 성공해야 함.

11.2.4. GPUCopyExternalImageDestInfo

WebGPU 텍스처는 색상에 대한 의미론적 메타데이터 없이 원시 숫자 데이터를 저장합니다. 그러나 copyExternalImageToTexture() 는 색상을 설명하는 소스에서 복사합니다.

"GPUCopyExternalImageDestInfo" 는 "copyExternalImageToTexture()" 연산의 "목적지"에 대한 "정보"를 설명합니다. 이것은 GPUTexelCopyTextureInfo 이며, 여기에 색상 공간/인코딩 및 알파 프리멀티플리케이션 메타데이터가 추가로 태그되어 있으므로, 복사 시 의미론적 색상 데이터가 보존될 수 있습니다. 이 메타데이터는 복사 연산의 의미에만 영향을 주며, 목적지 텍스처 객체의 상태나 의미에는 영향을 주지 않습니다.

dictionary GPUCopyExternalImageDestInfo
         : GPUTexelCopyTextureInfo {
    PredefinedColorSpace colorSpace = "srgb";
    boolean premultipliedAlpha = false;
};
colorSpace, 타입 PredefinedColorSpace, 기본값 "srgb"

목적지 텍스처에 데이터를 인코딩할 때 사용하는 색상 공간 및 인코딩을 설명합니다.

변환 결과는 대상 텍스처 포맷이 표현 가능하다면 [0, 1] 범위를 벗어난 값이 기록될 수 있습니다. 그렇지 않으면 결과가 대상 텍스처 포맷의 범위로 클램프됩니다.

참고: colorSpace 가 소스 이미지와 일치하면, 변환이 필요하지 않을 수 있습니다. § 3.10.2 색상 공간 변환 생략을 참고하세요.

premultipliedAlpha, 타입 boolean, 기본값 false

텍스처에 기록되는 데이터의 RGB 채널을 알파 채널로 프리멀티플리케이션할지 여부를 설명합니다.

이 옵션이 true이고 source 도 프리멀티플라이된 경우, 소스의 RGB 값은 해당 알파 값을 초과하더라도 그대로 보존되어야 합니다.

참고: premultipliedAlpha 가 소스 이미지와 일치하면, 변환이 필요하지 않을 수 있습니다. § 3.10.2 색상 공간 변환 생략을 참고하세요.

11.2.5. GPUCopyExternalImageSourceInfo

"GPUCopyExternalImageSourceInfo" 는 "copyExternalImageToTexture()" 연산의 "소스"에 대한 "정보"를 설명합니다.

typedef (ImageBitmap or
         ImageData or
         HTMLImageElement or
         HTMLVideoElement or
         VideoFrame or
         HTMLCanvasElement or
         OffscreenCanvas) GPUCopyExternalImageSource;

dictionary GPUCopyExternalImageSourceInfo {
    required GPUCopyExternalImageSource source;
    GPUOrigin2D origin = {};
    boolean flipY = false;
};

GPUCopyExternalImageSourceInfo 는 다음 멤버들을 갖습니다:

source, 타입 GPUCopyExternalImageSource

텍셀 복사의 소스입니다. 복사 소스 데이터는 copyExternalImageToTexture() 호출 시점에 캡처됩니다. 소스 크기는 외부 소스 크기 표에 따라 결정됩니다.

origin, 타입 GPUOrigin2D, 기본값 {}

복사할 서브영역의 원점(최소, 좌상단)입니다. copySize와 함께 전체 복사 서브영역을 정의합니다.

flipY, 타입 boolean, 기본값 false

소스 이미지가 수직으로 뒤집혀 있는지 여부를 설명합니다.

이 옵션이 true면, 복사가 수직으로 반전되어 진행됩니다: 소스 영역의 맨 아래 행이 목적지 영역의 첫 행에 복사되고, 그 다음이 이어집니다. origin 옵션은 여전히 소스 이미지의 좌상단 기준이며, 아래로 증가합니다.

외부 소스를 텍스처 생성 또는 복사에 사용할 때, 외부 소스 크기 는 소스 타입에 따라 다음 표와 같이 정의됩니다:

외부 소스 타입 크기
ImageBitmap ImageBitmap.width, ImageBitmap.height
HTMLImageElement HTMLImageElement.naturalWidth, HTMLImageElement.naturalHeight
HTMLVideoElement 프레임의 내재적 너비, 프레임의 내재적 높이
VideoFrame VideoFrame.displayWidth, VideoFrame.displayHeight
ImageData ImageData.width, ImageData.height
HTMLCanvasElement 또는 OffscreenCanvas CanvasRenderingContext2D 또는 GPUCanvasContext가 있는 경우 HTMLCanvasElement.width, HTMLCanvasElement.height
HTMLCanvasElement 또는 OffscreenCanvas WebGLRenderingContextBase가 있는 경우 WebGLRenderingContextBase.drawingBufferWidth, WebGLRenderingContextBase.drawingBufferHeight
HTMLCanvasElement 또는 OffscreenCanvas ImageBitmapRenderingContext가 있는 경우 ImageBitmapRenderingContext의 내부 출력 비트맵 ImageBitmap.width, ImageBitmap.height

11.2.6. 서브루틴

GPUTexelCopyTextureInfo 실제 서브리소스 크기

인자:

반환값: GPUExtent3D

texelCopyTextureInfoGPUTexelCopyTextureInfo 실제 서브리소스 크기는 다음과 같이 계산됩니다:

width, height, depthOrArrayLayers는 각각 texelCopyTextureInfo.texture subresource물리적 mip레벨별 텍스처 크기에서 mipmap level texelCopyTextureInfo.mipLevel의 width, height, depth 입니다.

직렬 텍스처 데이터 유효성 검사(layout, byteSize, format, copyExtent)

인자:

GPUTexelCopyBufferLayout layout

직렬 텍스처 데이터의 레이아웃입니다.

GPUSize64 byteSize

직렬 데이터의 총 바이트 크기입니다.

GPUTextureFormat format

텍스처의 포맷입니다.

GPUExtent3D copyExtent

복사할 텍스처 범위(크기)입니다.

디바이스 타임라인 단계:

  1. Let:

  2. 다음 입력 검증 요구사항을 만족하지 않으면 실패:

  3. Let:

    참고: 이 기본값들은 항상 0과 곱해지기 때문에 영향이 없습니다.

  4. requiredBytesInCopy를 0으로 한다.

  5. copyExtent.depthOrArrayLayers > 0인 경우:

    1. requiredBytesInCopy += bytesPerRow × rowsPerImage × (copyExtent.depthOrArrayLayers − 1)

    2. heightInBlocks > 0인 경우:

      1. requiredBytesInCopy += bytesPerRow × (heightInBlocks − 1) + bytesInLastRow

  6. 다음 조건을 만족하지 않으면 실패:

    • 레이아웃이 직렬 데이터 내에 들어가야 함: layout.offset + requiredBytesInCopybyteSize.

텍스처 복사 범위 유효성 검사

인자:

GPUTexelCopyTextureInfo texelCopyTextureInfo

복사 대상 텍스처 서브리소스와 복사 원점입니다.

GPUExtent3D copySize

텍스처의 크기입니다.

디바이스 타임라인 단계:

  1. blockWidth = texelCopyTextureInfo.texture.format텍셀 블록 너비.

  2. blockHeight = texelCopyTextureInfo.texture.format텍셀 블록 높이.

  3. subresourceSize = texelCopyTextureInfoGPUTexelCopyTextureInfo 실제 서브리소스 크기입니다.

  4. 다음 조건들을 모두 만족하는지 반환:

    참고: 텍스처 복사 범위는 물리적(올림 처리된) 크기에 대해 검증되므로, 압축 포맷의 경우 텍스처 내부에 완전히 포함되지 않는 텍스처 블록을 접근할 수 있습니다.

GPUTextureFormat format1, format2복사 호환(copy-compatible)이려면:
텍스처 복사를 위한 서브리소스 집합(texelCopyTextureInfo, copySize) 은 texture = texelCopyTextureInfo.texture 에 대해, 각 서브리소스 s가 다음을 만족하는 서브리소스의 부분집합입니다:

12. 커맨드 버퍼

커맨드 버퍼는 GPU 명령(큐 타임라인 단계 블록)의 사전 기록된 목록으로, GPUQueue에 제출하여 실행할 수 있습니다. 각 GPU 명령 은 상태 설정, 드로우, 리소스 복사 등 큐 타임라인에서 수행할 작업을 나타냅니다.

GPUCommandBuffer 는 한 번만 제출할 수 있으며, 제출 이후에는 무효화됩니다. 여러 번 제출해 렌더링 명령을 재사용하려면 GPURenderBundle을 사용하세요.

12.1. GPUCommandBuffer

[Exposed=(Window, Worker), SecureContext]
interface GPUCommandBuffer {
};
GPUCommandBuffer includes GPUObjectBase;

GPUCommandBuffer 는 다음 디바이스 타임라인 속성을 갖습니다:

[[command_list]], 타입은 list<GPU 명령>, 읽기 전용

커맨드 버퍼가 제출될 때 큐 타임라인에서 실행될 list 형태의 GPU 명령 목록입니다.

[[renderState]], 타입은 RenderState, 초기값은 null

실행 중인 렌더 패스 명령에 사용되는 현재 상태입니다.

12.1.1. 커맨드 버퍼 생성

dictionary GPUCommandBufferDescriptor
         : GPUObjectDescriptorBase {
};

13. 커맨드 인코딩

13.1. GPUCommandsMixin

GPUCommandsMixin 은 모든 커맨드 인코딩 인터페이스에 공통적인 상태를 정의합니다. 메서드는 없습니다.

interface mixin GPUCommandsMixin {
};

GPUCommandsMixin 은 다음 디바이스 타임라인 속성을 갖습니다:

[[state]], 타입 인코더 상태, 초기값 "open"

인코더의 현재 상태입니다.

[[commands]], 타입 list<GPU 명령>, 초기값 []

이 커맨드를 포함하는 GPUCommandBuffer가 제출될 때 listGPU 명령큐 타임라인에서 실행됩니다.

인코더 상태는 다음 중 하나일 수 있습니다:

"open"

인코더가 새로운 커맨드 인코딩에 사용 가능합니다.

"locked"

인코더가 자식 인코더에 의해 잠겼기 때문에 사용할 수 없습니다. 즉, GPUCommandEncoder이고, GPURenderPassEncoder 또는 GPUComputePassEncoder 가 활성화된 상태입니다. 패스가 종료되면 인코더는 다시 "open" 상태가 됩니다.

이 상태에서 커맨드를 발행하면 인코더가 무효화됩니다.

"ended"

인코더가 종료되어 새로운 커맨드를 인코딩할 수 없습니다.

이 상태에서 커맨드를 발행하면 유효성 오류가 생성됩니다.

인코더 상태 검증GPUCommandsMixin encoder에 대해 실행하려면
다음 디바이스 타임라인 단계를 수행합니다:
  1. encoder.[[state]] 값이 다음 중 무엇인지에 따라:

    "open"

    true 반환.

    "locked"

    인코더 무효화false 반환.

    "ended"

    유효성 오류 생성false 반환.

커맨드 대기열에 넣기GPUCommandsMixin encoder 에서 GPU 명령 command의 단계를 발행하려면, 다음 디바이스 타임라인 단계를 수행합니다:
  1. Append commandencoder.[[commands]]에 추가합니다.

  2. commandGPUCommandBuffer에서 실행될 때:

    1. command의 단계를 실행합니다.

13.2. GPUCommandEncoder

[Exposed=(Window, Worker), SecureContext]
interface GPUCommandEncoder {
    GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
    GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {});

    undefined copyBufferToBuffer(
        GPUBuffer source,
        GPUBuffer destination,
        optional GPUSize64 size);
    undefined copyBufferToBuffer(
        GPUBuffer source,
        GPUSize64 sourceOffset,
        GPUBuffer destination,
        GPUSize64 destinationOffset,
        optional GPUSize64 size);

    undefined copyBufferToTexture(
        GPUTexelCopyBufferInfo source,
        GPUTexelCopyTextureInfo destination,
        GPUExtent3D copySize);

    undefined copyTextureToBuffer(
        GPUTexelCopyTextureInfo source,
        GPUTexelCopyBufferInfo destination,
        GPUExtent3D copySize);

    undefined copyTextureToTexture(
        GPUTexelCopyTextureInfo source,
        GPUTexelCopyTextureInfo destination,
        GPUExtent3D copySize);

    undefined clearBuffer(
        GPUBuffer buffer,
        optional GPUSize64 offset = 0,
        optional GPUSize64 size);

    undefined resolveQuerySet(
        GPUQuerySet querySet,
        GPUSize32 firstQuery,
        GPUSize32 queryCount,
        GPUBuffer destination,
        GPUSize64 destinationOffset);

    GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {});
};
GPUCommandEncoder includes GPUObjectBase;
GPUCommandEncoder includes GPUCommandsMixin;
GPUCommandEncoder includes GPUDebugCommandsMixin;

13.2.1. 커맨드 인코더 생성

dictionary GPUCommandEncoderDescriptor
         : GPUObjectDescriptorBase {
};
createCommandEncoder(descriptor)

GPUCommandEncoder를 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createCommandEncoder(descriptor) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUCommandEncoderDescriptor 생성할 GPUCommandEncoder의 설명.

반환값: GPUCommandEncoder

컨텐트 타임라인 단계:

  1. e! create a new WebGPU object(this, GPUCommandEncoder, descriptor)로 한다.

  2. this디바이스 타임라인에서 초기화 단계를 실행한다.

  3. e를 반환한다.

디바이스 타임라인 초기화 단계:
  1. 아래 조건 중 하나라도 충족하지 않으면 유효성 오류 생성, e를 무효화하고 반환.

    • thislost 상태가 아니어야 함.

GPUCommandEncoder를 생성하고, 버퍼를 삭제(clear)하는 커맨드를 인코딩한 뒤, 인코더를 마쳐 GPUCommandBuffer를 얻고, GPUQueue에 제출합니다.
const commandEncoder = gpuDevice.createCommandEncoder();
commandEncoder.clearBuffer(buffer);
const commandBuffer = commandEncoder.finish();
gpuDevice.queue.submit([commandBuffer]);

13.3. 패스 인코딩

beginRenderPass(descriptor)

descriptor로 설명된 렌더 패스 인코딩을 시작합니다.

호출 대상: GPUCommandEncoder this.

인자:

GPUCommandEncoder.beginRenderPass(descriptor) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPURenderPassDescriptor 생성할 GPURenderPassEncoder의 설명.

반환값: GPURenderPassEncoder

컨텐트 타임라인 단계:

  1. descriptor.colorAttachments의 각 null이 아닌 colorAttachment에 대해:

    1. colorAttachment.clearValue제공된 경우:

      1. ? GPUColor 모양 유효성 검증(colorAttachment.clearValue).

  2. pass를 새 GPURenderPassEncoder 객체로 한다.

  3. this디바이스 타임라인에서 초기화 단계를 실행한다.

  4. pass를 반환한다.

디바이스 타임라인 초기화 단계:
  1. 인코더 상태 검증this에 대해 실행한다. false가 반환되면 pass를 무효화하고 반환.

  2. this.[[state]] 값을 "locked"로 설정.

  3. attachmentRegionslist([texture subresource, depthSlice?] 쌍)로 초기화한다. 각 쌍은 렌더링되는 텍스처 영역을 설명하며, "3d" 텍스처는 단일 depth slice를 포함한다.

  4. descriptor.colorAttachments의 각 null이 아닌 colorAttachment에 대해:

    1. [colorAttachment.view, colorAttachment.depthSlice ?? null]을 attachmentRegions에 추가.

    2. colorAttachment.resolveTargetnull이 아니면:

      1. [colorAttachment.resolveTarget, undefined]을 attachmentRegions에 추가.

  5. 아래 조건 중 하나라도 충족하지 않으면, pass를 무효화하고 반환.

    • descriptorValid Usage 규칙을 this.[[device]]에서 충족해야 함.

    • attachmentRegions에 있는 텍스처 영역 집합은 쌍별로 겹치지 않아야 함. 즉, 두 텍스처 영역이 겹치면 안 됨.

  6. attachment 사용으로 attachmentRegions의 각 texture subresourcepass.[[usage scope]]에 추가.

  7. depthStencilAttachmentdescriptor.depthStencilAttachment로 한다.

  8. depthStencilAttachmentnull이 아니면:

    1. depthStencilViewdepthStencilAttachment.view로 한다.

    2. depthReadOnly가 true면 attachment-read 사용으로, 아니면 attachment 사용으로 depthStencilViewdepth subresourcepass.[[usage scope]]에 추가.

    3. stencilReadOnly가 true면 attachment-read 사용으로, 아니면 attachment 사용으로 depthStencilViewstencil subresourcepass.[[usage scope]]에 추가.

    4. pass.[[depthReadOnly]] 값을 depthStencilAttachment.depthReadOnly로 설정.

    5. pass.[[stencilReadOnly]] 값을 depthStencilAttachment.stencilReadOnly로 설정.

  9. pass.[[layout]] 값을 derive render targets layout from pass(descriptor)로 설정.

  10. descriptor.timestampWrites제공된 경우:

    1. timestampWritesdescriptor.timestampWrites로 한다.

    2. timestampWrites.beginningOfPassWriteIndex제공된 경우, append GPU 명령을 this.[[commands]]에 추가하며, 아래 단계를 실행:

      1. 패스 커맨드 실행 전, 현재 큐 타임스탬프timestampWrites.beginningOfPassWriteIndex 인덱스에 timestampWrites.querySet에 기록.

    3. timestampWrites.endOfPassWriteIndex제공된 경우, pass.[[endTimestampWrite]] 에 아래 GPU 명령 단계를 설정:

      1. 패스 커맨드 실행 후, 현재 큐 타임스탬프timestampWrites.endOfPassWriteIndex 인덱스에 timestampWrites.querySet에 기록.

  11. pass.[[drawCount]] 값을 0으로 설정.

  12. pass.[[maxDrawCount]] 값을 descriptor.maxDrawCount로 설정.

  13. pass.[[maxDrawCount]] 값을 descriptor.maxDrawCount로 설정.

  14. Enqueue a commandthis에 실행하여, 실행 시 큐 타임라인에서 이후 단계를 실행.

큐 타임라인 단계:
  1. 현재 실행 중인 GPUCommandBuffer[[renderState]] 를 새 RenderState로 한다.

  2. [[renderState]].[[colorAttachments]] 값을 descriptor.colorAttachments로 설정.

  3. [[renderState]].[[depthStencilAttachment]] 값을 descriptor.depthStencilAttachment로 설정.

  4. descriptor.colorAttachments의 각 null이 아닌 colorAttachment에 대해:

    1. colorViewcolorAttachment.view로 한다.

    2. colorView.[[descriptor]].dimension 값에 따라:

      "3d"

      colorSubregioncolorAttachment.depthSlice로 한다.

      그 외

      colorSubregioncolorView로 한다.

    3. colorAttachment.loadOp 값에 따라:

      "load"

      colorSubregion에 연결된 프레임버퍼 메모리colorSubregion의 내용을 로드해야 함.

      "clear"

      colorSubregion에 연결된 프레임버퍼 메모리의 모든 텍셀colorAttachment.clearValue로 설정.

  5. depthStencilAttachmentnull이 아니면:

    1. depthStencilAttachment.depthLoadOp 값에 따라:

      제공되지 않은 경우

      Assert depthStencilAttachment.depthReadOnlytrue임을 보장하고, depthStencilViewdepth subresource프레임버퍼 메모리에 로드함.

      "load"

      depthStencilViewdepth subresource프레임버퍼 메모리에 로드함.

      "clear"

      depthStencilViewdepth subresource에 연결된 프레임버퍼 메모리의 모든 텍셀depthStencilAttachment.depthClearValue로 설정.

    2. depthStencilAttachment.stencilLoadOp 값에 따라:

      제공되지 않은 경우

      Assert depthStencilAttachment.stencilReadOnlytrue임을 보장하고, depthStencilViewstencil subresource프레임버퍼 메모리에 로드함.

      "load"

      depthStencilViewstencil subresource프레임버퍼 메모리에 로드함.

      "clear"

      depthStencilViewstencil subresource에 연결된 프레임버퍼 메모리의 모든 텍셀depthStencilAttachment.stencilClearValue로 설정.

참고: 읽기 전용 depth-stencil 어태치먼트는 암묵적으로 "load" 연산을 수행한 것으로 처리됩니다. 읽기 전용 어태치먼트에서 load op를 명시하지 않아야 한다는 유효성 검증은 GPURenderPassDepthStencilAttachment Valid Usage에서 수행됩니다.

beginComputePass(descriptor)

descriptor로 설명된 컴퓨트 패스 인코딩을 시작합니다.

호출 대상: GPUCommandEncoder this.

인자:

GPUCommandEncoder.beginComputePass(descriptor) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUComputePassDescriptor

반환값: GPUComputePassEncoder

컨텐트 타임라인 단계:

  1. pass를 새 GPUComputePassEncoder 객체로 한다.

  2. this디바이스 타임라인에서 초기화 단계를 실행한다.

  3. pass를 반환한다.

디바이스 타임라인 초기화 단계:
  1. 인코더 상태 검증this에 대해 실행한다. false가 반환되면 pass를 무효화하고 반환.

  2. this.[[state]] 값을 "locked"로 설정.

  3. 아래 조건 중 하나라도 충족하지 않으면, pass를 무효화하고 반환.

  4. descriptor.timestampWrites제공된 경우:

    1. timestampWritesdescriptor.timestampWrites로 한다.

    2. timestampWrites.beginningOfPassWriteIndex제공된 경우, append GPU 명령을 this.[[commands]]에 추가하며, 아래 단계를 실행:

      1. 패스 커맨드 실행 전, 현재 큐 타임스탬프timestampWrites.beginningOfPassWriteIndex 인덱스에 timestampWrites.querySet에 기록.

    3. timestampWrites.endOfPassWriteIndex제공된 경우, pass.[[endTimestampWrite]] 에 아래 GPU 명령 단계를 설정:

      1. 패스 커맨드 실행 후, 현재 큐 타임스탬프timestampWrites.endOfPassWriteIndex 인덱스에 timestampWrites.querySet에 기록.

13.4. 버퍼 복사 커맨드

copyBufferToBuffer()는 두 가지 오버로드를 지원합니다:

copyBufferToBuffer(source, destination, size)

간략 표기, copyBufferToBuffer(source, 0, destination, 0, size)와 동일합니다.

copyBufferToBuffer(source, sourceOffset, destination, destinationOffset, size)

GPUCommandEncoder에 한 GPUBuffer의 서브영역에서 다른 GPUBuffer의 서브영역으로 데이터를 복사하는 커맨드를 인코드합니다.

호출 대상: GPUCommandEncoder this.

인자:

GPUCommandEncoder.copyBufferToBuffer(source, sourceOffset, destination, destinationOffset, size) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
source GPUBuffer 복사할 GPUBuffer.
sourceOffset GPUSize64 source에서 복사를 시작할 바이트 오프셋.
destination GPUBuffer 복사 대상 GPUBuffer.
destinationOffset GPUSize64 destination에 복사 데이터가 저장될 바이트 오프셋.
size GPUSize64 복사할 바이트 수.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행한다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. sizeundefined이면, sizesource.sizesourceOffset으로 설정.

  3. 아래 조건 중 하나라도 충족하지 않으면, this를 무효화하고 반환.

  4. Enqueue a commandthis에 실행하여, 실행 시 큐 타임라인에서 이후 단계를 실행.

큐 타임라인 단계:
  1. sourceOffset에서 시작하여 sourcesize 바이트를 destinationOffset에서 시작하여 destination에 복사합니다.

clearBuffer(buffer, offset, size)

GPUCommandEncoderGPUBuffer의 일부 영역을 0으로 채우는 커맨드를 인코드합니다.

호출 대상: GPUCommandEncoder this.

인자:

GPUCommandEncoder.clearBuffer(buffer, offset, size) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
buffer GPUBuffer 초기화할 GPUBuffer.
offset GPUSize64 buffer에서 영역을 초기화할 바이트 오프셋.
size GPUSize64 초기화할 영역의 바이트 크기. 기본값은 버퍼 크기에서 offset만큼 뺀 값.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. size가 지정되지 않은 경우, sizemax(0, buffer.size - offset)로 설정.

  3. 아래 조건 중 하나라도 충족하지 않으면, this를 무효화하고 반환.

  4. Enqueue a commandthis에 실행하여, 실행 시 큐 타임라인에서 이후 단계를 실행.

큐 타임라인 단계:
  1. offset에서 시작하여 buffersize 바이트를 0으로 설정합니다.

13.5. 텍셀 복사 커맨드

copyBufferToTexture(source, destination, copySize)

GPUCommandEncoderGPUBuffer의 일부 영역에서 하나 이상의 연속 텍스처 서브리소스의 일부 영역으로 데이터를 복사하는 커맨드를 인코드합니다.

호출 대상: GPUCommandEncoder this.

인자:

GPUCommandEncoder.copyBufferToTexture(source, destination, copySize) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
source GPUTexelCopyBufferInfo copySize와 함께, 소스 버퍼 영역을 정의함.
destination GPUTexelCopyTextureInfo copySize와 함께, 목적지 텍스처 서브리소스 영역을 정의함.
copySize GPUExtent3D

반환값: undefined

컨텐트 타임라인 단계:

  1. GPUOrigin3D 형태 유효성 검증(destination.origin).

  2. GPUExtent3D 형태 유효성 검증(copySize).

  3. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. alignedtrue로 한다.

  3. dataLengthsource.buffer.size로 한다.

  4. 아래 조건 중 하나라도 충족하지 않으면, this를 무효화하고 반환.

  5. Enqueue a commandthis에 실행하여, 실행 시 큐 타임라인에서 이후 단계를 실행.

큐 타임라인 단계:
  1. blockWidthdestination.texture텍셀 블록 너비로 한다.

  2. blockHeightdestination.texture텍셀 블록 높이로 한다.

  3. dstOrigindestination.origin로 한다.

  4. dstBlockOriginX를 (dstOrigin.x ÷ blockWidth)로 한다.

  5. dstBlockOriginY를 (dstOrigin.y ÷ blockHeight)로 한다.

  6. blockColumns를 (copySize.width ÷ blockWidth)로 한다.

  7. blockRows를 (copySize.height ÷ blockHeight)로 한다.

  8. Assert dstBlockOriginX, dstBlockOriginY, blockColumns, blockRows가 정수임을 보장한다.

  9. z in [0, copySize.depthOrArrayLayers − 1]에 대해:

    1. dstSubregiontexture copy sub-region(z + dstOrigin.z) of destination로 한다.

    2. y in [0, blockRows − 1]에 대해:

      1. x in [0, blockColumns − 1]에 대해:

        1. blockOffsettexel block byte offset of source for (x, y, z) of destination.texture로 한다.

        2. dstSubregion의 (dstBlockOriginX + x, dstBlockOriginY + y) 텍셀 블록을 source.bufferblockOffset 위치의 동등 텍셀 표현으로 설정합니다.

copyTextureToBuffer(source, destination, copySize)

GPUCommandEncoder에 하나 이상의 연속 텍스처 서브리소스의 일부 영역에서 GPUBuffer의 일부 영역으로 데이터를 복사하는 커맨드를 인코드합니다.

호출 대상: GPUCommandEncoder this.

인자:

GPUCommandEncoder.copyTextureToBuffer(source, destination, copySize) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
source GPUTexelCopyTextureInfo copySize와 함께, 소스 텍스처 서브리소스 영역을 정의함.
destination GPUTexelCopyBufferInfo copySize와 함께, 목적지 버퍼 영역을 정의함.
copySize GPUExtent3D

반환값: undefined

컨텐트 타임라인 단계:

  1. GPUOrigin3D 형태 유효성 검증(source.origin).

  2. GPUExtent3D 형태 유효성 검증(copySize).

  3. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. alignedtrue로 한다.

  3. dataLengthdestination.buffer.size로 한다.

  4. 아래 조건 중 하나라도 충족하지 않으면, this를 무효화하고 반환.

  5. Enqueue a commandthis에 실행하여, 실행 시 큐 타임라인에서 이후 단계를 실행.

큐 타임라인 단계:
  1. blockWidthsource.texture텍셀 블록 너비로 한다.

  2. blockHeightsource.texture텍셀 블록 높이로 한다.

  3. srcOriginsource.origin로 한다.

  4. srcBlockOriginX를 (srcOrigin.x ÷ blockWidth)로 한다.

  5. srcBlockOriginY를 (srcOrigin.y ÷ blockHeight)로 한다.

  6. blockColumns를 (copySize.width ÷ blockWidth)로 한다.

  7. blockRows를 (copySize.height ÷ blockHeight)로 한다.

  8. Assert srcBlockOriginX, srcBlockOriginY, blockColumns, blockRows가 정수임을 보장한다.

  9. z in [0, copySize.depthOrArrayLayers − 1]에 대해:

    1. srcSubregiontexture copy sub-region(z + srcOrigin.z) of source로 한다.

    2. y in [0, blockRows − 1]에 대해:

      1. x in [0, blockColumns − 1]에 대해:

        1. blockOffsettexel block byte offset of destination for (x, y, z) of source.texture로 한다.

        2. destination.bufferblockOffset 위치에 동등 텍셀 표현텍셀 블록 (srcBlockOriginX + x, srcBlockOriginY + y) of srcSubregion을 설정한다.

copyTextureToTexture(source, destination, copySize)

GPUCommandEncoder에 하나 이상의 연속 텍스처 서브리소스의 일부 영역에서 다른 하나 이상의 연속 텍스처 서브리소스의 일부 영역으로 데이터를 복사하는 커맨드를 인코드합니다.

호출 대상: GPUCommandEncoder this.

인자:

GPUCommandEncoder.copyTextureToTexture(source, destination, copySize) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
source GPUTexelCopyTextureInfo copySize와 함께, 소스 텍스처 서브리소스 영역을 정의함.
destination GPUTexelCopyTextureInfo copySize와 함께, 목적지 텍스처 서브리소스 영역을 정의함.
copySize GPUExtent3D

반환값: undefined

컨텐트 타임라인 단계:

  1. GPUOrigin3D 형태 유효성 검증(source.origin).

  2. GPUOrigin3D 형태 유효성 검증(destination.origin).

  3. GPUExtent3D 형태 유효성 검증(copySize).

  4. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. 아래 조건 중 하나라도 충족하지 않으면, this를 무효화하고 반환.

  3. Enqueue a commandthis에 실행하여, 실행 시 큐 타임라인에서 이후 단계를 실행.

큐 타임라인 단계:
  1. blockWidthsource.texture텍셀 블록 너비로 한다.

  2. blockHeightsource.texture텍셀 블록 높이로 한다.

  3. srcOriginsource.origin로 한다.

  4. srcBlockOriginX를 (srcOrigin.x ÷ blockWidth)로 한다.

  5. srcBlockOriginY를 (srcOrigin.y ÷ blockHeight)로 한다.

  6. dstOrigindestination.origin로 한다.

  7. dstBlockOriginX를 (dstOrigin.x ÷ blockWidth)로 한다.

  8. dstBlockOriginY를 (dstOrigin.y ÷ blockHeight)로 한다.

  9. blockColumns를 (copySize.width ÷ blockWidth)로 한다.

  10. blockRows를 (copySize.height ÷ blockHeight)로 한다.

  11. Assert srcBlockOriginX, srcBlockOriginY, dstBlockOriginX, dstBlockOriginY, blockColumns, blockRows가 정수임을 보장한다.

  12. z in [0, copySize.depthOrArrayLayers − 1]에 대해:

    1. srcSubregiontexture copy sub-region(z + srcOrigin.z) of source로 한다.

    2. dstSubregiontexture copy sub-region(z + dstOrigin.z) of destination로 한다.

    3. y in [0, blockRows − 1]에 대해:

      1. x in [0, blockColumns − 1]에 대해:

        1. dstSubregion의 (dstBlockOriginX + x, dstBlockOriginY + y) 텍셀 블록을 srcSubregion의 (srcBlockOriginX + x, srcBlockOriginY + y) 동등 텍셀 표현텍셀 블록으로 설정한다.

13.6. 쿼리

resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset)

GPUQuerySet의 쿼리 결과를 GPUBuffer의 범위로 내보내는 커맨드를 인코드합니다.

호출 대상: GPUCommandEncoder this.

인자:

GPUCommandEncoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, destinationOffset) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
querySet GPUQuerySet
firstQuery GPUSize32
queryCount GPUSize32
destination GPUBuffer
destinationOffset GPUSize64

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. 아래 조건 중 하나라도 충족하지 않으면, this를 무효화하고 반환.

  3. Enqueue a commandthis에 실행하여, 실행 시 큐 타임라인에서 이후 단계를 실행.

큐 타임라인 단계:
  1. queryIndexfirstQuery로 한다.

  2. offsetdestinationOffset로 한다.

  3. queryIndex < firstQuery + queryCount인 동안:

    1. destinationoffset 위치의 8 바이트를 querySetqueryIndex 값으로 설정한다.

    2. queryIndexqueryIndex + 1로 설정.

    3. offsetoffset + 8로 설정.

13.7. 최종화

GPUCommandBufferGPUCommandEncoder로 기록된 커맨드들을 담아, finish()를 호출하여 생성할 수 있습니다. 한번 finish()가 호출되면, 해당 커맨드 인코더는 더 이상 사용할 수 없습니다.

finish(descriptor)

커맨드 시퀀스 기록을 완료하고, 이에 해당하는 GPUCommandBuffer를 반환합니다.

호출 대상: GPUCommandEncoder this.

인자:

GPUCommandEncoder.finish(descriptor) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUCommandBufferDescriptor

반환값: GPUCommandBuffer

컨텐트 타임라인 단계:

  1. commandBuffer를 새 GPUCommandBuffer로 한다.

  2. this.[[device]]디바이스 타임라인에서 finish steps를 실행한다.

  3. commandBuffer를 반환한다.

디바이스 타임라인 finish steps:
  1. 아래 모든 요구사항을 만족하면 validationSucceededtrue로, 아니면 false로 한다.

  2. this.[[state]] 값을 "ended"로 설정.

  3. validationSucceededfalse면:

    1. 유효성 오류 생성.

    2. 무효화된 GPUCommandBuffer를 반환.

  4. commandBuffer.[[command_list]] 값을 this.[[commands]]로 설정.

14. 프로그래머블 패스

interface mixin GPUBindingCommandsMixin {
    undefined setBindGroup(GPUIndex32 index, GPUBindGroup? bindGroup,
        optional sequence<GPUBufferDynamicOffset> dynamicOffsets = []);

    undefined setBindGroup(GPUIndex32 index, GPUBindGroup? bindGroup,
        [AllowShared] Uint32Array dynamicOffsetsData,
        GPUSize64 dynamicOffsetsDataStart,
        GPUSize32 dynamicOffsetsDataLength);
};

GPUBindingCommandsMixinGPUObjectBaseGPUCommandsMixin 멤버가 동일 객체에 존재함을 가정합니다. 반드시 해당 믹스인들을 포함하는 인터페이스에서만 포함되어야 합니다.

GPUBindingCommandsMixin 은 다음 디바이스 타임라인 속성을 갖습니다:

[[bind_groups]], 타입 ordered map<GPUIndex32, GPUBindGroup>, 초기값은 empty

각 인덱스의 현재 GPUBindGroup 값입니다.

[[dynamic_offsets]], 타입 ordered map<GPUIndex32, list<GPUBufferDynamicOffset>>, 초기값은 empty

[[bind_groups]] 항목의 현재 dynamic offset 값입니다.

14.1. 바인드 그룹

setBindGroup()는 두 가지 오버로드가 있습니다:

setBindGroup(index, bindGroup, dynamicOffsets)

주어진 인덱스에 대해 현재 GPUBindGroup을 설정합니다.

호출 대상: GPUBindingCommandsMixin this.

인자:

index, 타입 GPUIndex32, non-nullable, 필수

바인드 그룹을 설정할 인덱스입니다.

bindGroup, 타입 GPUBindGroup, nullable, 필수

이후 렌더/컴퓨트 커맨드에 사용할 바인드 그룹입니다.

dynamicOffsets, 타입 sequence<GPUBufferDynamicOffset>, non-nullable, 기본값 []

bindGroup에서 buffer.hasDynamicOffset 로 표시된 각 항목에 대해 바이트 단위 버퍼 오프셋을 담은 배열이며, GPUBindGroupLayoutEntry.binding 순서대로 정렬되어 있습니다. 추가적인 상세는 노트 참고.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. bindGroupnull이면 dynamicOffsetCount를 0으로, 아니면 bindGroup.[[layout]].[[dynamicOffsetCount]]로 한다.

  3. 아래 요구사항 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  4. bindGroupnull인 경우:

    1. Remove this.[[bind_groups]][index].

    2. Remove this.[[dynamic_offsets]][index].

    그 외의 경우:

    1. 아래 요구사항 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

    2. this.[[bind_groups]][index] 값을 bindGroup으로 설정.

    3. this.[[dynamic_offsets]][index] 값을 dynamicOffsets의 복사본으로 설정.

    4. thisGPURenderCommandsMixin인 경우:

      1. this.[[bind_groups]]의 각 bindGroup에 대해, merge bindGroup.[[usedResources]]this.[[usage scope]]에 병합.

setBindGroup(index, bindGroup, dynamicOffsetsData, dynamicOffsetsDataStart, dynamicOffsetsDataLength)

주어진 인덱스에 대해 현재 GPUBindGroup을 설정하며, dynamic offsets를 Uint32Array의 일부로 지정합니다.

호출 대상: GPUBindingCommandsMixin this.

인자:

GPUBindingCommandsMixin.setBindGroup(index, bindGroup, dynamicOffsetsData, dynamicOffsetsDataStart, dynamicOffsetsDataLength) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
index GPUIndex32 바인드 그룹을 설정할 인덱스.
bindGroup GPUBindGroup? 이후 렌더/컴퓨트 커맨드에 사용할 바인드 그룹.
dynamicOffsetsData Uint32Array bindGroup에서 buffer.hasDynamicOffset 로 표시된 각 항목에 대해 바이트 단위 버퍼 오프셋을 담은 배열이며, GPUBindGroupLayoutEntry.binding 순서대로 정렬되어 있습니다. 추가적인 상세는 노트 참고.
dynamicOffsetsDataStart GPUSize64 dynamicOffsetsData에서 버퍼 오프셋 데이터가 시작하는 요소 오프셋.
dynamicOffsetsDataLength GPUSize32 dynamicOffsetsData에서 읽을 버퍼 오프셋 수.

반환값: undefined

컨텐트 타임라인 단계:

  1. 아래 요구사항 중 하나라도 만족하지 않으면 RangeError를 throw하고 반환.

    • dynamicOffsetsDataStart가 0 이상이어야 함.

    • dynamicOffsetsDataStart + dynamicOffsetsDataLength 값이 dynamicOffsetsData.length 이하이어야 함.

  2. dynamicOffsetslist로 생성하며, dynamicOffsetsDataStart 인덱스에서 시작하여 dynamicOffsetsDataLength 개의 요소를 버퍼 소스 복사본에서 복사.

  3. this.setBindGroup(index, bindGroup, dynamicOffsets)을 호출.

참고:
Dynamic offset은 GPUBindGroupLayoutEntry.binding 순서대로 적용됩니다.

즉, dynamic bindingsGPUBindGroupLayoutEntryGPUBindGroupLayout에서 buffer?.hasDynamicOffsettrue로 설정된 항목을 GPUBindGroupLayoutEntry.binding 기준으로 정렬한 리스트라면, setBindGroup()에 전달된 dynamic offset[i]dynamic bindings[i]에 대응합니다.

다음 호출로 생성된 GPUBindGroupLayout의 예시:
// bindings 배열 순서는 무관하지만 binding 인덱스 기준으로 정렬됩니다.
// 순서가 바뀌어도 상관없습니다.
let layout = gpuDevice.createBindGroupLayout({
    entries: [{
        binding: 1,
        buffer: {},
    }, {
        binding: 2,
        buffer: { dynamicOffset: true },
    }, {
        binding: 0,
        buffer: { dynamicOffset: true },
    }]
});

다음 호출로 생성된 GPUBindGroup에서 사용:

// 위와 마찬가지로 배열 순서는 상관없습니다.
// layout에서 사용한 순서와 일치할 필요도 없습니다.
let bindGroup = gpuDevice.createBindGroup({
    layout: layout,
    entries: [{
        binding: 1,
        resource: { buffer: bufferA, offset: 256 },
    }, {
        binding: 2,
        resource: { buffer: bufferB, offset: 512 },
    }, {
        binding: 0,
        resource: { buffer: bufferC },
    }]
});

그리고 다음 호출로 바인딩:

pass.setBindGroup(0, bindGroup, [1024, 2048]);

적용되는 버퍼 오프셋은 다음과 같습니다:

바인딩 버퍼 오프셋
0 bufferC 1024 (Dynamic)
1 bufferA 256 (Static)
2 bufferB 2560 (Static + Dynamic)
각 dynamic binding offset 순회GPUBindGroup bindGroup에 대해 steps 리스트 단계를 각 dynamic offset에 실행하려면, 다음 디바이스 타임라인 단계를 수행합니다:
  1. dynamicOffsetIndex0으로 한다.

  2. layoutbindGroup.[[layout]]로 한다.

  3. bindGroup.[[entries]]에서 각 GPUBindGroupEntry entryentry.binding 값을 오름차순으로 정렬하여 순회:

    1. bindingDescriptorlayout.[[entryMap]][entry.binding]로 한다.

    2. bindingDescriptor.buffer?.hasDynamicOffsettrue인 경우:

      1. bufferBindingget as buffer binding(entry.resource)로 한다.

      2. bufferLayoutbindingDescriptor.buffer로 한다.

      3. stepsbufferBinding, bufferLayout, dynamicOffsetIndex를 전달해서 호출.

      4. dynamicOffsetIndexdynamicOffsetIndex + 1로 한다.

인코더 바인드 그룹 유효성 검증(encoder, pipeline)

인자:

GPUBindingCommandsMixin encoder

바인드 그룹을 검증할 인코더.

GPUPipelineBase pipeline

인코더의 바인드 그룹과 호환되는지 검증할 파이프라인.

디바이스 타임라인 단계:

  1. 아래 조건 중 하나라도 만족하지 않으면 false 반환:

그 외에는 true 반환.

인코더 바인드 그룹이 쓰기 가능한 리소스와 겹치는지 검사(encoder, pipeline) 쓰기 가능한 버퍼 바인딩 영역이 동일 버퍼의 다른 바인딩 영역과 겹치거나, 쓰기 가능한 텍스처 바인딩이 동일 또는 다른 GPUTextureView 객체의 텍스처 서브리소스와 겹칠 경우 참입니다.

참고: 이 알고리즘은 usage scope storage 예외 사용을 제한합니다.

인자:

GPUBindingCommandsMixin encoder

바인드 그룹을 검증할 인코더.

GPUPipelineBase pipeline

인코더의 바인드 그룹과 호환되는지 검증할 파이프라인.

디바이스 타임라인 단계:

  1. stage in [VERTEX, FRAGMENT, COMPUTE]에 대해:

    1. bufferBindings를 (GPUBufferBinding, boolean) 쌍의 list로 한다. 두 번째 값은 리소스가 쓰기 용도로 사용되었는지 여부.

    2. textureViews를 (GPUTextureView, boolean) 쌍의 list로 한다. 두 번째 값은 리소스가 쓰기 용도로 사용되었는지 여부.

    3. 각 (GPUIndex32 bindGroupIndex, GPUBindGroupLayout bindGroupLayout) 쌍에 대해 pipeline.[[layout]].[[bindGroupLayouts]]에서 반복:

      1. bindGroupencoder.[[bind_groups]][bindGroupIndex]로 한다.

      2. bindGroupLayoutEntriesbindGroupLayout.[[descriptor]].entries로 한다.

      3. bufferRangesbindGroup바인딩된 버퍼 범위로 한다. dynamic offset은 encoder.[[dynamic_offsets]][bindGroupIndex] 사용

      4. bindGroupLayoutEntriesbufferRanges에서, bindGroupLayoutEntry.visibility 값이 stage를 포함하는 각 (GPUBindGroupLayoutEntry bindGroupLayoutEntry, GPUBufferBinding resource)에 대해:

        1. resourceWritable를 (bindGroupLayoutEntry.buffer.type == "storage")로 한다.

        2. 각 (GPUBufferBinding pastResource, boolean pastResourceWritable) in bufferBindings에 대해:

          1. (resourceWritable 또는 pastResourceWritable)가 true이고, pastResourceresourcebuffer-binding-aliasing이면 true 반환.

        3. Append (resource, resourceWritable)를 bufferBindings에 추가.

      5. bindGroupLayoutEntriesbindGroup의 텍스처에 대해, bindGroupLayoutEntry.visibility 값이 stage를 포함하는 각 (GPUBindGroupLayoutEntry bindGroupLayoutEntry, GPUTextureView resource)에 대해:

        1. bindGroupLayoutEntry.storageTexture 값이 제공되지 않은 경우, continue.

        2. resourceWritablebindGroupLayoutEntry.storageTexture.access 값이 쓰기 모드인 경우로 한다.

        3. 각 (GPUTextureView pastResource, boolean pastResourceWritable) in textureViews에 대해,

          1. (resourceWritable 또는 pastResourceWritable)가 true이고, pastResourceresourcetexture-view-aliasing이면 true 반환.

        4. Append (resource, resourceWritable)를 textureViews에 추가.

  2. false 반환.

참고: 구현체는 이 알고리즘을 최대한 최적화하는 것이 권장됩니다.

15. 디버그 마커

GPUDebugCommandsMixin은 커맨드 그룹에 디버그 라벨을 적용하거나 커맨드 시퀀스에 단일 라벨을 삽입하는 메서드를 제공합니다.

디버그 그룹은 중첩하여 라벨 계층 구조를 만들 수 있으며, 반드시 균형 잡힌 구조여야 합니다.

객체 라벨과 마찬가지로, 이러한 라벨은 필수 동작을 요구하지 않지만, 오류 메시지, 브라우저 개발자 도구, 네이티브 API 백엔드에 표시될 수 있습니다.

interface mixin GPUDebugCommandsMixin {
    undefined pushDebugGroup(USVString groupLabel);
    undefined popDebugGroup();
    undefined insertDebugMarker(USVString markerLabel);
};

GPUDebugCommandsMixinGPUObjectBaseGPUCommandsMixin 멤버가 동일 객체에 존재함을 가정합니다. 반드시 해당 믹스인들을 포함하는 인터페이스에서만 포함되어야 합니다.

GPUDebugCommandsMixin 은 다음 디바이스 타임라인 속성을 갖습니다:

[[debug_group_stack]], 타입 stack<USVString>

활성화된 디버그 그룹 라벨의 스택입니다.

GPUDebugCommandsMixin 은 다음 메서드를 제공합니다:

pushDebugGroup(groupLabel)

이후 커맨드를 포함하는 라벨이 지정된 디버그 그룹을 시작합니다.

호출 대상: GPUDebugCommandsMixin this.

인자:

GPUDebugCommandsMixin.pushDebugGroup(groupLabel) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
groupLabel USVString 커맨드 그룹의 라벨.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. Push groupLabelthis.[[debug_group_stack]]에 추가.

popDebugGroup()

가장 최근에 시작된 디버그 그룹(pushDebugGroup())을 종료합니다.

호출 대상: GPUDebugCommandsMixin this.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. 아래 조건 중 하나라도 만족하지 않으면 this를 무효화하고 반환.

  3. Popthis.[[debug_group_stack]]에 대해 실행.

insertDebugMarker(markerLabel)

커맨드 스트림의 한 지점에 라벨을 삽입합니다.

호출 대상: GPUDebugCommandsMixin this.

인자:

GPUDebugCommandsMixin.insertDebugMarker(markerLabel) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
markerLabel USVString 삽입할 라벨.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

16. 컴퓨트 패스

16.1. GPUComputePassEncoder

[Exposed=(Window, Worker), SecureContext]
interface GPUComputePassEncoder {
    undefined setPipeline(GPUComputePipeline pipeline);
    undefined dispatchWorkgroups(GPUSize32 workgroupCountX, optional GPUSize32 workgroupCountY = 1, optional GPUSize32 workgroupCountZ = 1);
    undefined dispatchWorkgroupsIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);

    undefined end();
};
GPUComputePassEncoder includes GPUObjectBase;
GPUComputePassEncoder includes GPUCommandsMixin;
GPUComputePassEncoder includes GPUDebugCommandsMixin;
GPUComputePassEncoder includes GPUBindingCommandsMixin;

GPUComputePassEncoder 는 다음 디바이스 타임라인 속성을 가집니다:

[[command_encoder]], 타입 GPUCommandEncoder, 읽기 전용

이 컴퓨트 패스 인코더를 생성한 GPUCommandEncoder입니다.

[[endTimestampWrite]], 타입 GPU command?, 읽기 전용, 기본값 null

패스가 끝날 때 타임스탬프를 기록하는 GPU command가 있을 경우 해당 명령입니다.

[[pipeline]], 타입 GPUComputePipeline, 초기값 null

현재 GPUComputePipeline입니다.

16.1.1. 컴퓨트 패스 인코더 생성

dictionary GPUComputePassTimestampWrites {
    required GPUQuerySet querySet;
    GPUSize32 beginningOfPassWriteIndex;
    GPUSize32 endOfPassWriteIndex;
};
querySet, 타입 GPUQuerySet

GPUQuerySet의 쿼리 결과가 기록될 "timestamp" 타입 객체입니다.

beginningOfPassWriteIndex, 타입 GPUSize32

정의된 경우, compute 패스 시작 시 타임스탬프가 기록될 querySet의 쿼리 인덱스를 의미합니다.

endOfPassWriteIndex, 타입 GPUSize32

정의된 경우, compute 패스 종료 시 타임스탬프가 기록될 querySet의 쿼리 인덱스를 의미합니다.

참고: 타임스탬프 쿼리 값은 나노초 단위로 기록되지만, 값이 어떻게 결정되는지는 구현 정의이며 반드시 단조 증가하지 않을 수 있습니다. 자세한 내용은 § 20.4 타임스탬프 쿼리 참고.

dictionary GPUComputePassDescriptor
         : GPUObjectDescriptorBase {
    GPUComputePassTimestampWrites timestampWrites;
};
timestampWrites, 타입 GPUComputePassTimestampWrites

이 패스에서 어떤 타임스탬프 값을 어디에 기록할지 정의합니다.

16.1.2. 디스패치

setPipeline(pipeline)

현재 GPUComputePipeline을 설정합니다.

호출 대상: GPUComputePassEncoder this.

인자:

GPUComputePassEncoder.setPipeline(pipeline) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
pipeline GPUComputePipeline 이후 디스패치 명령에 사용할 컴퓨트 파이프라인.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. 아래 조건 중 하나라도 충족하지 않으면, this를 무효화하고 반환.

  3. this.[[pipeline]] 값을 pipeline으로 설정.

dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ)

현재 GPUComputePipeline을 사용해 작업을 디스패치합니다. 상세 명세는 § 23.1 컴퓨팅 참고.

호출 대상: GPUComputePassEncoder this.

인자:

GPUComputePassEncoder.dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
workgroupCountX GPUSize32 디스패치할 workgroup의 X 차원 크기.
workgroupCountY GPUSize32 디스패치할 workgroup의 Y 차원 크기.
workgroupCountZ GPUSize32 디스패치할 workgroup의 Z 차원 크기.
참고:
x, y, z 값은 dispatchWorkgroups()dispatchWorkgroupsIndirect() 에 전달될 때 각 차원의 workgroup 개수이지, 각 차원에 걸쳐 실행될 셰이더 호출 개수가 아닙니다. 이는 현행 GPU API 동작과 일치하지만 OpenCL과는 다릅니다.

예를 들어 GPUShaderModule 의 entry point가 @workgroup_size(4, 4)으로 정의되어 있고, computePass.dispatchWorkgroups(8, 8);로 디스패치하면, entry point는 총 1024번 호출됩니다: 4x4 workgroup을 X, Y축 각각 8번 디스패치해서 4*4*8*8=1024번 실행됩니다.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. usageScope를 비어 있는 usage scope로 한다.

  3. this.[[bind_groups]]의 각 bindGroup에 대해, merge bindGroup.[[usedResources]]this.[[usage scope]]에 병합합니다.

  4. 아래 조건 중 하나라도 충족하지 않으면, this를 무효화하고 반환.

  5. bindingStatethis의 현재 상태 스냅샷으로 한다.

  6. Enqueue a commandthis에 실행하여, 실행 시 큐 타임라인에서 이후 단계를 실행.

큐 타임라인 단계:
  1. [workgroupCountX, workgroupCountY, workgroupCountZ] 크기의 workgroup 그리드를 bindingState.[[pipeline]]로 실행하며, bindingState.[[bind_groups]]를 사용합니다.

dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset)

현재 GPUComputePipeline을 사용해 GPUBuffer에서 읽은 파라미터로 작업을 디스패치합니다. 상세 명세는 § 23.1 컴퓨팅 참고.

버퍼에 인코딩되는 indirect dispatch parameters세 개의 32비트 unsigned 정수 값(총 12 바이트)을 동일한 순서로 연속 저장해야 합니다. dispatchWorkgroups() 인자 순서와 동일합니다. 예시:

let dispatchIndirectParameters = new Uint32Array(3);
dispatchIndirectParameters[0] = workgroupCountX;
dispatchIndirectParameters[1] = workgroupCountY;
dispatchIndirectParameters[2] = workgroupCountZ;
호출 대상: GPUComputePassEncoder this.

인자:

GPUComputePassEncoder.dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
indirectBuffer GPUBuffer indirect dispatch parameters가 저장된 버퍼.
indirectOffset GPUSize64 indirectBuffer에서 디스패치 데이터가 시작하는 바이트 오프셋.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. false면 반환.

  2. usageScope를 비어 있는 usage scope로 한다.

  3. this.[[bind_groups]]의 각 bindGroup에 대해, merge bindGroup.[[usedResources]]this.[[usage scope]]에 병합합니다.

  4. Add indirectBufferusageScopeinput 용도로 추가합니다.

  5. 아래 조건 중 하나라도 충족하지 않으면, this를 무효화하고 반환.

  6. bindingStatethis의 현재 상태 스냅샷으로 한다.

  7. Enqueue a commandthis에 실행하여, 실행 시 큐 타임라인에서 이후 단계를 실행.

큐 타임라인 단계:
  1. workgroupCountXindirectBuffer에서 indirectOffset 바이트 위치에서 읽은 unsigned 32비트 정수로 설정.

  2. workgroupCountYindirectBuffer에서 (indirectOffset + 4) 바이트 위치에서 읽은 unsigned 32비트 정수로 설정.

  3. workgroupCountZindirectBuffer에서 (indirectOffset + 8) 바이트 위치에서 읽은 unsigned 32비트 정수로 설정.

  4. workgroupCountX, workgroupCountY, workgroupCountZ 중 하나라도 this.device.limits.maxComputeWorkgroupsPerDimension보다 크면 반환.

  5. [workgroupCountX, workgroupCountY, workgroupCountZ] 크기의 workgroup 그리드를 bindingState.[[pipeline]]로 실행하며, bindingState.[[bind_groups]]를 사용합니다.

16.1.3. 최종화

사용자가 패스에 대한 커맨드 기록을 끝낸 뒤 end()를 호출함으로써 컴퓨트 패스 인코더를 종료할 수 있습니다. end()가 호출된 후에는 해당 컴퓨트 패스 인코더를 더 이상 사용할 수 없습니다.

end()

컴퓨트 패스 커맨드 시퀀스 기록을 완료합니다.

호출 대상: GPUComputePassEncoder this.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. parentEncoderthis.[[command_encoder]]로 설정.

  2. 아래 요구사항 중 하나라도 만족하지 않으면, 유효성 오류 생성 후 반환.

  3. this.[[state]] 값을 "ended"로 설정.

  4. parentEncoder.[[state]] 값을 "open"로 설정.

  5. 아래 요구사항 중 하나라도 만족하지 않으면, parentEncoder를 무효화하고 반환.

  6. Extend parentEncoder.[[commands]] 값에 this.[[commands]] 를 확장.

  7. this.[[endTimestampWrite]] 값이 null이 아니면:

    1. Extend parentEncoder.[[commands]] 값에 this.[[endTimestampWrite]] 를 확장.

17. 렌더 패스

17.1. GPURenderPassEncoder

[Exposed=(Window, Worker), SecureContext]
interface GPURenderPassEncoder {
    undefined setViewport(float x, float y,
        float width, float height,
        float minDepth, float maxDepth);

    undefined setScissorRect(GPUIntegerCoordinate x, GPUIntegerCoordinate y,
                        GPUIntegerCoordinate width, GPUIntegerCoordinate height);

    undefined setBlendConstant(GPUColor color);
    undefined setStencilReference(GPUStencilValue reference);

    undefined beginOcclusionQuery(GPUSize32 queryIndex);
    undefined endOcclusionQuery();

    undefined executeBundles(sequence<GPURenderBundle> bundles);
    undefined end();
};
GPURenderPassEncoder includes GPUObjectBase;
GPURenderPassEncoder includes GPUCommandsMixin;
GPURenderPassEncoder includes GPUDebugCommandsMixin;
GPURenderPassEncoder includes GPUBindingCommandsMixin;
GPURenderPassEncoder includes GPURenderCommandsMixin;

GPURenderPassEncoder 는 다음 디바이스 타임라인 속성을 가집니다:

[[command_encoder]], 타입 GPUCommandEncoder, 읽기 전용

이 렌더 패스 인코더를 생성한 GPUCommandEncoder입니다.

[[attachment_size]], 읽기 전용

다음 크기로 설정됩니다:

  • width, height = 패스의 렌더 어태치먼트의 크기

[[occlusion_query_set]], 타입 GPUQuerySet, 읽기 전용

패스의 오클루전 쿼리 결과를 저장할 GPUQuerySet이며, 패스 생성 시 GPURenderPassDescriptor.occlusionQuerySet 으로 초기화됩니다.

[[endTimestampWrite]], 타입 GPU command?, 읽기 전용, 기본값 null

패스 종료 시 타임스탬프를 기록하는 GPU command가 있을 경우 해당 명령입니다.

[[maxDrawCount]] 타입 GPUSize64, 읽기 전용

이 패스에서 허용되는 최대 draw 수입니다.

[[occlusion_query_active]], 타입 boolean

패스의 [[occlusion_query_set]] 이 기록 중인지 여부.

렌더 패스 커맨드가 GPUCommandBuffer의 일부로 실행될 때, 내부 RenderState 객체가 렌더링에 필요한 현재 상태를 추적합니다.

RenderState는 다음 큐 타임라인 속성을 가집니다:

[[occlusionQueryIndex]], 타입 GPUSize32

오클루전 쿼리 결과를 저장할 [[occlusion_query_set]] 의 인덱스입니다.

[[viewport]]

현재 뷰포트 사각형 및 깊이 범위. 초기값은 다음과 같습니다:

  • x, y = 0.0, 0.0

  • width, height = 패스의 렌더 타겟 크기

  • minDepth, maxDepth = 0.0, 1.0

[[scissorRect]]

현재 시저(Scissor) 사각형. 초기값은 다음과 같습니다:

  • x, y = 0, 0

  • width, height = 패스의 렌더 타겟 크기

[[blendConstant]], 타입 GPUColor

현재 블렌드 상수값. 초기값은 [0, 0, 0, 0]입니다.

[[stencilReference]], 타입 GPUStencilValue

현재 스텐실 참조값. 초기값은 0입니다.

[[colorAttachments]], 타입 sequence<GPURenderPassColorAttachment?>

이 렌더 패스의 컬러 어태치먼트와 상태입니다.

[[depthStencilAttachment]], 타입 GPURenderPassDepthStencilAttachment?

이 렌더 패스의 깊이/스텐실 어태치먼트와 상태입니다.

렌더 패스에는 프레임버퍼 메모리도 있는데, 이는 draw 커맨드로 기록되고 블렌딩 및 깊이/스텐실 테스트에 읽히는 각 어태치먼트에 매핑된 텍셀 데이터를 포함합니다.

참고: GPU 하드웨어에 따라 프레임버퍼 메모리가 어태치먼트 텍스처에서 직접 할당된 메모리일 수도 있고, 타일 기반 등 아키텍처에서는 텍스처 데이터가 복사되는 별도의 메모리 영역일 수도 있습니다.

17.1.1. 렌더 패스 인코더 생성

dictionary GPURenderPassTimestampWrites {
    required GPUQuerySet querySet;
    GPUSize32 beginningOfPassWriteIndex;
    GPUSize32 endOfPassWriteIndex;
};
querySet, 타입 GPUQuerySet

GPUQuerySet의 쿼리 결과가 기록될 "timestamp" 타입 객체입니다.

beginningOfPassWriteIndex, 타입 GPUSize32

정의된 경우, 렌더 패스 시작 시 타임스탬프가 기록될 querySet의 쿼리 인덱스를 의미합니다.

endOfPassWriteIndex, 타입 GPUSize32

정의된 경우, 렌더 패스 종료 시 타임스탬프가 기록될 querySet의 쿼리 인덱스를 의미합니다.

참고: 타임스탬프 쿼리 값은 나노초 단위로 기록되지만, 값이 어떻게 결정되는지는 구현 정의이며 반드시 단조 증가하지 않을 수 있습니다. 자세한 내용은 § 20.4 타임스탬프 쿼리 참고.

dictionary GPURenderPassDescriptor
         : GPUObjectDescriptorBase {
    required sequence<GPURenderPassColorAttachment?> colorAttachments;
    GPURenderPassDepthStencilAttachment depthStencilAttachment;
    GPUQuerySet occlusionQuerySet;
    GPURenderPassTimestampWrites timestampWrites;
    GPUSize64 maxDrawCount = 50000000;
};
colorAttachments, 타입 sequence<GPURenderPassColorAttachment?>

이 시퀀스에 포함된 GPURenderPassColorAttachment 값들은 렌더 패스 실행 시 출력할 컬러 어태치먼트를 정의합니다.

사용 호환성에 따라, 어느 컬러 어태치먼트도 다른 어태치먼트나 렌더 패스 내 사용되는 리소스와 겹칠 수 없습니다.

depthStencilAttachment, 타입 GPURenderPassDepthStencilAttachment

실행 시 출력 및 테스트에 사용할 GPURenderPassDepthStencilAttachment 값입니다.

사용 호환성에 따라, 쓰기 가능한 깊이/스텐실 어태치먼트는 다른 어태치먼트나 패스 내 사용된 리소스와 겹칠 수 없습니다.

occlusionQuerySet, 타입 GPUQuerySet

이 패스의 오클루전 쿼리 결과를 저장할 GPUQuerySet 값입니다.

timestampWrites, 타입 GPURenderPassTimestampWrites

이 패스에서 어떤 타임스탬프 값을 어디에 기록할지 정의합니다.

maxDrawCount, 타입 GPUSize64, 기본값 50000000

렌더 패스에서 수행될 최대 draw 호출 수입니다. 일부 구현체는 렌더 패스 전에 작업 크기 결정에 사용합니다. 더 많은 draw가 필요하지 않다면 기본값을 유지하는 것이 좋습니다.

유효한 사용

GPUDevice deviceGPURenderPassDescriptor this가 주어진 경우, 다음과 같은 검증 규칙이 적용됩니다:

  1. this.colorAttachments.sizedevice.[[limits]].maxColorAttachments 이하이어야 합니다.

  2. this.colorAttachments의 각 non-null colorAttachment에 대해:

    1. colorAttachment.viewdevice와 함께 사용 가능한 상태여야 합니다.

    2. colorAttachment.resolveTarget 값이 제공된 경우:

      1. colorAttachment.resolveTarget 역시 device와 함께 사용 가능한 상태여야 합니다.

    3. colorAttachmentGPURenderPassColorAttachment 유효한 사용 규칙을 만족해야 합니다.

  3. this.depthStencilAttachment 값이 제공된 경우:

    1. this.depthStencilAttachment.viewdevice와 함께 사용 가능한 상태여야 합니다.

    2. this.depthStencilAttachmentGPURenderPassDepthStencilAttachment 유효한 사용 규칙을 만족해야 합니다.

  4. 최소 하나의 어태치먼트가 존재해야 합니다. 즉 다음 중 하나:

  5. GPURenderPassDescriptor의 color attachment bytes per sample 유효성 검증(device, this.colorAttachments) 가 성공해야 합니다.

  6. non-null this.colorAttachments 멤버의 모든 view와, this.depthStencilAttachment.view (존재시)의 sampleCount가 모두 같아야 합니다.

  7. non-null this.colorAttachments 멤버의 모든 view와, this.depthStencilAttachment.view (존재시)의 [[renderExtent]]가 일치해야 합니다.

  8. this.occlusionQuerySet 값이 제공된 경우:

    1. this.occlusionQuerySet 값은 device와 함께 사용 가능한 상태여야 합니다.

    2. this.occlusionQuerySet.type 값이 occlusion이어야 합니다.

  9. this.timestampWrites 값이 제공된 경우:

GPURenderPassDescriptor의 color attachment bytes per sample 유효성 검증(device, colorAttachments)

인자:

디바이스 타임라인 단계:

  1. formats를 빈 list<GPUTextureFormat?>로 초기화합니다.

  2. colorAttachments의 각 colorAttachment에 대해:

    1. colorAttachmentundefined인 경우 continue.

    2. Append colorAttachment.view.[[descriptor]].formatformats에 추가합니다.

  3. color attachment bytes per sample 계산(formats)이 device.[[limits]].maxColorAttachmentBytesPerSample 이하이어야 합니다.

17.1.1.1. 컬러 어태치먼트
dictionary GPURenderPassColorAttachment {
    required (GPUTexture or GPUTextureView) view;
    GPUIntegerCoordinate depthSlice;
    (GPUTexture or GPUTextureView) resolveTarget;

    GPUColor clearValue;
    required GPULoadOp loadOp;
    required GPUStoreOp storeOp;
};
view, 타입 (GPUTexture 또는 GPUTextureView)

이 컬러 어태치먼트에서 출력될 텍스처 서브리소스를 설명합니다. 서브리소스get as texture view(view) 호출로 결정됩니다.

depthSlice, 타입 GPUIntegerCoordinate

이 컬러 어태치먼트에서 출력될 "3d" view 의 깊이 슬라이스 인덱스를 나타냅니다.

resolveTarget, 타입 (GPUTexture 또는 GPUTextureView)

이 컬러 어태치먼트에서 view 값이 멀티샘플링일 경우, 해상된 출력이 기록될 텍스처 서브리소스를 설명합니다. 서브리소스get as texture view(resolveTarget) 호출로 결정됩니다.

clearValue, 타입 GPUColor

렌더 패스를 실행하기 전에 view 값을 초기화할 값입니다. 제공되지 않으면 기본값 {r: 0, g: 0, b: 0, a: 0}입니다. loadOp 값이 "clear"가 아니면 무시됩니다.

clearValue 각 구성 요소는 모두 double 값입니다. 렌더 어태치먼트에 맞는 텍스처 포맷 텍셀 값 변환 시도에 실패하면 유효성 오류가 발생합니다.

loadOp, 타입 GPULoadOp

렌더 패스를 실행하기 전에 view 에 수행할 load 연산을 지정합니다.

참고: 초기화(clear)를 우선 추천합니다. 자세한 내용은 "clear" 참고.

storeOp, 타입 GPUStoreOp

렌더 패스 실행 후 view 에 수행할 store 연산을 지정합니다.

GPURenderPassColorAttachment 유효한 사용

GPURenderPassColorAttachment this가 주어진 경우:

  1. renderViewDescriptorthis.view.[[descriptor]]로 설정.

  2. renderTexturethis.view.[[texture]]로 설정.

  3. 아래 모든 요구사항을 만족해야 합니다.

    1. renderViewDescriptor.format 값이 컬러 렌더링 포맷이어야 합니다.

    2. this.view 값이 렌더링 가능한 텍스처 뷰여야 합니다.

    3. renderViewDescriptor.dimension 값이 "3d"인 경우:

      1. this.depthSlice 값이 제공되어야 하며 또한 renderTexture 서브리소스depthOrArrayLayers 보다 작아야 합니다. (해당 논리적 mip레벨 특정 텍스처 크기 기준, renderViewDescriptor.baseMipLevel에서)

      그 외의 경우:

      1. this.depthSlice 값이 제공되어서는 안 됩니다.

    4. this.loadOp 값이 "clear"인 경우:

      1. IDL 값 this.clearValuerenderViewDescriptor.format에 맞는 텍셀 값 변환TypeError가 발생하면 안 됩니다.

        참고: 값이 포맷 범위 밖이더라도 WGSL 프리미티브 타입(f32, i32, u32) 범위 내라면 오류가 발생하지 않습니다.

    5. this.resolveTarget 값이 제공된 경우:

      1. resolveViewDescriptorthis.resolveTarget.[[descriptor]]로 설정.

      2. resolveTexturethis.resolveTarget.[[texture]]로 설정.

      3. renderTexture.sampleCount 값이 반드시 1보다 커야 합니다.

      4. resolveTexture.sampleCount 값이 반드시 1이어야 합니다.

      5. this.resolveTarget 값이 3d가 아닌 렌더링 가능한 텍스처 뷰여야 합니다.

      6. this.resolveTarget.[[renderExtent]] 값과 this.view.[[renderExtent]] 값이 반드시 일치해야 합니다.

      7. resolveViewDescriptor.format 값이 반드시 renderViewDescriptor.format 값과 같아야 합니다.

      8. resolveTexture.format 값이 반드시 renderTexture.format 값과 같아야 합니다.

      9. resolveViewDescriptor.format 값이 § 26.1.1 일반 컬러 포맷에 따라 resolve를 지원해야 합니다.

GPUTextureView view렌더링 가능한 텍스처 뷰이려면, 아래 디바이스 타임라인 단계 요구사항을 모두 만족해야 합니다:
  1. descriptorview.[[descriptor]]로 설정합니다.

  2. descriptor.usage 값에 RENDER_ATTACHMENT가 포함되어야 합니다.

  3. descriptor.dimension 값이 "2d" 또는 "2d-array" 또는 "3d"이어야 합니다.

  4. descriptor.mipLevelCount 값이 1이어야 합니다.

  5. descriptor.arrayLayerCount 값이 1이어야 합니다.

  6. descriptor.aspect 값이 view.[[texture]]의 모든 aspect을 참조해야 합니다.

color attachment bytes per sample 계산(formats)

인자:

반환값: GPUSize32

  1. total을 0으로 설정합니다.

  2. formats의 각 non-null format에 대해

    1. Assert: format 값이 컬러 렌더링 포맷이어야 합니다.

    2. renderTargetPixelByteCostformat렌더 타겟 픽셀 바이트 비용으로 설정합니다.

    3. renderTargetComponentAlignmentformat렌더 타겟 컴포넌트 정렬로 설정합니다.

    4. totalrenderTargetComponentAlignment의 배수 중 total 이상 중 가장 작은 값으로 올림합니다.

    5. renderTargetPixelByteCosttotal에 더합니다.

  3. total을 반환합니다.

17.1.1.2. 깊이/스텐실 어태치먼트
dictionary GPURenderPassDepthStencilAttachment {
    required (GPUTexture or GPUTextureView) view;

    float depthClearValue;
    GPULoadOp depthLoadOp;
    GPUStoreOp depthStoreOp;
    boolean depthReadOnly = false;

    GPUStencilValue stencilClearValue = 0;
    GPULoadOp stencilLoadOp;
    GPUStoreOp stencilStoreOp;
    boolean stencilReadOnly = false;
};
view, 타입 (GPUTexture 또는 GPUTextureView)

이 깊이/스텐실 어태치먼트에서 출력 및 읽기할 텍스처 서브리소스를 설명합니다. 서브리소스get as texture view(view) 호출로 결정됩니다.

depthClearValue, 타입 float

렌더 패스를 실행하기 전에 view의 depth 컴포넌트 값을 초기화할 값입니다. depthLoadOp 값이 "clear"가 아니면 무시됩니다. 반드시 0.0 이상 1.0 이하이어야 합니다.

depthLoadOp, 타입 GPULoadOp

렌더 패스를 실행하기 전에 view의 depth 컴포넌트에 수행할 load 연산을 지정합니다.

참고: 초기화(clear)를 우선 추천합니다. 자세한 내용은 "clear" 참고.

depthStoreOp, 타입 GPUStoreOp

렌더 패스 실행 후 view의 depth 컴포넌트에 수행할 store 연산을 지정합니다.

depthReadOnly, 타입 boolean, 기본값 false

view의 depth 컴포넌트가 읽기 전용임을 나타냅니다.

stencilClearValue, 타입 GPUStencilValue, 기본값 0

렌더 패스를 실행하기 전에 view의 stencil 컴포넌트 값을 초기화할 값입니다. stencilLoadOp 값이 "clear"가 아니면 무시됩니다.

값은 view의 stencil aspect 타입에 맞게 변환되며, view텍셀의 stencil aspect 비트 수만큼 LSB를 사용합니다.

stencilLoadOp, 타입 GPULoadOp

렌더 패스를 실행하기 전에 view의 stencil 컴포넌트에 수행할 load 연산을 지정합니다.

참고: 초기화(clear)를 우선 추천합니다. 자세한 내용은 "clear" 참고.

stencilStoreOp, 타입 GPUStoreOp

렌더 패스 실행 후 view의 stencil 컴포넌트에 수행할 store 연산을 지정합니다.

stencilReadOnly, 타입 boolean, 기본값 false

view의 stencil 컴포넌트가 읽기 전용임을 나타냅니다.

GPURenderPassDepthStencilAttachment 유효한 사용

GPURenderPassDepthStencilAttachment this가 주어진 경우, 다음과 같은 검증 규칙이 적용됩니다:

17.1.1.3. 로드 & 스토어 연산
enum GPULoadOp {
    "load",
    "clear",
};
"load"

이 어태치먼트의 기존 값을 렌더 패스로 불러옵니다.

"clear"

이 어태치먼트의 초기화(clear) 값을 렌더 패스로 불러옵니다.

참고: 일부 GPU 하드웨어(주로 모바일)에서는 "clear"가 훨씬 더 저렴합니다. 주 메모리에서 타일-로컬 메모리로 데이터를 불러오는 과정을 건너뛰기 때문입니다. 다른 GPU 하드웨어에서는 큰 차이가 없습니다. 따라서 초기 값이 중요하지 않을 때(예: 렌더 타겟이 스카이박스로 초기화될 경우) "clear""load" 대신 사용하는 것이 권장됩니다.

enum GPUStoreOp {
    "store",
    "discard",
};
"store"

렌더 패스의 결과값을 어태치먼트에 저장합니다.

"discard"

렌더 패스의 결과값을 어태치먼트에서 폐기(discard)합니다.

참고: 폐기된 어태치먼트는 0으로 초기화된 것처럼 동작하지만, 구현체는 패스 끝에 명시적 초기화를 수행할 필요가 없습니다. 패스 끝에 명시적으로 clear하지 않는 구현체는 해당 어태치먼트 내용을 읽기(샘플링, 복사, 이후 렌더 패스에서 "load"로 attach, 캔버스 디스플레이/리드백(get a copy of the image contents of a context 등) 하기 전에 지연(lazy) 초기화를 해야 합니다.

17.1.1.4. 렌더 패스 레이아웃

GPURenderPassLayoutGPURenderBundle의 렌더 타겟 레이아웃을 선언합니다. 내부적으로 GPURenderPassEncoder 레이아웃GPURenderPipeline 레이아웃에도 사용됩니다. 렌더 패스, 렌더 번들, 렌더 파이프라인 간 호환성을 결정합니다.

dictionary GPURenderPassLayout
         : GPUObjectDescriptorBase {
    required sequence<GPUTextureFormat?> colorFormats;
    GPUTextureFormat depthStencilFormat;
    GPUSize32 sampleCount = 1;
};
colorFormats, 타입 sequence<GPUTextureFormat?>

이 패스 또는 번들의 컬러 어태치먼트 GPUTextureFormat 리스트입니다.

depthStencilFormat, 타입 GPUTextureFormat

이 패스 또는 번들의 깊이/스텐실 어태치먼트 GPUTextureFormat입니다.

sampleCount, 타입 GPUSize32, 기본값 1

이 패스 또는 번들 어태치먼트의 픽셀당 샘플 수입니다.

GPURenderPassLayout 값이 동등(equal)하려면:
패스에서 렌더 타겟 레이아웃 도출

인자:

반환값: GPURenderPassLayout

디바이스 타임라인 단계:

  1. layout을 새 GPURenderPassLayout 객체로 한다.

  2. descriptor.colorAttachments의 각 colorAttachment에 대해:

    1. colorAttachmentnull이 아니면:

      1. layout.sampleCount 값을 colorAttachment.view.[[texture]].sampleCount로 설정.

      2. colorAttachment.view.[[descriptor]].formatlayout.colorFormats에 추가.

    2. 그 외의 경우:

      1. nulllayout.colorFormats에 추가.

  3. depthStencilAttachmentdescriptor.depthStencilAttachment로 한다.

  4. depthStencilAttachmentnull이 아니면:

    1. viewdepthStencilAttachment.view로 한다.

    2. layout.sampleCount 값을 view.[[texture]].sampleCount로 설정.

    3. layout.depthStencilFormat 값을 view.[[descriptor]].format으로 설정.

  5. layout을 반환합니다.

파이프라인에서 렌더 타겟 레이아웃 도출

인자:

반환값: GPURenderPassLayout

디바이스 타임라인 단계:

  1. layout을 새 GPURenderPassLayout 객체로 설정합니다.

  2. layout.sampleCount 값을 descriptor.multisample.count으로 설정합니다.

  3. descriptor.depthStencil 값이 제공된 경우:

    1. layout.depthStencilFormat 값을 descriptor.depthStencil.format으로 설정합니다.

  4. descriptor.fragment 값이 제공된 경우:

    1. descriptor.fragment.targets의 각 colorTarget에 대해:

      1. colorTargetnull이 아니면 colorTarget.format 값을 layout.colorFormats에 추가하고, null이면 null을 추가합니다.

  5. layout을 반환합니다.

17.1.2. 최종화

사용자가 해당 패스에 대한 커맨드 기록을 마친 뒤 end()를 호출하여 렌더 패스 인코더를 종료할 수 있습니다. end()가 호출된 후에는 해당 렌더 패스 인코더를 더 이상 사용할 수 없습니다.

end()

렌더 패스 커맨드 시퀀스 기록을 완료합니다.

호출 대상: GPURenderPassEncoder this.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. parentEncoderthis.[[command_encoder]]로 설정.

  2. 아래 요구사항 중 하나라도 만족하지 않으면, 유효성 오류 생성 후 반환.

  3. this.[[state]] 값을 "ended"로 설정.

  4. parentEncoder.[[state]] 값을 "open"로 설정.

  5. 아래 요구사항 중 하나라도 만족하지 않으면, parentEncoder를 무효화하고 반환.

  6. Extend parentEncoder.[[commands]] 값에 this.[[commands]] 를 확장.

  7. this.[[endTimestampWrite]] 값이 null이 아니면:

    1. Extend parentEncoder.[[commands]] 값에 this.[[endTimestampWrite]] 를 확장.

  8. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. non-null renderState.[[colorAttachments]] 멤버의 각 colorAttachment에 대해:

    1. colorViewcolorAttachment.view로 한다.

    2. colorView.[[descriptor]].dimension 값에 따라:

      "3d"

      colorSubregioncolorAttachment.depthSlice of colorView로 한다.

      그 외의 경우

      colorSubregioncolorView로 한다.

    3. colorAttachment.resolveTarget 값이 null이 아니면:

      1. 모든 텍셀의 멀티 샘플을 resolve하여 colorSubregion의 단일 샘플로 만들고, colorAttachment.resolveTarget에 복사합니다.

    4. colorAttachment.storeOp 값에 따라:

      "store"

      colorSubregion에 매핑된 프레임버퍼 메모리의 내용을 colorSubregion에 저장합니다.

      "discard"

      colorSubregion의 모든 텍셀 값을 0으로 설정합니다.

  2. depthStencilAttachmentrenderState.[[depthStencilAttachment]]로 한다.

  3. depthStencilAttachmentnull이 아니면:

    1. depthStencilAttachment.depthStoreOp 값에 따라:

      제공되지 않은 경우

      Assert: depthStencilAttachment.depthReadOnly 값이 true이며, depthStencilViewdepth 서브리소스는 변경하지 않습니다.

      "store"

      depthStencilViewdepth 서브리소스에 매핑된 프레임버퍼 메모리의 내용을 저장합니다.

      "discard"

      depthStencilViewdepth 서브리소스의 모든 텍셀 값을 0으로 설정합니다.

    2. depthStencilAttachment.stencilStoreOp 값에 따라:

      제공되지 않은 경우

      Assert: depthStencilAttachment.stencilReadOnly 값이 true이며, depthStencilViewstencil 서브리소스는 변경하지 않습니다.

      "store"

      depthStencilViewstencil 서브리소스에 매핑된 프레임버퍼 메모리의 내용을 저장합니다.

      "discard"

      depthStencilViewstencil 서브리소스의 모든 텍셀 값을 0으로 설정합니다.

  4. renderStatenull로 설정합니다.

참고: 폐기(discard)된 어태치먼트는 0으로 초기화된 것처럼 동작하지만, 구현체는 패스 끝에 명시적 초기화를 할 필요는 없습니다. 추가 내용은 "discard" 참고.

참고: 읽기 전용 depth-stencil 어태치먼트는 암묵적으로 "store" 연산을 사용하는 것으로 간주할 수 있지만, 패스 실행 중 내용이 변경되지 않으므로 구현체는 업데이트할 필요가 없습니다. 읽기 전용 어태치먼트에 store op가 제공되면 안 된다는 검증은 GPURenderPassDepthStencilAttachment 유효한 사용에서 수행합니다.

17.2. GPURenderCommandsMixin

GPURenderCommandsMixinGPURenderPassEncoderGPURenderBundleEncoder 에 공통인 렌더링 명령을 정의합니다.

interface mixin GPURenderCommandsMixin {
    undefined setPipeline(GPURenderPipeline pipeline);

    undefined setIndexBuffer(GPUBuffer buffer, GPUIndexFormat indexFormat, optional GPUSize64 offset = 0, optional GPUSize64 size);
    undefined setVertexBuffer(GPUIndex32 slot, GPUBuffer? buffer, optional GPUSize64 offset = 0, optional GPUSize64 size);

    undefined draw(GPUSize32 vertexCount, optional GPUSize32 instanceCount = 1,
        optional GPUSize32 firstVertex = 0, optional GPUSize32 firstInstance = 0);
    undefined drawIndexed(GPUSize32 indexCount, optional GPUSize32 instanceCount = 1,
        optional GPUSize32 firstIndex = 0,
        optional GPUSignedOffset32 baseVertex = 0,
        optional GPUSize32 firstInstance = 0);

    undefined drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
    undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
};

GPURenderCommandsMixin 은 동일 객체에 GPUObjectBase, GPUCommandsMixin, GPUBindingCommandsMixin 멤버가 존재함을 전제로 합니다. 반드시 위 믹스인을 포함한 인터페이스에서만 사용되어야 합니다.

GPURenderCommandsMixin 는 다음 디바이스 타임라인 속성을 가집니다:

[[layout]], 타입 GPURenderPassLayout, 읽기 전용

렌더 패스의 레이아웃입니다.

[[depthReadOnly]], 타입 boolean, 읽기 전용

true면 depth 컴포넌트가 변경되지 않음을 나타냅니다.

[[stencilReadOnly]], 타입 boolean, 읽기 전용

true면 stencil 컴포넌트가 변경되지 않음을 나타냅니다.

[[usage scope]], 타입 usage scope, 초기값은 비어 있음

이 렌더 패스 또는 번들의 usage scope입니다.

[[pipeline]], 타입 GPURenderPipeline, 초기값 null

현재 GPURenderPipeline입니다.

[[index_buffer]], 타입 GPUBuffer, 초기값 null

현재 인덱스 데이터를 읽는 버퍼입니다.

[[index_format]], 타입 GPUIndexFormat

현재 [[index_buffer]]의 인덱스 데이터 포맷입니다.

[[index_buffer_offset]], 타입 GPUSize64

현재 설정된 [[index_buffer]]의 바이트 오프셋입니다.

[[index_buffer_size]], 타입 GPUSize64

현재 설정된 [[index_buffer]]의 바이트 크기, 초기값은 0입니다.

[[vertex_buffers]], 타입 ordered map<slot, GPUBuffer>, 초기값은 비어 있음

각 슬롯별로 현재 설정된 버텍스 데이터 읽기용 GPUBuffer들입니다.

[[vertex_buffer_sizes]], 타입 ordered map<slot, GPUSize64>, 초기값은 비어 있음

각 슬롯별로 현재 설정된 GPUBuffer의 바이트 크기입니다.

[[drawCount]], 타입 GPUSize64

이 인코더에 기록된 draw 명령 개수입니다.

렌더 커맨드 enqueueGPURenderCommandsMixin encoder에 실행하여 GPU Command commandRenderState renderState와 함께 실행할 때, 다음 디바이스 타임라인 단계를 수행합니다:
  1. Append commandencoder.[[commands]]에 추가합니다.

  2. commandGPUCommandBuffer commandBuffer의 일부로 실행되는 경우:

    1. commandBuffer.[[renderState]]renderState로 하여 command 단계를 실행합니다.

17.2.1. 드로잉

setPipeline(pipeline)

현재 GPURenderPipeline을 설정합니다.

호출 대상: GPURenderCommandsMixin this.

인자:

GPURenderCommandsMixin.setPipeline(pipeline) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
pipeline GPURenderPipeline 이후 드로잉 명령에 사용할 렌더 파이프라인.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. pipelineTargetsLayout파이프라인에서 렌더 타겟 레이아웃 도출(pipeline.[[descriptor]])로 설정.

  3. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  4. this.[[pipeline]] 값을 pipeline으로 설정.

setIndexBuffer(buffer, indexFormat, offset, size)

현재 인덱스 버퍼를 설정합니다.

호출 대상: GPURenderCommandsMixin this.

인자:

GPURenderCommandsMixin.setIndexBuffer(buffer, indexFormat, offset, size) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
buffer GPUBuffer 이후 드로잉 명령에서 사용할 인덱스 데이터가 들어있는 버퍼.
indexFormat GPUIndexFormat buffer 내부 인덱스 데이터의 포맷.
offset GPUSize64 buffer에서 인덱스 데이터가 시작하는 바이트 오프셋. 기본값은 0.
size GPUSize64 buffer 내부 인덱스 데이터의 바이트 크기. 기본값은 버퍼 크기에서 오프셋을 뺀 값.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. size가 누락된 경우, size를 max(0, buffer.size - offset)으로 설정.

  3. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  4. Add buffer[[usage scope]] 에 input 용도로 추가.

  5. this.[[index_buffer]] 값을 buffer로 설정.

  6. this.[[index_format]] 값을 indexFormat으로 설정.

  7. this.[[index_buffer_offset]] 값을 offset으로 설정.

  8. this.[[index_buffer_size]] 값을 size로 설정.

setVertexBuffer(slot, buffer, offset, size)

지정한 슬롯에 현재 버텍스 버퍼를 설정합니다.

호출 대상: GPURenderCommandsMixin this.

인자:

GPURenderCommandsMixin.setVertexBuffer(slot, buffer, offset, size) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
slot GPUIndex32 버텍스 버퍼를 설정할 버텍스 버퍼 슬롯.
buffer GPUBuffer? 이후 드로잉 명령에 사용할 버텍스 데이터가 들어 있는 버퍼.
offset GPUSize64 buffer에서 버텍스 데이터가 시작하는 바이트 오프셋. 기본값 0.
size GPUSize64 buffer에서 버텍스 데이터의 바이트 크기. 기본값은 버퍼 크기에서 오프셋을 뺀 값.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인 단계에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. bufferSizebuffernull이면 0, 아니면 buffer.size로 설정.

  3. size가 누락된 경우, size를 max(0, bufferSize - offset)으로 설정.

  4. 아래 요구사항 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  5. buffernull인 경우:

    1. Remove this.[[vertex_buffers]][slot].

    2. Remove this.[[vertex_buffer_sizes]][slot].

    그 외의 경우:

    1. 아래 요구사항 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

    2. Add buffer[[usage scope]] 에 input 용도로 추가합니다.

    3. this.[[vertex_buffers]][slot] 값을 buffer로 설정합니다.

    4. this.[[vertex_buffer_sizes]][slot] 값을 size로 설정합니다.

draw(vertexCount, instanceCount, firstVertex, firstInstance)

프리미티브를 드로우합니다. 자세한 명세는 § 23.2 렌더링을 참고하세요.

호출 대상: GPURenderCommandsMixin this.

인자:

GPURenderCommandsMixin.draw(vertexCount, instanceCount, firstVertex, firstInstance) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
vertexCount GPUSize32 드로우할 버텍스 개수.
instanceCount GPUSize32 드로우할 인스턴스 개수.
firstVertex GPUSize32 버텍스 버퍼에서 시작할 오프셋(버텍스 단위).
firstInstance GPUSize32 드로우할 첫 번째 인스턴스.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인 단계에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 아래 단계의 모든 요구사항을 만족해야 합니다. 하나라도 만족하지 않으면 this를 무효화하고 반환.

    1. 현재 valid to draw 상태여야 합니다.

    2. buffersthis.[[pipeline]].[[descriptor]].vertex.buffers로 설정.

    3. GPUIndex32 slot에 대해 0부터 buffers.size (불포함)까지:

      1. buffers[slot] 값이 null이면 continue.

      2. bufferSizethis.[[vertex_buffer_sizes]][slot]로 설정.

      3. stridebuffers[slot].arrayStride로 설정.

      4. attributesbuffers[slot].attributes로 설정.

      5. lastStrideattributesattribute에 대해 (attribute.offset + byteSize(attribute.format))의 최댓값으로, attributes비어 있으면 0으로 설정.

      6. strideCountbuffers[slot].stepMode에 따라 계산:

        "vertex"

        firstVertex + vertexCount

        "instance"

        firstInstance + instanceCount

      7. strideCount0이면:

        1. (strideCount1) × stride + lastStride 값이 bufferSize 이하이어야 함.

  3. this.[[drawCount]] 값을 1 증가시킵니다.

  4. bindingStatethis의 현재 상태 스냅샷으로 설정합니다.

  5. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. 프리미티브를 vertexCount개의 버텍스(firstVertex부터 시작), instanceCount개의 인스턴스(firstInstance부터 시작)로 드로우하고, bindingStaterenderState의 상태를 사용합니다.

drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance)

인덱스드 프리미티브를 드로우합니다. 자세한 명세는 § 23.2 렌더링을 참고하세요.

호출 대상: GPURenderCommandsMixin this.

인자:

GPURenderCommandsMixin.drawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
indexCount GPUSize32 드로우할 인덱스 개수.
instanceCount GPUSize32 드로우할 인스턴스 개수.
firstIndex GPUSize32 인덱스 버퍼에서 시작할 오프셋(인덱스 단위).
baseVertex GPUSignedOffset32 각 인덱스 값에 더하여 버텍스 버퍼에 접근.
firstInstance GPUSize32 드로우할 첫 번째 인스턴스.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인 단계에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  3. this.[[drawCount]] 값을 1 증가시킵니다.

  4. bindingStatethis의 현재 상태 스냅샷으로 설정합니다.

  5. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. 프리미티브를 indexCount개의 인덱스드 버텍스(firstIndex부터 시작, baseVertex를 기준), instanceCount개의 인스턴스(firstInstance부터 시작)로 드로우하고, bindingStaterenderState의 상태를 사용합니다.

참고: WebGPU 애플리케이션은 항상 GPUVertexStepMode "vertex"를 가진 바운드 버텍스 버퍼의 범위를 벗어난 인덱스 데이터를 사용해서는 안 됩니다. WebGPU 구현체마다 처리 방식이 다르므로 다양한 동작이 허용됩니다. 전체 드로우 콜이 무시(discard)되거나, 범위를 벗어난 속성 접근은 WGSL의 invalid memory reference로 처리됩니다.

drawIndirect(indirectBuffer, indirectOffset)

GPUBuffer에서 읽어온 파라미터로 프리미티브를 드로우합니다. 자세한 명세는 § 23.2 렌더링을 참고하세요.

버퍼에 인코딩된 간접 드로우 파라미터32비트 부호없는 정수 4개(총 16바이트)를 순서대로 꽉 채워야 하며, draw()의 인자와 같은 순서로 배치되어야 합니다. 예시:

let drawIndirectParameters = new Uint32Array(4);
drawIndirectParameters[0] = vertexCount;
drawIndirectParameters[1] = instanceCount;
drawIndirectParameters[2] = firstVertex;
drawIndirectParameters[3] = firstInstance;

firstInstance에 해당하는 값은 "indirect-first-instance" feature가 활성화되어 있지 않으면 반드시 0이어야 합니다. 만약 "indirect-first-instance" feature가 활성화되어 있지 않고 firstInstance가 0이 아니라면, drawIndirect() 호출은 아무 동작도 하지 않습니다(no-op).

호출 대상: GPURenderCommandsMixin this.

인자:

GPURenderCommandsMixin.drawIndirect(indirectBuffer, indirectOffset) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
indirectBuffer GPUBuffer 간접 드로우 파라미터가 들어있는 버퍼.
indirectOffset GPUSize64 indirectBuffer에서 드로잉 데이터가 시작하는 바이트 오프셋.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  3. Add indirectBuffer[[usage scope]] 에 input 용도로 추가합니다.

  4. this.[[drawCount]] 값을 1 증가시킵니다.

  5. bindingStatethis의 현재 상태 스냅샷으로 설정합니다.

  6. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. vertexCountindirectBuffer에서 indirectOffset 바이트 위치에서 부호없는 32비트 정수로 읽어옴.

  2. instanceCountindirectBuffer에서 (indirectOffset + 4) 바이트 위치에서 부호없는 32비트 정수로 읽어옴.

  3. firstVertexindirectBuffer에서 (indirectOffset + 8) 바이트 위치에서 부호없는 32비트 정수로 읽어옴.

  4. firstInstanceindirectBuffer에서 (indirectOffset + 12) 바이트 위치에서 부호없는 32비트 정수로 읽어옴.

  5. 프리미티브를 vertexCount개의 버텍스(firstVertex부터 시작), instanceCount개의 인스턴스(firstInstance부터 시작)로 드로우하고, bindingStaterenderState의 상태를 사용합니다.

drawIndexedIndirect(indirectBuffer, indirectOffset)

GPUBuffer에서 읽어온 파라미터로 인덱스드 프리미티브를 드로우합니다. 자세한 명세는 § 23.2 렌더링을 참고하세요.

버퍼에 인코딩된 간접 drawIndexed 파라미터5개의 32비트 값(총 20바이트)을 순서대로 꽉 채워야 하며, drawIndexed()의 인자와 같은 순서로 배치되어야 합니다. baseVertex에 해당하는 값만 32비트 부호있는 정수이며, 나머지는 모두 부호없는 32비트 정수입니다. 예시:

let drawIndexedIndirectParameters = new Uint32Array(5);
let drawIndexedIndirectParametersSigned = new Int32Array(drawIndexedIndirectParameters.buffer);
drawIndexedIndirectParameters[0] = indexCount;
drawIndexedIndirectParameters[1] = instanceCount;
drawIndexedIndirectParameters[2] = firstIndex;
// baseVertex는 signed 값입니다.
drawIndexedIndirectParametersSigned[3] = baseVertex;
drawIndexedIndirectParameters[4] = firstInstance;

firstInstance에 해당하는 값은 "indirect-first-instance" feature가 활성화되어 있지 않으면 반드시 0이어야 합니다. 만약 "indirect-first-instance" feature가 활성화되어 있지 않고 firstInstance가 0이 아니라면, drawIndexedIndirect() 호출은 아무 동작도 하지 않습니다(no-op).

호출 대상: GPURenderCommandsMixin this.

인자:

GPURenderCommandsMixin.drawIndexedIndirect(indirectBuffer, indirectOffset) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
indirectBuffer GPUBuffer 간접 drawIndexed 파라미터가 들어있는 버퍼.
indirectOffset GPUSize64 indirectBuffer에서 드로잉 데이터가 시작하는 바이트 오프셋.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  3. Add indirectBuffer[[usage scope]] 에 input 용도로 추가합니다.

  4. this.[[drawCount]] 값을 1 증가시킵니다.

  5. bindingStatethis의 현재 상태 스냅샷으로 설정합니다.

  6. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. indexCountindirectBuffer에서 indirectOffset 바이트 위치에서 부호없는 32비트 정수로 읽어옴.

  2. instanceCountindirectBuffer에서 (indirectOffset + 4) 바이트 위치에서 부호없는 32비트 정수로 읽어옴.

  3. firstIndexindirectBuffer에서 (indirectOffset + 8) 바이트 위치에서 부호없는 32비트 정수로 읽어옴.

  4. baseVertexindirectBuffer에서 (indirectOffset + 12) 바이트 위치에서 부호있는 32비트 정수로 읽어옴.

  5. firstInstanceindirectBuffer에서 (indirectOffset + 16) 바이트 위치에서 부호없는 32비트 정수로 읽어옴.

  6. 프리미티브를 indexCount개의 인덱스드 버텍스(firstIndex부터 시작, baseVertex 기준), instanceCount개의 인스턴스(firstInstance부터 시작)로 드로우하고, bindingStaterenderState의 상태를 사용합니다.

GPURenderCommandsMixin encoder로 드로우가 유효한지(valid to draw) 판단하려면, 다음 디바이스 타임라인 단계를 실행합니다:
  1. 아래 조건 중 하나라도 만족하지 않으면 false를 반환합니다:

  2. 그 외의 경우 true를 반환합니다.

GPURenderCommandsMixin encoder로 인덱스드 드로우가 유효한지(valid to draw indexed) 판단하려면, 다음 디바이스 타임라인 단계를 실행합니다:
  1. 아래 조건 중 하나라도 만족하지 않으면 false를 반환합니다:

  2. 그 외의 경우 true를 반환합니다.

17.2.2. 래스터화 상태

GPURenderPassEncoder에는 이 인코더에서 사용되는 어태치먼트에 드로우 명령이 어떻게 래스터화(rasterize)되는지에 영향을 주는 여러 메서드가 있습니다.

setViewport(x, y, width, height, minDepth, maxDepth)

래스터화 단계에서 정규화된 장치 좌표에서 뷰포트 좌표로 선형 변환하는 데 사용되는 뷰포트를 설정합니다.

호출 대상: GPURenderPassEncoder this.

인자:

GPURenderPassEncoder.setViewport(x, y, width, height, minDepth, maxDepth) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
x float 뷰포트의 최소 X값(픽셀 단위).
y float 뷰포트의 최소 Y값(픽셀 단위).
width float 뷰포트의 너비(픽셀 단위).
height float 뷰포트의 높이(픽셀 단위).
minDepth float 뷰포트의 최소 깊이값.
maxDepth float 뷰포트의 최대 깊이값.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. maxViewportRangethis.limits.maxTextureDimension2D × 2로 설정.

  3. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

    • x ≥ -maxViewportRange

    • y ≥ -maxViewportRange

    • 0widththis.limits.maxTextureDimension2D

    • 0heightthis.limits.maxTextureDimension2D

    • x + widthmaxViewportRange1

    • y + heightmaxViewportRange1

    • 0.0minDepth1.0

    • 0.0maxDepth1.0

    • minDepthmaxDepth

  4. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. x, y, width, height 값을 정수 반올림 이상의 정밀도로 일관되게 반올림합니다.

  2. renderState.[[viewport]] 값을 x, y, width, height, minDepth, maxDepth 범위로 설정합니다.

setScissorRect(x, y, width, height)

래스터화 단계에서 사용할 시저(rect) 사각형을 설정합니다. 뷰포트 좌표로 변환된 후, 시저 사각형 밖에 위치한 프래그먼트는 폐기됩니다.

호출 대상: GPURenderPassEncoder this.

인자:

GPURenderPassEncoder.setScissorRect(x, y, width, height) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
x GPUIntegerCoordinate 시저 사각형의 최소 X값(픽셀 단위).
y GPUIntegerCoordinate 시저 사각형의 최소 Y값(픽셀 단위).
width GPUIntegerCoordinate 시저 사각형의 너비(픽셀 단위).
height GPUIntegerCoordinate 시저 사각형의 높이(픽셀 단위).

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  3. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. renderState.[[scissorRect]] 값을 x, y, width, height 범위로 설정합니다.

setBlendConstant(color)

"constant""one-minus-constant" GPUBlendFactor에서 사용할 블렌드 상수 색상 및 알파 값을 설정합니다.

호출 대상: GPURenderPassEncoder this.

인자:

GPURenderPassEncoder.setBlendConstant(color) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
color GPUColor 블렌딩에 사용할 색상 값.

반환값: undefined

컨텐트 타임라인 단계:

  1. ? GPUColor shape 검증(color).

  2. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. renderState.[[blendConstant]] 값을 color로 설정합니다.

setStencilReference(reference)

[[stencilReference]] 값을 "replace" GPUStencilOperation과 함께 사용하는 스텐실 테스트에 사용할 값을 설정합니다.

호출 대상: GPURenderPassEncoder this.

인자:

GPURenderPassEncoder.setStencilReference(reference) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
reference GPUStencilValue 새로운 스텐실 참조값.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. renderState.[[stencilReference]] 값을 reference로 설정합니다.

17.2.3. 쿼리

beginOcclusionQuery(queryIndex)
호출 대상: GPURenderPassEncoder this.

인자:

GPURenderPassEncoder.beginOcclusionQuery(queryIndex) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
queryIndex GPUSize32 쿼리 세트 내 쿼리의 인덱스.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  3. this.[[occlusion_query_active]] 값을 true로 설정.

  4. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. renderState.[[occlusionQueryIndex]] 값을 queryIndex로 설정합니다.

endOcclusionQuery()
호출 대상: GPURenderPassEncoder this.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  3. this.[[occlusion_query_active]] 값을 false로 설정.

  4. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 이후 단계를 실행.

큐 타임라인 단계:
  1. passingFragments를 해당 beginOcclusionQuery() 명령 실행 이후 모든 프래그먼트 샘플이 per-fragment 테스트를 통과했다면 0이 아닌 값으로, 그렇지 않으면 0으로 설정합니다.

    참고: 드로우 호출이 없으면 passingFragments 값은 0입니다.

  2. passingFragmentsthis.[[occlusion_query_set]]renderState.[[occlusionQueryIndex]] 인덱스에 기록합니다.

17.2.4. 번들

executeBundles(bundles)

해당 GPURenderBundle에 미리 기록된 명령들을 이 렌더 패스의 일부로 실행합니다.

GPURenderBundle이 실행될 때, 렌더 패스의 파이프라인, 바인드 그룹, 버텍스/인덱스 버퍼 상태를 상속하지 않습니다. GPURenderBundle 실행 후 렌더 패스의 파이프라인, 바인드 그룹, 버텍스/인덱스 버퍼 상태는 (초기 빈 값으로) 클리어됩니다.

참고: 상태는 이전 상태로 복원되지 않고 클리어됩니다. 0개의 GPURenderBundles를 실행해도 클리어가 발생합니다.

호출 대상: GPURenderPassEncoder this.

인자:

GPURenderPassEncoder.executeBundles(bundles) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
bundles sequence<GPURenderBundle> 실행할 렌더 번들 리스트.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[device]]디바이스 타임라인에서 이후 단계를 실행합니다.

디바이스 타임라인 단계:
  1. 인코더 상태 검증this에 대해 실행. 결과가 false면 반환.

  2. 아래 조건 중 하나라도 만족하지 않으면, this를 무효화하고 반환.

  3. bundle에 대해:

    1. this.[[drawCount]] 값을 bundle.[[drawCount]]만큼 증가시킵니다.

    2. Merge bundle.[[usage scope]]this.[[usage scope]]에 병합합니다.

    3. 렌더 커맨드 enqueuethis에 실행하여, 실행 시 큐 타임라인에서 renderState를 사용해 다음 단계를 실행:

      큐 타임라인 단계:
      1. bundle.[[command_list]] 의 각 명령을 renderState와 함께 실행합니다.

        참고: renderState는 번들을 실행해도 변경되지 않습니다. 바인딩 상태는 번들 인코딩 시 캡처됐으므로 번들 실행 시 사용되지 않습니다.

  4. 렌더 패스 바인딩 상태 초기화this에 실행합니다.

렌더 패스 바인딩 상태 초기화GPURenderPassEncoder encoder에 실행하려면 다음 디바이스 타임라인 단계를 실행합니다:
  1. Clear encoder.[[bind_groups]].

  2. encoder.[[pipeline]] 값을 null로 설정합니다.

  3. encoder.[[index_buffer]] 값을 null로 설정합니다.

  4. Clear encoder.[[vertex_buffers]].

18. 번들

번들은 한 번 인코딩된 후 여러 번 실행할 수 있는 부분적이고 제한적인 패스로, 일반적인 커맨드 버퍼처럼 사용 후 만료되지 않습니다. 반복적으로 변경 없이 발행되는 명령의 인코딩 및 제출 오버헤드를 줄일 수 있습니다.

18.1. GPURenderBundle

[Exposed=(Window, Worker), SecureContext]
interface GPURenderBundle {
};
GPURenderBundle includes GPUObjectBase;
[[command_list]], of type list<GPU command>

GPURenderBundle가 실행될 때 GPURenderPassEncoder에 제출되는 GPU 명령 리스트입니다.

[[usage scope]], of type usage scope, initially empty

해당 렌더 번들의 usage scope로, 나중에 executeBundles()에서 GPURenderPassEncoder[[usage scope]]에 병합할 때 사용됩니다.

[[layout]], of type GPURenderPassLayout

렌더 번들의 레이아웃입니다.

[[depthReadOnly]], of type boolean

true면 이 렌더 번들 실행 시 depth 컴포넌트가 변경되지 않음을 의미합니다.

[[stencilReadOnly]], of type boolean

true면 이 렌더 번들 실행 시 stencil 컴포넌트가 변경되지 않음을 의미합니다.

[[drawCount]], of type GPUSize64

GPURenderBundle의 드로우 명령 개수입니다.

18.1.1. 렌더 번들 생성

dictionary GPURenderBundleDescriptor
         : GPUObjectDescriptorBase {
};
[Exposed=(Window, Worker), SecureContext]
interface GPURenderBundleEncoder {
    GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {});
};
GPURenderBundleEncoder includes GPUObjectBase;
GPURenderBundleEncoder includes GPUCommandsMixin;
GPURenderBundleEncoder includes GPUDebugCommandsMixin;
GPURenderBundleEncoder includes GPUBindingCommandsMixin;
GPURenderBundleEncoder includes GPURenderCommandsMixin;
createRenderBundleEncoder(descriptor)

GPURenderBundleEncoder를 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createRenderBundleEncoder(descriptor) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPURenderBundleEncoderDescriptor 생성할 GPURenderBundleEncoder 설명.

반환값: GPURenderBundleEncoder

컨텐트 타임라인 단계:

  1. ? 텍스처 포맷 필수 기능 검증descriptor.colorFormats의 각 non-null 요소에 대해 this.[[device]]와 함께 실행.

  2. descriptor.depthStencilFormat 값이 제공된 경우:

    1. ? 텍스처 포맷 필수 기능 검증descriptor.depthStencilFormat에 대해 this.[[device]]와 함께 실행.

  3. e! 새 WebGPU 객체 생성(this, GPURenderBundleEncoder, descriptor)로 설정.

  4. this디바이스 타임라인에서 initialization steps 실행.

  5. e 반환.

디바이스 타임라인 initialization steps:
  1. 아래 조건 중 하나라도 만족하지 않으면 유효성 오류 생성, e를 무효화하고 반환.

  2. e.[[layout]] 값을 descriptor에 포함된 GPURenderPassLayout 인터페이스의 복사본으로 설정.

  3. e.[[depthReadOnly]] 값을 descriptor.depthReadOnly로 설정.

  4. e.[[stencilReadOnly]] 값을 descriptor.stencilReadOnly로 설정.

  5. e.[[state]] 값을 "open"으로 설정.

  6. e.[[drawCount]] 값을 0으로 설정.

18.1.2. 인코딩

dictionary GPURenderBundleEncoderDescriptor
         : GPURenderPassLayout {
    boolean depthReadOnly = false;
    boolean stencilReadOnly = false;
};
depthReadOnly, 타입 boolean, 기본값 false

true면 렌더 번들이 실행되는 어떤 렌더 패스의 GPURenderPassDepthStencilAttachment의 depth 컴포넌트를 수정하지 않음을 의미합니다.

읽기 전용 depth-stencil 참고.

stencilReadOnly, 타입 boolean, 기본값 false

true면 렌더 번들이 실행되는 어떤 렌더 패스의 GPURenderPassDepthStencilAttachment의 stencil 컴포넌트를 수정하지 않음을 의미합니다.

읽기 전용 depth-stencil 참고.

18.1.3. 최종화

finish(descriptor)

렌더 번들 커맨드 시퀀스 기록을 완료합니다.

호출 대상: GPURenderBundleEncoder this.

인자:

GPURenderBundleEncoder.finish(descriptor) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPURenderBundleDescriptor

반환값: GPURenderBundle

컨텐트 타임라인 단계:

  1. renderBundle을 새로운 GPURenderBundle로 설정.

  2. this.[[device]]디바이스 타임라인에서 finish steps 실행.

  3. renderBundle 반환.

디바이스 타임라인 finish steps:
  1. 아래 요구사항을 모두 만족하면 validationSucceededtrue로, 아니면 false로 설정.

  2. this.[[state]] 값을 "ended"로 설정.

  3. validationSucceededfalse면:

    1. 유효성 오류 생성.

    2. invalidated GPURenderBundle 반환.

  4. renderBundle.[[command_list]] 값을 this.[[commands]]로 설정.

  5. renderBundle.[[usage scope]] 값을 this.[[usage scope]]로 설정.

  6. renderBundle.[[drawCount]] 값을 this.[[drawCount]]로 설정.

19. 큐(Queues)

19.1. GPUQueueDescriptor

GPUQueueDescriptor 는 큐 요청을 설명합니다.

dictionary GPUQueueDescriptor
         : GPUObjectDescriptorBase {
};

19.2. GPUQueue

[Exposed=(Window, Worker), SecureContext]
interface GPUQueue {
    undefined submit(sequence<GPUCommandBuffer> commandBuffers);

    Promise<undefined> onSubmittedWorkDone();

    undefined writeBuffer(
        GPUBuffer buffer,
        GPUSize64 bufferOffset,
        AllowSharedBufferSource data,
        optional GPUSize64 dataOffset = 0,
        optional GPUSize64 size);

    undefined writeTexture(
        GPUTexelCopyTextureInfo destination,
        AllowSharedBufferSource data,
        GPUTexelCopyBufferLayout dataLayout,
        GPUExtent3D size);

    undefined copyExternalImageToTexture(
        GPUCopyExternalImageSourceInfo source,
        GPUCopyExternalImageDestInfo destination,
        GPUExtent3D copySize);
};
GPUQueue includes GPUObjectBase;

GPUQueue에는 다음과 같은 메서드가 있습니다:

writeBuffer(buffer, bufferOffset, data, dataOffset, size)

제공된 데이터를 GPUBuffer에 기록합니다.

호출 대상: GPUQueue this.

인자:

GPUQueue.writeBuffer(buffer, bufferOffset, data, dataOffset, size) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
buffer GPUBuffer 기록 대상 버퍼.
bufferOffset GPUSize64 buffer에서 기록을 시작할 바이트 오프셋.
data AllowSharedBufferSource buffer에 기록할 데이터.
dataOffset GPUSize64 data에서 기록을 시작할 오프셋. dataTypedArray면 요소 단위, 그렇지 않으면 바이트 단위.
size GPUSize64 data에서 buffer로 기록할 내용의 크기. dataTypedArray면 요소 단위, 그렇지 않으면 바이트 단위.

반환값: undefined

컨텐트 타임라인 단계:

  1. dataArrayBuffer 또는 DataView면, element type을 "byte"로 설정. 그렇지 않으면 data는 TypedArray이며, element type은 TypedArray의 타입.

  2. dataSizedata의 크기(요소 단위)로 설정.

  3. size가 없으면, contentsSizedataSizedataOffset으로, 아니면 contentsSizesize로 설정.

  4. 아래 조건 중 하나라도 만족하지 않으면, OperationError를 throw하고 반환.

    • contentsSize ≥ 0.

    • dataOffset + contentsSizedataSize.

    • contentsSize를 바이트로 변환했을 때 4바이트 배수여야 함.

  5. dataContentsdata의 버퍼 소스에서 복사한 바이트로 설정.

  6. contentsdataContentsdataOffset 위치에서 contentsSize만큼의 요소로 설정.

  7. 이후 단계는 this디바이스 타임라인에서 실행.

디바이스 타임라인 단계:
  1. 아래 조건 중 하나라도 만족하지 않으면, 유효성 오류 생성 후 반환.

  2. 이후 단계는 this큐 타임라인에서 실행.

큐 타임라인 단계:
  1. contentsbufferbufferOffset 위치부터 기록합니다.

writeTexture(destination, data, dataLayout, size)

제공된 데이터를 GPUTexture에 기록합니다.

호출 대상: GPUQueue this.

인자:

GPUQueue.writeTexture(destination, data, dataLayout, size) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
destination GPUTexelCopyTextureInfo 기록 대상 텍스처 서브리소스와 시작 위치.
data AllowSharedBufferSource destination에 기록할 데이터.
dataLayout GPUTexelCopyBufferLayout data의 레이아웃.
size GPUExtent3D data에서 destination으로 기록할 컨텐츠의 크기.

반환값: undefined

컨텐트 타임라인 단계:

  1. ? GPUOrigin3D shape 검증(destination.origin).

  2. ? GPUExtent3D shape 검증(size).

  3. dataBytesdata의 버퍼 소스에서 복사한 바이트 시퀀스로 설정.

    참고: 명세상 data 전체를 디바이스 타임라인으로 복사한다고 되어 있지만, 실제로는 필요한 바이트만 복사하는 것이 최적화됩니다.

  4. 이후 단계는 this디바이스 타임라인에서 실행.

디바이스 타임라인 단계:
  1. alignedfalse로 설정.

  2. dataLengthdataBytes의 길이로 설정.

  3. 아래 조건 중 하나라도 만족하지 않으면, 유효성 오류 생성 후 반환.

    참고: GPUCommandEncoder.copyBufferToTexture()와 달리 dataLayout.bytesPerRowdataLayout.offset에 대한 정렬 요구는 없음.

  4. 이후 단계는 this큐 타임라인에서 실행.

큐 타임라인 단계:
  1. blockWidthdestination.texture의 텍셀 블록 너비로 설정.

  2. blockHeightdestination.texture의 텍셀 블록 높이로 설정.

  3. dstOrigindestination.origin로 설정;

  4. dstBlockOriginX를 (dstOrigin.x ÷ blockWidth)로 설정.

  5. dstBlockOriginY를 (dstOrigin.y ÷ blockHeight)로 설정.

  6. blockColumns를 (copySize.width ÷ blockWidth)로 설정.

  7. blockRows를 (copySize.height ÷ blockHeight)로 설정.

  8. AssertdstBlockOriginX, dstBlockOriginY, blockColumns, blockRows가 정수임을 확인.

  9. z에 대해 [0, copySize.depthOrArrayLayers − 1] 범위:

    1. dstSubregiontexture copy sub-region (z + dstOrigin.z)로 설정.

    2. y에 대해 [0, blockRows − 1] 범위:

      1. x에 대해 [0, blockColumns − 1] 범위:

        1. blockOffsettexel block byte offset (x, y, z)로 설정.

        2. dstSubregion의 (dstBlockOriginX + x, dstBlockOriginY + y) 텍셀 블록을 dataBytesblockOffset 위치에서 동등한 텍셀 표현으로 설정.

copyExternalImageToTexture(source, destination, copySize)

플랫폼 이미지/캔버스의 내용을 대상 텍스처에 복사합니다.

이 작업은 GPUCopyExternalImageDestInfo 파라미터에 따라 대상 인코딩으로 컬러 인코딩을 수행합니다.

-srgb 텍스처에 복사할 경우, 동일한 디코드 값이 아닌 동일한 텍스처 바이트가 복사됩니다. 따라서 복사 후 대상 텍스처를 샘플링하면 포맷이 -srgb인지에 따라 결과가 달라집니다.

참고:
"webgl"/"webgl2" 컨텍스트 캔버스에서 복사할 때, WebGL Drawing Buffer는 프레임 표시 사이클 중 특정 시점에 존재하지 않을 수 있습니다(이미지가 디스플레이를 위해 컴포지터로 이동된 후). 이를 피하려면 다음 중 하나를 수행하세요:
  • WebGL 렌더링 작업과 동일 task에서 copyExternalImageToTexture()를 호출해 복사가 WebGL 캔버스 표시 전에 이루어지도록 하세요.

  • 불가능하다면 preserveDrawingBuffer 옵션을 WebGLContextAttributestrue로 설정해, 프레임 표시 후에도 드로잉 버퍼가 프레임 내용을 복사본으로 유지하도록 하세요. 단, 추가 복사로 인해 성능 저하가 있을 수 있습니다.

호출 대상: GPUQueue this.

인자:

GPUQueue.copyExternalImageToTexture(source, destination, copySize) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
source GPUCopyExternalImageSourceInfo 복사할 destination에 대한 소스 이미지와 원점.
destination GPUCopyExternalImageDestInfo 기록할 텍스처 서브리소스 및 원점, 그리고 인코딩 메타데이터.
copySize GPUExtent3D source에서 destination으로 기록할 콘텐츠의 범위.

반환값: undefined

컨텐트 타임라인 단계:

  1. ? GPUOrigin2D shape 검증(source.origin).

  2. ? GPUOrigin3D shape 검증(destination.origin).

  3. ? GPUExtent3D shape 검증(copySize).

  4. sourceImagesource.source로 설정.

  5. sourceImageorigin-clean 상태가 아니면, SecurityError를 throw하고 반환.

  6. 아래 요구사항 중 하나라도 만족하지 않으면 OperationError를 throw하고 반환.

    • source.origin.x + copySize.width 값이 sourceImage의 너비 이하이어야 함.

    • source.origin.y + copySize.height 값이 sourceImage의 높이 이하이어야 함.

    • copySize.depthOrArrayLayers 값이 1 이하이어야 함.

  7. usability? 이미지 인자 사용성 체크(source)로 설정.

  8. 이후 단계를 this디바이스 타임라인에서 실행.

디바이스 타임라인 단계:
  1. texturedestination.texture로 설정.

  2. 아래 요구사항 중 하나라도 만족하지 않으면 유효성 오류 생성하고 반환.

  3. copySize.depthOrArrayLayers 값이 0보다 크면, 이후 단계를 this큐 타임라인에서 실행.

큐 타임라인 단계:
  1. Assert destination.texturetexel block width가 1, texel block height가 1, copySize.depthOrArrayLayers가 1임을 확인.

  2. srcOriginsource.origin으로 설정.

  3. dstOrigindestination.origin으로 설정.

  4. dstSubregiontexture copy sub-region (dstOrigin.z) of destination으로 설정.

  5. y에 대해 [0, copySize.height − 1] 범위에서:

    1. srcYsource.flipY 값이 false이면 y로, 아니면 (copySize.height − 1 − y)로 설정.

    2. x에 대해 [0, copySize.width − 1] 범위에서:

      1. texel block (dstOrigin.x + x, dstOrigin.y + y) of dstSubregion을 (srcOrigin.x + x, srcOrigin.y + srcY) 위치의 source.source 픽셀의 동등 texel 표현으로 설정. destination.colorSpacedestination.premultipliedAlpha에 필요한 컬러스페이스 변환 적용 후.

submit(commandBuffers)

이 큐에서 GPU가 커맨드 버퍼를 실행하도록 예약합니다.

제출된 커맨드 버퍼는 다시 사용할 수 없습니다.

호출 대상: GPUQueue this.

인자:

GPUQueue.submit(commandBuffers) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
commandBuffers sequence<GPUCommandBuffer>

반환값: undefined

컨텐트 타임라인 단계:

  1. 이후 단계를 this디바이스 타임라인에서 실행:

디바이스 타임라인 단계:
  1. 다음 요구사항 중 하나라도 충족되지 않으면, 유효성 검사 오류를 발생시키고, invalidatecommandBuffers의 각 GPUCommandBuffer에 수행한 뒤 반환합니다.

  2. commandBuffer에 대해:

    1. commandBuffer 무효화.

  3. 이후 단계를 this큐 타임라인에서 실행:

큐 타임라인 단계:
  1. commandBuffer에 대해:

    1. commandBuffer.[[command_list]]의 각 명령을 실행합니다.

onSubmittedWorkDone()

이 큐가 지금까지 제출된 모든 작업을 처리하면 resolve되는 Promise를 반환합니다.

Promise가 resolve되면, 해당 호출 전에 mapAsync() 가 실행된 GPUBuffer 들에 대해, 마지막으로 해당 큐에서만 사용된 버퍼의 작업이 완료됨을 의미합니다.

호출 대상: GPUQueue this.

반환값: Promise<undefined>

컨텐트 타임라인 단계:

  1. contentTimeline을 현재 컨텐트 타임라인으로 설정.

  2. promise새로운 promise로 설정.

  3. this디바이스 타임라인에서 synchronization steps 실행.

  4. promise 반환.

디바이스 타임라인 synchronization steps:
  1. 현재 큐에 등록된 모든 작업이 완료되면 event가 발생하도록 설정.

  2. event를 타임라인 이벤트로 수신 하여, this.[[device]]에서 contentTimeline에서 후속 단계 처리.

컨텐트 타임라인 단계:
  1. promise resolve.

20. 쿼리(Queries)

20.1. GPUQuerySet

[Exposed=(Window, Worker), SecureContext]
interface GPUQuerySet {
    undefined destroy();

    readonly attribute GPUQueryType type;
    readonly attribute GPUSize32Out count;
};
GPUQuerySet includes GPUObjectBase;

GPUQuerySet 객체에는 다음 불변 속성이 있습니다:

type, 타입 GPUQueryType, 읽기전용

GPUQuerySet 이 관리하는 쿼리 타입입니다.

count, 타입 GPUSize32Out, 읽기전용

GPUQuerySet 이 관리하는 쿼리 개수입니다.

GPUQuerySet 객체에는 다음 디바이스 타임라인 속성이 있습니다:

[[destroyed]], 타입 boolean, 초기값 false

쿼리셋이 destroy되면 더 이상 작업에 사용할 수 없으며, 메모리도 해제될 수 있습니다.

20.1.1. 쿼리셋 생성(QuerySet Creation)

GPUQuerySetDescriptorGPUQuerySet 생성 시 사용할 옵션을 지정합니다.

dictionary GPUQuerySetDescriptor
         : GPUObjectDescriptorBase {
    required GPUQueryType type;
    required GPUSize32 count;
};
type, 타입 GPUQueryType

GPUQuerySet 이 관리하는 쿼리 타입입니다.

count, 타입 GPUSize32

GPUQuerySet 이 관리하는 쿼리 개수입니다.

createQuerySet(descriptor)

GPUQuerySet 을 생성합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.createQuerySet(descriptor) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
descriptor GPUQuerySetDescriptor 생성할 GPUQuerySet 설명.

반환값: GPUQuerySet

컨텐트 타임라인 단계:

  1. descriptor.type 값이 "timestamp"이지만, "timestamp-query"thisenabled for 상태가 아니라면:

    1. TypeError를 throw합니다.

  2. q! 새 WebGPU 객체 생성(this, GPUQuerySet, descriptor)로 설정.

  3. q.type 값을 descriptor.type로 설정.

  4. q.count 값을 descriptor.count로 설정.

  5. this디바이스 타임라인에서 initialization steps 실행.

  6. q 반환.

디바이스 타임라인 initialization steps:
  1. 아래 요구사항 중 하나라도 만족하지 않으면 유효성 오류 생성, q 무효화 후 반환.

    • thislost 상태가 아니어야 함.

    • descriptor.count 값이 4096 이하이어야 함.

  2. 각 쿼리셋 엔트리 0으로 초기화하는 디바이스 할당 생성.

    할당이 부작용 없이 실패하면, out-of-memory 오류 생성, q 무효화 후 반환.

32개의 occlusion 쿼리 결과를 보관하는 GPUQuerySet 생성 예시.
const querySet = gpuDevice.createQuerySet({
    type: 'occlusion',
    count: 32
});

20.1.2. 쿼리셋 소멸(Query Set Destruction)

더 이상 GPUQuerySet 이 필요하지 않은 애플리케이션은 destroy()를 호출하여 가비지 컬렉션 이전에 접근을 잃을 수 있습니다.

GPUQuerySet 객체에는 다음과 같은 메서드가 있습니다:

destroy()

GPUQuerySet을 소멸시킵니다.

호출 대상: GPUQuerySet this.

반환값: undefined

컨텐트 타임라인 단계:

  1. 이후 단계를 디바이스 타임라인에서 실행.

디바이스 타임라인 단계:
  1. this.[[destroyed]] 값을 true로 설정합니다.

20.2. QueryType

enum GPUQueryType {
    "occlusion",
    "timestamp",
};

20.3. Occlusion Query

Occlusion 쿼리는 렌더 패스에서만 사용할 수 있으며, 드로우 명령 집합에 대해 스크리서, 샘플 마스크, 알파 투 커버리지, 스텐실, 깊이 테스트 등 모든 프래그먼트 테스트를 통과한 프래그먼트 샘플의 개수를 쿼리합니다. 쿼리 결과가 0이 아닌 값이면 하나 이상의 샘플이 테스트를 통과해 렌더 파이프라인의 출력 머지 단계에 도달했다는 의미이고, 0이면 어떤 샘플도 테스트를 통과하지 않았다는 뜻입니다.

렌더 패스를 시작할 때 GPURenderPassDescriptor.occlusionQuerySet 을 지정해야 패스에서 occlusion 쿼리를 사용할 수 있습니다. 쿼리는 beginOcclusionQuery()endOcclusionQuery() 를 반드시 쌍으로 호출해야 하며 중첩될 수 없고, GPUBuffer64비트 부호 없는 정수 형태로 GPUCommandEncoder.resolveQuerySet()로 결과를 저장합니다.

20.4. Timestamp Query

Timestamp 쿼리를 사용하면 애플리케이션이 다음을 통해 GPUQuerySet에 타임스탬프를 기록할 수 있습니다:

그리고 타임스탬프 값을(나노초 단위의 64비트 부호 없는 정수 형태) GPUBufferGPUCommandEncoder.resolveQuerySet()를 통해 저장할 수 있습니다.

Timestamp 값은 구현 종속적이며 반드시 단조 증가하지 않을 수 있습니다. 물리 디바이스가 타임스탬프 카운터를 가끔 리셋할 수 있어 논리적으로 증가해야 할 타임스탬프 사이가 음수 등 예기치 않은 값이 나올 수 있습니다. 이런 경우는 드물며 무시해도 안전합니다. 애플리케이션이 예기치 않은 타임스탬프 때문에 실패하지 않도록 작성되어야 합니다.

There is a tracking vector here. Timestamp 쿼리는 고해상도 타이머(참고 § 2.1.7.2 디바이스/큐 타임라인 타이밍)로 구현됩니다. 보안 및 프라이버시 문제를 완화하기 위해 정밀도가 감소되어야 합니다:

현재 큐 타임스탬프를 얻으려면 다음 큐 타임라인 단계를 실행하세요:

참고: cross-origin 격리가 디바이스 타임라인이나 큐 타임라인에 적용되지 않을 수 있으므로, crossOriginIsolatedCapability는 항상 false로 설정됩니다.

timestampWrites 유효성 검사(device, timestampWrites)

인자:

디바이스 타임라인 단계:

  1. 아래 요구사항을 모두 만족하면 true, 아니면 false를 반환:

21. 캔버스 렌더링

21.1. HTMLCanvasElement.getContext()

GPUCanvasContext 객체는 getContext() 메서드를 통해 HTMLCanvasElement 인스턴스에서 문자열 리터럴 'webgpu'contextType 인자로 넘기면 생성됩니다.

오프스크린 HTMLCanvasElement에서 GPUCanvasContext 얻기:
const canvas = document.createElement('canvas');
const context = canvas.getContext('webgpu');

WebGL이나 2D 컨텍스트 생성과 달리, HTMLCanvasElement.getContext() 또는 OffscreenCanvas.getContext()의 두 번째 인자인 컨텍스트 생성 속성 딕셔너리 options는 무시됩니다. 대신, 캔버스를 교체하지 않고 캔버스 구성 변경이 가능한 GPUCanvasContext.configure()를 사용하세요.

캔버스에서 'webgpu' 컨텍스트 생성 (HTMLCanvasElement 또는 OffscreenCanvas) canvas에 대해, 다음 컨텐트 타임라인 단계를 실행합니다:
  1. context를 새로운 GPUCanvasContext로 설정합니다.

  2. context.canvas 값을 canvas로 설정합니다.

  3. drawing buffer 교체context에 대해 실행합니다.

  4. context를 반환합니다.

참고: getContext()로 WebGPU 캔버스 컨텍스트를 얻을 때 무시되는 options 인자가 제공되면 사용자 에이전트는 개발자에게 경고를 표시해야 합니다.

21.2. GPUCanvasContext

[Exposed=(Window, Worker), SecureContext]
interface GPUCanvasContext {
    readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas;

    undefined configure(GPUCanvasConfiguration configuration);
    undefined unconfigure();

    GPUCanvasConfiguration? getConfiguration();
    GPUTexture getCurrentTexture();
};

GPUCanvasContext 객체에는 다음 컨텐트 타임라인 속성이 있습니다:

canvas, 타입 (HTMLCanvasElement or OffscreenCanvas), 읽기전용

이 컨텍스트가 생성된 캔버스입니다.

[[configuration]], 타입 GPUCanvasConfiguration?, 초기값 null

현재 이 컨텍스트가 구성된 옵션입니다.

아직 구성되지 않았거나 unconfigure된 경우 null입니다.

[[textureDescriptor]], 타입 GPUTextureDescriptor?, 초기값 null

현재 구성된 텍스처 디스크립터로, [[configuration]] 및 캔버스에서 유도됩니다.

아직 구성되지 않았거나 unconfigure된 경우 null입니다.

[[drawingBuffer]], 이미지, 초기값은 캔버스와 동일한 크기의 투명 검정 이미지

드로잉 버퍼는 캔버스의 작업용 이미지 데이터입니다. [[currentTexture]] (즉, getCurrentTexture()로 반환)에서 쓰기 가능하게 노출됩니다.

드로잉 버퍼는 컨텍스트의 이미지 내용 복사에 사용되며, 캔버스 표시 또는 읽기 시 동작합니다. [[configuration]].alphaMode 값이 "opaque"여도 투명할 수 있습니다. alphaMode는 "컨텍스트의 이미지 내용 복사" 알고리즘의 결과에만 영향을 줍니다.

드로잉 버퍼는 [[currentTexture]] 보다 오래 존재하며, 캔버스가 표시된 후에도 이전 렌더링 내용이 남아 있습니다. drawing buffer 교체에서만 초기화됩니다.

드로잉 버퍼를 읽을 때마다 구현체는 이전에 제출된 모든 작업(예: 큐 제출)이 [[currentTexture]]를 통해 모두 기록을 완료했는지 보장해야 합니다.

[[currentTexture]], 타입 GPUTexture?, 초기값 null

현재 프레임에 그리기 위한 GPUTexture입니다. 이는 [[drawingBuffer]]에 대한 쓰기 가능한 뷰를 제공합니다. getCurrentTexture()가 이 슬롯이 null이면 할당 후 반환합니다.

표시 상태의 캔버스에서는 currentTexture로 드로잉 버퍼에 변경된 내용이 WebGPU 캔버스 렌더링 갱신 시점에 표시됩니다. 그 시점이나 그 이전에 텍스처가 destroy되고, [[currentTexture]] 값은 null로 바뀌어 다음 getCurrentTexture() 호출에서 새로 생성됨을 신호합니다.

currentTexture destroy는 드로잉 버퍼 내용에는 영향을 주지 않으며, 단지 드로잉 버퍼의 쓰기 접근을 즉시 중단시킵니다. 같은 프레임 내에서는 getCurrentTexture()가 계속해서 동일한 destroy된 텍스처를 반환할 수 있습니다.

currentTexture 만료는 currentTexture를 null로 설정합니다. 이는 configure(), 캔버스 크기 변경, 프레젠테이션, transferToImageBitmap() 등에서 호출됩니다.

[[lastPresentedImage]], 타입 (readonly image)?, 초기값 null

이 캔버스에서 "WebGPU 캔버스 렌더링 갱신" 시 가장 최근에 표시된 이미지입니다. 디바이스가 lost 또는 destroy된 경우, 캔버스가 빈 상태가 되지 않도록 "컨텍스트의 이미지 내용 복사"에서 fallback으로 사용할 수 있습니다.

참고: 이 속성은 fallback 구현하는 경우에만 필요하며 선택 사항입니다.

GPUCanvasContext 객체에는 다음과 같은 메서드가 있습니다:

configure(configuration)

이 캔버스의 컨텍스트를 구성합니다. drawing buffer를 투명 검정색으로 초기화합니다(drawing buffer 교체).

호출 대상: GPUCanvasContext this.

인자:

GPUCanvasContext.configure(configuration) 메서드의 인자.
파라미터 타입 Nullable Optional 설명
configuration GPUCanvasConfiguration 컨텍스트에 원하는 구성.

반환값: undefined

컨텐트 타임라인 단계:

  1. deviceconfiguration.device로 설정합니다.

  2. ? 텍스처 포맷 필수 기능 검증configuration.format에 대해 device.[[device]]와 함께 실행.

  3. ? 텍스처 포맷 필수 기능 검증configuration.viewFormats의 각 요소에 대해 device.[[device]]와 함께 실행.

  4. 지원하는 컨텍스트 포맷configuration.format포함하지 않으면, TypeError를 throw합니다.

  5. descriptor캔버스와 configuration용 GPUTextureDescriptor(this.canvas, configuration)로 설정.

  6. this.[[configuration]] 값을 configuration로 설정합니다.

    참고:
    이 명세는 toneMapping 옵션을 통해 HDR 지원을 요구합니다. 사용자가 toneMapping: "standard"만 지원하는 경우, toneMapping 멤버가 GPUCanvasConfiguration 에 존재하지 않아야 하며, getConfiguration() 결과에도 존재하지 않고, configure()에서도 접근되지 않아야 합니다. 이렇게 하면 웹사이트에서 기능 지원 여부를 감지할 수 있습니다.
  7. this.[[textureDescriptor]] 값을 descriptor로 설정합니다.

  8. drawing buffer 교체this에 대해 실행합니다.

  9. 이후 단계를 device디바이스 타임라인에서 실행합니다.

디바이스 타임라인 단계:
  1. 아래 요구사항 중 하나라도 만족하지 않으면 유효성 오류 생성 후 반환.

    참고: 이 초기 검증은 다음 configure() 호출까지 유효합니다. 단, size에 대한 검증은 캔버스 크기가 변경될 때만 예외입니다.

unconfigure()

컨텍스트 구성을 제거합니다. 구성 중 생성된 텍스처는 모두 destroy됩니다.

호출 대상: GPUCanvasContext this.

반환값: undefined

컨텐트 타임라인 단계:

  1. this.[[configuration]] 값을 null로 설정합니다.

  2. this.[[textureDescriptor]] 값을 null로 설정합니다.

  3. drawing buffer 교체this에 대해 실행합니다.

getConfiguration()

컨텍스트 구성을 반환합니다.

호출 대상: GPUCanvasContext this.

반환값: GPUCanvasConfiguration 또는 null

컨텐트 타임라인 단계:

  1. configurationthis.[[configuration]]의 복사본으로 설정합니다.

  2. configuration을 반환합니다.

참고:
getConfiguration()toneMapping이 구현되어 있고 dynamic-range 미디어 쿼리가 HDR 지원을 나타내면, WebGPU 캔버스는 반드시 HDR 디스플레이의 SDR 범위로 값을 클램핑하지 않고 전체 HDR 범위로 렌더링해야 합니다.
getCurrentTexture()

다음에 GPUCanvasContext가 문서에 합성할 GPUTexture를 반환합니다.

참고:
애플리케이션은 캔버스 텍스처에 렌더링하는 작업과 같은 태스크 내에서 getCurrentTexture()를 호출해야 합니다. 그렇지 않으면 아래 단계들에 의해 애플리케이션이 텍스처 렌더링을 완료하기 전에 텍스처가 소멸될 수 있습니다.

만료 태스크(아래 정의)는 구현 시 선택 사항입니다. 구현된 경우에도 태스크 소스 우선순위는 표준적으로 정의되지 않으므로 다음 태스크에서 일어날 수도, 모든 다른 태스크 소스가 비었을 때 일어날 수도 있습니다 (automatic expiry task source 참고). 만료는 가시 캔버스가 표시될 때만 보장됩니다 (WebGPU 캔버스 렌더링 업데이트), 그리고 "현재 텍스처 만료"를 호출하는 다른 곳에서도 발생할 수 있습니다.

호출 대상: GPUCanvasContext this.

반환값: GPUTexture

컨텐트 타임라인 단계:

  1. this.[[configuration]] 값이 null이면, InvalidStateError를 throw하고 반환합니다.

  2. this.[[textureDescriptor]] 값이 null이 아님을 확인(assert)합니다.

  3. devicethis.[[configuration]].device로 설정합니다.

  4. this.[[currentTexture]] 값이 null이면:

    1. 그리기 버퍼 교체this에 대해 실행합니다.

    2. this.[[currentTexture]] 값을 device.createTexture() 를 호출하여 this.[[textureDescriptor]]로 생성하되, GPUTexture의 내부 스토리지가 this.[[drawingBuffer]]를 가리키도록 설정합니다.

      참고: 텍스처 생성에 실패(예: 유효성 검사 실패 또는 메모리 부족)하면 에러가 발생하고 무효화된 GPUTexture가 반환됩니다. 일부 유효성 검사는 configure()에서 이미 수행됩니다. 구현체는 이러한 중복 검증을 절대 생략하면 안 됩니다.

  5. 선택적으로, 자동 만료 태스크 등록device와 함께 다음 단계로 실행할 수 있습니다:

    1. 현재 텍스처 만료this에 대해 실행합니다.

      참고: 만약 WebGPU 캔버스 렌더링 업데이트에서 이미 수행됐다면, 효과가 없습니다.

  6. this.[[currentTexture]] 를 반환합니다.

참고: "현재 텍스처 만료"가 실행되기 전까지는, GPUTexture가 소멸되거나 유효성 검사에 실패하거나 할당 실패해도 getCurrentTexture()를 호출할 때마다 같은 GPUTexture 객체가 반환됩니다.

컨텍스트의 이미지 콘텐츠 복사본을 얻으려면 다음과 같이 합니다:

인자:

반환값: 이미지 콘텐츠

컨텐트 타임라인 단계:

  1. snapshotcontext.canvas와 같은 크기의 투명한 검정 이미지로 설정합니다.

  2. configurationcontext.[[configuration]]로 설정합니다.

  3. configurationnull이면:

    1. snapshot을 반환합니다.

    참고: 컨텍스트가 구성되지 않았거나 unconfigure된 경우 configurationnull입니다. 이는 캔버스에 컨텍스트가 없는 경우와 동일한 동작입니다.

  4. 제출된 모든 작업 항목(예: 큐 제출)이 이미지(context.[[currentTexture]]를 통해)에 기록을 완료했는지 확인합니다.

  5. configuration.device유효한 상태라면:

    1. snapshotcontext.[[drawingBuffer]]의 복사본으로 설정합니다.

    그렇지 않고 context.[[lastPresentedImage]] 값이 null이 아니면:

    1. 선택적으로, snapshotcontext.[[lastPresentedImage]]의 복사본으로 설정합니다.

      참고: 이는 선택 사항이며, [[lastPresentedImage]]가 더 이상 존재하지 않을 수 있고, 디바이스 손실 원인에 따라 구현체는 해당 이미지를 사용할 수 있어도 건너뛸 수 있습니다.

  6. alphaModeconfiguration.alphaMode로 설정합니다.

  7. alphaMode"opaque"인 경우:
    1. snapshot의 알파 채널을 1.0으로 클리어합니다.

    2. snapshot을 불투명으로 태깅합니다.

    참고: [[currentTexture]]가 소멸된 경우(예: "현재 텍스처 만료") 알파 채널은 관찰할 수 없으므로 구현체는 알파 채널을 인플레이스로 클리어해도 됩니다.

    그 외의 경우:

    snapshotalphaMode를 태깅합니다.

  8. snapshotcolorSpacetoneMapping 을 태깅합니다.

  9. snapshot을 반환합니다.

그리기 버퍼 교체GPUCanvasContext context에 대해 실행하려면 다음 컨텐트 타임라인 단계를 따릅니다:
  1. 현재 텍스처 만료context에 대해 실행합니다.

  2. configurationcontext.[[configuration]]로 설정합니다.

  3. context.[[drawingBuffer]]context.canvas와 같은 크기의 투명한 검정 이미지로 설정합니다.

    • configuration이 null이면, drawing buffer에 "srgb" 컬러스페이스 태그를 부여합니다. 이 경우 drawing buffer는 컨텍스트가 구성될 때까지 빈 상태로 유지됩니다.

    • 그 외의 경우 drawing buffer는 지정된 configuration.format을 가지며, configuration.colorSpaceconfiguration.toneMapping 태그가 부여됩니다.

    참고: configuration.alphaMode 값은 "컨텍스트 이미지 콘텐츠 복사본 얻기" 전까지는 무시됩니다.

    참고:
    새로 교체된 drawing buffer 이미지는 투명한 검정으로 클리어된 것처럼 동작하지만, "discard" 이후처럼, 구현체는 필요 시에만 lazy하게 클리어할 수 있습니다.

    참고: drawing buffer가 이미 클리어되어 있고, 올바른 구성이라면 이 작업은 대부분 no-op입니다.

현재 텍스처 만료GPUCanvasContext context에 대해 실행하려면 다음 컨텐트 타임라인 단계를 따릅니다:
  1. context.[[currentTexture]] 값이 null이 아니면:

    1. context.[[currentTexture]].destroy() 를 호출하여(context.[[drawingBuffer]]는 삭제하지 않음) 이미지에 대한 쓰기 접근을 종료합니다.

    2. context.[[currentTexture]]null로 설정합니다.

21.3. HTML 명세 후크

아래 알고리즘들은 HTML 명세의 알고리즘에 "hook"되어 지정된 지점에서 실행되어야 합니다.

HTMLCanvasElement 또는 OffscreenCanvas 에서 GPUCanvasContext context의 "bitmap"을 읽을 때, 아래 컨텐트 타임라인 단계를 실행합니다:
  1. context이미지 콘텐츠 복사본을 반환합니다.

참고:
이는 다음과 같은 다양한 상황에서 발생합니다:

alphaMode"opaque"면, 알파 채널을 클리어합니다. 구현체가 알파 채널을 무시하거나 읽지 않고 이미지를 표시할 수 있으면 이 단계를 생략할 수 있습니다.

애플리케이션에서 캔버스를 단순 연동용(프레젠테이션 목적 아님)으로만 사용할 경우, 필요 없으면 "opaque"를 피하세요.

WebGPU 캔버스 렌더링 업데이트 (HTMLCanvasElement 또는 OffscreenCanvas플레이스홀더 캔버스 요소가 있는 경우) GPUCanvasContext context에 대해, 캔버스 이미지 콘텐츠를 얻기 전 아래 이벤트 루프 처리 모델의 하위 단계에서 실행합니다:

참고: 서비스 및 공유 워커는 "렌더링 업데이트" 단계가 없습니다. 사용자에게 보이는 캔버스에 렌더링할 수 없기 때문입니다. requestAnimationFrame()ServiceWorkerGlobalScopeSharedWorkerGlobalScope에 노출되지 않으며, OffscreenCanvastransferControlToOffscreen() 를 통해 이런 워커로 전달할 수 없습니다.

아래 컨텐트 타임라인 단계를 실행합니다:

  1. context에 대해 현재 텍스처 만료를 실행합니다.

    참고: 만약 getCurrentTexture()에서 큐된 태스크에서 이미 실행된 경우 아무 효과가 없습니다.

  2. context.[[lastPresentedImage]]context.[[drawingBuffer]]로 설정합니다.

    참고: 이는 복사본이 아니라 참조입니다. current texture가 만료된 후 drawing buffer의 콘텐츠는 인플레이스 변경되지 않습니다.

참고: 단독 OffscreenCanvas (new OffscreenCanvas()로 생성)에는 적용되지 않습니다.

WebGPU에서 transferToImageBitmap:

캔버스에서 transferToImageBitmap()가 호출되고, GPUCanvasContext context가 있다면, 캔버스 비트맵에서 ImageBitmap을 생성한 후, 아래 컨텐트 타임라인 단계를 실행합니다:

  1. context에 대해 그리기 버퍼 교체를 실행합니다.

참고: 이로 인해 transferToImageBitmap() 이 이미지 콘텐츠를 ImageBitmap으로 "이동"(그리고 필요 시 알파 클리어)하는 것과 동등해집니다. 복사본이 아닙니다.

21.4. GPUCanvasConfiguration

지원되는 컨텍스트 포맷집합에 해당하는 GPUTextureFormat들입니다: «"bgra8unorm", "rgba8unorm", "rgba16float"». 이 포맷들은 GPUCanvasConfiguration.format 으로 지정할 때 반드시 지원되어야 하며, GPUCanvasConfiguration.device 값과 관계없이 적용됩니다.

참고: 캔버스 구성에서는 srgb 포맷("bgra8unorm-srgb" 등)을 사용할 수 없습니다. 대신 비-srgb 대응 포맷("bgra8unorm")을 사용하고, srgb 포맷은 viewFormats에 지정한 뒤, createView()srgb 포맷의 뷰를 생성합니다.

enum GPUCanvasAlphaMode {
    "opaque",
    "premultiplied",
};

enum GPUCanvasToneMappingMode {
    "standard",
    "extended",
};

dictionary GPUCanvasToneMapping {
  GPUCanvasToneMappingMode mode = "standard";
};

dictionary GPUCanvasConfiguration {
    required GPUDevice device;
    required GPUTextureFormat format;
    GPUTextureUsageFlags usage = 0x10;  // GPUTextureUsage.RENDER_ATTACHMENT
    sequence<GPUTextureFormat> viewFormats = [];
    PredefinedColorSpace colorSpace = "srgb";
    GPUCanvasToneMapping toneMapping = {};
    GPUCanvasAlphaMode alphaMode = "opaque";
};

GPUCanvasConfiguration 객체의 멤버는 다음과 같습니다:

device, 타입 GPUDevice

GPUDevicegetCurrentTexture()로 반환되는 텍스처들이 호환되는 디바이스입니다.

format, 타입 GPUTextureFormat

getCurrentTexture()로 반환되는 텍스처의 포맷입니다. 반드시 지원되는 컨텍스트 포맷 중 하나여야 합니다.

usage, 타입 GPUTextureUsageFlags, 기본값 0x10

getCurrentTexture()로 반환되는 텍스처의 usage입니다. RENDER_ATTACHMENT가 기본값이지만, usage를 명시적으로 설정할 경우 자동으로 포함되지 않습니다. RENDER_ATTACHMENT 용도로 getCurrentTexture()의 텍스처를 렌더 패스의 색상 타겟으로 사용할 경우 반드시 포함하세요.

viewFormats, 타입 sequence<GPUTextureFormat>, 기본값 []

getCurrentTexture()로 반환되는 텍스처에서 생성되는 뷰가 사용할 수 있는 포맷 목록입니다.

colorSpace, 타입 PredefinedColorSpace, 기본값 "srgb"

getCurrentTexture()로 반환되는 텍스처에 기록된 값이 표시될 때 사용할 컬러스페이스입니다.

toneMapping, 타입 GPUCanvasToneMapping, 기본값 {}

톤 매핑은 getCurrentTexture()로 반환된 텍스처의 콘텐츠가 어떻게 표시될지 결정합니다.

참고: HDR WebGPU 캔버스를 지원하지 않는 경우, 이 멤버를 노출하지 않아 기능 감지가 가능하도록 해야 합니다. getConfiguration() 참고.

alphaMode, 타입 GPUCanvasAlphaMode, 기본값 "opaque"

getCurrentTexture()로 반환된 텍스처를 읽거나 표시하거나 이미지 소스로 사용할 때 알파 값의 효과를 결정합니다.

특정 GPUDevice와 함께 사용할 GPUCanvasContext를 구성하고, 이 컨텍스트에 권장 포맷을 사용하는 예시:
const canvas = document.createElement('canvas');
const context = canvas.getContext('webgpu');

context.configure({
    device: gpuDevice,
    format: navigator.gpu.getPreferredCanvasFormat(),
});
캔버스 및 구성의 GPUTextureDescriptor( (HTMLCanvasElement 또는 OffscreenCanvas) canvas, GPUCanvasConfiguration configuration) 은 다음 멤버를 가지는 GPUTextureDescriptor입니다:

그 외 멤버는 모두 기본값으로 설정됩니다.

canvas.width는 HTMLCanvasElement.width 또는 OffscreenCanvas.width 값을 의미합니다. canvas.height는 HTMLCanvasElement.height 또는 OffscreenCanvas.height 값을 의미합니다.

21.4.1. 캔버스 컬러스페이스(Canvas Color Space)

프레젠테이션 시, 캔버스의 색상 값은 화면의 컬러스페이스로 변환됩니다.

toneMapping은 화면 컬러스페이스에서 [0, 1] 구간 외 값의 처리를 결정합니다.

21.4.2. 캔버스 컨텍스트 크기(Canvas Context sizing)

모든 캔버스 구성은 configure()에서 설정되며, 해상도는 캔버스의 widthheight로 설정됩니다.

참고: WebGL 및 2d 캔버스와 마찬가지로, WebGPU 캔버스 크기를 변경하면 drawing buffer의 현재 내용이 손실됩니다. WebGPU에서는 drawing buffer 교체로 처리됩니다.

HTMLCanvasElement 또는 OffscreenCanvas canvasGPUCanvasContext context와 함께 widthheight 속성이 설정되면, 캔버스 크기 업데이트 알고리즘은 다음 컨텐트 타임라인 단계를 실행합니다:
  1. context에 대해 drawing buffer 교체를 실행합니다.

  2. configurationcontext.[[configuration]]로 설정합니다.

  3. configurationnull이 아니면:

    1. context.[[textureDescriptor]]캔버스 및 구성의 GPUTextureDescriptor(canvas, configuration)로 설정합니다.

참고: 이 과정에서 GPUTextureDescriptor가 디바이스의 maxTextureDimension2D를 초과할 수 있습니다. 이 경우, getCurrentTexture()에서 유효성 검사가 실패합니다.

참고: 이 알고리즘은 canvaswidth 또는 height 속성이 설정될 때마다 실행되며, 값이 실제로 변경되지 않아도 실행됩니다.

21.5. GPUCanvasToneMappingMode

이 enum은 색상 값이 화면에 어떻게 표시될지 지정합니다.

"standard"

화면의 표준 다이내믹 레인지 내 색상 값은 변경되지 않고, 나머지 색상 값은 화면의 표준 다이내믹 레인지로 투영(projected)됩니다.

참고: 이 투영은 종종 화면 컬러스페이스에서 색상 값을 [0, 1] 구간으로 클램핑(clamping)하는 방식으로 처리됩니다.

예를 들어, (1.035, -0.175, -0.140) 값을 'srgb' 캔버스에 기록한다고 가정합니다.

sRGB 화면에 프레젠트 하면, sRGB로 변환(캔버스가 sRGB이므로 변환 없음) 후 디스플레이 공간으로 투영됩니다. 컴포넌트별 클램핑을 사용하면 sRGB 값 (1.0, 0.0, 0.0)이 됩니다.

Display P3 화면에 프레젠트 하면, Display P3 컬러스페이스 값 (0.948, 0.106, 0.01)로 변환되고 클램핑은 필요 없습니다.

"extended"

화면의 확장 다이내믹 레인지 내 색상 값은 변경되지 않고, 나머지 색상 값은 화면의 확장 다이내믹 레인지로 투영됩니다.

참고: 이 투영은 종종 화면 컬러스페이스에서 색상 값을 해당 화면이 표시할 수 있는 값의 구간(1보다 큰 값 포함 가능)으로 클램핑하는 방식으로 처리됩니다.

예를 들어, (2.5, -0.15, -0.15) 값을 'srgb' 캔버스에 기록한다고 가정합니다.

sRGB 화면이 sRGB 공간에서 [0, 4] 구간 값을 표시할 수 있다면, sRGB로 변환(캔버스가 sRGB이므로 변환 없음) 후 디스플레이 공간으로 투영됩니다. 컴포넌트별 클램핑을 사용하면 sRGB 값 (2.5, 0.0, 0.0)이 됩니다.

Display P3 화면이 Display P3 공간에서 [0, 2] 구간 값을 표시할 수 있다면, Display P3 컬러스페이스 값 (2.3, 0.545, 0.386)으로 변환 후 디스플레이 공간으로 투영됩니다. 컴포넌트별 클램핑을 사용하면 Display P3 값 (2.0, 0.545, 0.386)이 됩니다.

21.6. GPUCanvasAlphaMode

이 enum은 캔버스의 콘텐츠를 읽거나, 화면에 표시하거나 이미지 소스로 사용할 때 (drawImage, toDataURL 등에서) 어떻게 해석할지 선택합니다.

아래에서 src는 캔버스 텍스처의 값이고, dst는 캔버스가 합성되는 이미지(예: HTML 페이지 렌더링, 2D 캔버스 등)입니다.

"opaque"

RGB를 불투명(opaque)으로 읽고 알파 값을 무시합니다. 콘텐츠가 이미 불투명하지 않으면, "컨텍스트 이미지 콘텐츠 복사본 얻기"에서 알파 채널이 1.0으로 클리어됩니다.

"premultiplied"

RGBA를 프리멀티플라이드로 읽습니다: 색상 값이 자신의 알파 값으로 곱해집니다. 100% 빨강에 50% 알파면 [0.5, 0, 0, 0.5]입니다.

캔버스 텍스처에 가무트 초과 프리멀티플라이드 RGBA 값이 존재할 때, 캔버스 콘텐츠를 읽을 때의 동작은 캔버스 사용 맥락에 따라 다릅니다:

이미지 소스로 사용

값이 보존되며, 컬러스페이스 변환에서 설명한 대로 동작합니다.

화면에 표시

합성 결과는 정의되지 않습니다.

참고: 컬러스페이스 변환으로 합성 전에 가무트 내 값이 되어도, 합성 중간 포맷이 명세되지 않았으므로 결과는 여전히 정의되지 않습니다.

22. 오류 및 디버깅

WebGPU의 정상적인 동작 과정에서, 오류는 에러 디스패치로 발생합니다.

디바이스가 손실된 이후에는, 가능한 경우 더 이상 오류가 노출되지 않습니다. 이 시점 이후로, 구현체는 유효성 검사나 오류 추적을 수행할 필요가 없습니다:

22.1. 치명적 오류

enum GPUDeviceLostReason {
    "unknown",
    "destroyed",
};

[Exposed=(Window, Worker), SecureContext]
interface GPUDeviceLostInfo {
    readonly attribute GPUDeviceLostReason reason;
    readonly attribute DOMString message;
};

partial interface GPUDevice {
    readonly attribute Promise<GPUDeviceLostInfo> lost;
};

GPUDevice는 다음과 같은 추가 속성을 가집니다:

lost, 타입 Promise<GPUDeviceLostInfo>, 읽기 전용

디바이스 생성 시 생성되며, 디바이스의 생명주기 동안 pending 상태로 유지되고, 디바이스가 손실되면 resolve되는 프라미스를 가지는 슬롯 기반 속성입니다.

초기화 시 새로운 프라미스로 설정됩니다.

22.2. GPUError

[Exposed=(Window, Worker), SecureContext]
interface GPUError {
    readonly attribute DOMString message;
};

GPUErrorpopErrorScope()uncapturederror 이벤트에서 발생하는 모든 오류의 기본 인터페이스입니다.

오류는 각 알고리즘에서 명시적으로 오류가 발생하는 조건과 생성될 오류의 하위 타입을 명시한 경우에만 생성되어야 합니다.

손실된 디바이스에서는 오류가 생성되지 않습니다. § 22 오류 및 디버깅 참고.

참고: GPUError는 향후 현행 표준에서 새로운 하위 타입을 가질 수 있습니다. 애플리케이션은 이 가능성에 대비해, 가능한 경우 에러의 message만 사용하고, 특수화가 필요할 때는 instanceof를 사용해야 합니다. 에러를 직렬화(예: JSON이나 디버그 리포트)에 사용할 경우 error.constructor.name를 쓰세요.

GPUError는 다음 불변 속성을 가집니다:

message, 타입 DOMString, 읽기 전용

오류에 대한 정보를 제공하는 사람이 읽을 수 있는 지역화 가능한 텍스트 메시지입니다.

참고: 이 메시지는 일반적으로 애플리케이션 개발자가 디버깅 및 디버그 리포트용 정보를 수집하는 용도이며, 최종 사용자에게 노출하는 용도가 아닙니다.

참고: 유저 에이전트는 이 메시지에 시스템의 사용 가능한 메모리 등 기계가 파싱 가능한 세부 정보를 포함해서는 안 됩니다("out-of-memory" 등에서 메모리가 고갈된 조건 등).

참고: message언어 및 방향 정보에 대한 권장사항을 따라야 합니다. 이는 향후 관련 표준이 등장할 경우 공식적으로 채택할 수 있습니다.

편집자 노트: 현재 시점에서는 레거시 API와 호환성과 일관성을 제공하는 언어/방향 권장사항이 없으나, 향후 표준화될 경우 공식적으로 채택하세요.

[Exposed=(Window, Worker), SecureContext]
interface GPUValidationError
        : GPUError {
    constructor(DOMString message);
};

GPUValidationErrorGPUError의 하위 타입으로, 연산이 모든 유효성 검사 요구사항을 만족하지 못한 경우를 나타냅니다. 유효성 검사 오류는 항상 애플리케이션 오류를 의미하며, 동일한 [[features]][[limits]]를 사용하는 경우 모든 디바이스에서 동일하게 실패해야 합니다.

유효성 검사 오류 생성GPUDevice device에 대해 수행하려면 다음 단계를 실행합니다:

디바이스 타임라인 단계:

  1. error를 적절한 오류 메시지와 함께 새 GPUValidationError로 생성합니다.

  2. 에러 디스패치errordevice에 전달합니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUOutOfMemoryError
        : GPUError {
    constructor(DOMString message);
};

GPUOutOfMemoryErrorGPUError의 하위 타입으로, 요청된 연산을 완료하기에 충분한 자유 메모리가 없음을 나타냅니다. 더 작은 텍스처 크기 등 적은 메모리 요구로 다시 시도하거나, 다른 리소스가 사용하는 메모리를 먼저 해제하면 성공할 수도 있습니다.

메모리 부족 오류 생성GPUDevice device에 대해 수행하려면 다음 단계를 실행합니다:

디바이스 타임라인 단계:

  1. error를 적절한 오류 메시지와 함께 새 GPUOutOfMemoryError로 생성합니다.

  2. 에러 디스패치errordevice에 전달합니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUInternalError
        : GPUError {
    constructor(DOMString message);
};

GPUInternalErrorGPUError의 하위 타입으로, 모든 유효성 검사 요구사항을 만족했음에도 시스템 또는 구현체 고유의 사유로 연산이 실패한 경우를 나타냅니다. 예를 들어, 구현체의 기능을 지원 한계로 쉽게 포착하기 어려운 방식으로 초과한 경우 등입니다. 동일 연산이 다른 디바이스나 상황에서는 성공할 수도 있습니다.

내부 오류 생성GPUDevice device에 대해 수행하려면 다음 단계를 실행합니다:

디바이스 타임라인 단계:

  1. error를 적절한 오류 메시지와 함께 새 GPUInternalError로 생성합니다.

  2. 에러 디스패치errordevice에 전달합니다.

22.3. 에러 스코프(Error Scopes)

GPU 에러 스코프GPUError가 현재 GPU 에러 스코프일 때 생성된 오류들을 캡처합니다. 에러 스코프는 WebGPU 호출 집합 내에서 발생한 오류를 분리하여 디버깅이나 연산의 내결함성을 높이기 위해 사용됩니다.

GPU 에러 스코프는 다음 디바이스 타임라인 속성을 가집니다:

[[errors]], 타입 list<GPUError>, 기본값 []

GPU 에러 스코프가 현재일 때 관찰된 GPUError 목록입니다.

[[filter]], 타입 GPUErrorFilter

GPU 에러 스코프가 관찰하는 GPUError 타입을 결정합니다.

enum GPUErrorFilter {
    "validation",
    "out-of-memory",
    "internal",
};

partial interface GPUDevice {
    undefined pushErrorScope(GPUErrorFilter filter);
    Promise<GPUError?> popErrorScope();
};

GPUErrorFilterpushErrorScope() 호출시 어떤 타입의 오류를 포착할지 정의합니다:

"validation"

에러 스코프가 GPUValidationError를 포착함을 나타냅니다.

"out-of-memory"

에러 스코프가 GPUOutOfMemoryError를 포착함을 나타냅니다.

"internal"

에러 스코프가 GPUInternalError를 포착함을 나타냅니다.

GPUDevice는 다음 디바이스 타임라인 속성을 가집니다:

[[errorScopeStack]], 타입 stack<GPU 에러 스코프>

GPUDevice푸시된 GPU 에러 스코프의 스택입니다.

현재 에러 스코프(current error scope)GPUError errorGPUDevice device에 대해 디바이스 타임라인에 다음 단계를 발행하여 결정합니다:

디바이스 타임라인 단계:

  1. 만약 error가 다음 인스턴스면:

    GPUValidationError

    type을 "validation"으로 설정.

    GPUOutOfMemoryError

    type을 "out-of-memory"로 설정.

    GPUInternalError

    type을 "internal"로 설정.

  2. scopedevice.[[errorScopeStack]]의 마지막 항목으로 설정.

  3. scopeundefined가 아닐 때까지:

    1. scope.[[filter]]type이면 scope 반환.

    2. scopedevice.[[errorScopeStack]]의 이전 항목으로 설정.

  4. undefined 반환.

에러 디스패치(dispatch error) GPUError errorGPUDevice device에서 실행하려면 다음 디바이스 타임라인 단계를 실행합니다:
디바이스 타임라인 단계:

참고: 손실된 디바이스에서는 오류가 생성되지 않습니다. 이 알고리즘이 device손실 상태에서 호출될 경우, 애플리케이션에서 관찰할 수 없습니다. § 22 오류 및 디버깅 참고.

  1. scope현재 에러 스코프(error, device)로 설정.

  2. scopeundefined가 아니면:

    1. 추가(append) errorscope.[[errors]]에.

    2. 반환.

  3. 그렇지 않으면 컨텐트 타임라인에 다음 단계를 실행:

컨텐트 타임라인 단계:
  1. 유저 에이전트가 선택하면, GPUUncapturedErrorEvent 이벤트를 "uncapturederror" 이름으로 device에 발생시키고, errorerror로 설정합니다.

참고: 이벤트 디스패치 후, 유저 에이전트는 uncaptured 오류를 개발자에게 노출해야 하며(예: 브라우저 개발자 콘솔의 경고), 단, 이벤트의 defaultPrevented 값이 true라면 콘솔 경고를 표시하지 않습니다. 즉 preventDefault()를 호출하면 콘솔 경고가 사라집니다.

참고: 유저 에이전트는 GPUUncapturedErrorEventGPUDevice에서 과도하게 발생하지 않도록 제한하거나 throttle 할 수 있습니다. 과도한 오류 처리/로깅이 성능에 영향을 미치는 것을 방지하기 위함입니다.

pushErrorScope(filter)

this[[errorScopeStack]]에 새 GPU 에러 스코프를 푸시합니다.

호출 대상: GPUDevice this.

인자:

GPUDevice.pushErrorScope(filter) 메서드의 인자.
Parameter Type Nullable Optional Description
filter GPUErrorFilter 이 에러 스코프가 관찰할 오류 클래스.

반환값: undefined

컨텐트 타임라인 단계:

  1. 이후 단계는 this디바이스 타임라인에서 실행.

디바이스 타임라인 단계:
  1. scope를 새 GPU 에러 스코프로 생성.

  2. scope.[[filter]]filter로 설정.

  3. 푸시(push) scopethis.[[errorScopeStack]]에.

popErrorScope()

this[[errorScopeStack]]에서 GPU 에러 스코프를 pop하고, 해당 스코프에서 관찰된 아무 GPUError 또는 없으면 null로 resolve됩니다.

프라미스 resolve 순서는 보장되지 않습니다.

호출 대상: GPUDevice this.

반환값: Promise<GPUError?>

컨텐트 타임라인 단계:

  1. 현재 컨텐트 타임라인contentTimeline으로 설정.

  2. promise새 프라미스로 생성.

  3. 이후 check stepsthis디바이스 타임라인에서 실행.

  4. promise 반환.

디바이스 타임라인 check steps:
  1. this손실 상태면:

    1. contentTimeline에 다음 단계 실행:

      컨텐트 타임라인 단계:
      1. resolve promisenull로.

    2. 반환.

    참고: 손실된 디바이스에서는 오류가 생성되지 않습니다. § 22 오류 및 디버깅 참고.

  2. 다음 요구사항 중 하나라도 충족하지 않으면:

    그렇다면 contentTimeline에 다음 단계 실행 후 반환:

  3. this.[[errorScopeStack]]에서 항목을 pop하여 scope로 설정합니다.

  4. scope.[[errors]]의 항목 중 아무거나 하나를 error로 설정하거나, 없으면 null로 설정합니다.

    리스트 내 오류 E1, E2에 대해 만약 E2가 E1에 의해 발생했다면, E2는 선택하면 안 됩니다.

    참고: 예시: E1이 t = createTexture()에서 발생하고, E2가 t.createView()에서 t잘못됨 상태로 인해 발생했다면, E1을 선택하는 것이 개발자가 문제를 더 잘 이해할 수 있습니다. 두 오류 모두 GPUValidationError이며, 차이는 message 필드뿐인데, 이는 사람이 읽기 위한 정보입니다.

  5. 지금 혹은 미래의 불특정 시점에, 이후 단계를 contentTimeline에서 수행합니다.

    참고: popErrorScope() 호출이 어느 순서로든, scope에서 관찰된 어떤 오류로든 resolve될 수 있게 허용함으로써, 이 명세는 유효성 검사가 순서와 무관하게 완료될 수 있도록 합니다. 상태 관찰만 명세 준수 시점에 맞게 이루어지면 됩니다. 예를 들어, 셰이더 컴파일은 비상태 입력에만 의존하므로, 다른 디바이스 타임라인 작업과 병렬로 백그라운드 스레드에서 완료되어 이후 오류를 보고할 수도 있습니다.

컨텐트 타임라인 단계:
  1. resolve promiseerror로 수행합니다.

GPUDevice 연산에서 발생할 수 있는 유효성 검사 오류를 error scope로 캡처하는 예시:
gpuDevice.pushErrorScope('validation');

let sampler = gpuDevice.createSampler({
    maxAnisotropy: 0, // 잘못됨, maxAnisotropy는 최소 1이어야 함.
});

gpuDevice.popErrorScope().then((error) => {
    if (error) {
        // 샘플러 생성 중 오류가 있었으므로 버린다.
        sampler = null;
        console.error(`샘플러 생성 중 오류 발생: ${error.message}`);
    }
});
참고:
Error scope는 필요한 만큼 많은 명령을 포함할 수 있습니다. error scope가 커버하는 명령 수는 일반적으로 애플리케이션이 오류 발생 시 어떤 대응을 할지에 비례합니다.

예시: 텍스처나 버퍼 등 단일 리소스 생성만을 포함하는 error scope는 out-of-memory 등 실패를 감지하는 데 사용할 수 있으며, 이 경우 애플리케이션은 리소스를 해제한 후 다시 할당 시도할 수 있습니다.

Error scope는 실패한 명령이 무엇인지 식별하지 못합니다. 예를 들어, 모델 로딩 중 실행된 모든 명령을 하나의 error scope로 감싸면, 해당 scope의 실패가 메모리 제약 때문인지 파악하기 어렵습니다. 따라서 리소스 해제는 비생산적일 수 있습니다. 더 적절한 대응은 다른 모델로 폴백하거나 경고를 출력하는 것입니다. 메모리 제약에 대응하고 싶다면, 메모리 할당 작업만을 더 작은 nested error scope로 감쌀 수 있습니다.

22.4. 텔레메트리

GPUError 가 생성되었지만 어떤 GPU error scope에서도 관찰되지 않은 경우, 사용자 에이전트는 선택적으로 이벤트를 발생시킬 수 있습니다. 이벤트 이름은 uncapturederror이고, GPUDevice 객체에서 GPUUncapturedErrorEvent를 사용하여 발생시킵니다.

참고: uncapturederror 이벤트는 텔레메트리 및 예기치 않은 오류 보고 용도로 사용됩니다. 모든 uncaptured 오류에 대해 반드시 디스패치되는 것은 아니며(예: 노출되는 오류 수에 제한이 있을 수 있음), 애플리케이션의 정상 동작 중 발생 가능한 알려진 오류 처리에는 사용하면 안 됩니다. 그런 경우에는 pushErrorScope()popErrorScope() 를 사용하는 것이 좋습니다.

[Exposed=(Window, Worker), SecureContext]
interface GPUUncapturedErrorEvent : Event {
    constructor(
        DOMString type,
        GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict
    );
    [SameObject] readonly attribute GPUError error;
};

dictionary GPUUncapturedErrorEventInit : EventInit {
    required GPUError error;
};

GPUUncapturedErrorEvent 는 다음 속성을 가집니다:

error, 타입 GPUError, 읽기 전용

uncaptured 오류를 나타내는 객체를 가진 슬롯 기반 속성입니다. popErrorScope()로 반환되는 오류 타입과 동일합니다.

partial interface GPUDevice {
    attribute EventHandler onuncapturederror;
};

GPUDevice는 다음 컨텐트 타임라인 속성을 가집니다:

onuncapturederror, 타입 EventHandler

uncapturederror 이벤트 타입에 대한 이벤트 핸들러 IDL 속성입니다.

GPUDevice에서 uncaptured 오류를 감지하는 예시:
gpuDevice.addEventListener('uncapturederror', (event) => {
    // 이벤트 리스너 추가 시 콘솔 로그가 사라질 수 있으므로 오류를 재노출함.
    console.error('WebGPU uncaptured 오류 발생:', event.error);

    myEngineDebugReport.uncapturedErrors.push({
        type: event.error.constructor.name,
        message: event.error.message,
    });
});

23. 상세 연산

이 섹션은 다양한 GPU 연산의 세부 사항을 설명합니다.

23.1. 컴퓨팅

컴퓨팅 연산은 GPU의 프로그래머블 하드웨어에 직접 접근할 수 있게 해줍니다. Compute 셰이더는 셰이더 스테이지 입력이나 출력을 갖지 않으며, 결과는 GPUBufferBindingLayout 에서 GPUBufferBindingType"storage" 또는 GPUStorageTextureBindingLayout 등 스토리지 바인딩에 데이터를 기록하는 부작용(side effect)으로 나타납니다. 이러한 연산은 GPUComputePassEncoder 내에 아래와 같이 인코딩됩니다:

주요 컴퓨트 알고리즘:

compute(descriptor, dispatchCall)

인자:

  1. computeInvocations비어 있는 리스트로 설정합니다.

  2. computeStagedescriptor.compute로 설정합니다.

  3. workgroupSizecomputeStage.entryPointcomputeStage.constants를 적용한 후, computeStage.module로부터 계산된 workgroup 크기로 설정합니다.

  4. workgroupX[0, dispatchCall.workgroupCountX] 범위에서 반복:

    1. workgroupY[0, dispatchCall.workgroupCountY] 범위에서 반복:

      1. workgroupZ[0, dispatchCall.workgroupCountZ] 범위에서 반복:

        1. localX[0, workgroupSize.x] 범위에서 반복:

          1. localY[0, workgroupSize.y] 범위에서 반복:

            1. localZ[0, workgroupSize.y] 범위에서 반복:

              1. invocation{ computeStage, workgroupX, workgroupY, workgroupZ, localX, localY, localZ }로 설정합니다.

              2. append invocationcomputeInvocations에 추가합니다.

  5. computeInvocations의 각 invocation에 대해, 디바이스가 선택한 임의의 순서(병렬 포함)로:

    1. 셰이더 내장값(builtins)을 설정:

      • num_workgroups 내장값이 있다면 (
        dispatchCall.workgroupCountX,
        dispatchCall.workgroupCountY,
        dispatchCall.workgroupCountZ
        )
        으로 설정합니다.

      • workgroup_id 내장값이 있다면 (
        invocation.workgroupX,
        invocation.workgroupY,
        invocation.workgroupZ
        )
        으로 설정합니다.

      • local_invocation_id 내장값이 있다면 (
        invocation.localX,
        invocation.localY,
        invocation.localZ
        )
        으로 설정합니다.

      • global_invocation_id 내장값이 있다면 (
        invocation.workgroupX * workgroupSize.x + invocation.localX,
        invocation.workgroupY * workgroupSize.y + invocation.localY,
        invocation.workgroupZ * workgroupSize.z + invocation.localZ
        )
        으로 설정합니다.

      • local_invocation_index 내장값이 있다면 invocation.localX + (invocation.localY * workgroupSize.x) + (invocation.localZ * workgroupSize.x * workgroupSize.y) 로 설정합니다.

    2. invocation.computeStage에 해당하는 컴퓨트 셰이더 entry point를 실행합니다.

참고: 셰이더 호출 순서는 보장되지 않으며, 디바이스 성능에 따라 주로 병렬로 실행됩니다. 개발자는 특정 호출이나 워크그룹이 다른 것보다 먼저 완료된다고 가정해서는 안 됩니다. 일부 디바이스는 일관된 순서로 실행되는 것처럼 보일 수 있지만, 이는 모든 디바이스에서 동일하지 않으므로 신뢰해서는 안 됩니다. 호출 간 동기화가 필요한 셰이더는 동기화 내장 함수를 사용하세요.

디바이스손실될 수 있습니다.
셰이더 실행이 종료되지 않을 경우, 사용자 에이전트가 판단한 합리적인 시간 내에 실행이 끝나지 않으면 디바이스가 손실될 수 있습니다.

23.2. 렌더링

렌더링은 GPURenderPassEncoder 내에서 실행되는 일련의 GPU 연산에 의해 수행되며, 렌더 패스 어태치먼트가 참조하는 텍스처 데이터가 수정되는 결과를 만듭니다. 이러한 연산은 아래와 같이 인코딩됩니다:

참고: 렌더링은 GPU의 전통적인 용도이며, 하드웨어 내 여러 고정 기능 블록에서 지원됩니다.

주요 렌더링 알고리즘:

render(pipeline, drawCall, state)

인자:

  1. descriptorpipeline.[[descriptor]]로 설정합니다.

  2. 인덱스 해석. § 23.2.1 인덱스 해석 참고.

    vertexListresolve indices(drawCall, state)의 결과로 설정합니다.

  3. 버텍스 처리. § 23.2.2 버텍스 처리 참고.

    process vertices(vertexList, drawCall, descriptor.vertex, state)를 실행합니다.

  4. 프리미티브 조립. § 23.2.3 프리미티브 조립 참고.

    assemble primitives(vertexList, drawCall, descriptor.primitive)를 실행합니다.

  5. 프리미티브 클리핑. § 23.2.4 프리미티브 클리핑 참고.

    이 단계의 결과로 primitiveList를 얻습니다.

  6. 래스터화. § 23.2.5 래스터화 참고.

    rasterizationListrasterize(primitiveList, state)의 결과로 설정합니다.

  7. 프래그먼트 처리. § 23.2.6 프래그먼트 처리 참고.

    rasterizationList의 각 rasterPoint에 대해 process fragment(rasterPoint, descriptor, state) 를 실행하여 fragments 리스트를 얻습니다.

  8. 픽셀 기록. § 23.2.7 출력 병합 참고.

    fragments의 각 non-null fragment에 대해:

23.2.1. 인덱스 해석

렌더링의 첫 단계에서 파이프라인은 각 인스턴스에 대해 처리할 버텍스 리스트를 만듭니다.

resolve indices(drawCall, state)

인자:

반환값: 정수 인덱스 리스트.

  1. vertexIndexList를 비어 있는 인덱스 리스트로 설정합니다.

  2. drawCall이 인덱스 기반 draw 호출이면:

    1. vertexIndexListdrawCall.indexCount 개의 정수로 초기화합니다.

    2. i를 0 .. drawCall.indexCount(미포함) 범위에서 반복:

      1. relativeVertexIndexfetch index(i + drawCall.firstIndex, state.[[index_buffer]])의 결과로 설정합니다.

      2. relativeVertexIndex가 특수 값 "out of bounds"라면, 빈 리스트를 반환합니다.

        참고: 구현체는 이 상황이 발생할 때(특히 감지하기 쉬운 경우, 예: 비-indirect 인덱스 draw 호출) 경고를 띄울 수 있습니다.

      3. drawCall.baseVertex + relativeVertexIndexvertexIndexList에 추가합니다.

  3. 그 외의 경우:

    1. vertexIndexListdrawCall.vertexCount 개의 정수로 초기화합니다.

    2. vertexIndexList의 항목 idrawCall.firstVertex + i로 설정합니다.

  4. vertexIndexList를 반환합니다.

참고: indirect draw 호출의 경우, indexCount, vertexCountdrawCall의 속성들은 draw 명령이 아니라 indirect 버퍼에서 읽습니다.

fetch index(i, buffer, offset, format)

인자:

반환값: unsigned integer 또는 "out of bounds"

  1. indexSizestate.[[index_format]]에 따라 정의:

    "uint16"

    2

    "uint32"

    4

  2. state.[[index_buffer_offset]] + |i + 1| × indexSize > state.[[index_buffer_size]]라면, 특수 값 "out of bounds"를 반환합니다.

  3. state.[[index_buffer]]의 데이터를, 오프셋 state.[[index_buffer_offset]] + i × indexSize 위치에서, indexSize 바이트 크기만큼 unsigned integer로 해석하여 반환합니다.

23.2.2. 버텍스 처리

버텍스 처리 단계는 렌더 파이프라인의 프로그래머블 단계로, 버텍스 속성 데이터를 처리하여 § 23.2.4 프리미티브 클리핑에 필요한 clip space 좌표와 § 23.2.6 프래그먼트 처리에 필요한 기타 데이터를 생성합니다.

process vertices(vertexIndexList, drawCall, desc, state)

인자:

vertexIndexvertexIndexList 내에서, 각 rawInstanceIndex 인스턴스마다 개별적으로 처리됩니다. rawInstanceIndex는 0부터 drawCall.instanceCount - 1까지 포함합니다. 이 처리는 병렬로 이루어지며, GPUBufferBindingType "storage" 바인딩 등에 대한 기록 같은 부작용(side effect)은 임의의 순서로 발생할 수 있습니다.

  1. instanceIndexrawInstanceIndex + drawCall.firstInstance로 설정.

  2. desc.buffers 리스트의 각 non-null vertexBufferLayout에 대해:

    1. 해당 리스트의 버퍼 레이아웃 인덱스를 i로 설정.

    2. 슬롯 istate.[[vertex_buffers]]에서 vertexBuffer, vertexBufferOffset, vertexBufferBindingSize를 가져옴.

    3. vertexElementIndexvertexBufferLayout.stepMode에 따라 달라집니다:

      "vertex"

      vertexIndex

      "instance"

      instanceIndex

    4. drawCallOutOfBoundsfalse로 설정.

    5. vertexBufferLayout.attributes의 각 attributeDesc에 대해:

      1. attributeOffsetvertexBufferOffset + vertexElementIndex * vertexBufferLayout.arrayStride + attributeDesc.offset로 설정.

      2. attributeOffset + byteSize(attributeDesc.format) > vertexBufferOffset + vertexBufferBindingSize이면:

        1. drawCallOutOfBoundstrue로 설정.

        2. 선택적으로 (구현체 정의), vertexIndexList를 비움 및 반환, draw 호출 취소.

          참고: 이렇게 하면 구현체가 draw 호출 전에 인덱스 버퍼에서 범위 초과 값을 감지할 수 있습니다. 잘못된 메모리 참조 동작 대신.

    6. vertexBufferLayout.attributes의 각 attributeDesc에 대해:

      1. drawCallOutOfBoundstrue면:

        1. WGSL의 잘못된 메모리 참조 동작에 따라 vertexBuffer에서 attribute data를 로드.

          참고: 잘못된 메모리 참조는 범위 내 attribute의 "정상" 결과를 실제로 로드하는 등 여러 동작을 허용합니다. draw-call-wide drawCallOutOfBoundstrue여도.

        그 외의 경우:

        1. attributeOffsetvertexBufferOffset + vertexElementIndex * vertexBufferLayout.arrayStride + attributeDesc.offset로 설정.

        2. vertexBuffer에서 attributeOffset 위치부터 attributeDesc.format 형식의 attribute data를 로드. 컴포넌트는 버퍼 메모리에서 x, y, z, w 순으로 로드됨.

      2. 채널 포맷 규칙에 따라 data를 셰이더에서 읽을 수 있는 포맷으로 변환.

        타입 "snorm8x2"의 attribute가 바이트 값 [0x70, 0xD0]이면, WGSL에서 vec2<f32>(0.88, -0.38)로 변환됨.
      3. 셰이더 타입에 따라 data 크기 조정:

        • 둘 다 스칼라인 경우, 또는 둘 다 같은 차원의 벡터인 경우 조정 불필요.

        • data가 벡터이고 셰이더 타입이 스칼라인 경우, 첫 번째 컴포넌트만 추출.

        • 둘 다 벡터이고 data의 차원이 더 높으면, 초과 컴포넌트는 버림.

          타입 "float32x3"의 attribute, 값 vec3<f32>(1.0, 2.0, 3.0)는 셰이더에서 2-컴포넌트 벡터가 필요하면 vec2<f32>(1.0, 2.0)로 노출됨.
        • 셰이더 타입이 더 높은 차원의 벡터이거나 data가 스칼라인 경우, 누락된 컴포넌트는 vec4<*>(0, 0, 0, 1) 값으로 채움.

          타입 "sint32"의 attribute, 값 5는 셰이더에서 4-컴포넌트 벡터가 필요하면 vec4<i32>(5, 0, 0, 1)로 노출됨.
      4. data를 버텍스 셰이더 입력 위치 attributeDesc.shaderLocation에 바인딩.

  3. state.[[bind_groups]]의 각 GPUBindGroup group(index)에 대해:

    1. 바인드 그룹의 각 GPUBindingResource 리소스에 대해:

      1. 해당 리소스에 해당하는 GPUBindGroupLayoutEntryentry로 설정.

      2. entry.visibilityVERTEX를 포함하면:

  4. 셰이더 내장값 설정:

    • vertex_index 내장값이 있다면 vertexIndex로 설정.

    • instance_index 내장값이 있다면 instanceIndex로 설정.

  5. desc에 기술된 버텍스 셰이더 entry point를 호출.

    참고: 타겟 플랫폼은 버텍스 셰이더 호출 결과를 캐싱합니다. vertexIndex가 두 번 이상 반복되어도 반드시 여러 번 호출된다는 보장은 없습니다. 마찬가지로, 하나의 vertexIndex가 한 번만 처리된다는 보장도 없습니다.

    디바이스손실될 수 있습니다.
    셰이더 실행이 종료되지 않을 경우, 사용자 에이전트가 판단한 합리적인 시간 내에 실행이 끝나지 않으면 디바이스가 손실될 수 있습니다.

23.2.3. 프리미티브 조립

프리미티브는 GPU의 고정 기능 단계에서 조립됩니다.

assemble primitives(vertexIndexList, drawCall, desc)

인자:

각 인스턴스마다, vertexIndexList를 기반으로 셰이더에서 처리한 버텍스들로 프리미티브가 조립됩니다.

  1. 먼저, 프리미티브 토폴로지가 스트립인 경우(desc.stripIndexFormat 이 undefined가 아니고) drawCall이 인덱스 기반 호출이면, vertexIndexListdesc.stripIndexFormat 최대값을 구분자로 사용하여 여러 서브 리스트로 분할됩니다.

    예시: "uint16" 타입의 vertexIndexList 값이 [1, 2, 65535, 4, 5, 6]이면, 서브 리스트 [1, 2][4, 5, 6]로 분할됩니다.

  2. 각 서브 리스트 vl에 대해, 프리미티브 생성은 desc.topology에 따라 수행됩니다:

    "line-list"

    라인 프리미티브는 (vl.0, vl.1), 그 다음 (vl.2, vl.3), 그 다음 (vl.4, vl.5) ... 식으로 구성됩니다. 각 프리미티브는 2개의 버텍스를 사용합니다.

    "line-strip"

    라인 프리미티브는 (vl.0, vl.1), 그 다음 (vl.1, vl.2), 그 다음 (vl.2, vl.3) ... 식으로 구성됩니다. 각 프리미티브는 1개의 버텍스를 추가로 사용합니다.

    "triangle-list"

    삼각형 프리미티브는 (vl.0, vl.1, vl.2), 그 다음 (vl.3, vl.4, vl.5), 그 다음 (vl.6, vl.7, vl.8) ... 식으로 구성됩니다. 각 프리미티브는 3개의 버텍스를 사용합니다.

    "triangle-strip"

    삼각형 프리미티브는 (vl.0, vl.1, vl.2), 그 다음 (vl.2, vl.1, vl.3), 그 다음 (vl.2, vl.3, vl.4), 그 다음 (vl.4, vl.3, vl.5) ... 식으로 구성됩니다. 각 프리미티브는 1개의 버텍스를 추가로 사용합니다.

    프리미티브가 불완전한 경우(버텍스가 부족한 경우)는 해당 프리미티브는 버려집니다.

23.2.4. 프리미티브 클리핑

버텍스 셰이더는 position(타입 vec4<f32>)이라는 내장값을 생성해야 하며, 이는 버텍스의 클립 공간 좌표클립 위치를 나타냅니다.

프리미티브는 클립 볼륨에 맞게 클리핑됩니다. 프리미티브 내 임의의 클립 위치 p에 대해, 클립 볼륨은 다음 부등식으로 정의됩니다:

"clip-distances" 기능이 활성화된 경우, 클립 볼륨은 버텍스 셰이더 출력에 clip_distances를 선언하여, 사용자 정의 반공간으로 더욱 제한될 수 있습니다. clip_distances 배열의 각 값은 프리미티브 전체에 선형 보간되며, 보간 결과가 0 미만인 부분은 클리핑됩니다.

descriptor.primitive.unclippedDepthtrue이면, 깊이 클리핑은 적용되지 않으며, 클립 볼륨의 z축 제한이 사라집니다.

프리미티브의 모든 엣지가 클립 볼륨 내부에 완전히 포함되면, 해당 프리미티브는 변경 없이 이 단계를 통과합니다. 프리미티브의 엣지가 클립 볼륨의 경계를 교차하면, 교차하는 엣지는 클립 볼륨의 경계선을 따라 새로운 엣지로 다시 연결됩니다. 삼각형 프리미티브(descriptor.primitive.topology"triangle-list" 또는 "triangle-strip"인 경우), 내부적으로 다각형에 새로운 버텍스가 추가될 수 있습니다.

프리미티브가 클립 볼륨 경계를 교차하면, 클리핑된 다각형에는 반드시 경계 위의 점이 포함되어야 합니다.

버텍스 셰이더가 "perspective" 보간으로 지정된 다른 부동소수점 값(스칼라 및 벡터)을 출력하면, 이 값들도 클리핑됩니다. 클립 볼륨 내에 있는 버텍스에 연관된 출력값은 클리핑되지 않습니다. 하지만 프리미티브가 클리핑되어 새 버텍스가 생성된 경우, 해당 버텍스에 할당된 출력값도 클리핑됩니다.

버텍스 ab 사이 엣지가 클리핑되어 새 버텍스 c가 만들어진 경우, t를 엣지 버텍스 간 비율로 정의합니다: c.p = t × a.p + (1 − t) × b.p, 여기서 x.p는 버텍스 x클립 위치입니다.

각 버텍스 출력값 "v"가 해당 프래그먼트 입력을 갖는 경우, a.v와 b.v는 각각 ab 버텍스의 출력값입니다. 클리핑된 셰이더 출력 c.v는 다음 보간 방식에 따라 생성됩니다:

flat

flat 보간은 영향을 받지 않으며, provoking vertex에 기반합니다. 이는 셰이더에 선언된 보간 샘플링 모드에 의해 결정됩니다. 출력값은 프리미티브 전체에 동일하며, provoking vertex의 버텍스 출력과 일치합니다.

linear

보간 비율은 클립 위치의 투영 좌표에 따라 조정되어, 화면 공간에서 선형적인 보간 결과가 됩니다.

perspective

값은 클립 공간에서 선형적으로 보간되어, 퍼스펙티브 보정된 값을 생성합니다.

프리미티브 클리핑 결과는 클립 볼륨 내에 포함된 새로운 프리미티브 집합입니다.

23.2.5. 래스터화

래스터화는 하드웨어 처리 단계로, 생성된 프리미티브를 프레임버퍼의 2차원 렌더링 영역(현재 GPURenderPassEncoder의 렌더 어태치먼트 집합)에 매핑합니다. 이 렌더링 영역은 픽셀의 균등한 격자로 나뉩니다.

프레임버퍼 좌표는 렌더 타겟의 좌상단에서 시작합니다. 각 단위는 정확히 한 픽셀에 해당합니다. 자세한 내용은 § 3.3 좌표계를 참고하세요.

래스터화는 프리미티브에 영향을 받는 픽셀 집합을 결정합니다. 멀티샘플링의 경우, 각 픽셀은 descriptor.multisample.count 개의 샘플로 추가 분할됩니다. 표준 샘플 패턴은 다음과 같으며, 픽셀의 좌상단 기준 프레임버퍼 좌표에서 위치가 주어집니다(픽셀 범위가 (0,0)~(1,1)):

multisample.count 샘플 위치
1 샘플 0: (0.5, 0.5)
4 샘플 0: (0.375, 0.125)
샘플 1: (0.875, 0.375)
샘플 2: (0.125, 0.625)
샘플 3: (0.625, 0.875)

구현체는 래스터화 수행 시 해당 표준 샘플 패턴을 반드시 사용해야 합니다. multisample.count에 맞게 적용됩니다.

FragmentDestination을 다음과 같이 정의합니다:

position

프레임버퍼 좌표를 사용하는 2D 픽셀 위치

sampleIndex

§ 23.2.10 샘플별 셰이딩이 활성화된 경우 정수, 그렇지 않으면 null

정규화 디바이스 좌표(NDC) 개념도 사용합니다. 이 좌표계에서 viewport 경계는 X, Y가 -1~1, Z가 0~1 범위입니다.

래스터화는 다음 데이터를 포함하는 RasterizationPoint 리스트를 생성합니다:

destination

FragmentDestination 참조

coverageMask

멀티샘플 커버리지 마스크 참조 (§ 23.2.11 샘플 마스킹 참고)

frontFacing

프리미티브의 전면(face) 포인트라면 true

perspectiveDivisor

프리미티브 전역에서 보간된 1.0 ÷ W 값 참조

depth

뷰포트 좌표 내 깊이 참조, 즉 [[viewport]] minDepth~maxDepth 범위

primitiveVertices

프리미티브를 구성하는 버텍스 출력값 리스트 참조

barycentricCoordinates

§ 23.2.5.3 바리센트릭 좌표 참조

rasterize(primitiveList, state)

인자:

반환값: RasterizationPoint 리스트.

primitiveList 내 각 프리미티브는 개별적으로 처리됩니다. 단, 프리미티브의 순서는 이후 단계(깊이/스텐실 연산, 픽셀 기록)에 영향을 줍니다.

  1. 먼저, 클리핑된 버텍스들은 NDC(정규화 디바이스 좌표)로 변환됩니다. 출력 위치 p를 주면, NDC 위치 및 퍼스펙티브 디바이저는 다음과 같습니다:

    ndc(p) = 벡터(p.x ÷ p.w, p.y ÷ p.w, p.z ÷ p.w)

    divisor(p) = 1.0 ÷ p.w

  2. vpstate.[[viewport]]로 설정합니다. NDC 위치 n뷰포트 좌표로 매핑:

    • 렌더 타겟 오프셋 및 크기로 프레임버퍼 좌표 계산:

      framebufferCoords(n) = 벡터(vp.x + 0.5 × (n.x + 1) × vp.width, vp.y + 0.5 × (−n.y + 1) × vp.height)

    • [0,1]을 뷰포트 깊이 범위에 선형 매핑하여 깊이 계산:

      depth(n) = vp.minDepth + n.z × ( vp.maxDepth - vp.minDepth )

  3. rasterizationPoints를, 프리미티브 내 위치에 따라(divisor(p), framebufferCoords(n), depth(n) 등), § 23.2.4 프리미티브 클리핑과 동일한 보간 방식으로 보간된 속성을 가진 포인트 리스트로 설정합니다. 속성이 사용자 정의(내장 출력값이 아닌)라면, WGSL @interpolate 속성에 지정된 보간 타입을 사용합니다.

  4. 아래 프리미티브 토폴로지에 따라 특정 래스터화 알고리즘 진행: primitive.topology:

    "point-list"

    포인트가 § 23.2.4 프리미티브 클리핑에서 필터링되지 않았다면 § 23.2.5.1 포인트 래스터화로 전달.

    "line-list" 또는 "line-strip"

    라인이 § 23.2.4 프리미티브 클리핑에서 잘린 경우 § 23.2.5.2 라인 래스터화로 전달.

    "triangle-list" 또는 "triangle-strip"

    § 23.2.4 프리미티브 클리핑에서 생성된 폴리곤은 § 23.2.5.4 폴리곤 래스터화로 전달.

  5. rasterizationPoints에서 rprp.destination.positionstate.[[scissorRect]] 밖인 것은 제거합니다.

  6. rasterizationPoints를 반환합니다.

23.2.5.1. 포인트 래스터화

포인트의 프레임버퍼 좌표가 포함된 픽셀 내에서 하나의 FragmentDestination이 선택됩니다.

커버리지 마스크는 멀티샘플링 모드에 따라 달라집니다:

샘플-주파수

coverageMask = 1 ≪ sampleIndex

픽셀-주파수 멀티샘플링

coverageMask = 1 ≪ descriptor.multisample.count − 1

멀티샘플링 없음

coverageMask = 1

23.2.5.2. 라인 래스터화

라인 래스터화에 사용되는 정확한 알고리즘은 정의되지 않았으며, 구현체마다 다를 수 있습니다. 예를 들어, 라인 세그먼트 주변 1px 너비의 사각형을 § 23.2.5.4 폴리곤 래스터화로 그릴 수도 있고, Bresenham 라인 알고리즘을 사용해 FragmentDestination을 선택할 수도 있습니다.

참고: 자세한 라인 래스터화 알고리즘 구현 방법은 기본 라인 세그먼트 래스터화Bresenham 라인 세그먼트 래스터화Vulkan 1.3 명세에서 참고할 수 있습니다.

23.2.5.3. 바리센트릭 좌표

바리센트릭 좌표란 n개의 숫자 bi의 리스트로, 프레임버퍼 공간 내 n개의 버텍스 vi를 가진 볼록 다각형 내부의 점 p에 대해 정의됩니다. 각 bi는 0~1 범위를 가지며, 해당 버텍스 vi와의 근접도를 나타냅니다. 이들의 합은 항상 일정합니다:

∑ (bi) = 1

이 좌표들은 다각형 내부(혹은 경계 위)의 임의의 점 p를 다음과 같이 유일하게 지정합니다:

p = ∑ (bi × pi)

버텍스가 3개인 삼각형의 경우, 임의의 점 p에 대한 바리센트릭 좌표는 다음과 같이 계산 가능합니다:

Apolygon = A(v1, v2, v3) b1 = A(p, b2, b3) ÷ Apolygon b2 = A(b1, p, b3) ÷ Apolygon b3 = A(b1, b2, p) ÷ Apolygon

여기서 A(점 리스트)는 주어진 버텍스 집합으로 이루어진 다각형의 면적입니다.

3개 초과 버텍스의 다각형은 정확한 알고리즘이 구현체마다 다릅니다. 하나의 가능한 구현 방법은 다각형을 삼각형들로 쪼개고, 점이 속하는 삼각형을 기준으로 바리센트릭 좌표를 계산하는 것입니다.

23.2.5.4. 폴리곤 래스터화

폴리곤이 투영 방향을 바라보고 있으면 전면입니다. 그렇지 않으면 후면입니다.

rasterize polygon()

인자:

반환값: RasterizationPoint 리스트.

  1. rasterizationPoints를 비어 있는 리스트로 설정.

  2. 클리핑된 버텍스 번호 i(1부터 시작)의 프레임버퍼 좌표를 v(i)로 설정. 다각형의 버텍스 개수는 n입니다.

    참고: 이 섹션에서는 "triangle" 대신 "polygon" 용어를 사용하는데, § 23.2.4 프리미티브 클리핑 단계에서 추가 버텍스가 생길 수 있기 때문입니다. 이는 애플리케이션에서 관찰할 수 없습니다.

  3. 폴리곤이 전면인지 판단하려면, 프레임버퍼 좌표에서 폴리곤이 차지하는 area의 부호에 따라 결정합니다:

    area = 0.5 × ((v1.x × vn.y − vn.x × v1.y) + ∑ (vi+1.x × vi.y − vi.x × vi+1.y))

    area의 부호는 primitive.frontFace에 따라 해석됩니다:

    "ccw"

    area > 0이면 전면, 아니면 후면

    "cw"

    area < 0이면 전면, 아니면 후면

  4. primitive.cullMode에 따라 컬링:

    "none"

    모든 폴리곤이 이 테스트를 통과합니다.

    "front"

    전면 폴리곤은 폐기되어 렌더 파이프라인의 후속 단계에서 처리되지 않습니다.

    "back"

    후면 폴리곤은 폐기됩니다.

  5. 폴리곤 내부 fragments 집합을 프레임버퍼 공간에서 결정합니다 - 이 위치들은 프래그먼트별 연산 대상입니다. 이 연산은 "포인트 샘플링"이라 불립니다. 로직은 descriptor.multisample에 따라 다릅니다:

    비활성화

    Fragment는 픽셀 중앙에 연결됩니다. 즉, 프레임버퍼 공간에서 좌표 C의 fract(C) = vector2(0.5, 0.5)인 점들이 폴리곤 내부에 있으면 포함됩니다. 픽셀 중앙이 폴리곤 경계에 있으면 포함 여부는 정의되어 있지 않습니다.

    참고: 이는 래스터라이저의 정밀도에 따라 달라집니다.

    활성화

    각 픽셀은 descriptor.multisample.count 개의 위치에 연결되며, 이 위치들은 구현체 정의입니다. 위치들은 정렬되어 있으며, 프레임버퍼의 각 픽셀에 대해 동일한 리스트입니다. 각 위치는 멀티샘플 프레임버퍼 내 하나의 프래그먼트에 대응합니다.

    래스터라이저는 각 픽셀 내에서 내부에 포함된 위치의 마스크를 만들고, 이를 프래그먼트 셰이더의 "sample-mask" 내장값으로 제공합니다.

  6. 생성된 각 FragmentDestination 타입 프래그먼트에 대해:

    1. rp를 새 RasterizationPoint 객체로 설정

    2. 그 프래그먼트의 § 23.2.5.3 바리센트릭 좌표를 리스트 b로 계산. rp.barycentricCoordinatesb를 설정.

    3. divi의 깊이 값으로 설정.

    4. rp.depth를 ∑ (bi × di)로 설정

    5. rprasterizationPoints에 추가.

  7. rasterizationPoints를 반환.

23.2.6. 프래그먼트 처리

프래그먼트 처리 단계는 렌더 파이프라인의 프로그래머블 단계로, 렌더 타겟에 기록될 프래그먼트 데이터(주로 색상 등)를 계산합니다.

이 단계는 각 RasterizationPoint에 대해 Fragment를 생성합니다:

process fragment(rp, descriptor, state)

인자:

반환값: Fragment 또는 null.

  1. fragmentDescdescriptor.fragment로 설정.

  2. depthStencilDescdescriptor.depthStencil로 설정.

  3. fragment를 새 Fragment 객체로 생성.

  4. fragment.destinationrp.destination을 설정.

  5. fragment.frontFacingrp.frontFacing을 설정.

  6. fragment.coverageMaskrp.coverageMask를 설정.

  7. fragment.depthrp.depth를 설정.

  8. 셰이더에서 frag_depth 내장값을 생성하지 않은 경우:

    1. fragment.depthPassedcompare fragment(fragment.destination, fragment.depth, "depth", state.[[depthStencilAttachment]], depthStencilDesc?.depthCompare)의 결과로 설정.

  9. stencilStatedepthStencilDesc?.stencilFront (만약 rp.frontFacingtrue면), 그 외에는 depthStencilDesc?.stencilBack로 설정.

  10. fragment.stencilPassedcompare fragment(fragment.destination, state.[[stencilReference]], "stencil", state.[[depthStencilAttachment]], stencilState?.compare)의 결과로 설정.

  11. fragmentDescnull이 아니라면:

    1. fragment.depthPassedfalse이고, 셰이더 entry point가 frag_depth 내장값을 생성하지 않았으며, 셰이더 entry point가 스토리지 바인딩에 기록하지 않았다면, 이후 단계는 생략할 수 있습니다.

    2. 셰이더 입력 내장값 설정. 각 entry point의 비복합 인자 중 내장값으로 어노테이션된 것은 해당 어노테이션에 따라 값 설정:

      position

      vec4<f32>(rp.destination.position, rp.depth, rp.perspectiveDivisor)

      front_facing

      rp.frontFacing

      sample_index

      rp.destination.sampleIndex

      sample_mask

      rp.coverageMask

    3. 프래그먼트 단계의 각 사용자 지정 셰이더 입력에 대해:

      1. value를, rp.barycentricCoordinates, rp.primitiveVertices, 입력의 보간 지정자에 따라 보간된 프래그먼트 입력값으로 설정.

      2. 해당 프래그먼트 셰이더 location 입력값에 value를 설정.

    4. fragmentDesc에 기술된 프래그먼트 셰이더 entry point를 호출.

      디바이스손실될 수 있습니다.
      셰이더 실행이 종료되지 않을 경우, 사용자 에이전트가 판단한 합리적인 시간 내에 실행이 끝나지 않으면 디바이스가 손실될 수 있습니다.

    5. 프래그먼트에서 discard를 호출하면 null을 반환.

    6. fragment.colors를 셰이더의 사용자 지정 셰이더 출력값으로 설정.

    7. 셰이더 출력 내장값에 대해:

      1. frag_depth 내장값이 셰이더에서 value로 생성된 경우:

        1. vpstate.[[viewport]]로 설정.

        2. fragment.depth를 clamp(value, vp.minDepth, vp.maxDepth)로 설정.

        3. fragment.depthPassedcompare fragment(fragment.destination, fragment.depth, "depth", state.[[depthStencilAttachment]], depthStencilDesc?.depthCompare)로 설정.

    8. sample_mask 내장값이 셰이더에서 value로 생성된 경우:

      1. fragment.coverageMaskfragment.coverageMaskvalue로 설정.

    그 외인 경우 § 23.2.8 색상 출력 없음 모드이며, fragment.colors는 비어 있음.

  12. fragment를 반환.

compare fragment(destination, value, aspect, attachment, compareFunc)

인자:

반환값: 비교가 통과하면 true, 그렇지 않으면 false

프래그먼트 처리는 병렬로 이루어지며, GPUBufferBindingType "storage" 바인딩 등에 대한 기록 같은 부작용은 임의의 순서로 발생할 수 있습니다.

23.2.7. 출력 병합

출력 병합은 렌더 파이프라인의 고정 기능 단계로, 프래그먼트의 색상, 깊이, 스텐실 데이터를 렌더 패스 어태치먼트에 기록합니다.

process depth stencil(fragment, pipeline, state)

인자:

  1. depthStencilDescpipeline.[[descriptor]].depthStencil로 설정.

  2. pipeline.[[writesDepth]]true이고 fragment.depthPassedtrue이면:

    1. state.[[depthStencilAttachment]] 의 depth aspect 값을 fragment.destination 위치에 fragment.depth로 설정.

  3. pipeline.[[writesStencil]] 이 true이면:

    1. stencilStatedepthStencilDesc.stencilFront (fragment.frontFacingtrue일 때), 아니면 depthStencilDesc.stencilBack로 설정.

    2. fragment.stencilPassedfalse이면:

      • stencilOpstencilState.failOp로 설정.

      그 외 fragment.depthPassedfalse이면:

      그 외의 경우:

      • stencilOpstencilState.passOp로 설정.

    3. state.[[depthStencilAttachment]] 의 stencil aspect 값을 fragment.destination 위치에 stencilOp에 따라 갱신.

이 단계의 깊이 입력값(있는 경우)은 현재 [[viewport]] 깊이 범위로 clamp됩니다(프래그먼트 셰이더 단계에서 frag_depth 내장값을 기록하는지 여부와 관계없이).

process color attachments(fragment, pipeline, state)

인자:

  1. fragment.depthPassedfalse거나 fragment.stencilPassedfalse면 return.

  2. targetspipeline.[[descriptor]].fragment.targets로 설정.

  3. state.[[colorAttachments]]의 각 attachment에 대해:

    1. colorfragment.colors에서 attachment에 해당하는 값으로 설정.

    2. targetDesctargets에서 attachment에 해당하는 엔트리로 설정.

    3. targetDesc.blend제공된 경우:

      1. colorBlendtargetDesc.blend.color로 설정.

      2. alphaBlendtargetDesc.blend.alpha로 설정.

      3. color의 RGB 컴포넌트를, colorBlend.operation에 따라, colorBlend.srcFactorcolorBlend.dstFactor 값으로 계산된 결과로 설정.

      4. color의 알파 컴포넌트를, alphaBlend.operation에 따라, alphaBlend.srcFactoralphaBlend.dstFactor 값으로 계산된 결과로 설정.

    4. fragment.destination 위치의 attachment 값을 color로 설정.

23.2.8. 색상 출력 없음

색상 출력 없음 모드에서는 파이프라인이 색상 어태치먼트 출력을 생성하지 않습니다.

파이프라인은 래스터화 및 버텍스 위치 출력에 기반한 깊이 값을 계속 생성합니다. 깊이 테스트와 스텐실 연산 역시 사용할 수 있습니다.

23.2.9. 알파 투 커버리지

알파 투 커버리지 모드에서는, 프래그먼트 셰이더 출력 @location(0)alpha 컴포넌트를 기반으로, MSAA 샘플들의 추가 alpha-to-coverage 마스크가 생성됩니다.

이 추가 마스크 생성 알고리즘은 플랫폼에 따라 다르며, 픽셀마다 달라질 수 있습니다. 다음을 보장합니다:

23.2.10. 샘플별 셰이딩

멀티샘플 렌더 어태치먼트에 렌더링할 때, 프래그먼트 셰이더는 픽셀당 한 번 또는 샘플당 한 번 실행될 수 있습니다. sample_index 내장값이나 sample 보간 샘플링이 셰이더 출력에 기여하면 프래그먼트 셰이더는 반드시 샘플별로 한 번씩 실행되어야 합니다. 그렇지 않으면 프래그먼트 셰이더는 픽셀당 한 번만 실행되어도 되고, 결과는 최종 샘플 마스크에 포함된 모든 샘플에 브로드캐스트됩니다.

샘플별 셰이딩을 사용할 때, 샘플 N에 대한 색상 출력은 프래그먼트 셰이더가 현재 픽셀에서 sample_index == N로 실행된 결과입니다.

23.2.11. 샘플 마스킹

픽셀의 최종 샘플 마스크는 다음과 같이 계산됩니다: 래스터화 마스크 & mask & 셰이더 출력 마스크.

마스크의 하위 count 비트만 고려됩니다.

최종 샘플 마스크의 위치 N의 최하위 비트가 "0"이면, 해당 샘플의 색상 출력(샘플 N에 해당)은 프래그먼트 셰이더의 모든 어태치먼트에서 폐기됩니다. 또한, depth-stencil 어태치먼트의 해당 샘플에서는 깊이 테스트나 스텐실 연산이 실행되지 않습니다.

래스터화 마스크는 래스터화 단계에서 생성되며, 래스터화된 폴리곤의 모양에 따라 결정됩니다. 도형에 포함된 샘플은 마스크의 해당 비트가 1이 됩니다.

셰이더 출력 마스크는 프래그먼트 셰이더의 "sample_mask" 내장값 출력값을 취합니다. 프래그먼트 셰이더에서 내장값을 출력하지 않고, alphaToCoverageEnabled 가 활성화된 경우, 셰이더 출력 마스크alpha-to-coverage 마스크가 됩니다. 그 외에는 0xFFFFFFFF가 기본값입니다.

24. 타입 정의

typedef [EnforceRange] unsigned long GPUBufferDynamicOffset;
typedef [EnforceRange] unsigned long GPUStencilValue;
typedef [EnforceRange] unsigned long GPUSampleMask;
typedef [EnforceRange] long GPUDepthBias;

typedef [EnforceRange] unsigned long long GPUSize64;
typedef [EnforceRange] unsigned long GPUIntegerCoordinate;
typedef [EnforceRange] unsigned long GPUIndex32;
typedef [EnforceRange] unsigned long GPUSize32;
typedef [EnforceRange] long GPUSignedOffset32;

typedef unsigned long long GPUSize64Out;
typedef unsigned long GPUIntegerCoordinateOut;
typedef unsigned long GPUSize32Out;

typedef unsigned long GPUFlagsConstant;

24.1. 색상 및 벡터

dictionary GPUColorDict {
    required double r;
    required double g;
    required double b;
    required double a;
};
typedef (sequence<double> or GPUColorDict) GPUColor;

참고: double은 32비트 부호/무부호 정수와 단정밀도(float) 값을 정확하게 표현할 수 있을 만큼 충분히 큽니다.

r, 타입 double

빨간색 채널 값입니다.

g, 타입 double

초록색 채널 값입니다.

b, 타입 double

파란색 채널 값입니다.

a, 타입 double

알파(투명도) 채널 값입니다.

주어진 GPUColorcolor의 타입에 따라 다음 문법을 사용합니다:
validate GPUColor shape(color)

인자:

반환값: undefined

컨텐트 타임라인 단계:

  1. color가 시퀀스이고 color.size ≠ 4이면 TypeError를 발생시킵니다.

dictionary GPUOrigin2DDict {
    GPUIntegerCoordinate x = 0;
    GPUIntegerCoordinate y = 0;
};
typedef (sequence<GPUIntegerCoordinate> or GPUOrigin2DDict) GPUOrigin2D;
주어진 GPUOrigin2Dorigin의 타입에 따라 다음 문법을 사용합니다:
validate GPUOrigin2D shape(origin)

인자:

반환값: undefined

컨텐트 타임라인 단계:

  1. origin이 시퀀스이고 origin.size > 2이면 TypeError를 발생시킵니다.

dictionary GPUOrigin3DDict {
    GPUIntegerCoordinate x = 0;
    GPUIntegerCoordinate y = 0;
    GPUIntegerCoordinate z = 0;
};
typedef (sequence<GPUIntegerCoordinate> or GPUOrigin3DDict) GPUOrigin3D;
주어진 GPUOrigin3Dorigin의 타입에 따라 다음 문법을 사용합니다:
validate GPUOrigin3D shape(origin)

인자:

반환값: undefined

컨텐트 타임라인 단계:

  1. 다음 경우 TypeError를 발생시킵니다:

dictionary GPUExtent3DDict {
    required GPUIntegerCoordinate width;
    GPUIntegerCoordinate height = 1;
    GPUIntegerCoordinate depthOrArrayLayers = 1;
};
typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D;
width, 타입 GPUIntegerCoordinate

extent의 너비입니다.

height, 타입 GPUIntegerCoordinate, 기본값 1

extent의 높이입니다.

depthOrArrayLayers, 타입 GPUIntegerCoordinate, 기본값 1

extent의 깊이 또는 포함된 배열 레이어 수입니다. GPUTextureGPUTextureDimension"3d"와 함께 사용되면 텍스처의 깊이를 정의합니다. GPUTextureGPUTextureDimension"2d"와 함께 사용되면 텍스처의 배열 레이어 수를 정의합니다.

주어진 GPUExtent3Dextent의 타입에 따라 다음 문법을 사용합니다:
validate GPUExtent3D shape(extent)

인자:

반환값: undefined

컨텐트 타임라인 단계:

  1. 다음 경우 TypeError를 발생시킵니다:

25. 기능 색인

25.1. "core-features-and-limits"

모든 핵심 WebGPU 기능과 제한을 사용할 수 있게 해줍니다.

참고: 현재 모든 어댑터에서 이용 가능하며, 요청하지 않아도 모든 디바이스에 자동으로 활성화됩니다.

25.2. "depth-clip-control"

깊이 클리핑을 비활성화할 수 있습니다.

이 기능은 다음 선택적 API 표면을 추가합니다:

25.3. "depth32float-stencil8"

"depth32float-stencil8" 포맷의 텍스처를 명시적으로 생성할 수 있습니다.

이 기능은 다음 선택적 API 표면을 추가합니다:

25.4. "texture-compression-bc"

BC 압축 포맷의 텍스처를 명시적으로 생성할 수 있습니다. 여기에는 "S3TC", "RGTC", "BPTC" 포맷이 포함됩니다. 2D 텍스처만 지원합니다.

참고: "texture-compression-bc" 를 지원하는 어댑터가 항상 "texture-compression-bc-sliced-3d" 를 지원하는 것은 아닙니다. "texture-compression-bc-sliced-3d" 를 사용하려면, "texture-compression-bc" 를 명시적으로 활성화해야 하며, 이 기능 자체로는 BC 포맷이 활성화되지 않습니다.

이 기능은 다음 선택적 API 표면을 추가합니다:

25.5. "texture-compression-bc-sliced-3d"

BC 압축 포맷 텍스처에 대해 3d 차원을 사용할 수 있습니다.

참고: "texture-compression-bc" 를 지원하는 어댑터가 항상 "texture-compression-bc-sliced-3d" 를 지원하는 것은 아닙니다. "texture-compression-bc-sliced-3d" 를 사용하려면, "texture-compression-bc" 를 명시적으로 활성화해야 하며, 이 기능 자체로는 BC 포맷이 활성화되지 않습니다.

이 기능은 선택적 API 표면을 추가하지 않습니다.

25.6. "texture-compression-etc2"

ETC2 압축 포맷의 텍스처를 명시적으로 생성할 수 있습니다. 2D 텍스처만 지원합니다.

이 기능은 다음 선택적 API 표면을 추가합니다:

25.7. "texture-compression-astc"

ASTC 압축 포맷의 텍스처를 명시적으로 생성할 수 있습니다. 2D 텍스처만 지원합니다.

이 기능은 다음 선택적 API 표면을 추가합니다:

25.8. "texture-compression-astc-sliced-3d"

ASTC 압축 포맷 텍스처에 대해 3d 차원을 사용할 수 있습니다.

참고: "texture-compression-astc" 를 지원하는 어댑터가 항상 "texture-compression-astc-sliced-3d" 를 지원하는 것은 아닙니다. "texture-compression-astc-sliced-3d" 를 사용하려면, "texture-compression-astc" 를 명시적으로 활성화해야 하며, 이 기능 자체로는 ASTC 포맷이 활성화되지 않습니다.

이 기능은 선택적 API 표면을 추가하지 않습니다.

25.9. "timestamp-query"

GPU 커맨드 버퍼에서 타임스탬프를 쿼리할 수 있는 기능을 추가합니다. § 20.4 타임스탬프 쿼리 참고.

이 기능은 다음 선택적 API 표면을 추가합니다:

25.10. "indirect-first-instance"

indirect draw parametersindirect drawIndexed parameters에서 0이 아닌 firstInstance 값을 사용할 수 있습니다.

이 기능은 선택적 API 표면을 추가하지 않습니다.

25.11. "shader-f16"

WGSL에서 반정밀도 부동소수점 타입 f16을 사용할 수 있습니다.

이 기능은 다음 선택적 API 표면을 추가합니다:

25.12. "rg11b10ufloat-renderable"

RENDER_ATTACHMENT 용도로 "rg11b10ufloat" 포맷의 텍스처를 사용할 수 있으며, 해당 포맷의 텍스처에 블렌딩, 멀티샘플링, 리졸브도 가능합니다.

이 기능은 선택적 API 표면을 추가하지 않습니다.

"texture-formats-tier1" 를 디바이스 생성 시 활성화하면 "rg11b10ufloat-renderable" 도 활성화됩니다.

25.13. "bgra8unorm-storage"

STORAGE_BINDING 용도로 "bgra8unorm" 포맷의 텍스처를 사용할 수 있습니다.

이 기능은 선택적 API 표면을 추가하지 않습니다.

25.14. "float32-filterable"

"r32float", "rg32float", "rgba32float" 포맷의 텍스처를 필터링 가능하게 만듭니다.

25.15. "float32-blendable"

"r32float", "rg32float", "rgba32float" 포맷의 텍스처를 블렌딩 가능하게 만듭니다.

25.16. "clip-distances"

WGSL에서 clip_distances를 사용할 수 있습니다.

이 기능은 다음 선택적 API 표면을 추가합니다:

25.17. "dual-source-blending"

WGSL에서 blend_src를 사용할 수 있으며, 동시에 두 개의 픽셀 셰이더 출력(@blend_src(0)@blend_src(1))을 색상 어태치먼트 0에 대한 블렌딩 연산의 입력으로 사용할 수 있습니다.

이 기능은 다음 선택적 API 표면을 추가합니다:

25.18. "subgroups"

WGSL에서 subgroup 및 quad 연산을 사용할 수 있습니다.

이 기능은 선택적 API 표면을 추가하지 않지만, 어댑터에서 이 기능을 사용할 수 있을 때 아래 GPUAdapterInfo 엔트리들이 실제 값을 노출합니다:

25.19. "texture-formats-tier1"

아래 새로운 GPUTextureFormatRENDER_ATTACHMENT, 블렌딩 가능, 멀티샘플링 기능과 STORAGE_BINDING 기능을 "read-only""write-only" GPUStorageTextureAccess로 지원합니다:

아래 GPUTextureFormatRENDER_ATTACHMENT, 블렌딩 가능, 멀티샘플링, 리졸브 기능을 지원합니다:

아래 GPUTextureFormat에 대해 "read-only" 또는 "write-only" GPUStorageTextureAccess를 지원합니다:

디바이스 생성 시 "texture-formats-tier2"를 활성화하면 "texture-formats-tier1"도 활성화됩니다.

디바이스 생성 시 "texture-formats-tier1"를 활성화하면 "rg11b10ufloat-renderable"도 활성화됩니다.

25.20. "texture-formats-tier2"

아래 GPUTextureFormat에 대해 "read-write" GPUStorageTextureAccess를 지원합니다:

디바이스 생성 시 "texture-formats-tier2"를 활성화하면 "texture-formats-tier1"도 활성화됩니다.

25.21. "primitive-index"

WGSL에서 primitive_index를 사용할 수 있습니다.

이 기능은 다음 선택적 API 표면을 추가합니다:

26. 부록

26.1. 텍스처 포맷 기능

26.1.1. 일반 색상 포맷

모든 지원되는 일반 색상 포맷은 COPY_SRC, COPY_DST, TEXTURE_BINDING 사용과, "3d" 차원을 지원합니다.

RENDER_ATTACHMENTSTORAGE_BINDING 열은 각각 GPUTextureUsage.RENDER_ATTACHMENTGPUTextureUsage.STORAGE_BINDING 사용 지원 여부를 나타냅니다.

렌더 타겟 픽셀 바이트 비용렌더 타겟 컴포넌트 정렬maxColorAttachmentBytesPerSample 제한을 검증하는 데 사용됩니다.

참고: 각 포맷의 텍셀 블록 메모리 비용텍셀 블록 복사 풋프린트와 동일합니다.

포맷 필수 기능 GPUTextureSampleType RENDER_ATTACHMENT 블렌딩 가능 멀티샘플링 리졸브 STORAGE_BINDING 텍셀 블록 복사 풋프린트 (바이트) 렌더 타겟 픽셀 바이트 비용 (바이트)
"write-only" "read-only" "read-write"
8비트 컴포넌트당 (1바이트 렌더 타겟 컴포넌트 정렬)
r8unorm "float",
"unfilterable-float"
"texture-formats-tier1" 활성화 시 "texture-formats-tier2" 활성화 시 1
r8snorm "float",
"unfilterable-float"
"texture-formats-tier1" 활성화 시 1
r8uint "uint" "texture-formats-tier1" 활성화 시 "texture-formats-tier2" 활성화 시 1
r8sint "sint" "texture-formats-tier1" 활성화 시 "texture-formats-tier2" 활성화 시 1
rg8unorm "float",
"unfilterable-float"
"texture-formats-tier1" 활성화 시 2
rg8snorm "float",
"unfilterable-float"
"texture-formats-tier1" 활성화 시 2
rg8uint "uint" "texture-formats-tier1" 활성화 시 2
rg8sint "sint" "texture-formats-tier1" 활성화 시 2
rgba8unorm "float",
"unfilterable-float"
"texture-formats-tier2" 활성화 시 4 8
rgba8unorm-srgb "float",
"unfilterable-float"
4 8
rgba8snorm "float",
"unfilterable-float"
"texture-formats-tier1" 활성화 시 4
rgba8uint "uint" "texture-formats-tier2" 활성화 시 4
rgba8sint "sint" "texture-formats-tier2" 활성화 시 4
bgra8unorm "float",
"unfilterable-float"
"bgra8unorm-storage" 활성화 시 4 8
bgra8unorm-srgb "float",
"unfilterable-float"
4 8
16비트 컴포넌트당 (2바이트 렌더 타겟 컴포넌트 정렬)
r16unorm "texture-formats-tier1" "unfilterable-float" 2
r16snorm "texture-formats-tier1" "unfilterable-float" 2
r16uint "uint" "texture-formats-tier1" 활성화 시 "texture-formats-tier2" 활성화 시 2
r16sint "sint" "texture-formats-tier1" 활성화 시 "texture-formats-tier2" 활성화 시 2
r16float "float",
"unfilterable-float"
"texture-formats-tier1" 활성화 시 "texture-formats-tier2" 활성화 시 2
rg16unorm "texture-formats-tier1" "unfilterable-float" 4
rg16snorm "texture-formats-tier1" "unfilterable-float" 4
rg16uint "uint" "texture-formats-tier1" 활성화 시 4
rg16sint "sint" "texture-formats-tier1" 활성화 시 4
rg16float "float",
"unfilterable-float"
"texture-formats-tier1" 활성화 시 4
rgba16unorm "texture-formats-tier1" "unfilterable-float" 8
rgba16snorm "texture-formats-tier1" "unfilterable-float" 8
rgba16uint "uint" 만약 "texture-formats-tier2" 가 활성화된 경우 8
rgba16sint "sint" 만약 "texture-formats-tier2" 가 활성화된 경우 8
rgba16float "float",
"unfilterable-float"
만약 "texture-formats-tier2" 가 활성화된 경우 8
컴포넌트당 32비트 (4바이트 렌더 타겟 컴포넌트 정렬)
r32uint "uint" 4
r32sint "sint" 4
r32float

"float" 만약 "float32-filterable" 가 활성화된 경우

"unfilterable-float"

만약 "float32-blendable" 가 활성화된 경우 4
rg32uint "uint" 8
rg32sint "sint" 8
rg32float

"float" 만약 "float32-filterable" 가 활성화된 경우

"unfilterable-float"

만약 "float32-blendable" 가 활성화된 경우 8
rgba32uint "uint" 만약 "texture-formats-tier2" 가 활성화된 경우 16
rgba32sint "sint" 만약 "texture-formats-tier2" 가 활성화된 경우 16
rgba32float

"float" 만약 "float32-filterable" 가 활성화된 경우

"unfilterable-float"

만약 "float32-blendable" 가 활성화된 경우 만약 "texture-formats-tier2" 가 활성화된 경우 16
혼합 컴포넌트 폭, 텍셀당 32비트 (4바이트 렌더 타겟 컴포넌트 정렬)
rgb10a2uint "uint" 만약 "texture-formats-tier1" 가 활성화된 경우 4 8
rgb10a2unorm "float",
"unfilterable-float"
만약 "texture-formats-tier1" 가 활성화된 경우 4 8
rg11b10ufloat "float",
"unfilterable-float"
만약 "rg11b10ufloat-renderable" 가 활성화된 경우 만약 "texture-formats-tier1" 가 활성화된 경우 4 8

26.1.2. 깊이-스텐실 포맷

깊이 또는 스텐실 포맷은 깊이와/또는 스텐실 aspect가 있는 모든 포맷입니다. 복합 깊이-스텐실 포맷깊이 또는 스텐실 포맷 중 깊이와 스텐실 aspect가 모두 있는 포맷을 말합니다.

모든 깊이 또는 스텐실 포맷COPY_SRC, COPY_DST, TEXTURE_BINDING, RENDER_ATTACHMENT 사용을 지원합니다. 이들 포맷은 모두 멀티샘플링을 지원합니다. 단, 특정 복사 작업은 소스와 대상 포맷에 제한이 있고, 이들 포맷은 "3d" 차원의 텍스처를 지원하지 않습니다.

깊이 텍스처는 "filtering" 샘플러와 함께 사용할 수 없지만, "comparison" 샘플러(필터링을 사용하는 경우에도)와는 항상 사용할 수 있습니다.

포맷
참고:
텍셀 블록 메모리 비용 (바이트)
Aspect GPUTextureSampleType 유효한 텍셀 복사 소스 유효한 텍셀 복사 대상 텍셀 블록 복사 풋프린트 (바이트) Aspect별 포맷
stencil8 1 − 4 스텐실 "uint" 1 stencil8
depth16unorm 2 깊이(depth) "depth", "unfilterable-float" 2 depth16unorm
depth24plus 4 깊이(depth) "depth", "unfilterable-float" depth24plus
depth24plus-stencil8 4 − 8 깊이(depth) "depth", "unfilterable-float" depth24plus
스텐실 "uint" 1 stencil8
depth32float 4 깊이(depth) "depth", "unfilterable-float" 4 depth32float
depth32float-stencil8 5 − 8 깊이(depth) "depth", "unfilterable-float" 4 depth32float
스텐실 "uint" 1 stencil8

24비트 깊이란 0.0~1.0 범위의 24비트 부호 없는 정규화된 깊이 포맷을 의미하며, 노출될 경우 "depth24unorm"으로 표기됩니다.

26.1.2.1. 깊이/스텐실 텍스처 읽기 및 샘플링

가능한 것은, depth aspect의 GPUTextureViewtexture_depth_* 바인딩이나, 다른 depth가 아닌 2d/cube 텍스처 타입 바인딩에 연결하는 것입니다.

스텐실 aspect의 GPUTextureView는 반드시 일반 텍스처 바인딩 타입에 연결해야 합니다. sampleTypeGPUBindGroupLayout에서 "uint"이어야 합니다.

텍스처의 깊이 또는 스텐실 aspect를 읽거나 샘플링하면, 해당 텍스처는 (V, X, X, X) 형식의 값을 가진 것으로 동작합니다. 여기서 V는 실제 깊이 또는 스텐실 값이고, 각 X는 구현 정의의 미정 값입니다.

depth aspect 바인딩의 경우, 미정 값은 texture_depth_* 타입 바인딩에서는 보이지 않습니다.

만약 depth 텍스처가 textexture_2d<f32> 타입으로 바인딩되어 있다면:

참고: depth와 같이 더 제한적인 스텐실 샘플러 타입을 추가하지 않는 이상, 구현에서 depth/stencil 읽기를 드라이버 차이를 효율적으로 감추기는 불가능합니다. WebGL에서는 이식성 문제점이 없었으므로, WebGPU에서도 문제가 될 것으로 예상되지 않습니다. 실제로는, 하드웨어에 따라 (V, V, V, V) 또는 (V, 0, 0, 1)(여기서 V는 깊이 또는 스텐실 값) 중 하나가 될 수 있습니다.

26.1.2.2. 깊이/스텐실 텍스처 복사

depth32float 포맷의 깊이 aspect ("depth32float""depth32float-stencil8" )는 범위가 제한되어 있습니다. 따라서 이런 텍스처로의 복사는 동일한 포맷의 다른 텍스처에서만 유효합니다.

depth24plus 포맷의 깊이 aspect ("depth24plus""depth24plus-stencil8") 는 불투명하게 표현됩니다(내부적으로 24비트 깊이 또는 "depth32float"로 구현됨). 따라서 depth aspect의 텍셀 복사는 이 포맷에서는 허용되지 않습니다.

참고:
이런 허용되지 않는 복사를 흉내낼 수 있습니다:

26.1.3. 패킹 포맷

모든 패킹 텍스처 포맷은 COPY_SRC, COPY_DST, TEXTURE_BINDING 사용을 지원합니다. 이들 포맷은 모두 필터링 가능합니다. 이들 포맷은 렌더링 가능하지 않으며 멀티샘플링도 지원하지 않습니다.

압축 포맷은 블록 크기가 1×1보다 큰 모든 포맷입니다.

참고: 각 포맷의 텍셀 블록 메모리 비용텍셀 블록 복사 풋프린트와 동일합니다.

포맷 텍셀 블록 복사 풋프린트 (바이트) GPUTextureSampleType 텍셀 블록 너비/높이 "3d" 기능
rgb9e5ufloat 4 "float",
"unfilterable-float"
1 × 1
bc1-rgba-unorm 8 "float",
"unfilterable-float"
4 × 4 만약 "texture-compression-bc-sliced-3d" 가 활성화되어 있으면 texture-compression-bc
bc1-rgba-unorm-srgb
bc2-rgba-unorm 16
bc2-rgba-unorm-srgb
bc3-rgba-unorm 16
bc3-rgba-unorm-srgb
bc4-r-unorm 8
bc4-r-snorm
bc5-rg-unorm 16
bc5-rg-snorm
bc6h-rgb-ufloat 16
bc6h-rgb-float
bc7-rgba-unorm 16
bc7-rgba-unorm-srgb
etc2-rgb8unorm 8 "float",
"unfilterable-float"
4 × 4 texture-compression-etc2
etc2-rgb8unorm-srgb
etc2-rgb8a1unorm 8
etc2-rgb8a1unorm-srgb
etc2-rgba8unorm 16
etc2-rgba8unorm-srgb
eac-r11unorm 8
eac-r11snorm
eac-rg11unorm 16
eac-rg11snorm
astc-4x4-unorm 16 "float",
"unfilterable-float"
4 × 4 만약 "texture-compression-astc-sliced-3d" 가 활성화되어 있으면 texture-compression-astc
astc-4x4-unorm-srgb
astc-5x4-unorm 16 5 × 4
astc-5x4-unorm-srgb
astc-5x5-unorm 16 5 × 5
astc-5x5-unorm-srgb
astc-6x5-unorm 16 6 × 5
astc-6x5-unorm-srgb
astc-6x6-unorm 16 6 × 6
astc-6x6-unorm-srgb
astc-8x5-unorm 16 8 × 5
astc-8x5-unorm-srgb
astc-8x6-unorm 16 8 × 6
astc-8x6-unorm-srgb
astc-8x8-unorm 16 8 × 8
astc-8x8-unorm-srgb
astc-10x5-unorm 16 10 × 5
astc-10x5-unorm-srgb
astc-10x6-unorm 16 10 × 6
astc-10x6-unorm-srgb
astc-10x8-unorm 16 10 × 8
astc-10x8-unorm-srgb
astc-10x10-unorm 16 10 × 10
astc-10x10-unorm-srgb
astc-12x10-unorm 16 12 × 10
astc-12x10-unorm-srgb
astc-12x12-unorm 16 12 × 12
astc-12x12-unorm-srgb

적합성

문서 규약

적합성 요구사항은 설명적 단언과 RFC 2119 용어의 조합으로 표현됩니다. “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL”과 같은 주요 단어들은 이 문서의 규범적인 부분에서 RFC 2119에 설명된 대로 해석되어야 합니다. 다만, 가독성을 위해 이 단어들은 이 명세에서 모두 대문자로 나타나지 않습니다.

명시적으로 비규범적, 예시, 또는 주석으로 표시된 섹션을 제외하면 이 명세의 모든 텍스트는 규범적입니다. [RFC2119]

이 명세서의 예시는 “for example”이라는 단어로 소개되거나, class="example"로 규범적 텍스트와 구분되어 표시됩니다. 예시는 다음과 같습니다:

이것은 정보 예시의 한 예입니다.

정보성 주석은 “Note”라는 단어로 시작하며, class="note"로 규범적 텍스트와 구분되어 표시됩니다. 예시는 다음과 같습니다:

Note, 이것은 정보성 주석입니다.

적합한 알고리즘

알고리즘의 일부로 명령문으로 표현된 요구사항(예: "앞의 공백 문자를 제거한다" 또는 "false를 반환하고 이 단계를 중단한다")은 알고리즘을 소개하는데 사용된 주요 단어("must", "should", "may" 등)의 의미로 해석되어야 합니다.

알고리즘이나 특정 단계로 표현된 적합성 요구사항은 최종 결과가 동일하다면 어떤 방식으로든 구현할 수 있습니다. 특히, 이 명세서에 정의된 알고리즘은 이해하기 쉽도록 작성된 것이며 성능을 고려한 것이 아닙니다. 구현자는 최적화를 권장합니다.

색인

이 명세서에서 정의된 용어

참조로 정의된 용어

참고문헌

규범적 참고문헌

[DOM]
Anne van Kesteren. DOM 표준. 현행 표준. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 언어 명세. URL: https://tc39.es/ecma262/multipage/
[HR-TIME-3]
Yoav Weiss. 고해상도 시간. 2024년 11월 7일. WD. URL: https://www.w3.org/TR/hr-time-3/
[HTML]
Anne van Kesteren; et al. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[I18N-GLOSSARY]
Richard Ishida; Addison Phillips. 국제화 용어집. 2024년 10월 17일. NOTE. URL: https://www.w3.org/TR/i18n-glossary/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. RFC에서 요구 수준을 표시하기 위한 핵심 단어. 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBCODECS]
Paul Adenot; Eugene Zemtsov. WebCodecs. 2025년 7월 8일. WD. URL: https://www.w3.org/TR/webcodecs/
[WEBGL-1]
Dean Jackson; Jeff Gilbert. WebGL 명세, 버전 1.0. 2017년 8월 9일. URL: https://www.khronos.org/registry/webgl/specs/latest/1.0/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/
[WEBXR]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR 디바이스 API. 2025년 4월 17일. CRD. URL: https://www.w3.org/TR/webxr/
[WGSL]
Alan Baker; Mehmet Oguz Derin; David Neto. WebGPU 셰이딩 언어. 2025년 8월 9일. CRD. URL: https://www.w3.org/TR/WGSL/

비규범적 참고문헌

[MEDIAQUERIES-5]
Dean Jackson; et al. 미디어 쿼리 레벨 5. 2021년 12월 18일. WD. URL: https://www.w3.org/TR/mediaqueries-5/
[SERVICE-WORKERS]
Yoshisato Yanagisawa; Monica CHINTALA. 서비스 워커. 2025년 3월 6일. CRD. URL: https://www.w3.org/TR/service-workers/
[VULKAN]
The Khronos Vulkan Working Group. Vulkan 1.3. URL: https://registry.khronos.org/vulkan/specs/1.3/html/vkspec.html

IDL 색인

interface mixin GPUObjectBase {
    attribute USVString label;
};

dictionary GPUObjectDescriptorBase {
    USVString label = "";
};

[Exposed=(Window, Worker), SecureContext]
interface GPUSupportedLimits {
    readonly attribute unsigned long maxTextureDimension1D;
    readonly attribute unsigned long maxTextureDimension2D;
    readonly attribute unsigned long maxTextureDimension3D;
    readonly attribute unsigned long maxTextureArrayLayers;
    readonly attribute unsigned long maxBindGroups;
    readonly attribute unsigned long maxBindGroupsPlusVertexBuffers;
    readonly attribute unsigned long maxBindingsPerBindGroup;
    readonly attribute unsigned long maxDynamicUniformBuffersPerPipelineLayout;
    readonly attribute unsigned long maxDynamicStorageBuffersPerPipelineLayout;
    readonly attribute unsigned long maxSampledTexturesPerShaderStage;
    readonly attribute unsigned long maxSamplersPerShaderStage;
    readonly attribute unsigned long maxStorageBuffersPerShaderStage;
    readonly attribute unsigned long maxStorageTexturesPerShaderStage;
    readonly attribute unsigned long maxUniformBuffersPerShaderStage;
    readonly attribute unsigned long long maxUniformBufferBindingSize;
    readonly attribute unsigned long long maxStorageBufferBindingSize;
    readonly attribute unsigned long minUniformBufferOffsetAlignment;
    readonly attribute unsigned long minStorageBufferOffsetAlignment;
    readonly attribute unsigned long maxVertexBuffers;
    readonly attribute unsigned long long maxBufferSize;
    readonly attribute unsigned long maxVertexAttributes;
    readonly attribute unsigned long maxVertexBufferArrayStride;
    readonly attribute unsigned long maxInterStageShaderVariables;
    readonly attribute unsigned long maxColorAttachments;
    readonly attribute unsigned long maxColorAttachmentBytesPerSample;
    readonly attribute unsigned long maxComputeWorkgroupStorageSize;
    readonly attribute unsigned long maxComputeInvocationsPerWorkgroup;
    readonly attribute unsigned long maxComputeWorkgroupSizeX;
    readonly attribute unsigned long maxComputeWorkgroupSizeY;
    readonly attribute unsigned long maxComputeWorkgroupSizeZ;
    readonly attribute unsigned long maxComputeWorkgroupsPerDimension;
};

[Exposed=(Window, Worker), SecureContext]
interface GPUSupportedFeatures {
    readonly setlike<DOMString>;
};

[Exposed=(Window, Worker), SecureContext]
interface WGSLLanguageFeatures {
    readonly setlike<DOMString>;
};

[Exposed=(Window, Worker), SecureContext]
interface GPUAdapterInfo {
    readonly attribute DOMString vendor;
    readonly attribute DOMString architecture;
    readonly attribute DOMString device;
    readonly attribute DOMString description;
    readonly attribute unsigned long subgroupMinSize;
    readonly attribute unsigned long subgroupMaxSize;
    readonly attribute boolean isFallbackAdapter;
};

interface mixin NavigatorGPU {
    [SameObject, SecureContext] readonly attribute GPU gpu;
};
Navigator includes NavigatorGPU;
WorkerNavigator includes NavigatorGPU;

[Exposed=(Window, Worker), SecureContext]
interface GPU {
    Promise<GPUAdapter?> requestAdapter(optional GPURequestAdapterOptions options = {});
    GPUTextureFormat getPreferredCanvasFormat();
    [SameObject] readonly attribute WGSLLanguageFeatures wgslLanguageFeatures;
};

dictionary GPURequestAdapterOptions {
    DOMString featureLevel = "core";
    GPUPowerPreference powerPreference;
    boolean forceFallbackAdapter = false;
    boolean xrCompatible = false;
};

enum GPUPowerPreference {
    "low-power",
    "high-performance",
};

[Exposed=(Window, Worker), SecureContext]
interface GPUAdapter {
    [SameObject] readonly attribute GPUSupportedFeatures features;
    [SameObject] readonly attribute GPUSupportedLimits limits;
    [SameObject] readonly attribute GPUAdapterInfo info;

    Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
};

dictionary GPUDeviceDescriptor
         : GPUObjectDescriptorBase {
    sequence<GPUFeatureName> requiredFeatures = [];
    record<DOMString, (GPUSize64 or undefined)> requiredLimits = {};
    GPUQueueDescriptor defaultQueue = {};
};

enum GPUFeatureName {
    "core-features-and-limits",
    "depth-clip-control",
    "depth32float-stencil8",
    "texture-compression-bc",
    "texture-compression-bc-sliced-3d",
    "texture-compression-etc2",
    "texture-compression-astc",
    "texture-compression-astc-sliced-3d",
    "timestamp-query",
    "indirect-first-instance",
    "shader-f16",
    "rg11b10ufloat-renderable",
    "bgra8unorm-storage",
    "float32-filterable",
    "float32-blendable",
    "clip-distances",
    "dual-source-blending",
    "subgroups",
    "texture-formats-tier1",
    "texture-formats-tier2",
    "primitive-index",
};

[Exposed=(Window, Worker), SecureContext]
interface GPUDevice : EventTarget {
    [SameObject] readonly attribute GPUSupportedFeatures features;
    [SameObject] readonly attribute GPUSupportedLimits limits;
    [SameObject] readonly attribute GPUAdapterInfo adapterInfo;

    [SameObject] readonly attribute GPUQueue queue;

    undefined destroy();

    GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
    GPUTexture createTexture(GPUTextureDescriptor descriptor);
    GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
    GPUExternalTexture importExternalTexture(GPUExternalTextureDescriptor descriptor);

    GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
    GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
    GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);

    GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
    GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
    GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
    Promise<GPUComputePipeline> createComputePipelineAsync(GPUComputePipelineDescriptor descriptor);
    Promise<GPURenderPipeline> createRenderPipelineAsync(GPURenderPipelineDescriptor descriptor);

    GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
    GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor);

    GPUQuerySet createQuerySet(GPUQuerySetDescriptor descriptor);
};
GPUDevice includes GPUObjectBase;

[Exposed=(Window, Worker), SecureContext]
interface GPUBuffer {
    readonly attribute GPUSize64Out size;
    readonly attribute GPUFlagsConstant usage;

    readonly attribute GPUBufferMapState mapState;

    Promise<undefined> mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size);
    ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size);
    undefined unmap();

    undefined destroy();
};
GPUBuffer includes GPUObjectBase;

enum GPUBufferMapState {
    "unmapped",
    "pending",
    "mapped",
};

dictionary GPUBufferDescriptor
         : GPUObjectDescriptorBase {
    required GPUSize64 size;
    required GPUBufferUsageFlags usage;
    boolean mappedAtCreation = false;
};

typedef [EnforceRange] unsigned long GPUBufferUsageFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUBufferUsage {
    const GPUFlagsConstant MAP_READ      = 0x0001;
    const GPUFlagsConstant MAP_WRITE     = 0x0002;
    const GPUFlagsConstant COPY_SRC      = 0x0004;
    const GPUFlagsConstant COPY_DST      = 0x0008;
    const GPUFlagsConstant INDEX         = 0x0010;
    const GPUFlagsConstant VERTEX        = 0x0020;
    const GPUFlagsConstant UNIFORM       = 0x0040;
    const GPUFlagsConstant STORAGE       = 0x0080;
    const GPUFlagsConstant INDIRECT      = 0x0100;
    const GPUFlagsConstant QUERY_RESOLVE = 0x0200;
};

typedef [EnforceRange] unsigned long GPUMapModeFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUMapMode {
    const GPUFlagsConstant READ  = 0x0001;
    const GPUFlagsConstant WRITE = 0x0002;
};

[Exposed=(Window, Worker), SecureContext]
interface GPUTexture {
    GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});

    undefined destroy();

    readonly attribute GPUIntegerCoordinateOut width;
    readonly attribute GPUIntegerCoordinateOut height;
    readonly attribute GPUIntegerCoordinateOut depthOrArrayLayers;
    readonly attribute GPUIntegerCoordinateOut mipLevelCount;
    readonly attribute GPUSize32Out sampleCount;
    readonly attribute GPUTextureDimension dimension;
    readonly attribute GPUTextureFormat format;
    readonly attribute GPUFlagsConstant usage;
};
GPUTexture includes GPUObjectBase;

dictionary GPUTextureDescriptor
         : GPUObjectDescriptorBase {
    required GPUExtent3D size;
    GPUIntegerCoordinate mipLevelCount = 1;
    GPUSize32 sampleCount = 1;
    GPUTextureDimension dimension = "2d";
    required GPUTextureFormat format;
    required GPUTextureUsageFlags usage;
    sequence<GPUTextureFormat> viewFormats = [];
};

enum GPUTextureDimension {
    "1d",
    "2d",
    "3d",
};

typedef [EnforceRange] unsigned long GPUTextureUsageFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUTextureUsage {
    const GPUFlagsConstant COPY_SRC          = 0x01;
    const GPUFlagsConstant COPY_DST          = 0x02;
    const GPUFlagsConstant TEXTURE_BINDING   = 0x04;
    const GPUFlagsConstant STORAGE_BINDING   = 0x08;
    const GPUFlagsConstant RENDER_ATTACHMENT = 0x10;
};

[Exposed=(Window, Worker), SecureContext]
interface GPUTextureView {
};
GPUTextureView includes GPUObjectBase;

dictionary GPUTextureViewDescriptor
         : GPUObjectDescriptorBase {
    GPUTextureFormat format;
    GPUTextureViewDimension dimension;
    GPUTextureUsageFlags usage = 0;
    GPUTextureAspect aspect = "all";
    GPUIntegerCoordinate baseMipLevel = 0;
    GPUIntegerCoordinate mipLevelCount;
    GPUIntegerCoordinate baseArrayLayer = 0;
    GPUIntegerCoordinate arrayLayerCount;
};

enum GPUTextureViewDimension {
    "1d",
    "2d",
    "2d-array",
    "cube",
    "cube-array",
    "3d",
};

enum GPUTextureAspect {
    "all",
    "stencil-only",
    "depth-only",
};

enum GPUTextureFormat {
    // 8-bit formats
    "r8unorm",
    "r8snorm",
    "r8uint",
    "r8sint",

    // 16-bit formats
    "r16unorm",
    "r16snorm",
    "r16uint",
    "r16sint",
    "r16float",
    "rg8unorm",
    "rg8snorm",
    "rg8uint",
    "rg8sint",

    // 32-bit formats
    "r32uint",
    "r32sint",
    "r32float",
    "rg16unorm",
    "rg16snorm",
    "rg16uint",
    "rg16sint",
    "rg16float",
    "rgba8unorm",
    "rgba8unorm-srgb",
    "rgba8snorm",
    "rgba8uint",
    "rgba8sint",
    "bgra8unorm",
    "bgra8unorm-srgb",
    // Packed 32-bit formats
    "rgb9e5ufloat",
    "rgb10a2uint",
    "rgb10a2unorm",
    "rg11b10ufloat",

    // 64-bit formats
    "rg32uint",
    "rg32sint",
    "rg32float",
    "rgba16unorm",
    "rgba16snorm",
    "rgba16uint",
    "rgba16sint",
    "rgba16float",

    // 128-bit formats
    "rgba32uint",
    "rgba32sint",
    "rgba32float",

    // Depth/stencil formats
    "stencil8",
    "depth16unorm",
    "depth24plus",
    "depth24plus-stencil8",
    "depth32float",

    // "depth32float-stencil8" feature
    "depth32float-stencil8",

    // BC compressed formats usable if "texture-compression-bc" is both
    // supported by the device/user agent and enabled in requestDevice.
    "bc1-rgba-unorm",
    "bc1-rgba-unorm-srgb",
    "bc2-rgba-unorm",
    "bc2-rgba-unorm-srgb",
    "bc3-rgba-unorm",
    "bc3-rgba-unorm-srgb",
    "bc4-r-unorm",
    "bc4-r-snorm",
    "bc5-rg-unorm",
    "bc5-rg-snorm",
    "bc6h-rgb-ufloat",
    "bc6h-rgb-float",
    "bc7-rgba-unorm",
    "bc7-rgba-unorm-srgb",

    // ETC2 compressed formats usable if "texture-compression-etc2" is both
    // supported by the device/user agent and enabled in requestDevice.
    "etc2-rgb8unorm",
    "etc2-rgb8unorm-srgb",
    "etc2-rgb8a1unorm",
    "etc2-rgb8a1unorm-srgb",
    "etc2-rgba8unorm",
    "etc2-rgba8unorm-srgb",
    "eac-r11unorm",
    "eac-r11snorm",
    "eac-rg11unorm",
    "eac-rg11snorm",

    // ASTC compressed formats usable if "texture-compression-astc" is both
    // supported by the device/user agent and enabled in requestDevice.
    "astc-4x4-unorm",
    "astc-4x4-unorm-srgb",
    "astc-5x4-unorm",
    "astc-5x4-unorm-srgb",
    "astc-5x5-unorm",
    "astc-5x5-unorm-srgb",
    "astc-6x5-unorm",
    "astc-6x5-unorm-srgb",
    "astc-6x6-unorm",
    "astc-6x6-unorm-srgb",
    "astc-8x5-unorm",
    "astc-8x5-unorm-srgb",
    "astc-8x6-unorm",
    "astc-8x6-unorm-srgb",
    "astc-8x8-unorm",
    "astc-8x8-unorm-srgb",
    "astc-10x5-unorm",
    "astc-10x5-unorm-srgb",
    "astc-10x6-unorm",
    "astc-10x6-unorm-srgb",
    "astc-10x8-unorm",
    "astc-10x8-unorm-srgb",
    "astc-10x10-unorm",
    "astc-10x10-unorm-srgb",
    "astc-12x10-unorm",
    "astc-12x10-unorm-srgb",
    "astc-12x12-unorm",
    "astc-12x12-unorm-srgb",
};

[Exposed=(Window, Worker), SecureContext]
interface GPUExternalTexture {
};
GPUExternalTexture includes GPUObjectBase;

dictionary GPUExternalTextureDescriptor
         : GPUObjectDescriptorBase {
    required (HTMLVideoElement or VideoFrame) source;
    PredefinedColorSpace colorSpace = "srgb";
};

[Exposed=(Window, Worker), SecureContext]
interface GPUSampler {
};
GPUSampler includes GPUObjectBase;

dictionary GPUSamplerDescriptor
         : GPUObjectDescriptorBase {
    GPUAddressMode addressModeU = "clamp-to-edge";
    GPUAddressMode addressModeV = "clamp-to-edge";
    GPUAddressMode addressModeW = "clamp-to-edge";
    GPUFilterMode magFilter = "nearest";
    GPUFilterMode minFilter = "nearest";
    GPUMipmapFilterMode mipmapFilter = "nearest";
    float lodMinClamp = 0;
    float lodMaxClamp = 32;
    GPUCompareFunction compare;
    [Clamp] unsigned short maxAnisotropy = 1;
};

enum GPUAddressMode {
    "clamp-to-edge",
    "repeat",
    "mirror-repeat",
};

enum GPUFilterMode {
    "nearest",
    "linear",
};

enum GPUMipmapFilterMode {
    "nearest",
    "linear",
};

enum GPUCompareFunction {
    "never",
    "less",
    "equal",
    "less-equal",
    "greater",
    "not-equal",
    "greater-equal",
    "always",
};

[Exposed=(Window, Worker), SecureContext]
interface GPUBindGroupLayout {
};
GPUBindGroupLayout includes GPUObjectBase;

dictionary GPUBindGroupLayoutDescriptor
         : GPUObjectDescriptorBase {
    required sequence<GPUBindGroupLayoutEntry> entries;
};

dictionary GPUBindGroupLayoutEntry {
    required GPUIndex32 binding;
    required GPUShaderStageFlags visibility;

    GPUBufferBindingLayout buffer;
    GPUSamplerBindingLayout sampler;
    GPUTextureBindingLayout texture;
    GPUStorageTextureBindingLayout storageTexture;
    GPUExternalTextureBindingLayout externalTexture;
};

typedef [EnforceRange] unsigned long GPUShaderStageFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUShaderStage {
    const GPUFlagsConstant VERTEX   = 0x1;
    const GPUFlagsConstant FRAGMENT = 0x2;
    const GPUFlagsConstant COMPUTE  = 0x4;
};

enum GPUBufferBindingType {
    "uniform",
    "storage",
    "read-only-storage",
};

dictionary GPUBufferBindingLayout {
    GPUBufferBindingType type = "uniform";
    boolean hasDynamicOffset = false;
    GPUSize64 minBindingSize = 0;
};

enum GPUSamplerBindingType {
    "filtering",
    "non-filtering",
    "comparison",
};

dictionary GPUSamplerBindingLayout {
    GPUSamplerBindingType type = "filtering";
};

enum GPUTextureSampleType {
    "float",
    "unfilterable-float",
    "depth",
    "sint",
    "uint",
};

dictionary GPUTextureBindingLayout {
    GPUTextureSampleType sampleType = "float";
    GPUTextureViewDimension viewDimension = "2d";
    boolean multisampled = false;
};

enum GPUStorageTextureAccess {
    "write-only",
    "read-only",
    "read-write",
};

dictionary GPUStorageTextureBindingLayout {
    GPUStorageTextureAccess access = "write-only";
    required GPUTextureFormat format;
    GPUTextureViewDimension viewDimension = "2d";
};

dictionary GPUExternalTextureBindingLayout {
};

[Exposed=(Window, Worker), SecureContext]
interface GPUBindGroup {
};
GPUBindGroup includes GPUObjectBase;

dictionary GPUBindGroupDescriptor
         : GPUObjectDescriptorBase {
    required GPUBindGroupLayout layout;
    required sequence<GPUBindGroupEntry> entries;
};

typedef (GPUSampler or
         GPUTexture or
         GPUTextureView or
         GPUBuffer or
         GPUBufferBinding or
         GPUExternalTexture) GPUBindingResource;

dictionary GPUBindGroupEntry {
    required GPUIndex32 binding;
    required GPUBindingResource resource;
};

dictionary GPUBufferBinding {
    required GPUBuffer buffer;
    GPUSize64 offset = 0;
    GPUSize64 size;
};

[Exposed=(Window, Worker), SecureContext]
interface GPUPipelineLayout {
};
GPUPipelineLayout includes GPUObjectBase;

dictionary GPUPipelineLayoutDescriptor
         : GPUObjectDescriptorBase {
    required sequence<GPUBindGroupLayout?> bindGroupLayouts;
};

[Exposed=(Window, Worker), SecureContext]
interface GPUShaderModule {
    Promise<GPUCompilationInfo> getCompilationInfo();
};
GPUShaderModule includes GPUObjectBase;

dictionary GPUShaderModuleDescriptor
         : GPUObjectDescriptorBase {
    required USVString code;
    sequence<GPUShaderModuleCompilationHint> compilationHints = [];
};

dictionary GPUShaderModuleCompilationHint {
    required USVString entryPoint;
    (GPUPipelineLayout or GPUAutoLayoutMode) layout;
};

enum GPUCompilationMessageType {
    "error",
    "warning",
    "info",
};

[Exposed=(Window, Worker), Serializable, SecureContext]
interface GPUCompilationMessage {
    readonly attribute DOMString message;
    readonly attribute GPUCompilationMessageType type;
    readonly attribute unsigned long long lineNum;
    readonly attribute unsigned long long linePos;
    readonly attribute unsigned long long offset;
    readonly attribute unsigned long long length;
};

[Exposed=(Window, Worker), Serializable, SecureContext]
interface GPUCompilationInfo {
    readonly attribute FrozenArray<GPUCompilationMessage> messages;
};

[Exposed=(Window, Worker), SecureContext, Serializable]
interface GPUPipelineError : DOMException {
    constructor(optional DOMString message = "", GPUPipelineErrorInit options);
    readonly attribute GPUPipelineErrorReason reason;
};

dictionary GPUPipelineErrorInit {
    required GPUPipelineErrorReason reason;
};

enum GPUPipelineErrorReason {
    "validation",
    "internal",
};

enum GPUAutoLayoutMode {
    "auto",
};

dictionary GPUPipelineDescriptorBase
         : GPUObjectDescriptorBase {
    required (GPUPipelineLayout or GPUAutoLayoutMode) layout;
};

interface mixin GPUPipelineBase {
    [NewObject] GPUBindGroupLayout getBindGroupLayout(unsigned long index);
};

dictionary GPUProgrammableStage {
    required GPUShaderModule module;
    USVString entryPoint;
    record<USVString, GPUPipelineConstantValue> constants = {};
};

typedef double GPUPipelineConstantValue; // May represent WGSL's bool, f32, i32, u32, and f16 if enabled.

[Exposed=(Window, Worker), SecureContext]
interface GPUComputePipeline {
};
GPUComputePipeline includes GPUObjectBase;
GPUComputePipeline includes GPUPipelineBase;

dictionary GPUComputePipelineDescriptor
         : GPUPipelineDescriptorBase {
    required GPUProgrammableStage compute;
};

[Exposed=(Window, Worker), SecureContext]
interface GPURenderPipeline {
};
GPURenderPipeline includes GPUObjectBase;
GPURenderPipeline includes GPUPipelineBase;

dictionary GPURenderPipelineDescriptor
         : GPUPipelineDescriptorBase {
    required GPUVertexState vertex;
    GPUPrimitiveState primitive = {};
    GPUDepthStencilState depthStencil;
    GPUMultisampleState multisample = {};
    GPUFragmentState fragment;
};

dictionary GPUPrimitiveState {
    GPUPrimitiveTopology topology = "triangle-list";
    GPUIndexFormat stripIndexFormat;
    GPUFrontFace frontFace = "ccw";
    GPUCullMode cullMode = "none";

    // Requires "depth-clip-control" feature.
    boolean unclippedDepth = false;
};

enum GPUPrimitiveTopology {
    "point-list",
    "line-list",
    "line-strip",
    "triangle-list",
    "triangle-strip",
};

enum GPUFrontFace {
    "ccw",
    "cw",
};

enum GPUCullMode {
    "none",
    "front",
    "back",
};

dictionary GPUMultisampleState {
    GPUSize32 count = 1;
    GPUSampleMask mask = 0xFFFFFFFF;
    boolean alphaToCoverageEnabled = false;
};

dictionary GPUFragmentState
         : GPUProgrammableStage {
    required sequence<GPUColorTargetState?> targets;
};

dictionary GPUColorTargetState {
    required GPUTextureFormat format;

    GPUBlendState blend;
    GPUColorWriteFlags writeMask = 0xF;  // GPUColorWrite.ALL
};

dictionary GPUBlendState {
    required GPUBlendComponent color;
    required GPUBlendComponent alpha;
};

typedef [EnforceRange] unsigned long GPUColorWriteFlags;
[Exposed=(Window, Worker), SecureContext]
namespace GPUColorWrite {
    const GPUFlagsConstant RED   = 0x1;
    const GPUFlagsConstant GREEN = 0x2;
    const GPUFlagsConstant BLUE  = 0x4;
    const GPUFlagsConstant ALPHA = 0x8;
    const GPUFlagsConstant ALL   = 0xF;
};

dictionary GPUBlendComponent {
    GPUBlendOperation operation = "add";
    GPUBlendFactor srcFactor = "one";
    GPUBlendFactor dstFactor = "zero";
};

enum GPUBlendFactor {
    "zero",
    "one",
    "src",
    "one-minus-src",
    "src-alpha",
    "one-minus-src-alpha",
    "dst",
    "one-minus-dst",
    "dst-alpha",
    "one-minus-dst-alpha",
    "src-alpha-saturated",
    "constant",
    "one-minus-constant",
    "src1",
    "one-minus-src1",
    "src1-alpha",
    "one-minus-src1-alpha",
};

enum GPUBlendOperation {
    "add",
    "subtract",
    "reverse-subtract",
    "min",
    "max",
};

dictionary GPUDepthStencilState {
    required GPUTextureFormat format;

    boolean depthWriteEnabled;
    GPUCompareFunction depthCompare;

    GPUStencilFaceState stencilFront = {};
    GPUStencilFaceState stencilBack = {};

    GPUStencilValue stencilReadMask = 0xFFFFFFFF;
    GPUStencilValue stencilWriteMask = 0xFFFFFFFF;

    GPUDepthBias depthBias = 0;
    float depthBiasSlopeScale = 0;
    float depthBiasClamp = 0;
};

dictionary GPUStencilFaceState {
    GPUCompareFunction compare = "always";
    GPUStencilOperation failOp = "keep";
    GPUStencilOperation depthFailOp = "keep";
    GPUStencilOperation passOp = "keep";
};

enum GPUStencilOperation {
    "keep",
    "zero",
    "replace",
    "invert",
    "increment-clamp",
    "decrement-clamp",
    "increment-wrap",
    "decrement-wrap",
};

enum GPUIndexFormat {
    "uint16",
    "uint32",
};

enum GPUVertexFormat {
    "uint8",
    "uint8x2",
    "uint8x4",
    "sint8",
    "sint8x2",
    "sint8x4",
    "unorm8",
    "unorm8x2",
    "unorm8x4",
    "snorm8",
    "snorm8x2",
    "snorm8x4",
    "uint16",
    "uint16x2",
    "uint16x4",
    "sint16",
    "sint16x2",
    "sint16x4",
    "unorm16",
    "unorm16x2",
    "unorm16x4",
    "snorm16",
    "snorm16x2",
    "snorm16x4",
    "float16",
    "float16x2",
    "float16x4",
    "float32",
    "float32x2",
    "float32x3",
    "float32x4",
    "uint32",
    "uint32x2",
    "uint32x3",
    "uint32x4",
    "sint32",
    "sint32x2",
    "sint32x3",
    "sint32x4",
    "unorm10-10-10-2",
    "unorm8x4-bgra",
};

enum GPUVertexStepMode {
    "vertex",
    "instance",
};

dictionary GPUVertexState
         : GPUProgrammableStage {
    sequence<GPUVertexBufferLayout?> buffers = [];
};

dictionary GPUVertexBufferLayout {
    required GPUSize64 arrayStride;
    GPUVertexStepMode stepMode = "vertex";
    required sequence<GPUVertexAttribute> attributes;
};

dictionary GPUVertexAttribute {
    required GPUVertexFormat format;
    required GPUSize64 offset;

    required GPUIndex32 shaderLocation;
};

dictionary GPUTexelCopyBufferLayout {
    GPUSize64 offset = 0;
    GPUSize32 bytesPerRow;
    GPUSize32 rowsPerImage;
};

dictionary GPUTexelCopyBufferInfo
         : GPUTexelCopyBufferLayout {
    required GPUBuffer buffer;
};

dictionary GPUTexelCopyTextureInfo {
    required GPUTexture texture;
    GPUIntegerCoordinate mipLevel = 0;
    GPUOrigin3D origin = {};
    GPUTextureAspect aspect = "all";
};

dictionary GPUCopyExternalImageDestInfo
         : GPUTexelCopyTextureInfo {
    PredefinedColorSpace colorSpace = "srgb";
    boolean premultipliedAlpha = false;
};

typedef (ImageBitmap or
         ImageData or
         HTMLImageElement or
         HTMLVideoElement or
         VideoFrame or
         HTMLCanvasElement or
         OffscreenCanvas) GPUCopyExternalImageSource;

dictionary GPUCopyExternalImageSourceInfo {
    required GPUCopyExternalImageSource source;
    GPUOrigin2D origin = {};
    boolean flipY = false;
};

[Exposed=(Window, Worker), SecureContext]
interface GPUCommandBuffer {
};
GPUCommandBuffer includes GPUObjectBase;

dictionary GPUCommandBufferDescriptor
         : GPUObjectDescriptorBase {
};

interface mixin GPUCommandsMixin {
};

[Exposed=(Window, Worker), SecureContext]
interface GPUCommandEncoder {
    GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
    GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {});

    undefined copyBufferToBuffer(
        GPUBuffer source,
        GPUBuffer destination,
        optional GPUSize64 size);
    undefined copyBufferToBuffer(
        GPUBuffer source,
        GPUSize64 sourceOffset,
        GPUBuffer destination,
        GPUSize64 destinationOffset,
        optional GPUSize64 size);

    undefined copyBufferToTexture(
        GPUTexelCopyBufferInfo source,
        GPUTexelCopyTextureInfo destination,
        GPUExtent3D copySize);

    undefined copyTextureToBuffer(
        GPUTexelCopyTextureInfo source,
        GPUTexelCopyBufferInfo destination,
        GPUExtent3D copySize);

    undefined copyTextureToTexture(
        GPUTexelCopyTextureInfo source,
        GPUTexelCopyTextureInfo destination,
        GPUExtent3D copySize);

    undefined clearBuffer(
        GPUBuffer buffer,
        optional GPUSize64 offset = 0,
        optional GPUSize64 size);

    undefined resolveQuerySet(
        GPUQuerySet querySet,
        GPUSize32 firstQuery,
        GPUSize32 queryCount,
        GPUBuffer destination,
        GPUSize64 destinationOffset);

    GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {});
};
GPUCommandEncoder includes GPUObjectBase;
GPUCommandEncoder includes GPUCommandsMixin;
GPUCommandEncoder includes GPUDebugCommandsMixin;

dictionary GPUCommandEncoderDescriptor
         : GPUObjectDescriptorBase {
};

interface mixin GPUBindingCommandsMixin {
    undefined setBindGroup(GPUIndex32 index, GPUBindGroup? bindGroup,
        optional sequence<GPUBufferDynamicOffset> dynamicOffsets = []);

    undefined setBindGroup(GPUIndex32 index, GPUBindGroup? bindGroup,
        [AllowShared] Uint32Array dynamicOffsetsData,
        GPUSize64 dynamicOffsetsDataStart,
        GPUSize32 dynamicOffsetsDataLength);
};

interface mixin GPUDebugCommandsMixin {
    undefined pushDebugGroup(USVString groupLabel);
    undefined popDebugGroup();
    undefined insertDebugMarker(USVString markerLabel);
};

[Exposed=(Window, Worker), SecureContext]
interface GPUComputePassEncoder {
    undefined setPipeline(GPUComputePipeline pipeline);
    undefined dispatchWorkgroups(GPUSize32 workgroupCountX, optional GPUSize32 workgroupCountY = 1, optional GPUSize32 workgroupCountZ = 1);
    undefined dispatchWorkgroupsIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);

    undefined end();
};
GPUComputePassEncoder includes GPUObjectBase;
GPUComputePassEncoder includes GPUCommandsMixin;
GPUComputePassEncoder includes GPUDebugCommandsMixin;
GPUComputePassEncoder includes GPUBindingCommandsMixin;

dictionary GPUComputePassTimestampWrites {
    required GPUQuerySet querySet;
    GPUSize32 beginningOfPassWriteIndex;
    GPUSize32 endOfPassWriteIndex;
};

dictionary GPUComputePassDescriptor
         : GPUObjectDescriptorBase {
    GPUComputePassTimestampWrites timestampWrites;
};

[Exposed=(Window, Worker), SecureContext]
interface GPURenderPassEncoder {
    undefined setViewport(float x, float y,
        float width, float height,
        float minDepth, float maxDepth);

    undefined setScissorRect(GPUIntegerCoordinate x, GPUIntegerCoordinate y,
                        GPUIntegerCoordinate width, GPUIntegerCoordinate height);

    undefined setBlendConstant(GPUColor color);
    undefined setStencilReference(GPUStencilValue reference);

    undefined beginOcclusionQuery(GPUSize32 queryIndex);
    undefined endOcclusionQuery();

    undefined executeBundles(sequence<GPURenderBundle> bundles);
    undefined end();
};
GPURenderPassEncoder includes GPUObjectBase;
GPURenderPassEncoder includes GPUCommandsMixin;
GPURenderPassEncoder includes GPUDebugCommandsMixin;
GPURenderPassEncoder includes GPUBindingCommandsMixin;
GPURenderPassEncoder includes GPURenderCommandsMixin;

dictionary GPURenderPassTimestampWrites {
    required GPUQuerySet querySet;
    GPUSize32 beginningOfPassWriteIndex;
    GPUSize32 endOfPassWriteIndex;
};

dictionary GPURenderPassDescriptor
         : GPUObjectDescriptorBase {
    required sequence<GPURenderPassColorAttachment?> colorAttachments;
    GPURenderPassDepthStencilAttachment depthStencilAttachment;
    GPUQuerySet occlusionQuerySet;
    GPURenderPassTimestampWrites timestampWrites;
    GPUSize64 maxDrawCount = 50000000;
};

dictionary GPURenderPassColorAttachment {
    required (GPUTexture or GPUTextureView) view;
    GPUIntegerCoordinate depthSlice;
    (GPUTexture or GPUTextureView) resolveTarget;

    GPUColor clearValue;
    required GPULoadOp loadOp;
    required GPUStoreOp storeOp;
};

dictionary GPURenderPassDepthStencilAttachment {
    required (GPUTexture or GPUTextureView) view;

    float depthClearValue;
    GPULoadOp depthLoadOp;
    GPUStoreOp depthStoreOp;
    boolean depthReadOnly = false;

    GPUStencilValue stencilClearValue = 0;
    GPULoadOp stencilLoadOp;
    GPUStoreOp stencilStoreOp;
    boolean stencilReadOnly = false;
};

enum GPULoadOp {
    "load",
    "clear",
};

enum GPUStoreOp {
    "store",
    "discard",
};

dictionary GPURenderPassLayout
         : GPUObjectDescriptorBase {
    required sequence<GPUTextureFormat?> colorFormats;
    GPUTextureFormat depthStencilFormat;
    GPUSize32 sampleCount = 1;
};

interface mixin GPURenderCommandsMixin {
    undefined setPipeline(GPURenderPipeline pipeline);

    undefined setIndexBuffer(GPUBuffer buffer, GPUIndexFormat indexFormat, optional GPUSize64 offset = 0, optional GPUSize64 size);
    undefined setVertexBuffer(GPUIndex32 slot, GPUBuffer? buffer, optional GPUSize64 offset = 0, optional GPUSize64 size);

    undefined draw(GPUSize32 vertexCount, optional GPUSize32 instanceCount = 1,
        optional GPUSize32 firstVertex = 0, optional GPUSize32 firstInstance = 0);
    undefined drawIndexed(GPUSize32 indexCount, optional GPUSize32 instanceCount = 1,
        optional GPUSize32 firstIndex = 0,
        optional GPUSignedOffset32 baseVertex = 0,
        optional GPUSize32 firstInstance = 0);

    undefined drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
    undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
};

[Exposed=(Window, Worker), SecureContext]
interface GPURenderBundle {
};
GPURenderBundle includes GPUObjectBase;

dictionary GPURenderBundleDescriptor
         : GPUObjectDescriptorBase {
};

[Exposed=(Window, Worker), SecureContext]
interface GPURenderBundleEncoder {
    GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {});
};
GPURenderBundleEncoder includes GPUObjectBase;
GPURenderBundleEncoder includes GPUCommandsMixin;
GPURenderBundleEncoder includes GPUDebugCommandsMixin;
GPURenderBundleEncoder includes GPUBindingCommandsMixin;
GPURenderBundleEncoder includes GPURenderCommandsMixin;

dictionary GPURenderBundleEncoderDescriptor
         : GPURenderPassLayout {
    boolean depthReadOnly = false;
    boolean stencilReadOnly = false;
};

dictionary GPUQueueDescriptor
         : GPUObjectDescriptorBase {
};

[Exposed=(Window, Worker), SecureContext]
interface GPUQueue {
    undefined submit(sequence<GPUCommandBuffer> commandBuffers);

    Promise<undefined> onSubmittedWorkDone();

    undefined writeBuffer(
        GPUBuffer buffer,
        GPUSize64 bufferOffset,
        AllowSharedBufferSource data,
        optional GPUSize64 dataOffset = 0,
        optional GPUSize64 size);

    undefined writeTexture(
        GPUTexelCopyTextureInfo destination,
        AllowSharedBufferSource data,
        GPUTexelCopyBufferLayout dataLayout,
        GPUExtent3D size);

    undefined copyExternalImageToTexture(
        GPUCopyExternalImageSourceInfo source,
        GPUCopyExternalImageDestInfo destination,
        GPUExtent3D copySize);
};
GPUQueue includes GPUObjectBase;

[Exposed=(Window, Worker), SecureContext]
interface GPUQuerySet {
    undefined destroy();

    readonly attribute GPUQueryType type;
    readonly attribute GPUSize32Out count;
};
GPUQuerySet includes GPUObjectBase;

dictionary GPUQuerySetDescriptor
         : GPUObjectDescriptorBase {
    required GPUQueryType type;
    required GPUSize32 count;
};

enum GPUQueryType {
    "occlusion",
    "timestamp",
};

[Exposed=(Window, Worker), SecureContext]
interface GPUCanvasContext {
    readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas;

    undefined configure(GPUCanvasConfiguration configuration);
    undefined unconfigure();

    GPUCanvasConfiguration? getConfiguration();
    GPUTexture getCurrentTexture();
};

enum GPUCanvasAlphaMode {
    "opaque",
    "premultiplied",
};

enum GPUCanvasToneMappingMode {
    "standard",
    "extended",
};

dictionary GPUCanvasToneMapping {
  GPUCanvasToneMappingMode mode = "standard";
};

dictionary GPUCanvasConfiguration {
    required GPUDevice device;
    required GPUTextureFormat format;
    GPUTextureUsageFlags usage = 0x10;  // GPUTextureUsage.RENDER_ATTACHMENT
    sequence<GPUTextureFormat> viewFormats = [];
    PredefinedColorSpace colorSpace = "srgb";
    GPUCanvasToneMapping toneMapping = {};
    GPUCanvasAlphaMode alphaMode = "opaque";
};

enum GPUDeviceLostReason {
    "unknown",
    "destroyed",
};

[Exposed=(Window, Worker), SecureContext]
interface GPUDeviceLostInfo {
    readonly attribute GPUDeviceLostReason reason;
    readonly attribute DOMString message;
};

partial interface GPUDevice {
    readonly attribute Promise<GPUDeviceLostInfo> lost;
};

[Exposed=(Window, Worker), SecureContext]
interface GPUError {
    readonly attribute DOMString message;
};

[Exposed=(Window, Worker), SecureContext]
interface GPUValidationError
        : GPUError {
    constructor(DOMString message);
};

[Exposed=(Window, Worker), SecureContext]
interface GPUOutOfMemoryError
        : GPUError {
    constructor(DOMString message);
};

[Exposed=(Window, Worker), SecureContext]
interface GPUInternalError
        : GPUError {
    constructor(DOMString message);
};

enum GPUErrorFilter {
    "validation",
    "out-of-memory",
    "internal",
};

partial interface GPUDevice {
    undefined pushErrorScope(GPUErrorFilter filter);
    Promise<GPUError?> popErrorScope();
};

[Exposed=(Window, Worker), SecureContext]
interface GPUUncapturedErrorEvent : Event {
    constructor(
        DOMString type,
        GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict
    );
    [SameObject] readonly attribute GPUError error;
};

dictionary GPUUncapturedErrorEventInit : EventInit {
    required GPUError error;
};

partial interface GPUDevice {
    attribute EventHandler onuncapturederror;
};

typedef [EnforceRange] unsigned long GPUBufferDynamicOffset;
typedef [EnforceRange] unsigned long GPUStencilValue;
typedef [EnforceRange] unsigned long GPUSampleMask;
typedef [EnforceRange] long GPUDepthBias;

typedef [EnforceRange] unsigned long long GPUSize64;
typedef [EnforceRange] unsigned long GPUIntegerCoordinate;
typedef [EnforceRange] unsigned long GPUIndex32;
typedef [EnforceRange] unsigned long GPUSize32;
typedef [EnforceRange] long GPUSignedOffset32;

typedef unsigned long long GPUSize64Out;
typedef unsigned long GPUIntegerCoordinateOut;
typedef unsigned long GPUSize32Out;

typedef unsigned long GPUFlagsConstant;

dictionary GPUColorDict {
    required double r;
    required double g;
    required double b;
    required double a;
};
typedef (sequence<double> or GPUColorDict) GPUColor;

dictionary GPUOrigin2DDict {
    GPUIntegerCoordinate x = 0;
    GPUIntegerCoordinate y = 0;
};
typedef (sequence<GPUIntegerCoordinate> or GPUOrigin2DDict) GPUOrigin2D;

dictionary GPUOrigin3DDict {
    GPUIntegerCoordinate x = 0;
    GPUIntegerCoordinate y = 0;
    GPUIntegerCoordinate z = 0;
};
typedef (sequence<GPUIntegerCoordinate> or GPUOrigin3DDict) GPUOrigin3D;

dictionary GPUExtent3DDict {
    required GPUIntegerCoordinate width;
    GPUIntegerCoordinate height = 1;
    GPUIntegerCoordinate depthOrArrayLayers = 1;
};
typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D;