react-native-wgpu 0.2.10 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +155 -69
- package/android/CMakeLists.txt +5 -7
- package/android/build.gradle +7 -18
- package/android/src/main/java/com/webgpu/WebGPUViewPackage.java +34 -10
- package/apple/MetalView.mm +0 -19
- package/apple/WebGPUModule.h +1 -9
- package/apple/WebGPUModule.mm +0 -3
- package/apple/WebGPUView.h +0 -3
- package/apple/WebGPUView.mm +0 -2
- package/cpp/WGPULogger.h +10 -0
- package/cpp/dawn/dawn_proc_table.h +1 -1
- package/cpp/dawn/webgpu.h +4855 -0
- package/cpp/dawn/webgpu_cpp.h +10168 -0
- package/cpp/dawn/wire/client/webgpu.h +354 -0
- package/cpp/dawn/wire/client/webgpu_cpp.h +10343 -0
- package/cpp/dawn/wire/client/webgpu_cpp_print.h +2715 -0
- package/cpp/jsi/RNFHybridObject.cpp +8 -4
- package/cpp/jsi/RNFHybridObject.h +7 -2
- package/cpp/jsi/RNFJSIConverter.h +13 -102
- package/cpp/jsi/RNFJSIHelper.h +5 -3
- package/cpp/jsi/RNFRuntimeState.cpp +18 -0
- package/cpp/jsi/RNFRuntimeState.h +106 -0
- package/cpp/rnwgpu/RNWebGPUManager.cpp +1 -9
- package/cpp/rnwgpu/api/GPU.cpp +51 -26
- package/cpp/rnwgpu/api/GPU.h +5 -18
- package/cpp/rnwgpu/api/GPUAdapter.cpp +79 -54
- package/cpp/rnwgpu/api/GPUAdapter.h +6 -6
- package/cpp/rnwgpu/api/GPUAdapterInfo.h +0 -1
- package/cpp/rnwgpu/api/GPUBindGroup.h +1 -3
- package/cpp/rnwgpu/api/GPUBindGroupLayout.h +1 -3
- package/cpp/rnwgpu/api/GPUBuffer.cpp +35 -32
- package/cpp/rnwgpu/api/GPUBuffer.h +9 -7
- package/cpp/rnwgpu/api/GPUCanvasContext.cpp +5 -1
- package/cpp/rnwgpu/api/GPUCanvasContext.h +0 -2
- package/cpp/rnwgpu/api/GPUCommandBuffer.h +1 -3
- package/cpp/rnwgpu/api/GPUCommandEncoder.h +1 -3
- package/cpp/rnwgpu/api/GPUCompilationInfo.h +0 -2
- package/cpp/rnwgpu/api/GPUCompilationMessage.h +1 -3
- package/cpp/rnwgpu/api/GPUComputePassEncoder.h +1 -3
- package/cpp/rnwgpu/api/GPUComputePipeline.h +1 -3
- package/cpp/rnwgpu/api/GPUDevice.cpp +183 -128
- package/cpp/rnwgpu/api/GPUDevice.h +22 -21
- package/cpp/rnwgpu/api/GPUDeviceLostInfo.h +1 -3
- package/cpp/rnwgpu/api/GPUExternalTexture.h +1 -3
- package/cpp/rnwgpu/api/GPUPipelineLayout.h +1 -3
- package/cpp/rnwgpu/api/GPUQuerySet.h +1 -3
- package/cpp/rnwgpu/api/GPUQueue.cpp +19 -8
- package/cpp/rnwgpu/api/GPUQueue.h +7 -6
- package/cpp/rnwgpu/api/GPURenderBundle.h +1 -3
- package/cpp/rnwgpu/api/GPURenderBundleEncoder.h +1 -3
- package/cpp/rnwgpu/api/GPURenderPassEncoder.h +1 -3
- package/cpp/rnwgpu/api/GPURenderPipeline.h +1 -3
- package/cpp/rnwgpu/api/GPUSampler.h +1 -3
- package/cpp/rnwgpu/api/GPUShaderModule.cpp +42 -28
- package/cpp/rnwgpu/api/GPUShaderModule.h +6 -6
- package/cpp/rnwgpu/api/GPUSupportedLimits.h +1 -3
- package/cpp/rnwgpu/api/GPUTexture.h +1 -3
- package/cpp/rnwgpu/api/GPUTextureView.h +1 -3
- package/cpp/rnwgpu/api/RNWebGPU.h +1 -7
- package/cpp/rnwgpu/async/AsyncDispatcher.h +28 -0
- package/cpp/rnwgpu/async/AsyncRunner.cpp +215 -0
- package/cpp/rnwgpu/async/AsyncRunner.h +53 -0
- package/cpp/rnwgpu/async/AsyncTaskHandle.cpp +181 -0
- package/cpp/rnwgpu/async/AsyncTaskHandle.h +55 -0
- package/cpp/rnwgpu/async/JSIMicrotaskDispatcher.cpp +23 -0
- package/cpp/rnwgpu/async/JSIMicrotaskDispatcher.h +22 -0
- package/cpp/webgpu/webgpu.h +5 -4827
- package/cpp/webgpu/webgpu_cpp.h +5 -10140
- package/cpp/{dawn/native/WebGPUBackend.h → webgpu/webgpu_cpp_print.h} +4 -20
- package/lib/commonjs/Canvas.js +6 -66
- package/lib/commonjs/Canvas.js.map +1 -1
- package/lib/commonjs/hooks.js +6 -42
- package/lib/commonjs/hooks.js.map +1 -1
- package/lib/module/Canvas.js +7 -67
- package/lib/module/Canvas.js.map +1 -1
- package/lib/module/hooks.js +5 -40
- package/lib/module/hooks.js.map +1 -1
- package/lib/typescript/lib/commonjs/hooks.d.ts +1 -5
- package/lib/typescript/lib/commonjs/hooks.d.ts.map +1 -1
- package/lib/typescript/lib/module/Canvas.d.ts.map +1 -1
- package/lib/typescript/lib/module/hooks.d.ts +1 -5
- package/lib/typescript/lib/module/hooks.d.ts.map +1 -1
- package/lib/typescript/src/Canvas.d.ts +0 -1
- package/lib/typescript/src/Canvas.d.ts.map +1 -1
- package/lib/typescript/src/hooks.d.ts +2 -7
- package/lib/typescript/src/hooks.d.ts.map +1 -1
- package/libs/android/arm64-v8a/libwebgpu_dawn.so +0 -0
- package/libs/android/armeabi-v7a/libwebgpu_dawn.so +0 -0
- package/libs/android/x86/libwebgpu_dawn.so +0 -0
- package/libs/android/x86_64/libwebgpu_dawn.so +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/Info.plist +5 -35
- package/libs/apple/libwebgpu_dawn.xcframework/ios-arm64/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/ios-arm64_x86_64-simulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/macos-arm64_x86_64/libwebgpu_dawn.a +0 -0
- package/package.json +4 -3
- package/react-native-wgpu.podspec +12 -16
- package/src/Canvas.tsx +8 -69
- package/src/hooks.tsx +14 -48
- package/android/cpp/platform/ThreadUtils.cpp +0 -41
- package/android/src/oldarch/com/webgpu/NativeWebGPUModuleSpec.java +0 -23
- package/android/src/oldarch/com/webgpu/WebGPUViewManagerSpec.java +0 -12
- package/apple/WebGPUViewManager.mm +0 -24
- package/apple/platform/ThreadUtils.cpp +0 -34
- package/cpp/dawn/dawn_proc.h +0 -50
- package/cpp/dawn/dawn_thread_dispatch_proc.h +0 -47
- package/cpp/dawn/native/D3D11Backend.h +0 -77
- package/cpp/dawn/native/D3D12Backend.h +0 -68
- package/cpp/dawn/native/D3DBackend.h +0 -56
- package/cpp/dawn/native/MetalBackend.h +0 -56
- package/cpp/dawn/platform/DawnPlatform.h +0 -167
- package/cpp/dawn/platform/dawn_platform_export.h +0 -49
- package/cpp/jsi/RNFRuntimeCache.cpp +0 -57
- package/cpp/jsi/RNFRuntimeCache.h +0 -79
- package/cpp/jsi/RNFWorkletRuntimeCollector.h +0 -43
- package/cpp/jsi/RNFWorkletRuntimeRegistry.cpp +0 -12
- package/cpp/jsi/RNFWorkletRuntimeRegistry.h +0 -44
- package/cpp/platform/ThreadUtils.h +0 -30
- package/cpp/rnwgpu/api/AsyncRunner.h +0 -30
- package/cpp/threading/CallInvokerDispatcher.h +0 -37
- package/cpp/threading/Dispatcher.cpp +0 -55
- package/cpp/threading/Dispatcher.h +0 -93
- package/cpp/threading/ThreadPool.cpp +0 -88
- package/cpp/threading/ThreadPool.h +0 -53
- package/cpp/webgpu/webgpu_glfw.h +0 -88
- package/lib/typescript/src/__tests__/Alpha.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/Alpha.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/ArrayBuffer.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/ArrayBuffer.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/Buffer.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/Buffer.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/ComputeShader.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/ComputeShader.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/Constants.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/Constants.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/Device.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/Device.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/ErrorScope.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/ErrorScope.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/ExternalTexture.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/ExternalTexture.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/GPU.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/GPU.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/ImageData.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/ImageData.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/Shaders.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/Shaders.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/Texture.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/Texture.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/Wireframe/Shaders.d.ts +0 -3
- package/lib/typescript/src/__tests__/components/Wireframe/Shaders.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/Wireframe/models.d.ts +0 -29
- package/lib/typescript/src/__tests__/components/Wireframe/models.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/Wireframe/utils.d.ts +0 -5
- package/lib/typescript/src/__tests__/components/Wireframe/utils.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/cube.d.ts +0 -7
- package/lib/typescript/src/__tests__/components/cube.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/meshes/mesh.d.ts +0 -22
- package/lib/typescript/src/__tests__/components/meshes/mesh.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/meshes/sphere.d.ts +0 -12
- package/lib/typescript/src/__tests__/components/meshes/sphere.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/meshes/stanfordDragon.d.ts +0 -7
- package/lib/typescript/src/__tests__/components/meshes/stanfordDragon.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/meshes/stanfordDragonData.d.ts +0 -6
- package/lib/typescript/src/__tests__/components/meshes/stanfordDragonData.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/meshes/teapot.d.ts +0 -6
- package/lib/typescript/src/__tests__/components/meshes/teapot.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/meshes/utils.d.ts +0 -10
- package/lib/typescript/src/__tests__/components/meshes/utils.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/components/triangle.d.ts +0 -3
- package/lib/typescript/src/__tests__/components/triangle.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/config.d.ts +0 -3
- package/lib/typescript/src/__tests__/config.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/demos/ABuffer.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/demos/ABuffer.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/demos/Blur.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/demos/Blur.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/demos/Cube.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/demos/Cube.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/demos/FractalCube.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/demos/FractalCube.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/demos/OcclusionQuery.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/demos/OcclusionQuery.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/demos/RenderBundles.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/demos/RenderBundles.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/demos/Triangle.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/demos/Triangle.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/demos/Wireframe.spec.d.ts +0 -2
- package/lib/typescript/src/__tests__/demos/Wireframe.spec.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/globalSetup.d.ts +0 -3
- package/lib/typescript/src/__tests__/globalSetup.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/globalTeardown.d.ts +0 -3
- package/lib/typescript/src/__tests__/globalTeardown.d.ts.map +0 -1
- package/lib/typescript/src/__tests__/setup.d.ts +0 -63
- package/lib/typescript/src/__tests__/setup.d.ts.map +0 -1
- package/libs/apple/arm64_iphoneos/libwebgpu_dawn.a +0 -0
- package/libs/apple/arm64_iphonesimulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/arm64_xros/libwebgpu_dawn.a +0 -0
- package/libs/apple/arm64_xrsimulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/iphonesimulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/xros-arm64/libwebgpu_dawn.a +0 -0
- package/libs/apple/libwebgpu_dawn.xcframework/xros-arm64-simulator/libwebgpu_dawn.a +0 -0
- package/libs/apple/universal_macosx/libwebgpu_dawn.a +0 -0
- package/libs/apple/x86_64_iphonesimulator/libwebgpu_dawn.a +0 -0
- package/libs/dawn.json +0 -4670
- package/src/__tests__/Alpha.spec.ts +0 -28
- package/src/__tests__/ArrayBuffer.spec.ts +0 -76
- package/src/__tests__/Buffer.spec.ts +0 -357
- package/src/__tests__/ComputeShader.spec.ts +0 -375
- package/src/__tests__/Constants.spec.ts +0 -89
- package/src/__tests__/Device.spec.ts +0 -84
- package/src/__tests__/ErrorScope.spec.ts +0 -92
- package/src/__tests__/ExternalTexture.spec.ts +0 -284
- package/src/__tests__/GPU.spec.ts +0 -272
- package/src/__tests__/ImageData.spec.ts +0 -26
- package/src/__tests__/Shaders.spec.ts +0 -232
- package/src/__tests__/Texture.spec.ts +0 -197
- package/src/__tests__/assets/Di-3d.png +0 -0
- package/src/__tests__/components/Wireframe/Shaders.ts +0 -138
- package/src/__tests__/components/Wireframe/models.ts +0 -113
- package/src/__tests__/components/Wireframe/utils.ts +0 -22
- package/src/__tests__/components/cube.ts +0 -51
- package/src/__tests__/components/meshes/mesh.ts +0 -96
- package/src/__tests__/components/meshes/sphere.ts +0 -103
- package/src/__tests__/components/meshes/stanfordDragon.ts +0 -44
- package/src/__tests__/components/meshes/stanfordDragonData.ts +0 -5
- package/src/__tests__/components/meshes/teapot.ts +0 -13
- package/src/__tests__/components/meshes/utils.ts +0 -235
- package/src/__tests__/components/triangle.ts +0 -17
- package/src/__tests__/config.ts +0 -2
- package/src/__tests__/demos/ABuffer.spec.ts +0 -890
- package/src/__tests__/demos/Blur.spec.ts +0 -398
- package/src/__tests__/demos/Cube.spec.ts +0 -929
- package/src/__tests__/demos/FractalCube.spec.ts +0 -240
- package/src/__tests__/demos/OcclusionQuery.spec.ts +0 -376
- package/src/__tests__/demos/RenderBundles.spec.ts +0 -580
- package/src/__tests__/demos/Triangle.spec.ts +0 -266
- package/src/__tests__/demos/Wireframe.spec.ts +0 -188
- package/src/__tests__/globalSetup.ts +0 -45
- package/src/__tests__/globalTeardown.ts +0 -11
- package/src/__tests__/setup.ts +0 -423
- package/src/__tests__/snapshots/abuffer.png +0 -0
- package/src/__tests__/snapshots/asteroid.png +0 -0
- package/src/__tests__/snapshots/blur.png +0 -0
- package/src/__tests__/snapshots/buffer.png +0 -0
- package/src/__tests__/snapshots/constant-triangle.png +0 -0
- package/src/__tests__/snapshots/cube.png +0 -0
- package/src/__tests__/snapshots/f.png +0 -0
- package/src/__tests__/snapshots/f2.png +0 -0
- package/src/__tests__/snapshots/fractal-cubes.png +0 -0
- package/src/__tests__/snapshots/instanced-cubes.png +0 -0
- package/src/__tests__/snapshots/occlusion-query.png +0 -0
- package/src/__tests__/snapshots/ref.png +0 -0
- package/src/__tests__/snapshots/semi-opaque-cyan.png +0 -0
- package/src/__tests__/snapshots/texture.png +0 -0
- package/src/__tests__/snapshots/textured-cube.png +0 -0
- package/src/__tests__/snapshots/triangle-msaa.png +0 -0
- package/src/__tests__/snapshots/triangle.png +0 -0
- package/src/__tests__/snapshots/two-cube.png +0 -0
|
@@ -1,890 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
2
|
-
import { checkImage, client, encodeImage } from "../setup";
|
|
3
|
-
import { mesh as teapotMesh } from "../components/meshes/teapot";
|
|
4
|
-
|
|
5
|
-
const opaque = /*wgsl*/ `struct Uniforms {
|
|
6
|
-
modelViewProjectionMatrix: mat4x4f,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
@binding(0) @group(0) var<uniform> uniforms: Uniforms;
|
|
10
|
-
|
|
11
|
-
struct VertexOutput {
|
|
12
|
-
@builtin(position) position: vec4f,
|
|
13
|
-
@location(0) @interpolate(flat) instance: u32
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
@vertex
|
|
17
|
-
fn main_vs(@location(0) position: vec4f, @builtin(instance_index) instance: u32) -> VertexOutput {
|
|
18
|
-
var output: VertexOutput;
|
|
19
|
-
|
|
20
|
-
// distribute instances into a staggered 4x4 grid
|
|
21
|
-
const gridWidth = 125.0;
|
|
22
|
-
const cellSize = gridWidth / 4.0;
|
|
23
|
-
let row = instance / 2u;
|
|
24
|
-
let col = instance % 2u;
|
|
25
|
-
|
|
26
|
-
let xOffset = -gridWidth / 2.0 + cellSize / 2.0 + 2.0 * cellSize * f32(col) + f32(row % 2u != 0u) * cellSize;
|
|
27
|
-
let zOffset = -gridWidth / 2.0 + cellSize / 2.0 + 2.0 + f32(row) * cellSize;
|
|
28
|
-
|
|
29
|
-
let offsetPos = vec4(position.x + xOffset, position.y, position.z + zOffset, position.w);
|
|
30
|
-
|
|
31
|
-
output.position = uniforms.modelViewProjectionMatrix * offsetPos;
|
|
32
|
-
output.instance = instance;
|
|
33
|
-
return output;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
@fragment
|
|
37
|
-
fn main_fs(@location(0) @interpolate(flat) instance: u32) -> @location(0) vec4f {
|
|
38
|
-
const colors = array<vec3f,6>(
|
|
39
|
-
vec3(1.0, 0.0, 0.0),
|
|
40
|
-
vec3(0.0, 1.0, 0.0),
|
|
41
|
-
vec3(0.0, 0.0, 1.0),
|
|
42
|
-
vec3(1.0, 0.0, 1.0),
|
|
43
|
-
vec3(1.0, 1.0, 0.0),
|
|
44
|
-
vec3(0.0, 1.0, 1.0),
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
return vec4(colors[instance % 6u], 1.0);
|
|
48
|
-
}
|
|
49
|
-
`;
|
|
50
|
-
|
|
51
|
-
const translucent = /*wgsl*/ `struct Uniforms {
|
|
52
|
-
modelViewProjectionMatrix: mat4x4f,
|
|
53
|
-
maxStorableFragments: u32,
|
|
54
|
-
targetWidth: u32,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
struct SliceInfo {
|
|
58
|
-
sliceStartY: i32
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
struct Heads {
|
|
62
|
-
numFragments: atomic<u32>,
|
|
63
|
-
data: array<atomic<u32>>
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
struct LinkedListElement {
|
|
67
|
-
color: vec4f,
|
|
68
|
-
depth: f32,
|
|
69
|
-
next: u32
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
struct LinkedList {
|
|
73
|
-
data: array<LinkedListElement>
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
@binding(0) @group(0) var<uniform> uniforms: Uniforms;
|
|
77
|
-
@binding(1) @group(0) var<storage, read_write> heads: Heads;
|
|
78
|
-
@binding(2) @group(0) var<storage, read_write> linkedList: LinkedList;
|
|
79
|
-
@binding(3) @group(0) var opaqueDepthTexture: texture_depth_2d;
|
|
80
|
-
@binding(4) @group(0) var<uniform> sliceInfo: SliceInfo;
|
|
81
|
-
|
|
82
|
-
struct VertexOutput {
|
|
83
|
-
@builtin(position) position: vec4f,
|
|
84
|
-
@location(0) @interpolate(flat) instance: u32
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
@vertex
|
|
88
|
-
fn main_vs(@location(0) position: vec4f, @builtin(instance_index) instance: u32) -> VertexOutput {
|
|
89
|
-
var output: VertexOutput;
|
|
90
|
-
|
|
91
|
-
// distribute instances into a staggered 4x4 grid
|
|
92
|
-
const gridWidth = 125.0;
|
|
93
|
-
const cellSize = gridWidth / 4.0;
|
|
94
|
-
let row = instance / 2u;
|
|
95
|
-
let col = instance % 2u;
|
|
96
|
-
|
|
97
|
-
let xOffset = -gridWidth / 2.0 + cellSize / 2.0 + 2.0 * cellSize * f32(col) + f32(row % 2u == 0u) * cellSize;
|
|
98
|
-
let zOffset = -gridWidth / 2.0 + cellSize / 2.0 + 2.0 + f32(row) * cellSize;
|
|
99
|
-
|
|
100
|
-
let offsetPos = vec4(position.x + xOffset, position.y, position.z + zOffset, position.w);
|
|
101
|
-
|
|
102
|
-
output.position = uniforms.modelViewProjectionMatrix * offsetPos;
|
|
103
|
-
output.instance = instance;
|
|
104
|
-
|
|
105
|
-
return output;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
@fragment
|
|
109
|
-
fn main_fs(@builtin(position) position: vec4f, @location(0) @interpolate(flat) instance: u32) {
|
|
110
|
-
const colors = array<vec3f,6>(
|
|
111
|
-
vec3(1.0, 0.0, 0.0),
|
|
112
|
-
vec3(0.0, 1.0, 0.0),
|
|
113
|
-
vec3(0.0, 0.0, 1.0),
|
|
114
|
-
vec3(1.0, 0.0, 1.0),
|
|
115
|
-
vec3(1.0, 1.0, 0.0),
|
|
116
|
-
vec3(0.0, 1.0, 1.0),
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
let fragCoords = vec2i(position.xy);
|
|
120
|
-
let opaqueDepth = textureLoad(opaqueDepthTexture, fragCoords, 0);
|
|
121
|
-
|
|
122
|
-
// reject fragments behind opaque objects
|
|
123
|
-
if position.z >= opaqueDepth {
|
|
124
|
-
discard;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// The index in the heads buffer corresponding to the head data for the fragment at
|
|
128
|
-
// the current location.
|
|
129
|
-
let headsIndex = u32(fragCoords.y - sliceInfo.sliceStartY) * uniforms.targetWidth + u32(fragCoords.x);
|
|
130
|
-
|
|
131
|
-
// The index in the linkedList buffer at which to store the new fragment
|
|
132
|
-
let fragIndex = atomicAdd(&heads.numFragments, 1u);
|
|
133
|
-
|
|
134
|
-
// If we run out of space to store the fragments, we just lose them
|
|
135
|
-
if fragIndex < uniforms.maxStorableFragments {
|
|
136
|
-
let lastHead = atomicExchange(&heads.data[headsIndex], fragIndex);
|
|
137
|
-
linkedList.data[fragIndex].depth = position.z;
|
|
138
|
-
linkedList.data[fragIndex].next = lastHead;
|
|
139
|
-
linkedList.data[fragIndex].color = vec4(colors[(instance + 3u) % 6u], 0.3);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
`;
|
|
143
|
-
|
|
144
|
-
const composite = /*wgsl*/ `struct Uniforms {
|
|
145
|
-
modelViewProjectionMatrix: mat4x4f,
|
|
146
|
-
maxStorableFragments: u32,
|
|
147
|
-
targetWidth: u32,
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
struct SliceInfo {
|
|
151
|
-
sliceStartY: i32
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
struct Heads {
|
|
155
|
-
numFragments: u32,
|
|
156
|
-
data: array<u32>
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
struct LinkedListElement {
|
|
160
|
-
color: vec4f,
|
|
161
|
-
depth: f32,
|
|
162
|
-
next: u32
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
struct LinkedList {
|
|
166
|
-
data: array<LinkedListElement>
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
@binding(0) @group(0) var<uniform> uniforms: Uniforms;
|
|
170
|
-
@binding(1) @group(0) var<storage, read_write> heads: Heads;
|
|
171
|
-
@binding(2) @group(0) var<storage, read_write> linkedList: LinkedList;
|
|
172
|
-
@binding(3) @group(0) var<uniform> sliceInfo: SliceInfo;
|
|
173
|
-
|
|
174
|
-
// Output a full screen quad
|
|
175
|
-
@vertex
|
|
176
|
-
fn main_vs(@builtin(vertex_index) vertIndex: u32) -> @builtin(position) vec4f {
|
|
177
|
-
const position = array<vec2f, 6>(
|
|
178
|
-
vec2(-1.0, -1.0),
|
|
179
|
-
vec2(1.0, -1.0),
|
|
180
|
-
vec2(1.0, 1.0),
|
|
181
|
-
vec2(-1.0, -1.0),
|
|
182
|
-
vec2(1.0, 1.0),
|
|
183
|
-
vec2(-1.0, 1.0),
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
return vec4(position[vertIndex], 0.0, 1.0);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
@fragment
|
|
190
|
-
fn main_fs(@builtin(position) position: vec4f) -> @location(0) vec4f {
|
|
191
|
-
let fragCoords = vec2i(position.xy);
|
|
192
|
-
let headsIndex = u32(fragCoords.y - sliceInfo.sliceStartY) * uniforms.targetWidth + u32(fragCoords.x);
|
|
193
|
-
|
|
194
|
-
// The maximum layers we can process for any pixel
|
|
195
|
-
const maxLayers = 12u;
|
|
196
|
-
|
|
197
|
-
var layers: array<LinkedListElement, maxLayers>;
|
|
198
|
-
|
|
199
|
-
var numLayers = 0u;
|
|
200
|
-
var elementIndex = heads.data[headsIndex];
|
|
201
|
-
|
|
202
|
-
// copy the list elements into an array up to the maximum amount of layers
|
|
203
|
-
while elementIndex != 0xFFFFFFFFu && numLayers < maxLayers {
|
|
204
|
-
layers[numLayers] = linkedList.data[elementIndex];
|
|
205
|
-
numLayers++;
|
|
206
|
-
elementIndex = linkedList.data[elementIndex].next;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if numLayers == 0u {
|
|
210
|
-
discard;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// sort the fragments by depth
|
|
214
|
-
for (var i = 1u; i < numLayers; i++) {
|
|
215
|
-
let toInsert = layers[i];
|
|
216
|
-
var j = i;
|
|
217
|
-
|
|
218
|
-
while j > 0u && toInsert.depth > layers[j - 1u].depth {
|
|
219
|
-
layers[j] = layers[j - 1u];
|
|
220
|
-
j--;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
layers[j] = toInsert;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// pre-multiply alpha for the first layer
|
|
227
|
-
var color = vec4(layers[0].color.a * layers[0].color.rgb, layers[0].color.a);
|
|
228
|
-
|
|
229
|
-
// blend the remaining layers
|
|
230
|
-
for (var i = 1u; i < numLayers; i++) {
|
|
231
|
-
let mixed = mix(color.rgb, layers[i].color.rgb, layers[i].color.aaa);
|
|
232
|
-
color = vec4(mixed, color.a);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return color;
|
|
236
|
-
}`;
|
|
237
|
-
|
|
238
|
-
describe("A Buffer", () => {
|
|
239
|
-
it("draw scene", async () => {
|
|
240
|
-
const result = await client.eval(
|
|
241
|
-
({
|
|
242
|
-
ctx,
|
|
243
|
-
device,
|
|
244
|
-
gpu,
|
|
245
|
-
mesh,
|
|
246
|
-
opaqueWGSL,
|
|
247
|
-
compositeWGSL,
|
|
248
|
-
translucentWGSL,
|
|
249
|
-
mat4,
|
|
250
|
-
vec3,
|
|
251
|
-
canvas,
|
|
252
|
-
}) => {
|
|
253
|
-
const presentationFormat = gpu.getPreferredCanvasFormat();
|
|
254
|
-
const settings = {
|
|
255
|
-
memoryStrategy: "multipass",
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
function roundUp(n: number, k: number): number {
|
|
259
|
-
return Math.ceil(n / k) * k;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Create the model vertex buffer
|
|
263
|
-
const vertexBuffer = device.createBuffer({
|
|
264
|
-
size: 3 * mesh.positions.length * Float32Array.BYTES_PER_ELEMENT,
|
|
265
|
-
usage: GPUBufferUsage.VERTEX,
|
|
266
|
-
mappedAtCreation: true,
|
|
267
|
-
label: "vertexBuffer",
|
|
268
|
-
});
|
|
269
|
-
{
|
|
270
|
-
const mapping = new Float32Array(vertexBuffer.getMappedRange());
|
|
271
|
-
for (let i = 0; i < mesh.positions.length; ++i) {
|
|
272
|
-
mapping.set(mesh.positions[i], 3 * i);
|
|
273
|
-
}
|
|
274
|
-
vertexBuffer.unmap();
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// Create the model index buffer
|
|
278
|
-
const indexCount = mesh.triangles.length * 3;
|
|
279
|
-
const indexBuffer = device.createBuffer({
|
|
280
|
-
size: indexCount * Uint16Array.BYTES_PER_ELEMENT,
|
|
281
|
-
usage: GPUBufferUsage.INDEX,
|
|
282
|
-
mappedAtCreation: true,
|
|
283
|
-
label: "indexBuffer",
|
|
284
|
-
});
|
|
285
|
-
{
|
|
286
|
-
const mapping = new Uint16Array(indexBuffer.getMappedRange());
|
|
287
|
-
for (let i = 0; i < mesh.triangles.length; ++i) {
|
|
288
|
-
mapping.set(mesh.triangles[i], 3 * i);
|
|
289
|
-
}
|
|
290
|
-
indexBuffer.unmap();
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Uniforms contains:
|
|
294
|
-
// * modelViewProjectionMatrix: mat4x4f
|
|
295
|
-
// * maxStorableFragments: u32
|
|
296
|
-
// * targetWidth: u32
|
|
297
|
-
const uniformsSize = roundUp(
|
|
298
|
-
16 * Float32Array.BYTES_PER_ELEMENT +
|
|
299
|
-
2 * Uint32Array.BYTES_PER_ELEMENT,
|
|
300
|
-
16,
|
|
301
|
-
);
|
|
302
|
-
|
|
303
|
-
const uniformBuffer = device.createBuffer({
|
|
304
|
-
size: uniformsSize,
|
|
305
|
-
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
306
|
-
label: "uniformBuffer",
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
const opaqueModule = device.createShaderModule({
|
|
310
|
-
code: opaqueWGSL,
|
|
311
|
-
label: "opaqueModule",
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
const opaquePipeline = device.createRenderPipeline({
|
|
315
|
-
layout: "auto",
|
|
316
|
-
vertex: {
|
|
317
|
-
module: opaqueModule,
|
|
318
|
-
buffers: [
|
|
319
|
-
{
|
|
320
|
-
arrayStride: 3 * Float32Array.BYTES_PER_ELEMENT,
|
|
321
|
-
attributes: [
|
|
322
|
-
{
|
|
323
|
-
// position
|
|
324
|
-
format: "float32x3",
|
|
325
|
-
offset: 0,
|
|
326
|
-
shaderLocation: 0,
|
|
327
|
-
},
|
|
328
|
-
],
|
|
329
|
-
},
|
|
330
|
-
],
|
|
331
|
-
},
|
|
332
|
-
fragment: {
|
|
333
|
-
module: opaqueModule,
|
|
334
|
-
targets: [
|
|
335
|
-
{
|
|
336
|
-
format: presentationFormat,
|
|
337
|
-
},
|
|
338
|
-
],
|
|
339
|
-
},
|
|
340
|
-
primitive: {
|
|
341
|
-
topology: "triangle-list",
|
|
342
|
-
},
|
|
343
|
-
depthStencil: {
|
|
344
|
-
depthWriteEnabled: true,
|
|
345
|
-
depthCompare: "less",
|
|
346
|
-
format: "depth24plus",
|
|
347
|
-
},
|
|
348
|
-
label: "opaquePipeline",
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
const opaquePassDescriptor: GPURenderPassDescriptor = {
|
|
352
|
-
// @ts-expect-error
|
|
353
|
-
colorAttachments: [
|
|
354
|
-
{
|
|
355
|
-
view: undefined,
|
|
356
|
-
clearValue: [0, 0, 0, 1.0],
|
|
357
|
-
loadOp: "clear",
|
|
358
|
-
storeOp: "store",
|
|
359
|
-
},
|
|
360
|
-
],
|
|
361
|
-
depthStencilAttachment: {
|
|
362
|
-
// @ts-expect-error
|
|
363
|
-
view: undefined,
|
|
364
|
-
depthClearValue: 1.0,
|
|
365
|
-
depthLoadOp: "clear",
|
|
366
|
-
depthStoreOp: "store",
|
|
367
|
-
},
|
|
368
|
-
label: "opaquePassDescriptor",
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
const opaqueBindGroup = device.createBindGroup({
|
|
372
|
-
layout: opaquePipeline.getBindGroupLayout(0),
|
|
373
|
-
entries: [
|
|
374
|
-
{
|
|
375
|
-
binding: 0,
|
|
376
|
-
resource: {
|
|
377
|
-
buffer: uniformBuffer,
|
|
378
|
-
size: 16 * Float32Array.BYTES_PER_ELEMENT,
|
|
379
|
-
label: "modelViewProjection",
|
|
380
|
-
},
|
|
381
|
-
},
|
|
382
|
-
],
|
|
383
|
-
label: "opaquePipeline",
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
const translucentModule = device.createShaderModule({
|
|
387
|
-
code: translucentWGSL,
|
|
388
|
-
label: "translucentModule",
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
const translucentBindGroupLayout = device.createBindGroupLayout({
|
|
392
|
-
label: "translucentBindGroupLayout",
|
|
393
|
-
entries: [
|
|
394
|
-
{
|
|
395
|
-
binding: 0,
|
|
396
|
-
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
|
|
397
|
-
buffer: {
|
|
398
|
-
type: "uniform",
|
|
399
|
-
},
|
|
400
|
-
},
|
|
401
|
-
{
|
|
402
|
-
binding: 1,
|
|
403
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
404
|
-
buffer: {
|
|
405
|
-
type: "storage",
|
|
406
|
-
},
|
|
407
|
-
},
|
|
408
|
-
{
|
|
409
|
-
binding: 2,
|
|
410
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
411
|
-
buffer: {
|
|
412
|
-
type: "storage",
|
|
413
|
-
},
|
|
414
|
-
},
|
|
415
|
-
{
|
|
416
|
-
binding: 3,
|
|
417
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
418
|
-
texture: { sampleType: "depth" },
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
binding: 4,
|
|
422
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
423
|
-
buffer: {
|
|
424
|
-
type: "uniform",
|
|
425
|
-
hasDynamicOffset: true,
|
|
426
|
-
},
|
|
427
|
-
},
|
|
428
|
-
],
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
const translucentPipeline = device.createRenderPipeline({
|
|
432
|
-
layout: device.createPipelineLayout({
|
|
433
|
-
bindGroupLayouts: [translucentBindGroupLayout],
|
|
434
|
-
label: "translucentPipelineLayout",
|
|
435
|
-
}),
|
|
436
|
-
vertex: {
|
|
437
|
-
module: translucentModule,
|
|
438
|
-
buffers: [
|
|
439
|
-
{
|
|
440
|
-
arrayStride: 3 * Float32Array.BYTES_PER_ELEMENT,
|
|
441
|
-
attributes: [
|
|
442
|
-
{
|
|
443
|
-
format: "float32x3",
|
|
444
|
-
offset: 0,
|
|
445
|
-
shaderLocation: 0,
|
|
446
|
-
},
|
|
447
|
-
],
|
|
448
|
-
},
|
|
449
|
-
],
|
|
450
|
-
},
|
|
451
|
-
fragment: {
|
|
452
|
-
module: translucentModule,
|
|
453
|
-
targets: [
|
|
454
|
-
{
|
|
455
|
-
format: presentationFormat,
|
|
456
|
-
writeMask: 0x0,
|
|
457
|
-
},
|
|
458
|
-
],
|
|
459
|
-
},
|
|
460
|
-
primitive: {
|
|
461
|
-
topology: "triangle-list",
|
|
462
|
-
},
|
|
463
|
-
label: "translucentPipeline",
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
const translucentPassDescriptor: GPURenderPassDescriptor = {
|
|
467
|
-
// @ts-expect-error
|
|
468
|
-
colorAttachments: [
|
|
469
|
-
{
|
|
470
|
-
loadOp: "load",
|
|
471
|
-
storeOp: "store",
|
|
472
|
-
view: undefined,
|
|
473
|
-
},
|
|
474
|
-
],
|
|
475
|
-
label: "translucentPassDescriptor",
|
|
476
|
-
};
|
|
477
|
-
|
|
478
|
-
const compositeModule = device.createShaderModule({
|
|
479
|
-
code: compositeWGSL,
|
|
480
|
-
label: "compositeModule",
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
const compositeBindGroupLayout = device.createBindGroupLayout({
|
|
484
|
-
label: "compositeBindGroupLayout",
|
|
485
|
-
entries: [
|
|
486
|
-
{
|
|
487
|
-
binding: 0,
|
|
488
|
-
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
|
|
489
|
-
buffer: {
|
|
490
|
-
type: "uniform",
|
|
491
|
-
},
|
|
492
|
-
},
|
|
493
|
-
{
|
|
494
|
-
binding: 1,
|
|
495
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
496
|
-
buffer: {
|
|
497
|
-
type: "storage",
|
|
498
|
-
},
|
|
499
|
-
},
|
|
500
|
-
{
|
|
501
|
-
binding: 2,
|
|
502
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
503
|
-
buffer: {
|
|
504
|
-
type: "storage",
|
|
505
|
-
},
|
|
506
|
-
},
|
|
507
|
-
{
|
|
508
|
-
binding: 3,
|
|
509
|
-
visibility: GPUShaderStage.FRAGMENT,
|
|
510
|
-
buffer: {
|
|
511
|
-
type: "uniform",
|
|
512
|
-
hasDynamicOffset: true,
|
|
513
|
-
},
|
|
514
|
-
},
|
|
515
|
-
],
|
|
516
|
-
});
|
|
517
|
-
|
|
518
|
-
const compositePipeline = device.createRenderPipeline({
|
|
519
|
-
layout: device.createPipelineLayout({
|
|
520
|
-
bindGroupLayouts: [compositeBindGroupLayout],
|
|
521
|
-
label: "compositePipelineLayout",
|
|
522
|
-
}),
|
|
523
|
-
vertex: {
|
|
524
|
-
module: compositeModule,
|
|
525
|
-
},
|
|
526
|
-
fragment: {
|
|
527
|
-
module: compositeModule,
|
|
528
|
-
targets: [
|
|
529
|
-
{
|
|
530
|
-
format: presentationFormat,
|
|
531
|
-
blend: {
|
|
532
|
-
color: {
|
|
533
|
-
srcFactor: "one",
|
|
534
|
-
operation: "add",
|
|
535
|
-
dstFactor: "one-minus-src-alpha",
|
|
536
|
-
},
|
|
537
|
-
alpha: {},
|
|
538
|
-
},
|
|
539
|
-
},
|
|
540
|
-
],
|
|
541
|
-
},
|
|
542
|
-
primitive: {
|
|
543
|
-
topology: "triangle-list",
|
|
544
|
-
},
|
|
545
|
-
label: "compositePipeline",
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
const compositePassDescriptor: GPURenderPassDescriptor = {
|
|
549
|
-
// @ts-expect-error
|
|
550
|
-
colorAttachments: [
|
|
551
|
-
{
|
|
552
|
-
view: undefined,
|
|
553
|
-
loadOp: "load",
|
|
554
|
-
storeOp: "store",
|
|
555
|
-
},
|
|
556
|
-
],
|
|
557
|
-
label: "compositePassDescriptor",
|
|
558
|
-
};
|
|
559
|
-
|
|
560
|
-
const configure = () => {
|
|
561
|
-
// The default maximum storage buffer binding size is 128Mib. The amount
|
|
562
|
-
// of memory we need to store transparent fragments depends on the size
|
|
563
|
-
// of the canvas and the average number of layers per fragment we want to
|
|
564
|
-
// support. When the devicePixelRatio is 1, we know that 128Mib is enough
|
|
565
|
-
// to store 4 layers per pixel at 600x600. However, when the device pixel
|
|
566
|
-
// ratio is high enough we will exceed this limit.
|
|
567
|
-
//
|
|
568
|
-
// We provide 2 choices of mitigations to this issue:
|
|
569
|
-
// 1) Clamp the device pixel ratio to a value which we know will not break
|
|
570
|
-
// the limit. The tradeoff here is that the canvas resolution will not
|
|
571
|
-
// match the native resolution and therefore may have a reduction in
|
|
572
|
-
// quality.
|
|
573
|
-
// 2) Break the frame into a series of horizontal slices using the scissor
|
|
574
|
-
// functionality and process a single slice at a time. This limits memory
|
|
575
|
-
// usage because we only need enough memory to process the dimensions
|
|
576
|
-
// of the slice. The tradeoff is the performance reduction due to multiple
|
|
577
|
-
// passes.
|
|
578
|
-
if (settings.memoryStrategy === "clamp-pixel-ratio") {
|
|
579
|
-
devicePixelRatio = 1;
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
const depthTexture = device.createTexture({
|
|
583
|
-
size: [ctx.canvas.width, ctx.canvas.height],
|
|
584
|
-
format: "depth24plus",
|
|
585
|
-
usage:
|
|
586
|
-
GPUTextureUsage.RENDER_ATTACHMENT |
|
|
587
|
-
GPUTextureUsage.TEXTURE_BINDING,
|
|
588
|
-
label: "depthTexture",
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
const depthTextureView = depthTexture.createView({
|
|
592
|
-
label: "depthTextureView",
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
// Determines how much memory is allocated to store linked-list elements
|
|
596
|
-
const averageLayersPerFragment = 4;
|
|
597
|
-
|
|
598
|
-
// Each element stores
|
|
599
|
-
// * color : vec4f
|
|
600
|
-
// * depth : f32
|
|
601
|
-
// * index of next element in the list : u32
|
|
602
|
-
const linkedListElementSize =
|
|
603
|
-
5 * Float32Array.BYTES_PER_ELEMENT +
|
|
604
|
-
1 * Uint32Array.BYTES_PER_ELEMENT;
|
|
605
|
-
|
|
606
|
-
// We want to keep the linked-list buffer size under the maxStorageBufferBindingSize.
|
|
607
|
-
// Split the frame into enough slices to meet that constraint.
|
|
608
|
-
const bytesPerline =
|
|
609
|
-
ctx.canvas.width * averageLayersPerFragment * linkedListElementSize;
|
|
610
|
-
const maxLinesSupported = Math.floor(
|
|
611
|
-
device.limits.maxStorageBufferBindingSize / bytesPerline,
|
|
612
|
-
);
|
|
613
|
-
const numSlices = Math.ceil(ctx.canvas.height / maxLinesSupported);
|
|
614
|
-
const sliceHeight = Math.ceil(ctx.canvas.height / numSlices);
|
|
615
|
-
const linkedListBufferSize = sliceHeight * bytesPerline;
|
|
616
|
-
|
|
617
|
-
const linkedListBuffer = device.createBuffer({
|
|
618
|
-
size: linkedListBufferSize,
|
|
619
|
-
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
620
|
-
label: "linkedListBuffer",
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
// To slice up the frame we need to pass the starting fragment y position of the slice.
|
|
624
|
-
// We do this using a uniform buffer with a dynamic offset.
|
|
625
|
-
const sliceInfoBuffer = device.createBuffer({
|
|
626
|
-
size: numSlices * device.limits.minUniformBufferOffsetAlignment,
|
|
627
|
-
usage: GPUBufferUsage.UNIFORM,
|
|
628
|
-
mappedAtCreation: true,
|
|
629
|
-
label: "sliceInfoBuffer",
|
|
630
|
-
});
|
|
631
|
-
{
|
|
632
|
-
const mapping = new Int32Array(sliceInfoBuffer.getMappedRange());
|
|
633
|
-
|
|
634
|
-
// This assumes minUniformBufferOffsetAlignment is a multiple of 4
|
|
635
|
-
const stride =
|
|
636
|
-
device.limits.minUniformBufferOffsetAlignment /
|
|
637
|
-
Int32Array.BYTES_PER_ELEMENT;
|
|
638
|
-
for (let i = 0; i < numSlices; ++i) {
|
|
639
|
-
mapping[i * stride] = i * sliceHeight;
|
|
640
|
-
}
|
|
641
|
-
sliceInfoBuffer.unmap();
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
// `Heads` struct contains the start index of the linked-list of translucent fragments
|
|
645
|
-
// for a given pixel.
|
|
646
|
-
// * numFragments : u32
|
|
647
|
-
// * data : array<u32>
|
|
648
|
-
const headsBuffer = device.createBuffer({
|
|
649
|
-
size:
|
|
650
|
-
(1 + ctx.canvas.width * sliceHeight) *
|
|
651
|
-
Uint32Array.BYTES_PER_ELEMENT,
|
|
652
|
-
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
653
|
-
label: "headsBuffer",
|
|
654
|
-
});
|
|
655
|
-
|
|
656
|
-
const headsInitBuffer = device.createBuffer({
|
|
657
|
-
size:
|
|
658
|
-
(1 + ctx.canvas.width * sliceHeight) *
|
|
659
|
-
Uint32Array.BYTES_PER_ELEMENT,
|
|
660
|
-
usage: GPUBufferUsage.COPY_SRC,
|
|
661
|
-
mappedAtCreation: true,
|
|
662
|
-
label: "headsInitBuffer",
|
|
663
|
-
});
|
|
664
|
-
{
|
|
665
|
-
const buffer = new Uint32Array(headsInitBuffer.getMappedRange());
|
|
666
|
-
|
|
667
|
-
for (let i = 0; i < buffer.length; ++i) {
|
|
668
|
-
buffer[i] = 0xffffffff;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
headsInitBuffer.unmap();
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
const translucentBindGroup = device.createBindGroup({
|
|
675
|
-
layout: translucentBindGroupLayout,
|
|
676
|
-
entries: [
|
|
677
|
-
{
|
|
678
|
-
binding: 0,
|
|
679
|
-
resource: {
|
|
680
|
-
buffer: uniformBuffer,
|
|
681
|
-
label: "uniforms",
|
|
682
|
-
},
|
|
683
|
-
},
|
|
684
|
-
{
|
|
685
|
-
binding: 1,
|
|
686
|
-
resource: {
|
|
687
|
-
buffer: headsBuffer,
|
|
688
|
-
label: "headsBuffer",
|
|
689
|
-
},
|
|
690
|
-
},
|
|
691
|
-
{
|
|
692
|
-
binding: 2,
|
|
693
|
-
resource: {
|
|
694
|
-
buffer: linkedListBuffer,
|
|
695
|
-
label: "linkedListBuffer",
|
|
696
|
-
},
|
|
697
|
-
},
|
|
698
|
-
{
|
|
699
|
-
binding: 3,
|
|
700
|
-
resource: depthTextureView,
|
|
701
|
-
},
|
|
702
|
-
{
|
|
703
|
-
binding: 4,
|
|
704
|
-
resource: {
|
|
705
|
-
buffer: sliceInfoBuffer,
|
|
706
|
-
size: device.limits.minUniformBufferOffsetAlignment,
|
|
707
|
-
label: "sliceInfoBuffer",
|
|
708
|
-
},
|
|
709
|
-
},
|
|
710
|
-
],
|
|
711
|
-
label: "translucentBindGroup",
|
|
712
|
-
});
|
|
713
|
-
|
|
714
|
-
const compositeBindGroup = device.createBindGroup({
|
|
715
|
-
layout: compositePipeline.getBindGroupLayout(0),
|
|
716
|
-
entries: [
|
|
717
|
-
{
|
|
718
|
-
binding: 0,
|
|
719
|
-
resource: {
|
|
720
|
-
buffer: uniformBuffer,
|
|
721
|
-
label: "uniforms",
|
|
722
|
-
},
|
|
723
|
-
},
|
|
724
|
-
{
|
|
725
|
-
binding: 1,
|
|
726
|
-
resource: {
|
|
727
|
-
buffer: headsBuffer,
|
|
728
|
-
label: "headsBuffer",
|
|
729
|
-
},
|
|
730
|
-
},
|
|
731
|
-
{
|
|
732
|
-
binding: 2,
|
|
733
|
-
resource: {
|
|
734
|
-
buffer: linkedListBuffer,
|
|
735
|
-
label: "linkedListBuffer",
|
|
736
|
-
},
|
|
737
|
-
},
|
|
738
|
-
{
|
|
739
|
-
binding: 3,
|
|
740
|
-
resource: {
|
|
741
|
-
buffer: sliceInfoBuffer,
|
|
742
|
-
size: device.limits.minUniformBufferOffsetAlignment,
|
|
743
|
-
label: "sliceInfoBuffer",
|
|
744
|
-
},
|
|
745
|
-
},
|
|
746
|
-
],
|
|
747
|
-
});
|
|
748
|
-
// @ts-expect-error
|
|
749
|
-
opaquePassDescriptor.depthStencilAttachment.view = depthTextureView;
|
|
750
|
-
|
|
751
|
-
// Rotates the camera around the origin based on time.
|
|
752
|
-
function getCameraViewProjMatrix() {
|
|
753
|
-
const aspect = ctx.canvas.width / ctx.canvas.height;
|
|
754
|
-
|
|
755
|
-
const projectionMatrix = mat4.perspective(
|
|
756
|
-
(2 * Math.PI) / 5,
|
|
757
|
-
aspect,
|
|
758
|
-
1,
|
|
759
|
-
2000.0,
|
|
760
|
-
);
|
|
761
|
-
|
|
762
|
-
const upVector = vec3.fromValues(0, 1, 0);
|
|
763
|
-
const origin = vec3.fromValues(0, 0, 0);
|
|
764
|
-
const eyePosition = vec3.fromValues(0, 5, -100);
|
|
765
|
-
|
|
766
|
-
const now = 1721824271091;
|
|
767
|
-
const rad = Math.PI * (now / 5000);
|
|
768
|
-
const rotation = mat4.rotateY(mat4.translation(origin), rad);
|
|
769
|
-
vec3.transformMat4(eyePosition, rotation, eyePosition);
|
|
770
|
-
|
|
771
|
-
const viewMatrix = mat4.lookAt(eyePosition, origin, upVector);
|
|
772
|
-
|
|
773
|
-
const viewProjMatrix = mat4.multiply(projectionMatrix, viewMatrix);
|
|
774
|
-
return viewProjMatrix;
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
return function doDraw() {
|
|
778
|
-
// update the uniform buffer
|
|
779
|
-
{
|
|
780
|
-
const buffer = new ArrayBuffer(uniformBuffer.size);
|
|
781
|
-
|
|
782
|
-
new Float32Array(buffer).set(getCameraViewProjMatrix());
|
|
783
|
-
new Uint32Array(buffer, 16 * Float32Array.BYTES_PER_ELEMENT).set([
|
|
784
|
-
averageLayersPerFragment * ctx.canvas.width * sliceHeight,
|
|
785
|
-
ctx.canvas.width,
|
|
786
|
-
]);
|
|
787
|
-
|
|
788
|
-
device.queue.writeBuffer(uniformBuffer, 0, buffer);
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
const commandEncoder = device.createCommandEncoder();
|
|
792
|
-
const textureView = ctx.getCurrentTexture().createView();
|
|
793
|
-
|
|
794
|
-
// Draw the opaque objects
|
|
795
|
-
// @ts-expect-error
|
|
796
|
-
opaquePassDescriptor.colorAttachments[0].view = textureView;
|
|
797
|
-
const opaquePassEncoder =
|
|
798
|
-
commandEncoder.beginRenderPass(opaquePassDescriptor);
|
|
799
|
-
opaquePassEncoder.setPipeline(opaquePipeline);
|
|
800
|
-
opaquePassEncoder.setBindGroup(0, opaqueBindGroup);
|
|
801
|
-
opaquePassEncoder.setVertexBuffer(0, vertexBuffer);
|
|
802
|
-
opaquePassEncoder.setIndexBuffer(indexBuffer, "uint16");
|
|
803
|
-
opaquePassEncoder.drawIndexed(mesh.triangles.length * 3, 8);
|
|
804
|
-
opaquePassEncoder.end();
|
|
805
|
-
|
|
806
|
-
for (let slice = 0; slice < numSlices; ++slice) {
|
|
807
|
-
// initialize the heads buffer
|
|
808
|
-
commandEncoder.copyBufferToBuffer(
|
|
809
|
-
headsInitBuffer,
|
|
810
|
-
0,
|
|
811
|
-
headsBuffer,
|
|
812
|
-
0,
|
|
813
|
-
headsInitBuffer.size,
|
|
814
|
-
);
|
|
815
|
-
|
|
816
|
-
const scissorX = 0;
|
|
817
|
-
const scissorY = slice * sliceHeight;
|
|
818
|
-
const scissorWidth = ctx.canvas.width;
|
|
819
|
-
const scissorHeight =
|
|
820
|
-
Math.min((slice + 1) * sliceHeight, ctx.canvas.height) -
|
|
821
|
-
slice * sliceHeight;
|
|
822
|
-
|
|
823
|
-
// Draw the translucent objects
|
|
824
|
-
// @ts-expect-error
|
|
825
|
-
translucentPassDescriptor.colorAttachments[0].view = textureView;
|
|
826
|
-
const translucentPassEncoder = commandEncoder.beginRenderPass(
|
|
827
|
-
translucentPassDescriptor,
|
|
828
|
-
);
|
|
829
|
-
|
|
830
|
-
// Set the scissor to only process a horizontal slice of the frame
|
|
831
|
-
translucentPassEncoder.setScissorRect(
|
|
832
|
-
scissorX,
|
|
833
|
-
scissorY,
|
|
834
|
-
scissorWidth,
|
|
835
|
-
scissorHeight,
|
|
836
|
-
);
|
|
837
|
-
|
|
838
|
-
translucentPassEncoder.setPipeline(translucentPipeline);
|
|
839
|
-
translucentPassEncoder.setBindGroup(0, translucentBindGroup, [
|
|
840
|
-
slice * device.limits.minUniformBufferOffsetAlignment,
|
|
841
|
-
]);
|
|
842
|
-
translucentPassEncoder.setVertexBuffer(0, vertexBuffer);
|
|
843
|
-
translucentPassEncoder.setIndexBuffer(indexBuffer, "uint16");
|
|
844
|
-
translucentPassEncoder.drawIndexed(mesh.triangles.length * 3, 8);
|
|
845
|
-
translucentPassEncoder.end();
|
|
846
|
-
|
|
847
|
-
// Composite the opaque and translucent objects
|
|
848
|
-
// @ts-expect-error
|
|
849
|
-
compositePassDescriptor.colorAttachments[0].view = textureView;
|
|
850
|
-
const compositePassEncoder = commandEncoder.beginRenderPass(
|
|
851
|
-
compositePassDescriptor,
|
|
852
|
-
);
|
|
853
|
-
|
|
854
|
-
// Set the scissor to only process a horizontal slice of the frame
|
|
855
|
-
compositePassEncoder.setScissorRect(
|
|
856
|
-
scissorX,
|
|
857
|
-
scissorY,
|
|
858
|
-
scissorWidth,
|
|
859
|
-
scissorHeight,
|
|
860
|
-
);
|
|
861
|
-
|
|
862
|
-
compositePassEncoder.setPipeline(compositePipeline);
|
|
863
|
-
compositePassEncoder.setBindGroup(0, compositeBindGroup, [
|
|
864
|
-
slice * device.limits.minUniformBufferOffsetAlignment,
|
|
865
|
-
]);
|
|
866
|
-
compositePassEncoder.draw(6);
|
|
867
|
-
compositePassEncoder.end();
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
device.queue.submit([commandEncoder.finish()]);
|
|
871
|
-
};
|
|
872
|
-
};
|
|
873
|
-
|
|
874
|
-
const doDraw = configure();
|
|
875
|
-
|
|
876
|
-
doDraw();
|
|
877
|
-
|
|
878
|
-
return canvas.getImageData();
|
|
879
|
-
},
|
|
880
|
-
{
|
|
881
|
-
mesh: teapotMesh,
|
|
882
|
-
opaqueWGSL: opaque,
|
|
883
|
-
translucentWGSL: translucent,
|
|
884
|
-
compositeWGSL: composite,
|
|
885
|
-
},
|
|
886
|
-
);
|
|
887
|
-
const image = encodeImage(result);
|
|
888
|
-
checkImage(image, "snapshots/abuffer.png");
|
|
889
|
-
});
|
|
890
|
-
});
|