@woosh/meep-engine 3.60.8 → 3.60.9
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/package.json +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.d.ts +4 -1
- package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.js +35 -5
- package/src/engine/graphics3/AnimationSystem.d.ts +1 -1
- package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationSystem.js +34 -5
- package/src/engine/graphics3/FoliageWindSystem.d.ts +2 -1
- package/src/engine/graphics3/FoliageWindSystem.d.ts.map +1 -1
- package/src/engine/graphics3/FoliageWindSystem.js +50 -3
- package/src/engine/graphics3/GPUFluidSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUFluidSystem.js +16 -14
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +2 -2
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.js +84 -32
- package/src/engine/graphics3/LightSystem.d.ts +4 -0
- package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
- package/src/engine/graphics3/LightSystem.js +23 -6
- package/src/engine/graphics3/MeshSkinSystem.d.ts +1 -1
- package/src/engine/graphics3/MeshSkinSystem.d.ts.map +1 -1
- package/src/engine/graphics3/MeshSkinSystem.js +50 -5
- package/src/engine/graphics3/MeshSystem.d.ts +1 -0
- package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
- package/src/engine/graphics3/MeshSystem.js +22 -8
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts +5 -1
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics3/ShadedGeometrySystem.js +56 -7
- package/src/engine/graphics3/WaterSystem.d.ts +3 -0
- package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/WaterSystem.js +10 -2
- package/src/engine/graphics3/animation/AnimationClipsSink.d.ts +15 -7
- package/src/engine/graphics3/animation/AnimationClipsSink.d.ts.map +1 -1
- package/src/engine/graphics3/animation/AnimationClipsSink.js +42 -8
- package/src/engine/network/state/ReplicationSlotTable.d.ts +9 -5
- package/src/engine/network/state/ReplicationSlotTable.d.ts.map +1 -1
- package/src/engine/network/state/ReplicationSlotTable.js +36 -8
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/renderer/GraphicsContext.d.ts +8 -0
- package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
- package/src/shade/renderer/GraphicsContext.js +29 -0
- package/src/shade/renderer/Renderer.d.ts +10 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +22 -2
- package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
- package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +1 -1
- package/src/shade/renderer/light/GPULightCollection.d.ts +3 -1
- package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/GPULightCollection.js +34 -9
- package/src/shade/renderer/light/LightCollection.d.ts +13 -3
- package/src/shade/renderer/light/LightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/LightCollection.js +19 -3
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.d.ts +22 -0
- package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.js +30 -0
- package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.d.ts +75 -0
- package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.js +338 -0
- package/src/shade/renderer/material/dispatch/MATERIAL_DISPATCH_CONSTANTS.d.ts +50 -0
- package/src/shade/renderer/material/dispatch/MATERIAL_DISPATCH_CONSTANTS.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/MATERIAL_DISPATCH_CONSTANTS.js +54 -0
- package/src/shade/renderer/material/dispatch/MaterialDispatch.d.ts +37 -0
- package/src/shade/renderer/material/dispatch/MaterialDispatch.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/MaterialDispatch.js +31 -0
- package/src/shade/renderer/material/dispatch/MaterialDispatchRecords.d.ts +42 -0
- package/src/shade/renderer/material/dispatch/MaterialDispatchRecords.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/MaterialDispatchRecords.js +132 -0
- package/src/shade/renderer/material/dispatch/chunk_material_mesh_key.d.ts +21 -0
- package/src/shade/renderer/material/dispatch/chunk_material_mesh_key.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/chunk_material_mesh_key.js +46 -0
- package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.d.ts +20 -0
- package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.js +111 -0
- package/src/shade/renderer/material/dispatch/chunk_material_quad_pack.d.ts +18 -0
- package/src/shade/renderer/material/dispatch/chunk_material_quad_pack.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/chunk_material_quad_pack.js +33 -0
- package/src/shade/renderer/material/dispatch/gbuffer_compute.d.ts +116 -0
- package/src/shade/renderer/material/dispatch/gbuffer_compute.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/gbuffer_compute.js +249 -0
- package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.d.ts +56 -0
- package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.js +315 -0
- package/src/shade/renderer/material/dispatch/shader_material_dispatch_commands.d.ts +16 -0
- package/src/shade/renderer/material/dispatch/shader_material_dispatch_commands.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/shader_material_dispatch_commands.js +83 -0
- package/src/shade/renderer/material/dispatch/shader_material_pixel_count.d.ts +22 -0
- package/src/shade/renderer/material/dispatch/shader_material_pixel_count.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/shader_material_pixel_count.js +133 -0
- package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.d.ts +14 -0
- package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.d.ts.map +1 -0
- package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.js +98 -0
- package/src/shade/renderer/material/standard/VT_MATERIAL_TEMPLATE.d.ts +1 -0
- package/src/shade/renderer/material/standard/VT_MATERIAL_TEMPLATE.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/VT_MATERIAL_TEMPLATE.js +11 -0
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts +41 -6
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer.js +88 -29
- package/src/shade/renderer/material/template/ShadeMaterialTemplate.d.ts +13 -1
- package/src/shade/renderer/material/template/ShadeMaterialTemplate.d.ts.map +1 -1
- package/src/shade/renderer/material/template/ShadeMaterialTemplate.js +18 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +6 -0
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +17 -7
- package/src/shade/renderer/scene/Scene.d.ts +4 -3
- package/src/shade/renderer/scene/Scene.d.ts.map +1 -1
- package/src/shade/renderer/scene/Scene.js +54 -53
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts +16 -0
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.js +34 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_anti_alias_roughness_kaplanyan.d.ts +19 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_anti_alias_roughness_kaplanyan.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_anti_alias_roughness_kaplanyan.js +55 -20
- package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_keyed_append.d.ts +31 -0
- package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_keyed_append.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_keyed_append.js +77 -0
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts +6 -0
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +15 -1
- package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { GPUShaderStage } from "../../../descriptor/GPUShaderStage.js";
|
|
2
|
+
import { ComputePipelineDescriptor } from "../../../descriptor/pipeline/compute/ComputePipelineDescriptor.js";
|
|
3
|
+
import { PipelineLayoutDescriptor } from "../../../descriptor/pipeline/PipelineLayoutDescriptor.js";
|
|
4
|
+
import { WebGPUExtensionType } from "../../../descriptor/WebGPUExtensionType.js";
|
|
5
|
+
import { G_BUFFER_COLOR_TARGETS } from "../../gbuffer/G_BUFFER_COLOR_TARGETS.js";
|
|
6
|
+
import { chunk_subgroup_reserve_workgroup } from "../../shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.js";
|
|
7
|
+
import { chunk_folded_workgroup_index } from "../../shader/chunk/grid/chunk_folded_workgroup_index.js";
|
|
8
|
+
import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
|
|
9
|
+
import { ShaderResourceGroupDescriptor } from "../../shader/resource/ShaderResourceGroupDescriptor.js";
|
|
10
|
+
import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
11
|
+
import { ShaderDescriptor } from "../../shader/ShaderDescriptor.js";
|
|
12
|
+
import { u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
13
|
+
import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
|
|
14
|
+
import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
|
|
15
|
+
import {
|
|
16
|
+
add_g_buffer_viz_resources,
|
|
17
|
+
build_gbuffer_laydown,
|
|
18
|
+
g_buffer_scene_resources
|
|
19
|
+
} from "../standard/fragment_gbuffer.js";
|
|
20
|
+
import { chunk_material_quad_pack } from "./chunk_material_quad_pack.js";
|
|
21
|
+
import { MATERIAL_DISPATCH_GROUP_SIZE, MATERIAL_DISPATCH_QUADS_PER_GROUP } from "./MATERIAL_DISPATCH_CONSTANTS.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* What one material's compute dispatch is for: its indirect workgroup counts, which the dispatch is
|
|
25
|
+
* issued with, and the run of the pixel list it shades. Written by
|
|
26
|
+
* {@link shader_material_dispatch_commands}, one per material at
|
|
27
|
+
* {@link MATERIAL_DISPATCH_RECORD_STRIDE}, and bound to the dispatch as its own uniform.
|
|
28
|
+
*
|
|
29
|
+
* @type {WebGPUStruct}
|
|
30
|
+
*/
|
|
31
|
+
export const MATERIAL_DISPATCH_RECORD_STRUCT = WebGPUStruct.from({
|
|
32
|
+
groups_x: u32,
|
|
33
|
+
groups_y: u32,
|
|
34
|
+
groups_z: u32,
|
|
35
|
+
/**
|
|
36
|
+
* Index of the material's first quad in the list.
|
|
37
|
+
*/
|
|
38
|
+
start: u32,
|
|
39
|
+
/**
|
|
40
|
+
* How many quads the material has — 2×2 quads of pixels holding at least one of its pixels.
|
|
41
|
+
*/
|
|
42
|
+
count: u32,
|
|
43
|
+
}, "MaterialDispatchRecord");
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {import("../../../descriptor/binding/BindGroupLayoutDescriptor.js").BindGroupLayoutDescriptor} BindGroupLayoutDescriptor
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Group 1 of every template's compute G-buffer pipeline: what {@link build_gbuffer_laydown} reads
|
|
51
|
+
* of the visibility buffer and the view, under the names the laydown reads them by, then the quad
|
|
52
|
+
* lists the dispatch walks and the G-buffer it writes.
|
|
53
|
+
*
|
|
54
|
+
* One bind group a frame serves every template.
|
|
55
|
+
*
|
|
56
|
+
* @type {ShaderResourceGroupDescriptor}
|
|
57
|
+
*/
|
|
58
|
+
export const g_buffer_viz_compute_resources = new ShaderResourceGroupDescriptor();
|
|
59
|
+
|
|
60
|
+
g_buffer_viz_compute_resources.label = "viz buffer / compute";
|
|
61
|
+
|
|
62
|
+
add_g_buffer_viz_resources(g_buffer_viz_compute_resources)
|
|
63
|
+
// every material's quads, each as chunk_material_quad_pack packs it
|
|
64
|
+
.addStorageBuffer("material_quads", WebGPUArray.u32)
|
|
65
|
+
.addStorageTexture("g_buffer_pbr", G_BUFFER_COLOR_TARGETS[0].format, "2d", "write-only")
|
|
66
|
+
.addStorageTexture("g_buffer_normal", G_BUFFER_COLOR_TARGETS[1].format, "2d", "write-only")
|
|
67
|
+
.addStorageTexture("g_buffer_albedo", G_BUFFER_COLOR_TARGETS[2].format, "2d", "write-only")
|
|
68
|
+
.addStorageTexture("g_buffer_emissive", G_BUFFER_COLOR_TARGETS[3].format, "2d", "write-only")
|
|
69
|
+
;
|
|
70
|
+
|
|
71
|
+
g_buffer_viz_compute_resources.addVisibility(GPUShaderStage.COMPUTE);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Group 3 of every template's compute G-buffer pipeline: the dispatch's own record. A bind group
|
|
75
|
+
* per material, over that material's slice of the record buffer, so the shader learns which run of
|
|
76
|
+
* the pixel list is its own from the one thing that differs between the dispatches.
|
|
77
|
+
*
|
|
78
|
+
* @type {ShaderResourceGroupDescriptor}
|
|
79
|
+
*/
|
|
80
|
+
export const g_buffer_dispatch_resources = new ShaderResourceGroupDescriptor();
|
|
81
|
+
|
|
82
|
+
g_buffer_dispatch_resources.label = "material dispatch";
|
|
83
|
+
|
|
84
|
+
g_buffer_dispatch_resources.addUniform("material_dispatch", MATERIAL_DISPATCH_RECORD_STRUCT);
|
|
85
|
+
|
|
86
|
+
g_buffer_dispatch_resources.addVisibility(GPUShaderStage.COMPUTE);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Group 1 as every compute G-buffer pipeline lays it out.
|
|
90
|
+
*
|
|
91
|
+
* @type {BindGroupLayoutDescriptor}
|
|
92
|
+
*/
|
|
93
|
+
export const GBUFFER_COMPUTE_VIZ_LAYOUT = g_buffer_viz_compute_resources.generateBindGroupLayoutDescriptor(GPUShaderStage.COMPUTE);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Group 2 as every compute G-buffer pipeline lays it out: the fragment pipelines' scene group,
|
|
97
|
+
* visible to compute.
|
|
98
|
+
*
|
|
99
|
+
* @type {BindGroupLayoutDescriptor}
|
|
100
|
+
*/
|
|
101
|
+
export const GBUFFER_COMPUTE_SCENE_LAYOUT = g_buffer_scene_resources.generateBindGroupLayoutDescriptor(GPUShaderStage.COMPUTE);
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Group 3 as every compute G-buffer pipeline lays it out.
|
|
105
|
+
*
|
|
106
|
+
* @type {BindGroupLayoutDescriptor}
|
|
107
|
+
*/
|
|
108
|
+
export const GBUFFER_COMPUTE_DISPATCH_LAYOUT = g_buffer_dispatch_resources.generateBindGroupLayoutDescriptor(GPUShaderStage.COMPUTE);
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The resource set of a compute G-buffer pipeline whose group 0 is `material_group`: the template's
|
|
112
|
+
* own group 0 and the fragment pipelines' group 2, which this code reads under the same names, and
|
|
113
|
+
* groups 1 and 3 of its own.
|
|
114
|
+
*
|
|
115
|
+
* @param {ShaderResourceGroupDescriptor} material_group
|
|
116
|
+
* @returns {ShaderResourceSetDescriptor}
|
|
117
|
+
*/
|
|
118
|
+
export function build_gbuffer_compute_shader_resources(material_group) {
|
|
119
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
120
|
+
|
|
121
|
+
resources.addGroup(material_group);
|
|
122
|
+
resources.addGroup(g_buffer_viz_compute_resources);
|
|
123
|
+
resources.addGroup(g_buffer_scene_resources);
|
|
124
|
+
resources.addGroup(g_buffer_dispatch_resources);
|
|
125
|
+
|
|
126
|
+
return resources;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* `fn gbuffer_fwidth(v: vec2<f32>) -> vec2<f32>` for {@link build_gbuffer_laydown} in the compute
|
|
131
|
+
* material dispatch, whose quad of lanes is a 2×2 quad of pixels: `fwidth` taken coarse, across the
|
|
132
|
+
* quad's top row and left column. That is what a fragment's `fwidth` is on D3D12; WGSL lets a backend
|
|
133
|
+
* take it fine instead, and there the two paths' filtered roughness differs where the normal varies
|
|
134
|
+
* between a quad's rows.
|
|
135
|
+
*
|
|
136
|
+
* Called from uniform control flow, with every lane of the quad running the laydown.
|
|
137
|
+
*
|
|
138
|
+
* @type {CodeChunk}
|
|
139
|
+
*/
|
|
140
|
+
export const chunk_gbuffer_fwidth_quad = CodeChunk.from(
|
|
141
|
+
// language=WGSL
|
|
142
|
+
`
|
|
143
|
+
@diagnostic(off, subgroup_uniformity)
|
|
144
|
+
fn gbuffer_fwidth(v: vec2<f32>) -> vec2<f32> {
|
|
145
|
+
let top_left = quadBroadcast(v, 0u);
|
|
146
|
+
|
|
147
|
+
return abs(quadBroadcast(v, 1u) - top_left) + abs(quadBroadcast(v, 2u) - top_left);
|
|
148
|
+
}
|
|
149
|
+
`);
|
|
150
|
+
|
|
151
|
+
chunk_gbuffer_fwidth_quad.addExtension(WebGPUExtensionType.Subgroups);
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* The compute entry of a template's G-buffer pipeline: a quad of lanes per 2×2 quad of pixels in
|
|
155
|
+
* the material's run of the list, {@link build_gbuffer_laydown} at each pixel's centre, and the
|
|
156
|
+
* result stored, for the pixels of the quad that are the material's, where the fragment dispatch's
|
|
157
|
+
* colour targets would have taken it.
|
|
158
|
+
*
|
|
159
|
+
* The quad's other pixels run the laydown as a fragment quad's helper lanes do, so the derivative
|
|
160
|
+
* the laydown takes is a fragment quad's — see {@link chunk_gbuffer_fwidth_quad}. So does the tail
|
|
161
|
+
* of the material's last workgroup, on its last quad again; every lane of a workgroup that holds any
|
|
162
|
+
* of the list runs the laydown, which keeps the quad operations in uniform control flow, and a
|
|
163
|
+
* workgroup wholly past the list leaves at once.
|
|
164
|
+
*
|
|
165
|
+
* Lanes take their places in subgroup order, through {@link chunk_subgroup_reserve_workgroup}, so a
|
|
166
|
+
* quad of places is a quad of lanes however subgroups are laid over the workgroup.
|
|
167
|
+
*
|
|
168
|
+
* Dispatched with a folded command — see {@link chunk_folded_workgroup_index} — so one material can
|
|
169
|
+
* cover more of the screen than one dispatch dimension reaches.
|
|
170
|
+
*
|
|
171
|
+
* @param {CodeChunk} surface defines `fn material_surface(s: MaterialSurfaceInput) -> MaterialSurfaceOutput`
|
|
172
|
+
* @returns {CodeChunk}
|
|
173
|
+
*/
|
|
174
|
+
export function build_gbuffer_compute_body(surface) {
|
|
175
|
+
return CodeChunk.from(
|
|
176
|
+
// language=WGSL
|
|
177
|
+
`
|
|
178
|
+
var<workgroup> material_dispatch_places: atomic<u32>;
|
|
179
|
+
|
|
180
|
+
@compute @workgroup_size(${MATERIAL_DISPATCH_GROUP_SIZE})
|
|
181
|
+
fn main(
|
|
182
|
+
@builtin(workgroup_id) workgroup_id : vec3<u32>,
|
|
183
|
+
) {
|
|
184
|
+
let first_quad = folded_workgroup_index(workgroup_id) * ${MATERIAL_DISPATCH_QUADS_PER_GROUP}u;
|
|
185
|
+
let count = material_dispatch.count;
|
|
186
|
+
|
|
187
|
+
// a folded grid's last row runs past the list; the whole workgroup leaves together, so what
|
|
188
|
+
// follows stays in uniform control flow
|
|
189
|
+
if (first_quad >= count) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
let place = subgroup_reserve_workgroup(&material_dispatch_places, 1u);
|
|
194
|
+
|
|
195
|
+
let quad_index = first_quad + place / 4u;
|
|
196
|
+
let corner = place & 3u;
|
|
197
|
+
|
|
198
|
+
let in_list = quad_index < count;
|
|
199
|
+
|
|
200
|
+
let entry = material_quad_unpack(material_quads[material_dispatch.start + min(quad_index, count - 1u)]);
|
|
201
|
+
|
|
202
|
+
let pixel = entry.quad * 2u + vec2<u32>(corner & 1u, corner >> 1u);
|
|
203
|
+
|
|
204
|
+
// the pixel's centre, which is what a fragment's position holds
|
|
205
|
+
let g = gbuffer_laydown(vec2<f32>(pixel) + vec2<f32>(0.5));
|
|
206
|
+
|
|
207
|
+
if (in_list && ((entry.mask >> corner) & 1u) != 0u) {
|
|
208
|
+
textureStore(g_buffer_pbr, pixel, vec4<f32>(g.pbr, 0.0, 0.0));
|
|
209
|
+
textureStore(g_buffer_normal, pixel, g.normal);
|
|
210
|
+
textureStore(g_buffer_albedo, pixel, g.albedo);
|
|
211
|
+
textureStore(g_buffer_emissive, pixel, vec4<u32>(g.emissive, 0u, 0u, 0u));
|
|
212
|
+
}
|
|
213
|
+
}`, [
|
|
214
|
+
build_gbuffer_laydown(surface, chunk_gbuffer_fwidth_quad),
|
|
215
|
+
chunk_folded_workgroup_index,
|
|
216
|
+
chunk_subgroup_reserve_workgroup,
|
|
217
|
+
chunk_material_quad_pack,
|
|
218
|
+
]
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The compute G-buffer pipeline of a template: its group 0 and surface function around the shared
|
|
224
|
+
* laydown. Every group is laid out for the compute stage, whatever stages its declaration names, so
|
|
225
|
+
* no template has to declare anything for this pipeline: a material's group 0 for it is a bind group
|
|
226
|
+
* of its own, made by the template's own hook over this layout.
|
|
227
|
+
*
|
|
228
|
+
* @param {Object} options
|
|
229
|
+
* @param {string} options.label
|
|
230
|
+
* @param {ShaderResourceGroupDescriptor} options.material_group the template's group 0
|
|
231
|
+
* @param {CodeChunk} options.surface defines `material_surface`
|
|
232
|
+
* @returns {ComputePipelineDescriptor}
|
|
233
|
+
*/
|
|
234
|
+
export function build_gbuffer_compute_pipeline_descriptor({ label, material_group, surface }) {
|
|
235
|
+
const shader = ShaderDescriptor.from({
|
|
236
|
+
label,
|
|
237
|
+
resources: build_gbuffer_compute_shader_resources(material_group),
|
|
238
|
+
body: build_gbuffer_compute_body(surface),
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
const layout = PipelineLayoutDescriptor.from([
|
|
242
|
+
material_group.generateBindGroupLayoutDescriptor(GPUShaderStage.COMPUTE),
|
|
243
|
+
GBUFFER_COMPUTE_VIZ_LAYOUT,
|
|
244
|
+
GBUFFER_COMPUTE_SCENE_LAYOUT,
|
|
245
|
+
GBUFFER_COMPUTE_DISPATCH_LAYOUT,
|
|
246
|
+
]);
|
|
247
|
+
|
|
248
|
+
return ComputePipelineDescriptor.from(label, shader.source, layout);
|
|
249
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lay the G-buffer down with the compute material dispatch — see {@link MaterialDispatch.Compute}:
|
|
3
|
+
*
|
|
4
|
+
* 1. **count** every 2×2 quad into the (material, tile) list of each material it holds, and clear
|
|
5
|
+
* the pixels no material shades;
|
|
6
|
+
* 2. **scan** the counts, so each list knows where it starts;
|
|
7
|
+
* 3. write each material's **dispatch record** — its run of the lists and its workgroup counts;
|
|
8
|
+
* 4. **scatter** every quad into its lists;
|
|
9
|
+
* 5. **shade**: one compute pass, one indirect dispatch per material over its own run, with the
|
|
10
|
+
* material's compute bind group, its template's compute pipeline, and its record as group 3.
|
|
11
|
+
*
|
|
12
|
+
* The material lists are ordered as `contexts` is, which is by template, so pipeline switches in the
|
|
13
|
+
* shade pass are one per template; within a material its quads run tile by tile.
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} options
|
|
16
|
+
* @param {FrameGraph} options.graph
|
|
17
|
+
* @param {GPUViewContext} options.view
|
|
18
|
+
* @param {GPUMaterialContext[]} options.contexts the G-buffer materials, as the fragment dispatch
|
|
19
|
+
* draws them
|
|
20
|
+
* @param {Uint32Array} options.material_slots a {@link cpu_hash_table_create} table from each
|
|
21
|
+
* context's material id to its place in `contexts`
|
|
22
|
+
* @param {MaterialDispatchRecords} options.records with room for every context
|
|
23
|
+
* @param {BindGroupManager} options.bindings
|
|
24
|
+
* @param {function(GPUMaterialContext):GPUComputePipeline} options.pipeline_of the context's
|
|
25
|
+
* compute G-buffer pipeline
|
|
26
|
+
* @param {function(GPUMaterialContext):GPUBindGroup} options.group_of the context's group 0 for
|
|
27
|
+
* that pipeline
|
|
28
|
+
* @param {number} options.texture_viz_mesh
|
|
29
|
+
* @param {number} options.texture_viz_triangle
|
|
30
|
+
* @param {number} options.texture_normal
|
|
31
|
+
* @returns {{g_pbr: number, g_normal: number, g_albedo: number, g_emissive: number}}
|
|
32
|
+
*/
|
|
33
|
+
export function graph_material_dispatch_compute({ graph, view, contexts, material_slots, records, bindings, pipeline_of, group_of, texture_viz_mesh, texture_viz_triangle, texture_normal, }: {
|
|
34
|
+
graph: FrameGraph;
|
|
35
|
+
view: GPUViewContext;
|
|
36
|
+
contexts: GPUMaterialContext[];
|
|
37
|
+
material_slots: Uint32Array;
|
|
38
|
+
records: MaterialDispatchRecords;
|
|
39
|
+
bindings: BindGroupManager;
|
|
40
|
+
pipeline_of: (arg0: GPUMaterialContext) => GPUComputePipeline;
|
|
41
|
+
group_of: (arg0: GPUMaterialContext) => GPUBindGroup;
|
|
42
|
+
texture_viz_mesh: number;
|
|
43
|
+
texture_viz_triangle: number;
|
|
44
|
+
texture_normal: number;
|
|
45
|
+
}): {
|
|
46
|
+
g_pbr: number;
|
|
47
|
+
g_normal: number;
|
|
48
|
+
g_albedo: number;
|
|
49
|
+
g_emissive: number;
|
|
50
|
+
};
|
|
51
|
+
export type FrameGraph = import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
|
|
52
|
+
export type BindGroupManager = import("../../binding/BindGroupManager.js").BindGroupManager;
|
|
53
|
+
export type GPUViewContext = import("../../view/GPUViewContext.js").GPUViewContext;
|
|
54
|
+
export type GPUMaterialContext = import("../GPUMaterialContext.js").GPUMaterialContext;
|
|
55
|
+
export type MaterialDispatchRecords = import("./MaterialDispatchRecords.js").MaterialDispatchRecords;
|
|
56
|
+
//# sourceMappingURL=graph_material_dispatch_compute.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph_material_dispatch_compute.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/dispatch/graph_material_dispatch_compute.js"],"names":[],"mappings":"AAkDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH;IAjB+B,KAAK,EAAzB,UAAU;IACc,IAAI,EAA5B,cAAc;IACgB,QAAQ,EAAtC,kBAAkB,EAAE;IAEC,cAAc,EAAnC,WAAW;IAEsB,OAAO,EAAxC,uBAAuB;IACG,QAAQ,EAAlC,gBAAgB;IACyC,WAAW,SAA3D,kBAAkB;IAEwB,QAAQ,SAAlD,kBAAkB;IAEX,gBAAgB,EAAhC,MAAM;IACU,oBAAoB,EAApC,MAAM;IACU,cAAc,EAA9B,MAAM;IACJ;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAC,CA0OnF;yBA/RY,OAAO,8DAA8D,EAAE,UAAU;+BACjF,OAAO,mCAAmC,EAAE,gBAAgB;6BAC5D,OAAO,8BAA8B,EAAE,cAAc;iCACrD,OAAO,0BAA0B,EAAE,kBAAkB;sCACrD,OAAO,8BAA8B,EAAE,uBAAuB"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { round_up } from "../../../../core/math/round_up.js";
|
|
3
|
+
import { BufferResourceDescriptor } from "../../../device/graph/BufferResourceDescriptor.js";
|
|
4
|
+
import { TextureResourceDescriptor } from "../../../device/graph/TextureResourceDescriptor.js";
|
|
5
|
+
import { BindGroupDescriptor } from "../../binding/BindGroupDescriptor.js";
|
|
6
|
+
import { G_BUFFER_COLOR_TARGETS } from "../../gbuffer/G_BUFFER_COLOR_TARGETS.js";
|
|
7
|
+
import {
|
|
8
|
+
graph_prefix_scan_csdldf,
|
|
9
|
+
prefix_scan_csdldf_output_descriptor
|
|
10
|
+
} from "../../gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js";
|
|
11
|
+
import { graph_create_buffer } from "../../shader/graph/graph_create_buffer.js";
|
|
12
|
+
import { graph_import_buffer } from "../../shader/graph/graph_import_buffer.js";
|
|
13
|
+
import { graph_import_raw_buffer } from "../../shader/graph/graph_import_raw_buffer.js";
|
|
14
|
+
import { GBUFFER_COMPUTE_SCENE_LAYOUT, GBUFFER_COMPUTE_VIZ_LAYOUT } from "./gbuffer_compute.js";
|
|
15
|
+
import {
|
|
16
|
+
MATERIAL_CLASSIFY_BLOCK_SIZE,
|
|
17
|
+
MATERIAL_DISPATCH_RECORD_STRIDE,
|
|
18
|
+
MATERIAL_DISPATCH_TILE_SIZE
|
|
19
|
+
} from "./MATERIAL_DISPATCH_CONSTANTS.js";
|
|
20
|
+
import {
|
|
21
|
+
MATERIAL_DISPATCH_COMMANDS_SETTINGS_STRUCT,
|
|
22
|
+
shader_material_dispatch_commands
|
|
23
|
+
} from "./shader_material_dispatch_commands.js";
|
|
24
|
+
import { MATERIAL_CLASSIFY_SETTINGS_STRUCT, shader_material_pixel_count } from "./shader_material_pixel_count.js";
|
|
25
|
+
import { shader_material_pixel_scatter } from "./shader_material_pixel_scatter.js";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
|
|
29
|
+
* @typedef {import("../../binding/BindGroupManager.js").BindGroupManager} BindGroupManager
|
|
30
|
+
* @typedef {import("../../view/GPUViewContext.js").GPUViewContext} GPUViewContext
|
|
31
|
+
* @typedef {import("../GPUMaterialContext.js").GPUMaterialContext} GPUMaterialContext
|
|
32
|
+
* @typedef {import("./MaterialDispatchRecords.js").MaterialDispatchRecords} MaterialDispatchRecords
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The G-buffer targets the compute dispatch creates, in the formats every G-buffer pass writes, and
|
|
37
|
+
* written as storage. They stay render attachments for whatever composites into them later.
|
|
38
|
+
*
|
|
39
|
+
* @param {GPUTextureFormat} format
|
|
40
|
+
* @param {number[]} resolution
|
|
41
|
+
* @returns {TextureResourceDescriptor}
|
|
42
|
+
*/
|
|
43
|
+
function storage_target(format, resolution) {
|
|
44
|
+
return TextureResourceDescriptor.from({
|
|
45
|
+
format,
|
|
46
|
+
resolution,
|
|
47
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Lay the G-buffer down with the compute material dispatch — see {@link MaterialDispatch.Compute}:
|
|
53
|
+
*
|
|
54
|
+
* 1. **count** every 2×2 quad into the (material, tile) list of each material it holds, and clear
|
|
55
|
+
* the pixels no material shades;
|
|
56
|
+
* 2. **scan** the counts, so each list knows where it starts;
|
|
57
|
+
* 3. write each material's **dispatch record** — its run of the lists and its workgroup counts;
|
|
58
|
+
* 4. **scatter** every quad into its lists;
|
|
59
|
+
* 5. **shade**: one compute pass, one indirect dispatch per material over its own run, with the
|
|
60
|
+
* material's compute bind group, its template's compute pipeline, and its record as group 3.
|
|
61
|
+
*
|
|
62
|
+
* The material lists are ordered as `contexts` is, which is by template, so pipeline switches in the
|
|
63
|
+
* shade pass are one per template; within a material its quads run tile by tile.
|
|
64
|
+
*
|
|
65
|
+
* @param {Object} options
|
|
66
|
+
* @param {FrameGraph} options.graph
|
|
67
|
+
* @param {GPUViewContext} options.view
|
|
68
|
+
* @param {GPUMaterialContext[]} options.contexts the G-buffer materials, as the fragment dispatch
|
|
69
|
+
* draws them
|
|
70
|
+
* @param {Uint32Array} options.material_slots a {@link cpu_hash_table_create} table from each
|
|
71
|
+
* context's material id to its place in `contexts`
|
|
72
|
+
* @param {MaterialDispatchRecords} options.records with room for every context
|
|
73
|
+
* @param {BindGroupManager} options.bindings
|
|
74
|
+
* @param {function(GPUMaterialContext):GPUComputePipeline} options.pipeline_of the context's
|
|
75
|
+
* compute G-buffer pipeline
|
|
76
|
+
* @param {function(GPUMaterialContext):GPUBindGroup} options.group_of the context's group 0 for
|
|
77
|
+
* that pipeline
|
|
78
|
+
* @param {number} options.texture_viz_mesh
|
|
79
|
+
* @param {number} options.texture_viz_triangle
|
|
80
|
+
* @param {number} options.texture_normal
|
|
81
|
+
* @returns {{g_pbr: number, g_normal: number, g_albedo: number, g_emissive: number}}
|
|
82
|
+
*/
|
|
83
|
+
export function graph_material_dispatch_compute({
|
|
84
|
+
graph,
|
|
85
|
+
view,
|
|
86
|
+
contexts,
|
|
87
|
+
material_slots,
|
|
88
|
+
records,
|
|
89
|
+
bindings,
|
|
90
|
+
pipeline_of,
|
|
91
|
+
group_of,
|
|
92
|
+
texture_viz_mesh,
|
|
93
|
+
texture_viz_triangle,
|
|
94
|
+
texture_normal,
|
|
95
|
+
}) {
|
|
96
|
+
assert.defined(graph, 'graph');
|
|
97
|
+
assert.defined(view, 'view');
|
|
98
|
+
assert.isArray(contexts, 'contexts');
|
|
99
|
+
|
|
100
|
+
const resolution = view.resolution;
|
|
101
|
+
|
|
102
|
+
const width = resolution[0];
|
|
103
|
+
const height = resolution[1];
|
|
104
|
+
|
|
105
|
+
const tiles_x = Math.ceil(width / MATERIAL_DISPATCH_TILE_SIZE);
|
|
106
|
+
const tile_count = tiles_x * Math.ceil(height / MATERIAL_DISPATCH_TILE_SIZE);
|
|
107
|
+
|
|
108
|
+
const slot_count = contexts.length;
|
|
109
|
+
// never empty: an empty list still clears the G-buffer, and the scan wants room for one
|
|
110
|
+
const list_count = Math.max(1, slot_count * tile_count);
|
|
111
|
+
|
|
112
|
+
const classify_settings = {
|
|
113
|
+
resolution,
|
|
114
|
+
tiles_x,
|
|
115
|
+
tile_count,
|
|
116
|
+
slot_count,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const block_count_x = Math.ceil(width / MATERIAL_CLASSIFY_BLOCK_SIZE);
|
|
120
|
+
const block_count_y = Math.ceil(height / MATERIAL_CLASSIFY_BLOCK_SIZE);
|
|
121
|
+
|
|
122
|
+
// at least one, so there is a buffer to name in the graph when the list is empty
|
|
123
|
+
records.reserve(Math.max(1, slot_count));
|
|
124
|
+
|
|
125
|
+
const gr_material_slots = graph_import_raw_buffer({
|
|
126
|
+
graph,
|
|
127
|
+
value: material_slots.buffer,
|
|
128
|
+
offset: material_slots.byteOffset,
|
|
129
|
+
size: material_slots.byteLength,
|
|
130
|
+
label: "material slots",
|
|
131
|
+
usage: GPUBufferUsage.STORAGE,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// 1. count
|
|
135
|
+
const count_data = {};
|
|
136
|
+
|
|
137
|
+
const count_pass = graph.add("Material dispatch / count", count_data, (data, resources, context) => {
|
|
138
|
+
const encoder = context.encoder;
|
|
139
|
+
|
|
140
|
+
shader_material_pixel_count.dispatch({
|
|
141
|
+
encoder,
|
|
142
|
+
bindings: {
|
|
143
|
+
viz_buffer_mesh: resources.get(data.viz_mesh).obtainView(),
|
|
144
|
+
material_slots: resources.get(data.material_slots),
|
|
145
|
+
counts: resources.get(data.counts),
|
|
146
|
+
settings: encoder.allocateTransientValueBuffer(MATERIAL_CLASSIFY_SETTINGS_STRUCT, classify_settings, GPUBufferUsage.UNIFORM),
|
|
147
|
+
g_buffer_pbr: resources.get(data.g_pbr).obtainView(),
|
|
148
|
+
g_buffer_normal: resources.get(data.g_normal).obtainView(),
|
|
149
|
+
g_buffer_albedo: resources.get(data.g_albedo).obtainView(),
|
|
150
|
+
g_buffer_emissive: resources.get(data.g_emissive).obtainView(),
|
|
151
|
+
scene_database: view.scene.scene_database_buffer,
|
|
152
|
+
},
|
|
153
|
+
group_count_x: block_count_x,
|
|
154
|
+
group_count_y: block_count_y,
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
count_data.viz_mesh = count_pass.read(texture_viz_mesh);
|
|
159
|
+
count_data.material_slots = count_pass.read(gr_material_slots);
|
|
160
|
+
count_data.counts = count_pass.create("material pixel counts", BufferResourceDescriptor.empty(
|
|
161
|
+
round_up(16 + list_count * 4, 16),
|
|
162
|
+
GPUBufferUsage.STORAGE
|
|
163
|
+
));
|
|
164
|
+
count_data.g_pbr = count_pass.create("g-buffer / PBR", storage_target(G_BUFFER_COLOR_TARGETS[0].format, resolution));
|
|
165
|
+
count_data.g_normal = count_pass.write(texture_normal);
|
|
166
|
+
count_data.g_albedo = count_pass.create("g-buffer / Albedo", storage_target(G_BUFFER_COLOR_TARGETS[2].format, resolution));
|
|
167
|
+
count_data.g_emissive = count_pass.create("g-buffer / Emissive", storage_target(G_BUFFER_COLOR_TARGETS[3].format, resolution));
|
|
168
|
+
|
|
169
|
+
// 2. scan
|
|
170
|
+
const gr_offsets = graph_prefix_scan_csdldf({
|
|
171
|
+
graph,
|
|
172
|
+
input: count_data.counts,
|
|
173
|
+
output: graph_create_buffer(graph, "material pixel offsets", prefix_scan_csdldf_output_descriptor(list_count)),
|
|
174
|
+
element_max_count: list_count,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// 3. dispatch records
|
|
178
|
+
const commands_settings = { tile_count, slot_count };
|
|
179
|
+
|
|
180
|
+
const commands_data = {};
|
|
181
|
+
|
|
182
|
+
const commands_pass = graph.add("Material dispatch / commands", commands_data, (data, resources, context) => {
|
|
183
|
+
if (slot_count === 0) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const encoder = context.encoder;
|
|
188
|
+
|
|
189
|
+
shader_material_dispatch_commands.dispatchThreads({
|
|
190
|
+
encoder,
|
|
191
|
+
bindings: {
|
|
192
|
+
offsets: resources.get(data.offsets),
|
|
193
|
+
records: resources.get(data.records),
|
|
194
|
+
settings: encoder.allocateTransientValueBuffer(MATERIAL_DISPATCH_COMMANDS_SETTINGS_STRUCT, commands_settings, GPUBufferUsage.UNIFORM),
|
|
195
|
+
},
|
|
196
|
+
thread_count_x: slot_count,
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
commands_data.offsets = commands_pass.read(gr_offsets);
|
|
201
|
+
commands_data.records = commands_pass.write(graph_import_buffer(graph, records.buffer, "material dispatch records"));
|
|
202
|
+
|
|
203
|
+
// 4. scatter
|
|
204
|
+
const scatter_data = {};
|
|
205
|
+
|
|
206
|
+
const scatter_pass = graph.add("Material dispatch / scatter", scatter_data, (data, resources, context) => {
|
|
207
|
+
const encoder = context.encoder;
|
|
208
|
+
|
|
209
|
+
shader_material_pixel_scatter.dispatch({
|
|
210
|
+
encoder,
|
|
211
|
+
bindings: {
|
|
212
|
+
viz_buffer_mesh: resources.get(data.viz_mesh).obtainView(),
|
|
213
|
+
material_slots: resources.get(data.material_slots),
|
|
214
|
+
settings: encoder.allocateTransientValueBuffer(MATERIAL_CLASSIFY_SETTINGS_STRUCT, classify_settings, GPUBufferUsage.UNIFORM),
|
|
215
|
+
offsets: resources.get(data.offsets),
|
|
216
|
+
cursors: resources.get(data.cursors),
|
|
217
|
+
material_quads: resources.get(data.material_quads),
|
|
218
|
+
scene_database: view.scene.scene_database_buffer,
|
|
219
|
+
},
|
|
220
|
+
group_count_x: block_count_x,
|
|
221
|
+
group_count_y: block_count_y,
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
scatter_data.viz_mesh = scatter_pass.read(texture_viz_mesh);
|
|
226
|
+
scatter_data.material_slots = scatter_pass.read(gr_material_slots);
|
|
227
|
+
scatter_data.offsets = scatter_pass.read(gr_offsets);
|
|
228
|
+
scatter_data.cursors = scatter_pass.create("material pixel cursors", BufferResourceDescriptor.empty(
|
|
229
|
+
round_up(list_count * 4, 16),
|
|
230
|
+
GPUBufferUsage.STORAGE
|
|
231
|
+
));
|
|
232
|
+
scatter_data.material_quads = scatter_pass.create("material quads", BufferResourceDescriptor.from(
|
|
233
|
+
round_up(width * height * 4, 16),
|
|
234
|
+
GPUBufferUsage.STORAGE
|
|
235
|
+
));
|
|
236
|
+
|
|
237
|
+
// 5. shade
|
|
238
|
+
const shade_data = {};
|
|
239
|
+
|
|
240
|
+
const shade_pass = graph.add("Material dispatch / shade", shade_data, (data, resources, context) => {
|
|
241
|
+
const encoder = context.encoder;
|
|
242
|
+
|
|
243
|
+
const g_pbr = resources.get(data.g_pbr);
|
|
244
|
+
const g_normal = resources.get(data.g_normal);
|
|
245
|
+
const g_albedo = resources.get(data.g_albedo);
|
|
246
|
+
const g_emissive = resources.get(data.g_emissive);
|
|
247
|
+
|
|
248
|
+
const record_buffer = resources.get(data.records);
|
|
249
|
+
|
|
250
|
+
// the group 3s are made over the records' current buffer; a growth since this frame was
|
|
251
|
+
// recorded would leave them on a different one than the commands
|
|
252
|
+
assert.equal(record_buffer, records.buffer, 'the dispatch records were replaced between recording and executing the frame');
|
|
253
|
+
|
|
254
|
+
const bind_1 = bindings.obtain(BindGroupDescriptor.from(GBUFFER_COMPUTE_VIZ_LAYOUT, [
|
|
255
|
+
resources.get(data.viz_triangle).obtainView(),
|
|
256
|
+
resources.get(data.viz_mesh).obtainView(),
|
|
257
|
+
{ buffer: view.uniform_buffer.buffer },
|
|
258
|
+
{ buffer: view.camera.buffer.buffer },
|
|
259
|
+
{ buffer: resources.get(data.material_quads) },
|
|
260
|
+
g_pbr.obtainView(),
|
|
261
|
+
g_normal.obtainView(),
|
|
262
|
+
g_albedo.obtainView(),
|
|
263
|
+
g_emissive.obtainView(),
|
|
264
|
+
]));
|
|
265
|
+
|
|
266
|
+
const bind_2 = bindings.obtain(BindGroupDescriptor.from(GBUFFER_COMPUTE_SCENE_LAYOUT, [
|
|
267
|
+
{ buffer: view.scene.scene_database_buffer },
|
|
268
|
+
{ buffer: view.scene.geometries.buffer_metadata },
|
|
269
|
+
{ buffer: view.scene.geometries.meshlets.buffer_metadata },
|
|
270
|
+
{ buffer: view.scene.geometries.meshlets.buffer_data },
|
|
271
|
+
]));
|
|
272
|
+
|
|
273
|
+
const pass = encoder.beginComputePass({ label: "Material dispatch / shade" });
|
|
274
|
+
|
|
275
|
+
pass.setBindGroup(1, bind_1);
|
|
276
|
+
pass.setBindGroup(2, bind_2);
|
|
277
|
+
|
|
278
|
+
let bound_pipeline = null;
|
|
279
|
+
|
|
280
|
+
for (let slot = 0; slot < slot_count; slot++) {
|
|
281
|
+
const material_ctx = contexts[slot];
|
|
282
|
+
|
|
283
|
+
const pipeline = pipeline_of(material_ctx);
|
|
284
|
+
|
|
285
|
+
if (pipeline !== bound_pipeline) {
|
|
286
|
+
pass.setPipeline(pipeline);
|
|
287
|
+
|
|
288
|
+
bound_pipeline = pipeline;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
pass.setBindGroup(0, group_of(material_ctx));
|
|
292
|
+
pass.setBindGroup(3, records.bind_group(slot));
|
|
293
|
+
|
|
294
|
+
pass.dispatchWorkgroupsIndirect(record_buffer, slot * MATERIAL_DISPATCH_RECORD_STRIDE);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
pass.end();
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
shade_data.viz_triangle = shade_pass.read(texture_viz_triangle);
|
|
301
|
+
shade_data.viz_mesh = shade_pass.read(texture_viz_mesh);
|
|
302
|
+
shade_data.material_quads = shade_pass.read(scatter_data.material_quads);
|
|
303
|
+
shade_data.records = shade_pass.read(commands_data.records);
|
|
304
|
+
shade_data.g_pbr = shade_pass.write(shade_pass.read(count_data.g_pbr));
|
|
305
|
+
shade_data.g_normal = shade_pass.write(shade_pass.read(count_data.g_normal));
|
|
306
|
+
shade_data.g_albedo = shade_pass.write(shade_pass.read(count_data.g_albedo));
|
|
307
|
+
shade_data.g_emissive = shade_pass.write(shade_pass.read(count_data.g_emissive));
|
|
308
|
+
|
|
309
|
+
return {
|
|
310
|
+
g_pbr: shade_data.g_pbr,
|
|
311
|
+
g_normal: shade_data.g_normal,
|
|
312
|
+
g_albedo: shade_data.g_albedo,
|
|
313
|
+
g_emissive: shade_data.g_emissive,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @type {WebGPUStruct}
|
|
3
|
+
*/
|
|
4
|
+
export const MATERIAL_DISPATCH_COMMANDS_SETTINGS_STRUCT: WebGPUStruct;
|
|
5
|
+
/**
|
|
6
|
+
* Write each material's {@link MATERIAL_DISPATCH_RECORD_STRUCT}: its run of the pixel list, from
|
|
7
|
+
* the inclusive sums of the (material, tile) counts, and the folded workgroup counts its dispatch is
|
|
8
|
+
* issued with — `(0, 1, 1)` for a material with no pixel on screen. One invocation per material,
|
|
9
|
+
* dispatched directly over the G-buffer pass's list.
|
|
10
|
+
*
|
|
11
|
+
* @type {ComputeShader}
|
|
12
|
+
*/
|
|
13
|
+
export const shader_material_dispatch_commands: ComputeShader;
|
|
14
|
+
import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
|
|
15
|
+
import { ComputeShader } from "../../shader/ComputeShader.js";
|
|
16
|
+
//# sourceMappingURL=shader_material_dispatch_commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader_material_dispatch_commands.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/dispatch/shader_material_dispatch_commands.js"],"names":[],"mappings":"AAWA;;GAEG;AACH,yDAFU,YAAY,CAKiB;AAqDvC;;;;;;;GAOG;AACH,gDAFU,aAAa,CAMpB;6BA1E0B,mCAAmC;8BAJlC,+BAA+B"}
|