@woosh/meep-engine 3.14.0 → 3.14.2
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 +33 -64
- package/package.json +1 -1
- package/src/avif/native/DECISIONS.md +544 -536
- package/src/avif/native/heif/parse_avif_file.d.ts.map +1 -1
- package/src/avif/native/heif/parse_avif_file.js +384 -383
- package/src/avif/native/heif/parse_image_grid.d.ts.map +1 -1
- package/src/avif/native/heif/parse_image_grid.js +49 -48
- package/src/basis/BasisBitReader.d.ts +77 -0
- package/src/basis/BasisBitReader.d.ts.map +1 -0
- package/src/basis/BasisBitReader.js +231 -0
- package/src/basis/BasisHuffmanTable.d.ts +53 -0
- package/src/basis/BasisHuffmanTable.d.ts.map +1 -0
- package/src/basis/BasisHuffmanTable.js +263 -0
- package/src/basis/basis_read_huffman_table.d.ts +20 -0
- package/src/basis/basis_read_huffman_table.d.ts.map +1 -0
- package/src/basis/basis_read_huffman_table.js +187 -0
- package/src/basis/etc1s/Etc1sSelectorHistory.d.ts +50 -0
- package/src/basis/etc1s/Etc1sSelectorHistory.d.ts.map +1 -0
- package/src/basis/etc1s/Etc1sSelectorHistory.js +89 -0
- package/src/basis/etc1s/etc1s_block_colors.d.ts +14 -0
- package/src/basis/etc1s/etc1s_block_colors.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_block_colors.js +75 -0
- package/src/basis/etc1s/etc1s_decode_slice.d.ts +57 -0
- package/src/basis/etc1s/etc1s_decode_slice.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_decode_slice.js +258 -0
- package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts +48 -0
- package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_read_endpoint_codebook.js +111 -0
- package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts +42 -0
- package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_read_selector_codebook.js +127 -0
- package/src/basis/etc1s/etc1s_read_slice_tables.d.ts +54 -0
- package/src/basis/etc1s/etc1s_read_slice_tables.d.ts.map +1 -0
- package/src/basis/etc1s/etc1s_read_slice_tables.js +47 -0
- package/src/basis/transcode/build_range_plan.js +54 -0
- package/src/basis/transcode/etc1s_to_bc1.d.ts +24 -0
- package/src/basis/transcode/etc1s_to_bc1.d.ts.map +1 -0
- package/src/basis/transcode/etc1s_to_bc1.js +205 -0
- package/src/basis/transcode/etc1s_to_bc7.d.ts +30 -0
- package/src/basis/transcode/etc1s_to_bc7.d.ts.map +1 -0
- package/src/basis/transcode/etc1s_to_bc7.js +496 -0
- package/src/basis/transcode/fit_endpoints.d.ts +59 -0
- package/src/basis/transcode/fit_endpoints.d.ts.map +1 -0
- package/src/basis/transcode/fit_endpoints.js +226 -0
- package/src/{avif/native/isobmff → core/binary}/ByteCursor.d.ts +19 -6
- package/src/core/binary/ByteCursor.d.ts.map +1 -0
- package/src/{avif/native/isobmff → core/binary}/ByteCursor.js +41 -14
- package/src/engine/EngineHarness.js +1 -1
- package/src/engine/asset/codec/Codec.d.ts.map +1 -0
- package/src/engine/asset/codec/CodecWithFallback.d.ts.map +1 -0
- package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.js +2 -2
- package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +4 -4
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +1 -1
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts +1 -1
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.js +1 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts +1 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts.map +1 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +1 -1
- package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/TextureAtlas.js +13 -0
- package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
- package/src/engine/physics/broadphase/generate_pairs.js +7 -1
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/ktx2/KTX2_IDENTIFIER.d.ts +14 -0
- package/src/ktx2/KTX2_IDENTIFIER.d.ts.map +1 -0
- package/src/ktx2/KTX2_IDENTIFIER.js +15 -0
- package/src/ktx2/KhrDfModel.d.ts +35 -0
- package/src/ktx2/KhrDfModel.d.ts.map +1 -0
- package/src/ktx2/KhrDfModel.js +49 -0
- package/src/ktx2/SupercompressionScheme.d.ts +16 -0
- package/src/ktx2/SupercompressionScheme.d.ts.map +1 -0
- package/src/ktx2/SupercompressionScheme.js +23 -0
- package/src/ktx2/ktx2_read.d.ts +71 -0
- package/src/ktx2/ktx2_read.d.ts.map +1 -0
- package/src/ktx2/ktx2_read.js +581 -0
- package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts +27 -0
- package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts.map +1 -0
- package/src/ktx2/ktx2_read_basis_lz_global_data.js +189 -0
- package/src/ktx2/vk_format_to_texture_format.d.ts +55 -0
- package/src/ktx2/vk_format_to_texture_format.d.ts.map +1 -0
- package/src/ktx2/vk_format_to_texture_format.js +290 -0
- package/src/shade/descriptor/GPUTextureUsage.d.ts +23 -0
- package/src/shade/descriptor/GPUTextureUsage.d.ts.map +1 -0
- package/src/shade/descriptor/GPUTextureUsage.js +24 -0
- package/src/shade/descriptor/WebGPUExtensionType.d.ts +3 -0
- package/src/shade/descriptor/WebGPUExtensionType.js +26 -0
- package/src/shade/descriptor/texture/TextureDescriptor.d.ts +2 -6
- package/src/shade/descriptor/texture/TextureDescriptor.d.ts.map +1 -1
- package/src/shade/descriptor/texture/TextureDescriptor.js +24 -40
- package/src/shade/descriptor/texture/format/TextureFormat.d.ts +125 -0
- package/src/shade/descriptor/texture/format/TextureFormat.d.ts.map +1 -0
- package/src/shade/descriptor/texture/format/TextureFormat.js +146 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts +60 -0
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts.map +1 -1
- package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +102 -0
- package/src/shade/device/graph/TextureResourceDescriptor.d.ts.map +1 -1
- package/src/shade/device/graph/TextureResourceDescriptor.js +160 -155
- package/src/shade/device/mock/SoftwareGPUQueue.d.ts +11 -4
- package/src/shade/device/mock/SoftwareGPUQueue.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUQueue.js +31 -37
- package/src/shade/device/mock/SoftwareGPUTexture.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUTexture.js +8 -4
- package/src/shade/device/timing/profile/frame_graph_extract_topology.d.ts.map +1 -1
- package/src/shade/device/timing/profile/frame_graph_extract_topology.js +164 -174
- package/src/shade/playground/ground_seam/README.md +235 -0
- package/src/shade/playground/ground_seam/capture_scene_color.d.ts +45 -0
- package/src/shade/playground/ground_seam/capture_scene_color.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/capture_scene_color.js +242 -0
- package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts +11 -0
- package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/depth_step_across_seam.js +185 -0
- package/src/shade/playground/ground_seam/index.html +195 -0
- package/src/shade/playground/ground_seam/main.d.ts +2 -0
- package/src/shade/playground/ground_seam/main.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/main.js +879 -0
- package/src/shade/playground/ground_seam/make_grid_texture.d.ts +29 -0
- package/src/shade/playground/ground_seam/make_grid_texture.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/make_grid_texture.js +105 -0
- package/src/shade/playground/ground_seam/make_ground.d.ts +70 -0
- package/src/shade/playground/ground_seam/make_ground.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/make_ground.js +161 -0
- package/src/shade/playground/ground_seam/measure_flicker.d.ts +71 -0
- package/src/shade/playground/ground_seam/measure_flicker.d.ts.map +1 -0
- package/src/shade/playground/ground_seam/measure_flicker.js +531 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +2519 -2511
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +275 -274
- package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/GPULightCollection.js +323 -314
- package/src/shade/renderer/lightmap/GPULightMap.js +336 -336
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +12 -2
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer.js +3 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +3 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.js +3 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.js +3 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts +28 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.js +39 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts +45 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.js +94 -61
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts +24 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.js +43 -0
- package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +1462 -0
- package/src/shade/renderer/texture/TextureManager.d.ts.map +1 -1
- package/src/shade/renderer/texture/TextureManager.js +20 -8
- package/src/shade/renderer/texture/TextureRole.d.ts +19 -0
- package/src/shade/renderer/texture/TextureRole.d.ts.map +1 -0
- package/src/shade/renderer/texture/TextureRole.js +26 -0
- package/src/shade/renderer/texture/TextureVariantSet.d.ts +71 -0
- package/src/shade/renderer/texture/TextureVariantSet.d.ts.map +1 -0
- package/src/shade/renderer/texture/TextureVariantSet.js +105 -0
- package/src/shade/renderer/texture/download_texture_data.d.ts.map +1 -1
- package/src/shade/renderer/texture/download_texture_data.js +22 -0
- package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts +15 -0
- package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/gpu_texture_compression_support.js +50 -0
- package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts +27 -0
- package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.js +65 -0
- package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts +11 -0
- package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/infer_format_from_parameters.js +88 -0
- package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts +24 -0
- package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/texture_format_from_shade_image.js +71 -0
- package/src/shade/renderer/texture/format/texture_format_preference.d.ts +22 -0
- package/src/shade/renderer/texture/format/texture_format_preference.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/texture_format_preference.js +89 -0
- package/src/shade/renderer/texture/format/texture_variant_select.d.ts +24 -0
- package/src/shade/renderer/texture/format/texture_variant_select.d.ts.map +1 -0
- package/src/shade/renderer/texture/format/texture_variant_select.js +38 -0
- package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts +9 -1
- package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts.map +1 -1
- package/src/shade/renderer/texture/shade_texture_might_have_alpha.js +73 -8
- package/src/shade/renderer/texture/source/AlphaMode.d.ts +27 -0
- package/src/shade/renderer/texture/source/AlphaMode.d.ts.map +1 -0
- package/src/shade/renderer/texture/source/AlphaMode.js +52 -0
- package/src/shade/renderer/texture/source/ShadeImage.d.ts +33 -0
- package/src/shade/renderer/texture/source/ShadeImage.d.ts.map +1 -1
- package/src/shade/renderer/texture/source/ShadeImage.js +74 -0
- package/src/shade/renderer/texture/source/ShadeTexelData.d.ts +78 -0
- package/src/shade/renderer/texture/source/ShadeTexelData.d.ts.map +1 -0
- package/src/shade/renderer/texture/source/ShadeTexelData.js +158 -0
- package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts +0 -10
- package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts.map +1 -1
- package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.js +73 -175
- package/src/shade/renderer/texture/texture_write_level.d.ts +32 -0
- package/src/shade/renderer/texture/texture_write_level.d.ts.map +1 -0
- package/src/shade/renderer/texture/texture_write_level.js +77 -0
- package/src/shade/renderer/texture/texture_write_to_gpu.d.ts +8 -1
- package/src/shade/renderer/texture/texture_write_to_gpu.d.ts.map +1 -1
- package/src/shade/renderer/texture/texture_write_to_gpu.js +62 -37
- package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts +8 -0
- package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +8 -0
- package/src/shade/util/texture_mip_extent.d.ts +49 -0
- package/src/shade/util/texture_mip_extent.d.ts.map +1 -0
- package/src/shade/util/texture_mip_extent.js +87 -0
- package/src/avif/native/isobmff/ByteCursor.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/codec/Codec.d.ts.map +0 -1
- package/src/engine/asset/loaders/image/codec/CodecWithFallback.d.ts.map +0 -1
- package/src/shade/util/compute_max_mip_count.d.ts +0 -8
- package/src/shade/util/compute_max_mip_count.d.ts.map +0 -1
- package/src/shade/util/compute_max_mip_count.js +0 -27
- /package/src/engine/asset/{loaders/image/codec → codec}/Codec.d.ts +0 -0
- /package/src/engine/asset/{loaders/image/codec → codec}/Codec.js +0 -0
- /package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.d.ts +0 -0
|
@@ -1,174 +1,164 @@
|
|
|
1
|
-
import { assert } from "../../../../core/assert.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
GPUProfilePass,
|
|
5
|
-
GPUProfileResource,
|
|
6
|
-
GPUProfileResourceKind,
|
|
7
|
-
GPUProfileScope,
|
|
8
|
-
GPUProfileTopology
|
|
9
|
-
} from "./GPUProfileTopology.js";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Declared bytes for a texture descriptor: the whole mip chain, at the given sample count.
|
|
13
|
-
*
|
|
14
|
-
* A format the engine's table does not know reports 0 rather than throwing. A capture is a
|
|
15
|
-
* diagnostic; refusing to record one because a size could not be worked out would be the wrong
|
|
16
|
-
* trade every time.
|
|
17
|
-
*
|
|
18
|
-
* @param {TextureResourceDescriptor} descriptor
|
|
19
|
-
* @returns {number}
|
|
20
|
-
*/
|
|
21
|
-
function texture_byte_size(descriptor) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
*
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
resource.
|
|
152
|
-
resource.
|
|
153
|
-
resource.
|
|
154
|
-
|
|
155
|
-
resource.
|
|
156
|
-
resource.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
resource.usage = descriptor.usage;
|
|
166
|
-
resource.byte_size = texture_byte_size(descriptor);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
topology.resources.push(resource);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return topology;
|
|
174
|
-
}
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { gpu_texture_format_memory_footprint } from "../../../descriptor/texture/format/gpu_texture_format_info.js";
|
|
3
|
+
import {
|
|
4
|
+
GPUProfilePass,
|
|
5
|
+
GPUProfileResource,
|
|
6
|
+
GPUProfileResourceKind,
|
|
7
|
+
GPUProfileScope,
|
|
8
|
+
GPUProfileTopology
|
|
9
|
+
} from "./GPUProfileTopology.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Declared bytes for a texture descriptor: the whole mip chain, at the given sample count.
|
|
13
|
+
*
|
|
14
|
+
* A format the engine's table does not know reports 0 rather than throwing. A capture is a
|
|
15
|
+
* diagnostic; refusing to record one because a size could not be worked out would be the wrong
|
|
16
|
+
* trade every time.
|
|
17
|
+
*
|
|
18
|
+
* @param {TextureResourceDescriptor} descriptor
|
|
19
|
+
* @returns {number}
|
|
20
|
+
*/
|
|
21
|
+
function texture_byte_size(descriptor) {
|
|
22
|
+
try {
|
|
23
|
+
return gpu_texture_format_memory_footprint(
|
|
24
|
+
descriptor.format,
|
|
25
|
+
descriptor.resolution,
|
|
26
|
+
descriptor.dimension,
|
|
27
|
+
descriptor.mipLevelCount,
|
|
28
|
+
descriptor.sampleCount
|
|
29
|
+
);
|
|
30
|
+
} catch {
|
|
31
|
+
// `gpu_texture_format_info` throws on a name it does not know. Correct for the renderer,
|
|
32
|
+
// wrong here: a capture is a diagnostic, and losing the whole recording because one
|
|
33
|
+
// resource used a format the table has not caught up with is the wrong trade every time.
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Record the shape of a compiled frame graph.
|
|
40
|
+
*
|
|
41
|
+
* **Call after `compile`, and ideally after `execute`.** Reference counts and cull decisions are
|
|
42
|
+
* what `compile` derives; before it every pass reads as culled, which would be recorded as a frame
|
|
43
|
+
* in which nothing ran.
|
|
44
|
+
*
|
|
45
|
+
* Resources are keyed by **node**, one per version, matching `FrameGraph.exportToJson`. Passes
|
|
46
|
+
* record the node they touched rather than the underlying resource, so a registry-keyed model would
|
|
47
|
+
* leave every reference past version 0 pointing at nothing.
|
|
48
|
+
*
|
|
49
|
+
* @param {FrameGraph} graph
|
|
50
|
+
* @returns {GPUProfileTopology}
|
|
51
|
+
*
|
|
52
|
+
* @author Alex Goldring
|
|
53
|
+
* @copyright Company Named Limited (c) 2026
|
|
54
|
+
*/
|
|
55
|
+
export function frame_graph_extract_topology(graph) {
|
|
56
|
+
assert.defined(graph, 'graph');
|
|
57
|
+
|
|
58
|
+
const topology = new GPUProfileTopology();
|
|
59
|
+
|
|
60
|
+
topology.name = graph.name;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Scopes are reached through the nodes that were recorded inside them, and flattened to an
|
|
64
|
+
* array here. `FrameGraph` keeps them as a parent chain rather than a list, so this walk is
|
|
65
|
+
* what turns the chain into something a reader can index.
|
|
66
|
+
*
|
|
67
|
+
* @type {Map<FrameGraphScope, number>}
|
|
68
|
+
*/
|
|
69
|
+
const scope_ids = new Map();
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {FrameGraphScope|null} scope
|
|
73
|
+
* @returns {number} index, or -1
|
|
74
|
+
*/
|
|
75
|
+
function intern_scope(scope) {
|
|
76
|
+
if (scope === null || scope === undefined) {
|
|
77
|
+
return -1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const existing = scope_ids.get(scope);
|
|
81
|
+
|
|
82
|
+
if (existing !== undefined) {
|
|
83
|
+
return existing;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// parent first, so a parent always has a lower index than its children and a reader can
|
|
87
|
+
// resolve the chain in one forward pass
|
|
88
|
+
const parent = intern_scope(scope.parent);
|
|
89
|
+
|
|
90
|
+
const record = new GPUProfileScope();
|
|
91
|
+
|
|
92
|
+
record.name = scope.name;
|
|
93
|
+
record.parent = parent;
|
|
94
|
+
|
|
95
|
+
const id = topology.scopes.length;
|
|
96
|
+
|
|
97
|
+
topology.scopes.push(record);
|
|
98
|
+
scope_ids.set(scope, id);
|
|
99
|
+
|
|
100
|
+
return id;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (const node of graph.__pass_nodes) {
|
|
104
|
+
const pass = new GPUProfilePass();
|
|
105
|
+
|
|
106
|
+
pass.id = node.id;
|
|
107
|
+
pass.name = node.name;
|
|
108
|
+
pass.scope = intern_scope(node.scope);
|
|
109
|
+
pass.culled = !node.can_execute();
|
|
110
|
+
pass.has_side_effects = node.has_side_effects;
|
|
111
|
+
pass.ref_count = node.ref_count;
|
|
112
|
+
pass.reads = node.resource_reads.slice();
|
|
113
|
+
pass.writes = node.resource_writes.slice();
|
|
114
|
+
pass.creates = node.resource_creates.slice();
|
|
115
|
+
|
|
116
|
+
topology.passes.push(pass);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
for (const node of graph.__resource_nodes) {
|
|
120
|
+
const entry = graph.__resource_registry[node.resource_id];
|
|
121
|
+
|
|
122
|
+
const resource = new GPUProfileResource();
|
|
123
|
+
|
|
124
|
+
resource.id = node.id;
|
|
125
|
+
resource.name = node.name;
|
|
126
|
+
resource.version = node.version;
|
|
127
|
+
resource.producer = node.producer !== null ? node.producer.id : -1;
|
|
128
|
+
|
|
129
|
+
if (entry !== undefined) {
|
|
130
|
+
resource.transient = entry.isTransient();
|
|
131
|
+
resource.imported = entry.isImported();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const descriptor = entry?.resource_descriptor;
|
|
135
|
+
|
|
136
|
+
if (descriptor !== undefined && descriptor !== null) {
|
|
137
|
+
const type = descriptor.type;
|
|
138
|
+
|
|
139
|
+
if (type === 'buffer') {
|
|
140
|
+
resource.kind = GPUProfileResourceKind.BUFFER;
|
|
141
|
+
resource.size = descriptor.size;
|
|
142
|
+
resource.usage = descriptor.usage;
|
|
143
|
+
resource.byte_size = descriptor.size;
|
|
144
|
+
} else if (type === 'texture') {
|
|
145
|
+
resource.kind = GPUProfileResourceKind.TEXTURE;
|
|
146
|
+
resource.resolution = [
|
|
147
|
+
Math.floor(descriptor.resolution[0]),
|
|
148
|
+
Math.floor(descriptor.resolution[1]),
|
|
149
|
+
Math.floor(descriptor.resolution[2])
|
|
150
|
+
];
|
|
151
|
+
resource.mip_level_count = descriptor.mipLevelCount;
|
|
152
|
+
resource.sample_count = descriptor.sampleCount;
|
|
153
|
+
resource.format = descriptor.format;
|
|
154
|
+
resource.dimension = descriptor.dimension;
|
|
155
|
+
resource.usage = descriptor.usage;
|
|
156
|
+
resource.byte_size = texture_byte_size(descriptor);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
topology.resources.push(resource);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return topology;
|
|
164
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# ground seam
|
|
2
|
+
|
|
3
|
+
A 425×425 ground quad, two triangles, a tiling grid albedo, a still camera. Under TAA the half of
|
|
4
|
+
the quad on one side of the triangles' shared edge boils at texel granularity and the other half is
|
|
5
|
+
clean, with a hard straight seam between them. It is invisible in a still frame and only exists in a
|
|
6
|
+
multi-frame difference.
|
|
7
|
+
|
|
8
|
+
`npm run dev`, then `/src/shade/playground/ground_seam/`. HMR is off across the playground by
|
|
9
|
+
design — a reload drops the temporal accumulation this page exists to measure.
|
|
10
|
+
|
|
11
|
+
## What it does differently from looking at the screen
|
|
12
|
+
|
|
13
|
+
The report this page was built from was written from outside the engine, by screenshotting a demo
|
|
14
|
+
through CDP, and three of its conclusions had to be retracted — two stated before they were
|
|
15
|
+
measured, one from a sign error in a hand-rolled camera basis. So nothing here is read off a
|
|
16
|
+
picture:
|
|
17
|
+
|
|
18
|
+
- **Frames are read back from a texture the page owns.** A canvas texture cannot carry `COPY_SRC`
|
|
19
|
+
and is rotated away the moment it is presented; a `drawImage` off it a task later returns an empty
|
|
20
|
+
bitmap, and a comparison of two blanks reports perfect agreement. `Renderer.render_to_target`
|
|
21
|
+
shares the view context, so the history being measured is the history the on-screen path builds.
|
|
22
|
+
- **Frames are driven from JS**, so the burst length is a number chosen here rather than one the
|
|
23
|
+
compositor handed over. The jitter sequence is 16 phases at scale 1, and the default burst is 16.
|
|
24
|
+
- **Pixels are assigned to triangles, not to a fitted line.** Each pixel is unprojected through
|
|
25
|
+
`camera.view_projection_matrix`, intersected with the ground plane and labelled by the sign of
|
|
26
|
+
`x + z` — the shared edge, derived from the index buffer. The unprojection round-trips itself and
|
|
27
|
+
reports the error, which runs about `4e-11` px.
|
|
28
|
+
- **Both diagonals are always reported.** The one in the mesh and the one that is not, so a whole-
|
|
29
|
+
frame asymmetry caused by the view cannot be mistaken for a seam.
|
|
30
|
+
- **Profiles, not half-plane means.** A mean over each half reports the same number for a step at
|
|
31
|
+
the boundary and for a smooth gradient across the frame, and those are different findings.
|
|
32
|
+
|
|
33
|
+
Pin `feature_automatic_exposure_enabled = false` before measuring anything — it drifts for seconds
|
|
34
|
+
after any change, by more than the signal is worth. The page does this at startup. And check the
|
|
35
|
+
frame is not black before believing a stability win; a black frame is perfectly stable.
|
|
36
|
+
|
|
37
|
+
## What it found
|
|
38
|
+
|
|
39
|
+
Reproduced at 1258×566, pixel ratio 1. Profiling the relative luminance spread across a 16-frame
|
|
40
|
+
burst against screen distance from the shared edge gives a step from 0.046 to 0.022 centred on the
|
|
41
|
+
edge, over about four pixels. The control cut along the *other* diagonal, through the same picture,
|
|
42
|
+
is flat.
|
|
43
|
+
|
|
44
|
+
**The rasterizer is not the source.** For a planar surface under reverse-Z with an infinite far
|
|
45
|
+
plane the written depth is exactly affine in screen space, so each triangle's depth was fitted
|
|
46
|
+
separately by least squares and the two fits evaluated on the shared edge. Residuals `6e-11`, and
|
|
47
|
+
the two planes disagree by **0.23 ULP of f32** at worst. There is no depth step.
|
|
48
|
+
|
|
49
|
+
**The disocclusion chain the report suspected does not exist.** `shader_depth_occlusion_clip`'s
|
|
50
|
+
confidence is **exactly 1.0 at every pixel**, both sides. Velocity is ~`1e-5` px and flat.
|
|
51
|
+
|
|
52
|
+
**TAA creates the step out of continuous inputs.** Captured at `AfterTransparency` — the exact
|
|
53
|
+
texture the resolve reads — the incoming colour's per-pixel swing is 0.371 vs 0.366 across the edge
|
|
54
|
+
and flat in profile. Captured at `BeforePresent` it is 0.046 vs 0.022 with a hard step. And it is
|
|
55
|
+
not a blend-weight difference: re-running the resolve's own arithmetic with its own chunks gives
|
|
56
|
+
blend 0.0222 vs 0.0248 — nearly equal, and *lower* on the noisy side. What moves is the clipped
|
|
57
|
+
history. (That probe is no longer here; see "The two probes that are gone".)
|
|
58
|
+
|
|
59
|
+
**The incoming colour does differ per triangle — in temporal shape, not amplitude.** Total variation
|
|
60
|
+
along the burst divided by its range ("jaggedness": 1 for a single sweep, 15 for a full alternation)
|
|
61
|
+
steps from **7.28 to 5.32 in a single pixel** at the edge, while the range itself is flat to 1.5%. A
|
|
62
|
+
neighbourhood-clamped filter rebuilds its box from the current frame every frame, so a value that
|
|
63
|
+
jumps to the far end of its range each frame keeps the history at the box boundary and never
|
|
64
|
+
settles, while a value that sweeps smoothly converges.
|
|
65
|
+
|
|
66
|
+
**The source is `chunk_barycentric_full`'s anchor.** The decisive control is
|
|
67
|
+
`GROUND_TRIANGULATION.rotated`: the same two triangles, same diagonal, same winding, same three
|
|
68
|
+
vertices per face, same UVs, same coverage, same depth — each index triple cyclically rotated so a
|
|
69
|
+
different corner is first. Nothing geometric changes. The reconstruction anchors every pixel on
|
|
70
|
+
`pixel - ndc0` and divides by `determinant(mat2x2(ndc2 - ndc1, ndc0 - ndc1))`, so vertex 0 is the
|
|
71
|
+
origin the whole thing is measured from, and in f32 the rotation changes which differences are
|
|
72
|
+
formed and how they round.
|
|
73
|
+
|
|
74
|
+
| 1258×566 | jaggedness − / + | ratio | post-TAA spread − / + | ratio |
|
|
75
|
+
|---|---|---|---|---|
|
|
76
|
+
| default `(0,2,1) (2,3,1)` | 7.28 / 5.32 | 1.37 | 0.0458 / 0.0218 | **2.11** |
|
|
77
|
+
| anchor-rotated `(2,1,0) (3,1,2)` | 4.33 / 4.36 | 0.99 | 0.0139 / 0.0149 | **0.94** |
|
|
78
|
+
|
|
79
|
+
`globalThis.__meshlet_signature` is published on every rebuild so a null result on an index-order
|
|
80
|
+
A/B cannot be mistaken for "the reconstruction does not care" — the two builds' meshlet data
|
|
81
|
+
differ, so the change reached the GPU.
|
|
82
|
+
|
|
83
|
+
This also accounts for the rest: subdividing fixes it because each small triangle's anchor is near
|
|
84
|
+
its own pixels; flipping the diagonal changes each triangle's vertex set and so its conditioning;
|
|
85
|
+
it is TAA-specific because a static ~`1e-4` bias is invisible until jitter turns it into a temporal
|
|
86
|
+
signal; and it is resolution-dependent because the NDC magnitudes and the pixel footprint both are.
|
|
87
|
+
|
|
88
|
+
## The fix
|
|
89
|
+
|
|
90
|
+
`chunk_barycentric_full` was rewritten to solve the same system without an anchor and without ever
|
|
91
|
+
dividing by w. A point with barycentric `l` sits at screen position
|
|
92
|
+
`sum(l_i * P_i.xy) / sum(l_i * P_i.w)`; setting that equal to the pixel and adding `sum(l) == 1`
|
|
93
|
+
gives a 3×3 system whose Cramer solution is three 2×2 determinants of `u = x - pixel.x*w` and
|
|
94
|
+
`v = y - pixel.y*w`, normalised by their sum. Each `l_i` is the same expression in the other two, so
|
|
95
|
+
rotating the corners permutes the outputs and changes nothing else. The derivatives are the same
|
|
96
|
+
system solved at `pixel + (1,0)` and `pixel + (0,1)` — exactly the whole-pixel forward difference
|
|
97
|
+
the old code produced by algebra, reusing every input.
|
|
98
|
+
|
|
99
|
+
Measured here, 1258×566, per-pixel relative luminance spread over a 16-frame burst:
|
|
100
|
+
|
|
101
|
+
| | before | after |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| default `(0,2,1) (2,3,1)` | 0.0458 / 0.0218 — **2.11** | 0.0153 / 0.0127 — **1.21** |
|
|
104
|
+
| anchor-rotated | 0.0139 / 0.0149 — 0.94 | 0.0154 / 0.0121 — 1.27 |
|
|
105
|
+
| flipped diagonal | 0.0382 / 0.0322 — 1.19 | 0.0120 / 0.0156 — 0.77 |
|
|
106
|
+
| 8×8 subdivided | 0.0185 / 0.0164 — 1.13 | 0.0154 / 0.0127 — 1.21 |
|
|
107
|
+
| 1898×926 anchor-rotated | 0.0216 / 0.0062 — **3.49** | 0.0105 / 0.0076 — 1.38 |
|
|
108
|
+
| 640×360 default | 0.0218 / 0.0534 — **0.41** | 0.0216 / 0.0208 — 1.04 |
|
|
109
|
+
|
|
110
|
+
Repeated three times from a fresh page, the first row reads 1.205 / 1.206 / 1.206 — so the change
|
|
111
|
+
from 2.11 is some three orders of magnitude larger than the run-to-run spread. (The brief that
|
|
112
|
+
prompted this warned that its whole-frame "pixels changed" number swung between 0.5% and 3.8% on
|
|
113
|
+
identical configurations. A metric that is profiled against a classified boundary rather than summed
|
|
114
|
+
over the frame does not have that problem.)
|
|
115
|
+
|
|
116
|
+
The two-triangle quad now measures the same as the same quad subdivided 8×8 — 1.21 against 1.21 —
|
|
117
|
+
and the subdivided case is the reference for "no seam is possible here", so the residual asymmetry
|
|
118
|
+
is the view's own, one half being more oblique than the other. The absolute flicker also falls 3×
|
|
119
|
+
on the side that was boiling and 1.7× on the side that was not, so this is a stability improvement
|
|
120
|
+
everywhere and not only at the edge.
|
|
121
|
+
|
|
122
|
+
It changes stability, not appearance, and does not cost anything:
|
|
123
|
+
|
|
124
|
+
- the converged image is unchanged — mean luminance per side 0.02902 / 0.03243 before,
|
|
125
|
+
0.02918 / 0.03244 after;
|
|
126
|
+
- on Sponza, two builds differ by *less* than two runs of the same build (mean channel difference
|
|
127
|
+
0.0277 against a 0.0295 run-to-run control, and the same 191 maximum on TAA edge pixels either
|
|
128
|
+
way — that control is what makes the 191 readable, and without it the number looks alarming);
|
|
129
|
+
- in a g-buffer-bound configuration (2400×1300, full-screen geometry, post chain off) it is
|
|
130
|
+
*faster*: 1.440 ms/frame against 1.502, medians of five 120-frame runs. Three reciprocals replace
|
|
131
|
+
seven divides, which is where that comes from;
|
|
132
|
+
- all 35 pre-existing tests in `chunk_barycentric_full.spec.js` pass unchanged, 8 were added for
|
|
133
|
+
the case that was failing, and the full `src/shade` suite (3051 tests) passes.
|
|
134
|
+
|
|
135
|
+
Of the 8 new tests, **6 also pass against the old implementation** — the algebra was never wrong
|
|
136
|
+
for `w != 0`, so those are characterisation, not regression. The two that fail against it are the
|
|
137
|
+
ones that matter: a vertex exactly on the eye plane (the old code divides by its w), and cyclic
|
|
138
|
+
rotation of the corners. On that second one the old code moves by exactly one f32 ULP even with the
|
|
139
|
+
emulator's f64 arithmetic; the new code is bit-identical.
|
|
140
|
+
|
|
141
|
+
Residual order-dependence is not zero — the anchor-rotated build still differs slightly, because
|
|
142
|
+
`barycentric_interpolate_uv` and the attribute interpolators sum `uv_i * l_i` in index order. That
|
|
143
|
+
is a sum of three same-signed terms with no catastrophic cancellation, and it no longer produces a
|
|
144
|
+
seam.
|
|
145
|
+
|
|
146
|
+
### Why the pixel-relative offsets use `fma`
|
|
147
|
+
|
|
148
|
+
`u` and `v` are formed with `fma(-pixel.x, w, x)` rather than `x - pixel.x * w`. It is the one place
|
|
149
|
+
in the function where operands cancel, so it is the one place a fused multiply-add is worth asking
|
|
150
|
+
for: a single rounding, with the error bounded relative to the result rather than to the
|
|
151
|
+
intermediate product.
|
|
152
|
+
|
|
153
|
+
Measured rather than assumed, because our own tooling cannot answer it — `WGSLLanguageCore`
|
|
154
|
+
implements `fma` as plain `x * y + z`, so no emulator test observes fusion:
|
|
155
|
+
|
|
156
|
+
- **it changes the emitted code.** Full-precision aggregates over 356k pixels are bit-reproducible
|
|
157
|
+
within a build and move in the fifth digit between the two forms, so this driver was *not* already
|
|
158
|
+
contracting the plain expression;
|
|
159
|
+
- **it is faster** — 2.230 / 2.298 ms per frame against 2.429 for the plain form, medians of seven
|
|
160
|
+
120-frame runs, alternating between builds. One op instead of two. Absolute frame times drift
|
|
161
|
+
between sessions by more than this difference, so only the adjacent pairs mean anything;
|
|
162
|
+
- **it buys no measurable image quality**, because there is none left to buy: the two-triangle quad
|
|
163
|
+
already matches its own 32×32 subdivision at extents of 425, 4000 and 40000, and the residual is
|
|
164
|
+
texture aliasing that subdivision does not fix either. The `extent` control exists to look for
|
|
165
|
+
headroom, and there is none up to a quad 94× the size of the repro.
|
|
166
|
+
|
|
167
|
+
An attempt to measure reconstruction accuracy directly — treating the subdivided quad as ground
|
|
168
|
+
truth for the same surface — **does not work**: 1×1 and 32×32 differ by about 1% in mean luminance
|
|
169
|
+
from causes unrelated to reconstruction, which swamps the effect. Recorded here so nobody spends the
|
|
170
|
+
afternoon on it twice.
|
|
171
|
+
|
|
172
|
+
What WGSL *guarantees* about fusion is not established either; the spec's §15.7.5 and §17.5.32 did
|
|
173
|
+
not come back legible. Portably the claim is "at worst a no-op, measured to help here".
|
|
174
|
+
|
|
175
|
+
The other cancellation site is `u.y*v.z - u.z*v.y` in `chunk_barycentric_solve`, a difference of two
|
|
176
|
+
products, which cancels hardest when a pixel sits near an edge. **The rewrite created it**, and it
|
|
177
|
+
is worth being clear about that rather than filing it as inherited debt: the old formulation
|
|
178
|
+
evaluated *one* 2×2 determinant, via the `determinant()` builtin, and it was a per-triangle constant
|
|
179
|
+
that only cancelled for slivers. This one evaluates *nine* — three cofactors in each of three solves
|
|
180
|
+
— and they depend on the pixel.
|
|
181
|
+
|
|
182
|
+
That trade is deliberate and it measures out well: when a cofactor cancels, the weight it produces
|
|
183
|
+
is near zero, so the absolute error in the interpolated attribute stays small, which is the benign
|
|
184
|
+
direction. The badly conditioned part of the old code was never its determinant but the
|
|
185
|
+
`deltaVec`/`interpInvW` chain that followed, and that is gone.
|
|
186
|
+
|
|
187
|
+
Kahan's fma-based 2×2 determinant would hold each of the nine to ~1.5 ulp regardless of
|
|
188
|
+
cancellation, for about 27 extra operations across the three solves. Nothing measurable currently
|
|
189
|
+
demands it; it is where to go if conditioning bites here again.
|
|
190
|
+
|
|
191
|
+
## What is not established
|
|
192
|
+
|
|
193
|
+
- **The anchor rotation was a diagnostic, not a fix.** Before the rewrite it removed the seam at
|
|
194
|
+
1258×566 and made it *worse* at 1898×926 (ratio 3.49 against the default's 1.11) — which is what
|
|
195
|
+
a rounding-conditioning story predicts, and why the fix had to remove the anchor rather than pick
|
|
196
|
+
a better one.
|
|
197
|
+
- **Jaggedness is a strong correlate, not a proven complete chain.** It tracks the output seam in
|
|
198
|
+
five of six configurations measured and fails in one (1898×926 anchor-rotated: jaggedness flat,
|
|
199
|
+
output ratio 3.49).
|
|
200
|
+
- **Which term dominates is unknown.** The anchor subtraction, the determinant and the gradient
|
|
201
|
+
terms were not separated.
|
|
202
|
+
- Anisotropy is *not* it: dropping the sampler to 1× leaves the step nearly intact (jaggedness ratio
|
|
203
|
+
1.34, output ratio 1.86).
|
|
204
|
+
|
|
205
|
+
## The two probes that are gone
|
|
206
|
+
|
|
207
|
+
Ruling out the disocclusion chain took reaching two things no extension can see: the velocity and
|
|
208
|
+
disocclusion buffers are not published to any frame record — `ViewTextures` says so deliberately —
|
|
209
|
+
and the resolve's blend weight is a local in a fragment shader. `capture_taa_inputs.js` and
|
|
210
|
+
`capture_taa_decision.js` read them through two hooks added to `Renderer` for the purpose, the
|
|
211
|
+
second one importing the resolve's own code chunks so the arithmetic it reports is the frame's
|
|
212
|
+
rather than a re-implementation of it.
|
|
213
|
+
|
|
214
|
+
Both are **removed**, along with the hooks. They were instrumentation for one question, that
|
|
215
|
+
question is answered above, and the cost of keeping them is two permanent fields on `Renderer` and
|
|
216
|
+
a per-frame branch in the hot path for everyone who never runs this page. Their findings survive in
|
|
217
|
+
"What it found"; the code survives in the history — `git log -- src/shade/playground/ground_seam`,
|
|
218
|
+
commit `df0b623f6`. Anything needing them again should restore the pair together and delete them
|
|
219
|
+
again afterwards.
|
|
220
|
+
|
|
221
|
+
What is left needs no hooks: `capture_scene_color.js` uses the sanctioned `RenderExtension` API,
|
|
222
|
+
and the depth readback goes through the public `Renderer.texture_depth_current`.
|
|
223
|
+
|
|
224
|
+
## Reproducing
|
|
225
|
+
|
|
226
|
+
```js
|
|
227
|
+
await configure({ segments: 1, triangulation: 'default', taa: true });
|
|
228
|
+
|
|
229
|
+
await measure(); // burst, difference map, per-side split, profile across both diagonals
|
|
230
|
+
await probe_depth(); // do the two triangles' depth planes meet on the shared edge?
|
|
231
|
+
await probe_pre_taa(16, 'pre_taa'); // the resolve's input
|
|
232
|
+
await probe_pre_taa(16, 'post_taa'); // its output
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Every one leaves its full result on `globalThis.__last_*`.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The scene colour *before* the temporal filter, made readable.
|
|
3
|
+
*
|
|
4
|
+
* This exists to split one question in two. The burst measurement sees the picture the temporal
|
|
5
|
+
* filter produced, and a seam in it can come from either side of that filter: the shading may be
|
|
6
|
+
* responding differently to the sub-pixel jitter on the two triangles, or the shading may be
|
|
7
|
+
* identical and the filter may be resolving it differently. Those want opposite fixes, and no
|
|
8
|
+
* amount of staring at the output distinguishes them.
|
|
9
|
+
*
|
|
10
|
+
* {@link FramePhase.AfterTransparency} is the last phase before the upscale, so what is captured
|
|
11
|
+
* here is the full pre-TAA frame at internal resolution — the temporal filter's *input*.
|
|
12
|
+
*
|
|
13
|
+
* The pass writes an imported texture, which the graph treats as a side effect, so it is not elided
|
|
14
|
+
* for having no consumer inside the frame.
|
|
15
|
+
*/
|
|
16
|
+
export class CaptureSceneColor extends RenderExtension {
|
|
17
|
+
/**
|
|
18
|
+
* @param {GPUDevice} device
|
|
19
|
+
*/
|
|
20
|
+
constructor(device: GPUDevice);
|
|
21
|
+
/**
|
|
22
|
+
* Whether to record at all. Off by default: a capture costs a full-resolution copy every frame,
|
|
23
|
+
* and the burst measurement this page mostly runs does not want one.
|
|
24
|
+
*
|
|
25
|
+
* @type {boolean}
|
|
26
|
+
*/
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Luminance of the captured frame, one entry per pixel.
|
|
30
|
+
*
|
|
31
|
+
* Rec. 709 weights on the linear HDR values — this is upstream of the tonemap, so the numbers
|
|
32
|
+
* are radiance rather than display code values and there is no 8-bit quantization floor under
|
|
33
|
+
* the measurement.
|
|
34
|
+
*
|
|
35
|
+
* @returns {Promise<{luma: Float32Array, width: number, height: number}>}
|
|
36
|
+
*/
|
|
37
|
+
read_luminance(): Promise<{
|
|
38
|
+
luma: Float32Array;
|
|
39
|
+
width: number;
|
|
40
|
+
height: number;
|
|
41
|
+
}>;
|
|
42
|
+
#private;
|
|
43
|
+
}
|
|
44
|
+
import { RenderExtension } from "../../renderer/extension/RenderExtension.js";
|
|
45
|
+
//# sourceMappingURL=capture_scene_color.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture_scene_color.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/ground_seam/capture_scene_color.js"],"names":[],"mappings":"AA8CA;;;;;;;;;;;;;;GAcG;AACH;IA2CI;;OAEG;IACH,+BAIC;IAfD;;;;;OAKG;IACH,SAFU,OAAO,CAED;IAuEhB;;;;;;;;OAQG;IACH;cAF4B,YAAY;eAAS,MAAM;gBAAU,MAAM;OAwCtE;;CACJ;gCA5N+B,6CAA6C"}
|