@aura3d/rendering 1.4.0 → 1.4.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.
Files changed (308) hide show
  1. package/package.json +38 -4
  2. package/AGENTS.md +0 -46
  3. package/src/ArchitecturalLightingFixtures.ts +0 -241
  4. package/src/ArchitecturalMaterialCatalog.ts +0 -130
  5. package/src/ArchitecturalMeasurementFixtures.ts +0 -155
  6. package/src/BRDFLut.ts +0 -47
  7. package/src/CameraFraming.ts +0 -200
  8. package/src/CanonicalSceneFixtures.ts +0 -95
  9. package/src/CascadedShadowMaps.ts +0 -449
  10. package/src/ColorManagement.ts +0 -127
  11. package/src/CullingFixtures.ts +0 -280
  12. package/src/DecalGeometry.ts +0 -26
  13. package/src/DepthPass.ts +0 -110
  14. package/src/EnvironmentBackgroundPass.ts +0 -194
  15. package/src/EnvironmentBackgroundResources.ts +0 -309
  16. package/src/EnvironmentLighting.ts +0 -96
  17. package/src/EnvironmentMapResources.ts +0 -1026
  18. package/src/EnvironmentPipeline.ts +0 -69
  19. package/src/EnvironmentPlatform.ts +0 -1306
  20. package/src/EnvironmentPreset.ts +0 -155
  21. package/src/Exposure.ts +0 -66
  22. package/src/ExternalParityRenderPreset.ts +0 -725
  23. package/src/ForwardPass.ts +0 -1668
  24. package/src/FrameVisualMetrics.ts +0 -301
  25. package/src/Geometry.ts +0 -461
  26. package/src/GeometryPrimitives.ts +0 -2
  27. package/src/HDRRenderPipeline.ts +0 -94
  28. package/src/IBL.ts +0 -86
  29. package/src/IndexBuffer.ts +0 -57
  30. package/src/InstancedPBRMaterial.ts +0 -186
  31. package/src/InstancedUnlitMaterial.ts +0 -60
  32. package/src/Instancing.ts +0 -19
  33. package/src/LightCollector.ts +0 -82
  34. package/src/LightUniforms.ts +0 -47
  35. package/src/LightingDebug.ts +0 -80
  36. package/src/LightingDefaults.ts +0 -79
  37. package/src/LightingRig.ts +0 -301
  38. package/src/LineGeometry.ts +0 -2
  39. package/src/Material.ts +0 -209
  40. package/src/MaterialBinding.ts +0 -131
  41. package/src/MaterialInstance.ts +0 -59
  42. package/src/MaterialPresets.ts +0 -272
  43. package/src/MorphTarget.ts +0 -124
  44. package/src/MorphTargetPlan.ts +0 -178
  45. package/src/MorphUnlitMaterial.ts +0 -60
  46. package/src/NormalMappedPBRMaterial.ts +0 -188
  47. package/src/OceanFixtures.ts +0 -318
  48. package/src/PBRLightingDefaults.ts +0 -12
  49. package/src/PBRMaterial.ts +0 -442
  50. package/src/PMREM.ts +0 -53
  51. package/src/PbrReference.ts +0 -681
  52. package/src/PostProcessPass.ts +0 -2507
  53. package/src/ProceduralTextureFixtures.ts +0 -393
  54. package/src/ProductTurntableFixtures.ts +0 -815
  55. package/src/Raycaster.ts +0 -21
  56. package/src/ReflectionProbe.ts +0 -13
  57. package/src/ReflectionSurfaces.ts +0 -219
  58. package/src/RenderBackend.ts +0 -43
  59. package/src/RenderDebugViews.ts +0 -138
  60. package/src/RenderDevice.ts +0 -836
  61. package/src/RenderGraph.ts +0 -194
  62. package/src/RenderPass.ts +0 -27
  63. package/src/RenderPipeline.ts +0 -101
  64. package/src/RenderQueue.ts +0 -12
  65. package/src/RenderState.ts +0 -12
  66. package/src/Renderer.ts +0 -2631
  67. package/src/RendererDebugOverlay.ts +0 -80
  68. package/src/RendererFeatureGates.ts +0 -150
  69. package/src/RendererPostprocessPlan.ts +0 -279
  70. package/src/RendererTiming.ts +0 -251
  71. package/src/RendererVisualPipelineReport.ts +0 -836
  72. package/src/ResourceLifecycle.ts +0 -21
  73. package/src/Sampler.ts +0 -37
  74. package/src/SceneOptimization.ts +0 -518
  75. package/src/ShaderChunks.ts +0 -393
  76. package/src/ShaderLibrary.ts +0 -2766
  77. package/src/ShaderModule.ts +0 -36
  78. package/src/ShaderPreprocessor.ts +0 -260
  79. package/src/ShaderReflection.ts +0 -201
  80. package/src/ShadowMap.ts +0 -237
  81. package/src/ShadowPass.ts +0 -198
  82. package/src/ShadowProjection.ts +0 -115
  83. package/src/SkinnedLitMaterial.ts +0 -397
  84. package/src/SkinnedUnlitMaterial.ts +0 -63
  85. package/src/SkinningBounds.ts +0 -131
  86. package/src/SpaceEnvironmentFixtures.ts +0 -200
  87. package/src/SpriteGeometry.ts +0 -21
  88. package/src/StereoCameraRig.ts +0 -127
  89. package/src/StereoEffects.ts +0 -274
  90. package/src/TerrainFixtures.ts +0 -180
  91. package/src/Texture.ts +0 -307
  92. package/src/TextureBinding.ts +0 -91
  93. package/src/TexturedPBRMaterial.ts +0 -1112
  94. package/src/TexturedUnlitMaterial.ts +0 -67
  95. package/src/ToneMapping.ts +0 -105
  96. package/src/UniformBinder.ts +0 -16
  97. package/src/UniformLayout.ts +0 -129
  98. package/src/UnlitMaterial.ts +0 -75
  99. package/src/VegetationFixtures.ts +0 -314
  100. package/src/VertexBuffer.ts +0 -120
  101. package/src/VertexFormat.ts +0 -171
  102. package/src/VoxelWorldFixtures.ts +0 -280
  103. package/src/WeatherFixtures.ts +0 -223
  104. package/src/WebGL2Device.ts +0 -2280
  105. package/src/WebGL2StateCache.ts +0 -330
  106. package/src/WebGPUDevice.ts +0 -2877
  107. package/src/WebGPURenderToTextureProof.ts +0 -139
  108. package/src/advanced-runtime/AdvancedRenderer.ts +0 -73
  109. package/src/advanced-runtime/index.ts +0 -9
  110. package/src/animation/AnimationMaterialStyle.ts +0 -32
  111. package/src/animation/AnimationRenderPreset.ts +0 -45
  112. package/src/animation/AnimationToonMaterial.ts +0 -387
  113. package/src/animation/AnimationVisualQuality.ts +0 -71
  114. package/src/animation/applyAnimationRenderPreset.ts +0 -180
  115. package/src/animation/index.ts +0 -5
  116. package/src/cinematic/BloomPass.ts +0 -26
  117. package/src/cinematic/CinematicDepthComposition.ts +0 -30
  118. package/src/cinematic/CinematicEvidence.ts +0 -123
  119. package/src/cinematic/CinematicLightingRig.ts +0 -144
  120. package/src/cinematic/CinematicMaterialPresets.ts +0 -130
  121. package/src/cinematic/CinematicPostProcess.ts +0 -83
  122. package/src/cinematic/DepthHazePass.ts +0 -30
  123. package/src/cinematic/EmissivePracticalLightSystem.ts +0 -45
  124. package/src/cinematic/FilmGrainPass.ts +0 -24
  125. package/src/cinematic/FogVolumeSystem.ts +0 -30
  126. package/src/cinematic/GlowCardSystem.ts +0 -44
  127. package/src/cinematic/RainParticleSystem.ts +0 -151
  128. package/src/cinematic/VignettePass.ts +0 -25
  129. package/src/cinematic/WetReflectionApproximation.ts +0 -27
  130. package/src/cinematic/index.ts +0 -14
  131. package/src/effects/CollisionModule.ts +0 -64
  132. package/src/effects/ColorModule.ts +0 -60
  133. package/src/effects/ForceModule.ts +0 -25
  134. package/src/effects/GPUParticleBackend.ts +0 -569
  135. package/src/effects/Particle.ts +0 -108
  136. package/src/effects/ParticleDiagnostics.ts +0 -224
  137. package/src/effects/ParticleEffectPresets.ts +0 -147
  138. package/src/effects/ParticleEmitter.ts +0 -326
  139. package/src/effects/ParticleModule.ts +0 -26
  140. package/src/effects/ParticleRenderPass.ts +0 -117
  141. package/src/effects/ParticleRenderer.ts +0 -132
  142. package/src/effects/ParticleSystem.ts +0 -333
  143. package/src/effects/SizeModule.ts +0 -56
  144. package/src/effects/TrailModule.ts +0 -72
  145. package/src/effects/VelocityModule.ts +0 -75
  146. package/src/effects/index.ts +0 -15
  147. package/src/index.ts +0 -925
  148. package/src/materials/AlphaSorting.ts +0 -30
  149. package/src/materials/MaterialExtensions.ts +0 -42
  150. package/src/materials/PhysicalMaterial.ts +0 -133
  151. package/src/materials/TransmissionPass.ts +0 -51
  152. package/src/performance/BVH.ts +0 -18
  153. package/src/performance/Batcher.ts +0 -2
  154. package/src/performance/FrustumCuller.ts +0 -9
  155. package/src/performance/LOD.ts +0 -20
  156. package/src/performance/Octree.ts +0 -10
  157. package/src/performance/RenderItemSorting.ts +0 -170
  158. package/src/performance/RendererStats.ts +0 -43
  159. package/src/performance/ResourceBudget.ts +0 -44
  160. package/src/postprocess/BloomPass.ts +0 -28
  161. package/src/postprocess/CinematicDiagnostics.ts +0 -642
  162. package/src/postprocess/ColorGradingPass.ts +0 -24
  163. package/src/postprocess/DepthOfFieldPass.ts +0 -12
  164. package/src/postprocess/EffectComposer.ts +0 -349
  165. package/src/postprocess/SSAOPass.ts +0 -20
  166. package/src/postprocess/index.ts +0 -34
  167. package/src/production-runtime/AnimationControlsPipeline.ts +0 -77
  168. package/src/production-runtime/PBRHDRPipeline.ts +0 -381
  169. package/src/production-runtime/ProductionEffectsPipeline.ts +0 -85
  170. package/src/production-runtime/ProductionRendererTypes.ts +0 -136
  171. package/src/production-runtime/ProductionRuntimeRenderer.ts +0 -172
  172. package/src/production-runtime/ProductionWebGL2Renderer.ts +0 -313
  173. package/src/production-runtime/ProductionWebGPURenderer.ts +0 -396
  174. package/src/production-runtime/TransmissionBackdropCapture.ts +0 -130
  175. package/src/production-runtime/animation/MorphTargetRenderer.ts +0 -2
  176. package/src/production-runtime/animation/SkinningRenderer.ts +0 -2
  177. package/src/production-runtime/backends/RendererBackend.ts +0 -17
  178. package/src/production-runtime/backends/WebGL2RendererBackend.ts +0 -30
  179. package/src/production-runtime/backends/WebGPURendererBackend.ts +0 -24
  180. package/src/production-runtime/backends/webgl2/WebGL2Buffer.ts +0 -2
  181. package/src/production-runtime/backends/webgl2/WebGL2Capabilities.ts +0 -2
  182. package/src/production-runtime/backends/webgl2/WebGL2RenderTarget.ts +0 -2
  183. package/src/production-runtime/backends/webgl2/WebGL2Shader.ts +0 -2
  184. package/src/production-runtime/backends/webgl2/WebGL2StateCache.ts +0 -1
  185. package/src/production-runtime/backends/webgl2/WebGL2Texture.ts +0 -2
  186. package/src/production-runtime/backends/webgpu/WebGPUBuffer.ts +0 -2
  187. package/src/production-runtime/backends/webgpu/WebGPUCapabilities.ts +0 -2
  188. package/src/production-runtime/backends/webgpu/WebGPURenderTarget.ts +0 -2
  189. package/src/production-runtime/backends/webgpu/WebGPUShader.ts +0 -2
  190. package/src/production-runtime/backends/webgpu/WebGPUTexture.ts +0 -2
  191. package/src/production-runtime/color/ColorManagement.ts +0 -3
  192. package/src/production-runtime/color/ToneMapping.ts +0 -7
  193. package/src/production-runtime/diagnostics/FrameCapture.ts +0 -2
  194. package/src/production-runtime/diagnostics/GPUCapabilities.ts +0 -2
  195. package/src/production-runtime/diagnostics/RendererStats.ts +0 -2
  196. package/src/production-runtime/environment/EnvironmentMap.ts +0 -1
  197. package/src/production-runtime/environment/HDRLoader.ts +0 -57
  198. package/src/production-runtime/environment/PMREMGenerator.ts +0 -713
  199. package/src/production-runtime/framegraph/FrameGraph.ts +0 -18
  200. package/src/production-runtime/framegraph/RenderPass.ts +0 -15
  201. package/src/production-runtime/geometry/ProjectedDecalGeometry.ts +0 -439
  202. package/src/production-runtime/index.ts +0 -127
  203. package/src/production-runtime/lights/LightManager.ts +0 -7
  204. package/src/production-runtime/lights/ShadowMapRenderer.ts +0 -5
  205. package/src/production-runtime/materials/GLTFMaterialAdapter.ts +0 -6
  206. package/src/production-runtime/materials/GLTFPBRMaterialAdapter.ts +0 -2
  207. package/src/production-runtime/materials/MaterialCompiler.ts +0 -7
  208. package/src/production-runtime/materials/MaterialTextureBindings.ts +0 -5
  209. package/src/production-runtime/materials/PBRMaterial.ts +0 -2
  210. package/src/production-runtime/materials/PBRShaderFeatures.ts +0 -2
  211. package/src/production-runtime/passes/ContactShadowPass.ts +0 -184
  212. package/src/production-runtime/passes/DepthPrepass.ts +0 -7
  213. package/src/production-runtime/passes/OpaquePass.ts +0 -7
  214. package/src/production-runtime/passes/ShadowPass.ts +0 -7
  215. package/src/production-runtime/passes/SkyboxPass.ts +0 -7
  216. package/src/production-runtime/passes/ToneMappingPass.ts +0 -7
  217. package/src/production-runtime/passes/TransparentPass.ts +0 -7
  218. package/src/production-runtime/postprocess/BloomPass.ts +0 -51
  219. package/src/production-runtime/postprocess/ColorGradingPass.ts +0 -49
  220. package/src/production-runtime/postprocess/DOFPass.ts +0 -47
  221. package/src/production-runtime/postprocess/FXAAPass.ts +0 -53
  222. package/src/production-runtime/postprocess/ProductionEffectComposer.ts +0 -78
  223. package/src/production-runtime/postprocess/ProductionPostProcessTypes.ts +0 -174
  224. package/src/production-runtime/postprocess/SSAOPass.ts +0 -45
  225. package/src/production-runtime/resources/GPUBuffer.ts +0 -2
  226. package/src/production-runtime/resources/GPUTexture.ts +0 -2
  227. package/src/production-runtime/resources/RenderTarget.ts +0 -3
  228. package/src/production-runtime/resources/ResourceCache.ts +0 -7
  229. package/src/production-runtime/scene/Camera.ts +0 -1
  230. package/src/production-runtime/scene/Lights.ts +0 -2
  231. package/src/production-runtime/scene/RenderableMesh.ts +0 -2
  232. package/src/production-runtime/scene/RenderablePrimitive.ts +0 -1
  233. package/src/production-runtime/scene/RenderableScene.ts +0 -4
  234. package/src/production-runtime/shaders/ShaderProgramLibrary.ts +0 -7
  235. package/src/production-runtime/shaders/chunks/brdf.glsl +0 -2
  236. package/src/production-runtime/shaders/chunks/ibl.glsl +0 -3
  237. package/src/production-runtime/shaders/chunks/pbr.frag.glsl +0 -47
  238. package/src/production-runtime/shaders/chunks/pbr.vert.glsl +0 -8
  239. package/src/production-runtime/shaders/chunks/shadows.glsl +0 -2
  240. package/src/production-runtime/shaders/wgsl/pbr.wgsl +0 -3
  241. package/src/production-runtime/shaders/wgsl/postprocess.wgsl +0 -2
  242. package/src/production-runtime/shaders/wgsl/skybox.wgsl +0 -2
  243. package/src/shaders/depth.frag.glsl +0 -5
  244. package/src/shaders/depth.vert.glsl +0 -8
  245. package/src/shaders/pbr-direct.frag.glsl +0 -687
  246. package/src/shaders/pbr-direct.vert.glsl +0 -18
  247. package/src/shaders/unlit.frag.glsl +0 -18
  248. package/src/shaders/unlit.vert.glsl +0 -13
  249. package/src/shadows/CascadedShadowPipeline.ts +0 -53
  250. package/src/shadows/ContactShadows.ts +0 -106
  251. package/src/shadows/ShadowDebugViews.ts +0 -46
  252. package/src/threejs-compatibility/InstancingSystem.ts +0 -17
  253. package/src/threejs-compatibility/LightingSystem.ts +0 -22
  254. package/src/threejs-compatibility/MaterialSystem.ts +0 -9
  255. package/src/threejs-compatibility/RenderTargetSystem.ts +0 -35
  256. package/src/threejs-compatibility/RendererDiagnostics.ts +0 -61
  257. package/src/threejs-compatibility/SceneRenderer.ts +0 -34
  258. package/src/threejs-compatibility/ShadowSystem.ts +0 -19
  259. package/src/threejs-compatibility/TextureSystem.ts +0 -19
  260. package/src/threejs-compatibility/ThreeCompatRenderer.ts +0 -90
  261. package/src/threejs-compatibility/TransparencySystem.ts +0 -19
  262. package/src/threejs-compatibility/index.ts +0 -29
  263. package/src/threejs-compatibility/performance/BVH.ts +0 -14
  264. package/src/threejs-compatibility/performance/FrustumCulling.ts +0 -10
  265. package/src/threejs-compatibility/performance/Instancing.ts +0 -4
  266. package/src/threejs-compatibility/performance/LODSystem.ts +0 -16
  267. package/src/threejs-compatibility/performance/OcclusionCulling.ts +0 -6
  268. package/src/threejs-compatibility/performance/RaycastAcceleration.ts +0 -12
  269. package/src/threejs-compatibility/performance/RendererProfiler.ts +0 -19
  270. package/src/threejs-compatibility/performance/TextureStreaming.ts +0 -4
  271. package/src/threejs-compatibility/performance/index.ts +0 -12
  272. package/src/threejs-compatibility/postprocess/BloomPass.ts +0 -16
  273. package/src/threejs-compatibility/postprocess/ColorGradingPass.ts +0 -16
  274. package/src/threejs-compatibility/postprocess/DepthOfFieldPass.ts +0 -21
  275. package/src/threejs-compatibility/postprocess/EffectComposer.ts +0 -14
  276. package/src/threejs-compatibility/postprocess/FXAAPass.ts +0 -15
  277. package/src/threejs-compatibility/postprocess/MotionBlurPass.ts +0 -20
  278. package/src/threejs-compatibility/postprocess/OutlinePass.ts +0 -21
  279. package/src/threejs-compatibility/postprocess/PostProcessTypes.ts +0 -169
  280. package/src/threejs-compatibility/postprocess/RenderPass.ts +0 -9
  281. package/src/threejs-compatibility/postprocess/SMAAPass.ts +0 -15
  282. package/src/threejs-compatibility/postprocess/SSAOPass.ts +0 -21
  283. package/src/threejs-compatibility/postprocess/ShaderPass.ts +0 -7
  284. package/src/threejs-compatibility/postprocess/TAAPass.ts +0 -15
  285. package/src/threejs-compatibility/postprocess/VignettePass.ts +0 -16
  286. package/src/threejs-compatibility/postprocess/index.ts +0 -15
  287. package/src/threejs-compatibility/shaders/NodeMaterial.ts +0 -21
  288. package/src/threejs-compatibility/shaders/RawShaderMaterial.ts +0 -6
  289. package/src/threejs-compatibility/shaders/ShaderDiagnostics.ts +0 -17
  290. package/src/threejs-compatibility/shaders/ShaderMaterial.ts +0 -18
  291. package/src/threejs-compatibility/shaders/ThreeCompatShaderChunks.ts +0 -6
  292. package/src/threejs-compatibility/shaders/Uniforms.ts +0 -18
  293. package/src/threejs-compatibility/shaders/index.ts +0 -9
  294. package/src/threejs-compatibility/vfx/GPUPointCloud.ts +0 -7
  295. package/src/threejs-compatibility/vfx/LineRenderer.ts +0 -13
  296. package/src/threejs-compatibility/vfx/ParticleSystem.ts +0 -23
  297. package/src/threejs-compatibility/vfx/SpriteSystem.ts +0 -14
  298. package/src/threejs-compatibility/vfx/TrailRenderer.ts +0 -8
  299. package/src/threejs-compatibility/vfx/VFXDiagnostics.ts +0 -23
  300. package/src/threejs-compatibility/vfx/index.ts +0 -9
  301. package/src/threejs-example-parity/index.ts +0 -205
  302. package/src/webgpu/WebGPUBuffer.ts +0 -1
  303. package/src/webgpu/WebGPUCompute.ts +0 -2
  304. package/src/webgpu/WebGPUPipelineCache.ts +0 -15
  305. package/src/webgpu/WebGPUPostProcess.ts +0 -2
  306. package/src/webgpu/WebGPUTexture.ts +0 -2
  307. package/tsconfig.json +0 -26
  308. package/vitest.config.ts +0 -20
@@ -1,836 +0,0 @@
1
- import {
2
- createExternalParityColorManagementPolicy,
3
- type A3DColorManagementPolicy,
4
- type A3DColorSpace,
5
- type A3DTextureSemantic
6
- } from "./ColorManagement";
7
- import {
8
- createToneMappingCalibration,
9
- type BloomOptions,
10
- type ChromaticAberrationOptions,
11
- type ColorGradeOptions,
12
- type ContactShadowPostProcessOptions,
13
- type DepthOfFieldOptions,
14
- type FXAAOptions,
15
- type FilmGrainOptions,
16
- type MotionBlurOptions,
17
- type OutlineOptions,
18
- type PostProcessColorSpace,
19
- type SSAOOptions,
20
- type SSROptions,
21
- type TAAOptions,
22
- type ToneMappingCalibration,
23
- type ToneMappingOperator,
24
- type ToneMappingOptions,
25
- type ToneMappingPresetName
26
- } from "./PostProcessPass";
27
- import {
28
- createRendererPostprocessPlanDiagnostics,
29
- type RendererPostprocessExecutionMode,
30
- type RendererPostprocessPlanDiagnostics
31
- } from "./RendererPostprocessPlan";
32
- import { listExternalParityToneMappingPresets } from "./ToneMapping";
33
- import type {
34
- RenderDevice,
35
- RenderDeviceCapability,
36
- RenderDeviceDiagnostics,
37
- RenderTargetDescriptor
38
- } from "./RenderDevice";
39
-
40
- export type RendererVisualPipelineStatus = "supported" | "partial" | "unsupported";
41
- export type RendererVisualTargetFormat = Extract<RenderTargetDescriptor["format"], "rgba8" | "rgba16f" | "rgba32f">;
42
- export type RendererVisualPostprocessPassName =
43
- | "tone-mapping"
44
- | "color-grade"
45
- | "bloom"
46
- | "chromatic-aberration"
47
- | "film-grain"
48
- | "depth-of-field"
49
- | "motion-blur"
50
- | "contact-shadow"
51
- | "ssao"
52
- | "ssr"
53
- | "taa"
54
- | "outline"
55
- | "fxaa";
56
-
57
- export type RendererUnsupportedVisualCapability =
58
- | "display-p3-output"
59
- | "rec2020-output"
60
- | "hdr-display-swapchain"
61
- | "automatic-png-color-profile";
62
-
63
- export interface RendererVisualPostprocessDescriptor {
64
- readonly targetFormat?: RendererVisualTargetFormat;
65
- readonly toneMapping?: ToneMappingOptions | false;
66
- readonly colorGrade?: ColorGradeOptions | boolean;
67
- readonly bloom?: BloomOptions | boolean;
68
- readonly chromaticAberration?: ChromaticAberrationOptions | boolean;
69
- readonly filmGrain?: FilmGrainOptions | boolean;
70
- readonly depthOfField?: DepthOfFieldOptions | false;
71
- readonly motionBlur?: MotionBlurOptions | false;
72
- readonly contactShadow?: ContactShadowPostProcessOptions | false;
73
- readonly ssao?: SSAOOptions | false;
74
- readonly ssr?: SSROptions | false;
75
- readonly taa?: TAAOptions | false;
76
- readonly outline?: OutlineOptions | boolean;
77
- readonly fxaa?: FXAAOptions | boolean;
78
- }
79
-
80
- export interface RendererCanvasBackingInput {
81
- readonly cssWidth: number;
82
- readonly cssHeight: number;
83
- readonly devicePixelRatio: number;
84
- readonly actualWidth?: number;
85
- readonly actualHeight?: number;
86
- }
87
-
88
- export interface RendererCanvasBackingReport {
89
- readonly status: RendererVisualPipelineStatus;
90
- readonly cssWidth: number;
91
- readonly cssHeight: number;
92
- readonly devicePixelRatio: number;
93
- readonly expectedWidth: number;
94
- readonly expectedHeight: number;
95
- readonly actualWidth?: number;
96
- readonly actualHeight?: number;
97
- readonly effectiveDevicePixelRatio?: number;
98
- readonly backingStoreMatchesDisplay: boolean;
99
- readonly warnings: readonly string[];
100
- }
101
-
102
- export interface RendererScreenshotConsistencyInput {
103
- readonly width: number;
104
- readonly height: number;
105
- readonly byteLength: number;
106
- readonly expectedWidth: number;
107
- readonly expectedHeight: number;
108
- readonly expectedByteLength?: number;
109
- readonly colorSpace?: A3DColorSpace;
110
- }
111
-
112
- export interface RendererScreenshotConsistencyReport {
113
- readonly status: RendererVisualPipelineStatus;
114
- readonly width: number;
115
- readonly height: number;
116
- readonly byteLength: number;
117
- readonly expectedWidth: number;
118
- readonly expectedHeight: number;
119
- readonly expectedByteLength: number;
120
- readonly colorSpace: A3DColorSpace;
121
- readonly pixelFormat: "rgba8";
122
- readonly readbackMatchesBackingStore: boolean;
123
- readonly colorProfileEmbedded: false;
124
- readonly warnings: readonly string[];
125
- }
126
-
127
- export interface RendererCaptureQualityInput {
128
- readonly cssWidth: number;
129
- readonly cssHeight: number;
130
- readonly backingWidth: number;
131
- readonly backingHeight: number;
132
- readonly screenshotWidth: number;
133
- readonly screenshotHeight: number;
134
- readonly captureCssWidth?: number;
135
- readonly captureCssHeight?: number;
136
- readonly devicePixelRatio?: number;
137
- readonly minimumEffectiveDpr?: number;
138
- readonly label?: string;
139
- }
140
-
141
- export interface RendererCaptureQualityReport {
142
- readonly status: RendererVisualPipelineStatus;
143
- readonly label?: string;
144
- readonly cssWidth: number;
145
- readonly cssHeight: number;
146
- readonly backingWidth: number;
147
- readonly backingHeight: number;
148
- readonly screenshotWidth: number;
149
- readonly screenshotHeight: number;
150
- readonly captureCssWidth: number;
151
- readonly captureCssHeight: number;
152
- readonly devicePixelRatio?: number;
153
- readonly minimumEffectiveDpr: number;
154
- readonly effectiveBackingDprX: number;
155
- readonly effectiveBackingDprY: number;
156
- readonly effectiveCaptureDprX: number;
157
- readonly effectiveCaptureDprY: number;
158
- readonly captureToBackingScaleX: number;
159
- readonly captureToBackingScaleY: number;
160
- readonly capturesFullCanvas: boolean;
161
- readonly fullCanvasPixelMatch: boolean;
162
- readonly captureDownsamplesCanvas: boolean;
163
- readonly captureUpscalesCanvas: boolean;
164
- readonly meetsMinimumEffectiveDpr: boolean;
165
- readonly warnings: readonly string[];
166
- }
167
-
168
- export interface RendererFrameCadenceInput {
169
- readonly targetFrameMs?: number;
170
- readonly renderMs?: number;
171
- readonly loopMs?: number;
172
- readonly frameIntervalMs?: number;
173
- readonly readbackMs?: number;
174
- readonly screenshotCaptureOverheadMs?: number;
175
- readonly sampleCount?: number;
176
- }
177
-
178
- export interface RendererFrameCadenceReport {
179
- readonly status: RendererVisualPipelineStatus;
180
- readonly targetFrameMs: number;
181
- readonly renderMs?: number;
182
- readonly loopMs?: number;
183
- readonly frameIntervalMs?: number;
184
- readonly readbackMs?: number;
185
- readonly screenshotCaptureOverheadMs?: number;
186
- readonly sampleCount?: number;
187
- readonly renderBudgetRatio?: number;
188
- readonly loopBudgetRatio?: number;
189
- readonly frameIntervalBudgetRatio?: number;
190
- readonly readbackBudgetRatio?: number;
191
- readonly captureOverheadFrames?: number;
192
- readonly loopHeadroomMs?: number;
193
- readonly stableForCapture: boolean;
194
- readonly warnings: readonly string[];
195
- }
196
-
197
- export interface RendererVisualPipelineReportOptions {
198
- readonly device: RenderDevice;
199
- readonly width: number;
200
- readonly height: number;
201
- readonly postprocess?: RendererVisualPostprocessDescriptor | boolean;
202
- readonly colorManagement?: A3DColorManagementPolicy;
203
- readonly canvas?: RendererCanvasBackingInput;
204
- readonly screenshot?: Omit<RendererScreenshotConsistencyInput, "expectedWidth" | "expectedHeight" | "colorSpace"> & {
205
- readonly colorSpace?: A3DColorSpace;
206
- };
207
- readonly capture?: RendererCaptureQualityInput;
208
- readonly frameCadence?: RendererFrameCadenceInput;
209
- readonly diagnostics?: RenderDeviceDiagnostics;
210
- }
211
-
212
- export interface RendererVisualColorReport {
213
- readonly lightingColorSpace: "linear";
214
- readonly outputColorSpace: A3DColorSpace;
215
- readonly supportedOutputColorSpaces: readonly A3DColorSpace[];
216
- readonly unsupportedOutputColorSpaces: readonly ["display-p3", "rec2020"];
217
- readonly texturePolicy: Readonly<Record<A3DTextureSemantic, A3DColorSpace>>;
218
- readonly ldrFallbackAllowed: boolean;
219
- readonly fallbackBehavior: string;
220
- }
221
-
222
- export interface RendererVisualToneMappingReport {
223
- readonly status: RendererVisualPipelineStatus;
224
- readonly enabled: boolean;
225
- readonly operator?: ToneMappingOperator;
226
- readonly exposure?: number;
227
- readonly whitePoint?: number;
228
- readonly gamma?: number;
229
- readonly inputColorSpace?: PostProcessColorSpace;
230
- readonly outputColorSpace?: PostProcessColorSpace;
231
- readonly calibration?: ToneMappingCalibration;
232
- readonly availablePresets: readonly ToneMappingPresetName[];
233
- readonly warnings: readonly string[];
234
- }
235
-
236
- export interface RendererVisualPostprocessReport {
237
- readonly status: RendererVisualPipelineStatus;
238
- readonly enabled: boolean;
239
- readonly passNames: readonly RendererVisualPostprocessPassName[];
240
- readonly targetFormat: RendererVisualTargetFormat;
241
- readonly sourceTargetFormat: RendererVisualTargetFormat;
242
- readonly executionMode: RendererPostprocessExecutionMode;
243
- readonly nativePresentation: boolean;
244
- readonly usesReadback: boolean;
245
- readonly missingInputs: readonly string[];
246
- readonly readbackPassNames: readonly RendererVisualPostprocessPassName[];
247
- readonly rendererOwnedPassNames: readonly RendererVisualPostprocessPassName[];
248
- readonly clarityWarnings: readonly string[];
249
- readonly forwardOutputColorSpace: PostProcessColorSpace;
250
- readonly presentationColorSpace: A3DColorSpace;
251
- readonly renderTargetWidth: number;
252
- readonly renderTargetHeight: number;
253
- readonly plan?: RendererPostprocessPlanDiagnostics;
254
- readonly warnings: readonly string[];
255
- }
256
-
257
- export interface RendererVisualHdrTargetReport {
258
- readonly status: RendererVisualPipelineStatus;
259
- readonly requested: boolean;
260
- readonly supportedByBackend: boolean;
261
- readonly capabilityAdvertised: boolean;
262
- readonly targetFormat: RendererVisualTargetFormat;
263
- readonly fallbackFormat?: "rgba8";
264
- readonly toneMappingRequired: boolean;
265
- readonly warnings: readonly string[];
266
- }
267
-
268
- export interface RendererVisualPipelineReport {
269
- readonly status: RendererVisualPipelineStatus;
270
- readonly backend: RenderDevice["kind"];
271
- readonly renderer: string;
272
- readonly width: number;
273
- readonly height: number;
274
- readonly capabilities: readonly RenderDeviceCapability[];
275
- readonly color: RendererVisualColorReport;
276
- readonly toneMapping: RendererVisualToneMappingReport;
277
- readonly hdrTarget: RendererVisualHdrTargetReport;
278
- readonly postprocess: RendererVisualPostprocessReport;
279
- readonly canvas?: RendererCanvasBackingReport;
280
- readonly screenshot?: RendererScreenshotConsistencyReport;
281
- readonly capture?: RendererCaptureQualityReport;
282
- readonly frameCadence?: RendererFrameCadenceReport;
283
- readonly diagnostics?: RenderDeviceDiagnostics;
284
- readonly unsupportedCapabilities: Readonly<Record<RendererUnsupportedVisualCapability, string>>;
285
- readonly warnings: readonly string[];
286
- }
287
-
288
- const SUPPORTED_OUTPUT_COLOR_SPACES: readonly A3DColorSpace[] = ["linear", "srgb"];
289
- const UNSUPPORTED_OUTPUT_COLOR_SPACES = ["display-p3", "rec2020"] as const;
290
- const HDR_FORMATS: readonly RendererVisualTargetFormat[] = ["rgba16f", "rgba32f"];
291
-
292
- const UNSUPPORTED_CAPABILITIES: Readonly<Record<RendererUnsupportedVisualCapability, string>> = {
293
- "display-p3-output": "Renderer output color space is limited to linear or sRGB; display-p3 output is not exposed.",
294
- "rec2020-output": "Renderer output color space is limited to linear or sRGB; Rec.2020 output is not exposed.",
295
- "hdr-display-swapchain": "HDR render targets can be tone-mapped, but HDR display swapchain output is not exposed.",
296
- "automatic-png-color-profile": "Screenshot readback is RGBA8 bytes; PNG/ICC profile tagging is owned by the caller."
297
- };
298
-
299
- export function createRendererVisualPipelineReport(
300
- options: RendererVisualPipelineReportOptions
301
- ): RendererVisualPipelineReport {
302
- assertPositiveInteger(options.width, "width");
303
- assertPositiveInteger(options.height, "height");
304
-
305
- const capabilities = [...(options.device.info.capabilities ?? [])];
306
- const capabilitySet = new Set<RenderDeviceCapability>(capabilities);
307
- const colorManagement = options.colorManagement ?? createExternalParityColorManagementPolicy();
308
- const postprocess = normalizePostprocess(options.postprocess);
309
- const postprocessEnabled = postprocess !== undefined;
310
- const passNames = postprocess ? collectPostprocessPassNames(postprocess) : [];
311
- const targetFormat = postprocess ? resolvePostprocessTargetFormat(capabilitySet, postprocess) : "rgba8";
312
- const postprocessPlan = postprocess
313
- ? createRendererPostprocessPlanDiagnostics(postprocess, {
314
- sourceTargetFormat: targetFormat,
315
- targetFormat,
316
- nativeLdrPostprocess: Boolean(options.device.presentLdrPostprocess),
317
- rendererDepthAvailable: capabilitySet.has("depth-textures")
318
- })
319
- : undefined;
320
- const hdrTarget = createHdrTargetReport(capabilitySet, targetFormat, postprocess?.toneMapping);
321
- const toneMapping = createToneMappingReport(postprocess, targetFormat);
322
- const postprocessReport = createPostprocessReport({
323
- enabled: postprocessEnabled,
324
- passNames,
325
- targetFormat,
326
- plan: postprocessPlan,
327
- width: options.width,
328
- height: options.height,
329
- presentationColorSpace: colorManagement.outputColorSpace,
330
- hdrTargetStatus: hdrTarget.status,
331
- toneMappingStatus: toneMapping.status
332
- });
333
- const canvas = options.canvas ? evaluateRendererCanvasBacking(options.canvas) : undefined;
334
- const screenshot = options.screenshot
335
- ? evaluateRendererScreenshotConsistency({
336
- ...options.screenshot,
337
- expectedWidth: options.width,
338
- expectedHeight: options.height,
339
- colorSpace: options.screenshot.colorSpace ?? colorManagement.outputColorSpace
340
- })
341
- : undefined;
342
- const capture = options.capture ? evaluateRendererCaptureQuality(options.capture) : undefined;
343
- const frameCadence = options.frameCadence ? evaluateRendererFrameCadence(options.frameCadence) : undefined;
344
- const warnings = [
345
- ...hdrTarget.warnings,
346
- ...toneMapping.warnings,
347
- ...postprocessReport.warnings,
348
- ...(canvas?.warnings ?? []),
349
- ...(screenshot?.warnings ?? []),
350
- ...(capture?.warnings ?? []),
351
- ...(frameCadence?.warnings ?? [])
352
- ];
353
-
354
- return {
355
- status: combineStatuses([
356
- hdrTarget.status,
357
- toneMapping.status,
358
- postprocessReport.status,
359
- canvas?.status,
360
- screenshot?.status,
361
- capture?.status,
362
- frameCadence?.status
363
- ]),
364
- backend: options.device.kind,
365
- renderer: options.device.info.renderer,
366
- width: options.width,
367
- height: options.height,
368
- capabilities,
369
- color: {
370
- lightingColorSpace: colorManagement.lightingColorSpace,
371
- outputColorSpace: colorManagement.outputColorSpace,
372
- supportedOutputColorSpaces: SUPPORTED_OUTPUT_COLOR_SPACES,
373
- unsupportedOutputColorSpaces: UNSUPPORTED_OUTPUT_COLOR_SPACES,
374
- texturePolicy: colorManagement.texturePolicy,
375
- ldrFallbackAllowed: colorManagement.allowLdrFallback,
376
- fallbackBehavior: colorManagement.fallbackBehavior
377
- },
378
- toneMapping,
379
- hdrTarget,
380
- postprocess: postprocessReport,
381
- ...(canvas ? { canvas } : {}),
382
- ...(screenshot ? { screenshot } : {}),
383
- ...(capture ? { capture } : {}),
384
- ...(frameCadence ? { frameCadence } : {}),
385
- ...(options.diagnostics ? { diagnostics: options.diagnostics } : {}),
386
- unsupportedCapabilities: UNSUPPORTED_CAPABILITIES,
387
- warnings
388
- };
389
- }
390
-
391
- export function evaluateRendererCanvasBacking(input: RendererCanvasBackingInput): RendererCanvasBackingReport {
392
- assertPositiveFinite(input.cssWidth, "cssWidth");
393
- assertPositiveFinite(input.cssHeight, "cssHeight");
394
- assertPositiveFinite(input.devicePixelRatio, "devicePixelRatio");
395
- const expectedWidth = Math.max(1, Math.round(input.cssWidth * input.devicePixelRatio));
396
- const expectedHeight = Math.max(1, Math.round(input.cssHeight * input.devicePixelRatio));
397
- const hasActualDimensions = input.actualWidth !== undefined && input.actualHeight !== undefined;
398
- const matches = hasActualDimensions
399
- ? input.actualWidth === expectedWidth && input.actualHeight === expectedHeight
400
- : false;
401
- const warnings = createCanvasBackingWarnings(input, expectedWidth, expectedHeight, hasActualDimensions, matches);
402
-
403
- return {
404
- status: matches ? "supported" : "partial",
405
- cssWidth: input.cssWidth,
406
- cssHeight: input.cssHeight,
407
- devicePixelRatio: input.devicePixelRatio,
408
- expectedWidth,
409
- expectedHeight,
410
- ...(input.actualWidth !== undefined ? { actualWidth: input.actualWidth } : {}),
411
- ...(input.actualHeight !== undefined ? { actualHeight: input.actualHeight } : {}),
412
- ...(hasActualDimensions ? { effectiveDevicePixelRatio: round(input.actualWidth! / input.cssWidth) } : {}),
413
- backingStoreMatchesDisplay: matches,
414
- warnings
415
- };
416
- }
417
-
418
- export function evaluateRendererScreenshotConsistency(
419
- input: RendererScreenshotConsistencyInput
420
- ): RendererScreenshotConsistencyReport {
421
- assertPositiveInteger(input.width, "width");
422
- assertPositiveInteger(input.height, "height");
423
- assertPositiveInteger(input.expectedWidth, "expectedWidth");
424
- assertPositiveInteger(input.expectedHeight, "expectedHeight");
425
- assertPositiveInteger(input.byteLength, "byteLength");
426
- if (input.expectedByteLength !== undefined) assertPositiveInteger(input.expectedByteLength, "expectedByteLength");
427
- const expectedByteLength = input.expectedByteLength ?? input.expectedWidth * input.expectedHeight * 4;
428
- const dimensionsMatch = input.width === input.expectedWidth && input.height === input.expectedHeight;
429
- const bytesMatch = input.byteLength === expectedByteLength;
430
- const warnings: string[] = [];
431
- if (!dimensionsMatch) {
432
- warnings.push(`Screenshot readback ${input.width}x${input.height} does not match renderer backing store ${input.expectedWidth}x${input.expectedHeight}.`);
433
- }
434
- if (!bytesMatch) {
435
- warnings.push(`Screenshot byte length ${input.byteLength} does not match expected RGBA8 byte length ${expectedByteLength}.`);
436
- }
437
- warnings.push("Screenshot readback reports RGBA8 pixels; embedded PNG/ICC color profiles are not guaranteed by the renderer.");
438
-
439
- return {
440
- status: dimensionsMatch && bytesMatch ? "supported" : "partial",
441
- width: input.width,
442
- height: input.height,
443
- byteLength: input.byteLength,
444
- expectedWidth: input.expectedWidth,
445
- expectedHeight: input.expectedHeight,
446
- expectedByteLength,
447
- colorSpace: input.colorSpace ?? "srgb",
448
- pixelFormat: "rgba8",
449
- readbackMatchesBackingStore: dimensionsMatch && bytesMatch,
450
- colorProfileEmbedded: false,
451
- warnings
452
- };
453
- }
454
-
455
- export function evaluateRendererCaptureQuality(input: RendererCaptureQualityInput): RendererCaptureQualityReport {
456
- assertPositiveFinite(input.cssWidth, "cssWidth");
457
- assertPositiveFinite(input.cssHeight, "cssHeight");
458
- assertPositiveInteger(input.backingWidth, "backingWidth");
459
- assertPositiveInteger(input.backingHeight, "backingHeight");
460
- assertPositiveInteger(input.screenshotWidth, "screenshotWidth");
461
- assertPositiveInteger(input.screenshotHeight, "screenshotHeight");
462
- if (input.captureCssWidth !== undefined) assertPositiveFinite(input.captureCssWidth, "captureCssWidth");
463
- if (input.captureCssHeight !== undefined) assertPositiveFinite(input.captureCssHeight, "captureCssHeight");
464
- if (input.devicePixelRatio !== undefined) assertPositiveFinite(input.devicePixelRatio, "devicePixelRatio");
465
- if (input.minimumEffectiveDpr !== undefined) assertPositiveFinite(input.minimumEffectiveDpr, "minimumEffectiveDpr");
466
-
467
- const captureCssWidth = input.captureCssWidth ?? input.cssWidth;
468
- const captureCssHeight = input.captureCssHeight ?? input.cssHeight;
469
- const minimumEffectiveDpr = input.minimumEffectiveDpr ?? 1;
470
- const effectiveBackingDprX = input.backingWidth / input.cssWidth;
471
- const effectiveBackingDprY = input.backingHeight / input.cssHeight;
472
- const effectiveCaptureDprX = input.screenshotWidth / captureCssWidth;
473
- const effectiveCaptureDprY = input.screenshotHeight / captureCssHeight;
474
- const captureToBackingScaleX = effectiveCaptureDprX / effectiveBackingDprX;
475
- const captureToBackingScaleY = effectiveCaptureDprY / effectiveBackingDprY;
476
- const capturesFullCanvas = nearlyEqual(captureCssWidth, input.cssWidth) && nearlyEqual(captureCssHeight, input.cssHeight);
477
- const fullCanvasPixelMatch = capturesFullCanvas
478
- && input.screenshotWidth === input.backingWidth
479
- && input.screenshotHeight === input.backingHeight;
480
- const captureDownsamplesCanvas = captureToBackingScaleX < 0.98 || captureToBackingScaleY < 0.98;
481
- const captureUpscalesCanvas = captureToBackingScaleX > 1.02 || captureToBackingScaleY > 1.02;
482
- const meetsMinimumEffectiveDpr = effectiveBackingDprX >= minimumEffectiveDpr && effectiveBackingDprY >= minimumEffectiveDpr;
483
- const warnings = createCaptureQualityWarnings({
484
- ...input,
485
- captureCssWidth,
486
- captureCssHeight,
487
- minimumEffectiveDpr,
488
- effectiveBackingDprX,
489
- effectiveBackingDprY,
490
- effectiveCaptureDprX,
491
- effectiveCaptureDprY,
492
- captureDownsamplesCanvas,
493
- captureUpscalesCanvas,
494
- fullCanvasPixelMatch,
495
- capturesFullCanvas,
496
- meetsMinimumEffectiveDpr
497
- });
498
-
499
- return {
500
- status: warnings.length > 0 ? "partial" : "supported",
501
- ...(input.label ? { label: input.label } : {}),
502
- cssWidth: input.cssWidth,
503
- cssHeight: input.cssHeight,
504
- backingWidth: input.backingWidth,
505
- backingHeight: input.backingHeight,
506
- screenshotWidth: input.screenshotWidth,
507
- screenshotHeight: input.screenshotHeight,
508
- captureCssWidth,
509
- captureCssHeight,
510
- ...(input.devicePixelRatio !== undefined ? { devicePixelRatio: input.devicePixelRatio } : {}),
511
- minimumEffectiveDpr,
512
- effectiveBackingDprX: round(effectiveBackingDprX),
513
- effectiveBackingDprY: round(effectiveBackingDprY),
514
- effectiveCaptureDprX: round(effectiveCaptureDprX),
515
- effectiveCaptureDprY: round(effectiveCaptureDprY),
516
- captureToBackingScaleX: round(captureToBackingScaleX),
517
- captureToBackingScaleY: round(captureToBackingScaleY),
518
- capturesFullCanvas,
519
- fullCanvasPixelMatch,
520
- captureDownsamplesCanvas,
521
- captureUpscalesCanvas,
522
- meetsMinimumEffectiveDpr,
523
- warnings
524
- };
525
- }
526
-
527
- export function evaluateRendererFrameCadence(input: RendererFrameCadenceInput): RendererFrameCadenceReport {
528
- const targetFrameMs = input.targetFrameMs ?? 16.667;
529
- assertPositiveFinite(targetFrameMs, "targetFrameMs");
530
- if (input.renderMs !== undefined) assertNonNegativeFinite(input.renderMs, "renderMs");
531
- if (input.loopMs !== undefined) assertNonNegativeFinite(input.loopMs, "loopMs");
532
- if (input.frameIntervalMs !== undefined) assertNonNegativeFinite(input.frameIntervalMs, "frameIntervalMs");
533
- if (input.readbackMs !== undefined) assertNonNegativeFinite(input.readbackMs, "readbackMs");
534
- if (input.screenshotCaptureOverheadMs !== undefined) assertNonNegativeFinite(input.screenshotCaptureOverheadMs, "screenshotCaptureOverheadMs");
535
- if (input.sampleCount !== undefined) assertPositiveInteger(input.sampleCount, "sampleCount");
536
-
537
- const renderBudgetRatio = input.renderMs !== undefined ? input.renderMs / targetFrameMs : undefined;
538
- const loopBudgetRatio = input.loopMs !== undefined ? input.loopMs / targetFrameMs : undefined;
539
- const frameIntervalBudgetRatio = input.frameIntervalMs !== undefined ? input.frameIntervalMs / targetFrameMs : undefined;
540
- const readbackBudgetRatio = input.readbackMs !== undefined ? input.readbackMs / targetFrameMs : undefined;
541
- const captureOverheadFrames = input.screenshotCaptureOverheadMs !== undefined ? input.screenshotCaptureOverheadMs / targetFrameMs : undefined;
542
- const loopHeadroomMs = input.loopMs !== undefined ? targetFrameMs - input.loopMs : undefined;
543
- const warnings = createFrameCadenceWarnings({
544
- ...input,
545
- targetFrameMs,
546
- renderBudgetRatio,
547
- loopBudgetRatio,
548
- frameIntervalBudgetRatio,
549
- readbackBudgetRatio,
550
- captureOverheadFrames
551
- });
552
-
553
- return {
554
- status: warnings.length > 0 ? "partial" : "supported",
555
- targetFrameMs: round(targetFrameMs),
556
- ...(input.renderMs !== undefined ? { renderMs: round(input.renderMs) } : {}),
557
- ...(input.loopMs !== undefined ? { loopMs: round(input.loopMs) } : {}),
558
- ...(input.frameIntervalMs !== undefined ? { frameIntervalMs: round(input.frameIntervalMs) } : {}),
559
- ...(input.readbackMs !== undefined ? { readbackMs: round(input.readbackMs) } : {}),
560
- ...(input.screenshotCaptureOverheadMs !== undefined ? { screenshotCaptureOverheadMs: round(input.screenshotCaptureOverheadMs) } : {}),
561
- ...(input.sampleCount !== undefined ? { sampleCount: input.sampleCount } : {}),
562
- ...(renderBudgetRatio !== undefined ? { renderBudgetRatio: round(renderBudgetRatio) } : {}),
563
- ...(loopBudgetRatio !== undefined ? { loopBudgetRatio: round(loopBudgetRatio) } : {}),
564
- ...(frameIntervalBudgetRatio !== undefined ? { frameIntervalBudgetRatio: round(frameIntervalBudgetRatio) } : {}),
565
- ...(readbackBudgetRatio !== undefined ? { readbackBudgetRatio: round(readbackBudgetRatio) } : {}),
566
- ...(captureOverheadFrames !== undefined ? { captureOverheadFrames: round(captureOverheadFrames) } : {}),
567
- ...(loopHeadroomMs !== undefined ? { loopHeadroomMs: round(loopHeadroomMs) } : {}),
568
- stableForCapture: warnings.length === 0,
569
- warnings
570
- };
571
- }
572
-
573
- function normalizePostprocess(
574
- postprocess: RendererVisualPipelineReportOptions["postprocess"]
575
- ): RendererVisualPostprocessDescriptor | undefined {
576
- if (postprocess === undefined || postprocess === false) return undefined;
577
- if (postprocess === true) return {};
578
- return postprocess;
579
- }
580
-
581
- function collectPostprocessPassNames(postprocess: RendererVisualPostprocessDescriptor): readonly RendererVisualPostprocessPassName[] {
582
- const passes: RendererVisualPostprocessPassName[] = [];
583
- if (postprocess.bloom) passes.push("bloom");
584
- if (postprocess.toneMapping !== false) passes.push("tone-mapping");
585
- if (postprocess.colorGrade) passes.push("color-grade");
586
- if (postprocess.chromaticAberration) passes.push("chromatic-aberration");
587
- if (postprocess.filmGrain) passes.push("film-grain");
588
- if (postprocess.depthOfField) passes.push("depth-of-field");
589
- if (postprocess.motionBlur) passes.push("motion-blur");
590
- if (postprocess.contactShadow) passes.push("contact-shadow");
591
- if (postprocess.ssao) passes.push("ssao");
592
- if (postprocess.ssr) passes.push("ssr");
593
- if (postprocess.taa) passes.push("taa");
594
- if (postprocess.outline) passes.push("outline");
595
- if (postprocess.fxaa) passes.push("fxaa");
596
- return passes;
597
- }
598
-
599
- function resolvePostprocessTargetFormat(
600
- capabilities: ReadonlySet<RenderDeviceCapability>,
601
- postprocess: RendererVisualPostprocessDescriptor
602
- ): RendererVisualTargetFormat {
603
- if (postprocess.targetFormat) return postprocess.targetFormat;
604
- if (postprocess.toneMapping === false) return "rgba8";
605
- return capabilities.has("hdr-render-targets") ? "rgba16f" : "rgba8";
606
- }
607
-
608
- function createHdrTargetReport(
609
- capabilities: ReadonlySet<RenderDeviceCapability>,
610
- targetFormat: RendererVisualTargetFormat,
611
- toneMapping: ToneMappingOptions | false | undefined
612
- ): RendererVisualHdrTargetReport {
613
- const requested = HDR_FORMATS.includes(targetFormat);
614
- const capabilityAdvertised = capabilities.has("hdr-render-targets");
615
- const warnings: string[] = [];
616
- if (requested && !capabilityAdvertised) {
617
- warnings.push(`HDR postprocess target ${targetFormat} was requested, but the backend does not advertise hdr-render-targets.`);
618
- }
619
- if (requested && toneMapping === false) {
620
- warnings.push(`HDR postprocess target ${targetFormat} requires tone mapping before RGBA8 presentation.`);
621
- }
622
-
623
- return {
624
- status: warnings.length > 0 ? "unsupported" : "supported",
625
- requested,
626
- supportedByBackend: !requested || capabilityAdvertised,
627
- capabilityAdvertised,
628
- targetFormat,
629
- ...(requested && !capabilityAdvertised ? { fallbackFormat: "rgba8" } : {}),
630
- toneMappingRequired: requested,
631
- warnings
632
- };
633
- }
634
-
635
- function createToneMappingReport(
636
- postprocess: RendererVisualPostprocessDescriptor | undefined,
637
- targetFormat: RendererVisualTargetFormat
638
- ): RendererVisualToneMappingReport {
639
- const availablePresets = listExternalParityToneMappingPresets().map((preset) => preset.name);
640
- if (!postprocess || postprocess.toneMapping === false) {
641
- const warnings = HDR_FORMATS.includes(targetFormat)
642
- ? [`HDR target ${targetFormat} cannot be presented honestly without tone mapping.`]
643
- : [];
644
- return {
645
- status: warnings.length > 0 ? "unsupported" : "supported",
646
- enabled: false,
647
- availablePresets,
648
- warnings
649
- };
650
- }
651
-
652
- const options = postprocess.toneMapping ?? {};
653
- const resolved = {
654
- exposure: options.exposure ?? 1,
655
- whitePoint: options.whitePoint ?? 1,
656
- gamma: options.gamma ?? 2.2,
657
- operator: options.operator ?? "reinhard",
658
- inputColorSpace: options.inputColorSpace ?? "linear",
659
- outputColorSpace: options.outputColorSpace ?? "srgb"
660
- } satisfies Required<ToneMappingOptions>;
661
- const warnings: string[] = [];
662
- if (resolved.outputColorSpace !== "srgb") {
663
- warnings.push(`Tone mapping outputColorSpace is ${resolved.outputColorSpace}; screenshot and browser presentation consistency is strongest with srgb.`);
664
- }
665
-
666
- return {
667
- status: warnings.length > 0 ? "partial" : "supported",
668
- enabled: true,
669
- operator: resolved.operator,
670
- exposure: resolved.exposure,
671
- whitePoint: resolved.whitePoint,
672
- gamma: resolved.gamma,
673
- inputColorSpace: resolved.inputColorSpace,
674
- outputColorSpace: resolved.outputColorSpace,
675
- calibration: createToneMappingCalibration(resolved),
676
- availablePresets,
677
- warnings
678
- };
679
- }
680
-
681
- function createPostprocessReport(options: {
682
- readonly enabled: boolean;
683
- readonly passNames: readonly RendererVisualPostprocessPassName[];
684
- readonly targetFormat: RendererVisualTargetFormat;
685
- readonly plan?: RendererPostprocessPlanDiagnostics;
686
- readonly width: number;
687
- readonly height: number;
688
- readonly presentationColorSpace: A3DColorSpace;
689
- readonly hdrTargetStatus: RendererVisualPipelineStatus;
690
- readonly toneMappingStatus: RendererVisualPipelineStatus;
691
- }): RendererVisualPostprocessReport {
692
- const warnings: string[] = [];
693
- if (options.enabled && options.passNames.length === 0) {
694
- warnings.push("Postprocess is enabled with no passes; renderer will copy/present the forward target without color changes.");
695
- }
696
- if (options.plan && options.plan.missingInputs.length > 0) {
697
- warnings.push(`Postprocess plan is missing required inputs: ${options.plan.missingInputs.join(", ")}.`);
698
- }
699
- if (options.hdrTargetStatus === "unsupported" || options.toneMappingStatus === "unsupported") {
700
- warnings.push("Postprocess plan is not executable as requested; renderer guards will reject unsupported HDR presentation.");
701
- }
702
- const executionMode = options.plan?.executionMode ?? "none";
703
-
704
- return {
705
- status: combineStatuses([
706
- options.hdrTargetStatus,
707
- options.toneMappingStatus,
708
- warnings.length > 0 ? "partial" : "supported"
709
- ]),
710
- enabled: options.enabled,
711
- passNames: options.passNames,
712
- targetFormat: options.targetFormat,
713
- sourceTargetFormat: options.plan?.sourceTargetFormat ?? options.targetFormat,
714
- executionMode,
715
- nativePresentation: executionMode === "renderer-owned-fused-ldr-native",
716
- usesReadback: (options.plan?.readbackPassNames.length ?? 0) > 0,
717
- missingInputs: options.plan?.missingInputs ?? [],
718
- readbackPassNames: options.plan?.readbackPassNames ?? [],
719
- rendererOwnedPassNames: options.plan?.rendererOwnedPassNames ?? [],
720
- clarityWarnings: options.plan?.clarityWarnings ?? [],
721
- forwardOutputColorSpace: options.enabled ? "linear" : "srgb",
722
- presentationColorSpace: options.presentationColorSpace,
723
- renderTargetWidth: options.width,
724
- renderTargetHeight: options.height,
725
- ...(options.plan ? { plan: options.plan } : {}),
726
- warnings
727
- };
728
- }
729
-
730
- function combineStatuses(statuses: readonly (RendererVisualPipelineStatus | undefined)[]): RendererVisualPipelineStatus {
731
- if (statuses.includes("unsupported")) return "unsupported";
732
- if (statuses.includes("partial")) return "partial";
733
- return "supported";
734
- }
735
-
736
- function createCanvasBackingWarnings(
737
- input: RendererCanvasBackingInput,
738
- expectedWidth: number,
739
- expectedHeight: number,
740
- hasActualDimensions: boolean,
741
- matches: boolean
742
- ): readonly string[] {
743
- if (!hasActualDimensions) {
744
- return [`Canvas backing store dimensions were not provided; expected ${expectedWidth}x${expectedHeight} for CSS ${input.cssWidth}x${input.cssHeight} at DPR ${input.devicePixelRatio}.`];
745
- }
746
- if (!matches) {
747
- return [`Canvas backing store ${input.actualWidth}x${input.actualHeight} does not match CSS ${input.cssWidth}x${input.cssHeight} at DPR ${input.devicePixelRatio}; expected ${expectedWidth}x${expectedHeight}.`];
748
- }
749
- return [];
750
- }
751
-
752
- function createCaptureQualityWarnings(input: RendererCaptureQualityInput & {
753
- readonly captureCssWidth: number;
754
- readonly captureCssHeight: number;
755
- readonly minimumEffectiveDpr: number;
756
- readonly effectiveBackingDprX: number;
757
- readonly effectiveBackingDprY: number;
758
- readonly effectiveCaptureDprX: number;
759
- readonly effectiveCaptureDprY: number;
760
- readonly captureDownsamplesCanvas: boolean;
761
- readonly captureUpscalesCanvas: boolean;
762
- readonly fullCanvasPixelMatch: boolean;
763
- readonly capturesFullCanvas: boolean;
764
- readonly meetsMinimumEffectiveDpr: boolean;
765
- }): readonly string[] {
766
- const warnings: string[] = [];
767
- if (!input.meetsMinimumEffectiveDpr) {
768
- warnings.push(`Canvas backing DPR ${round(input.effectiveBackingDprX)}x${round(input.effectiveBackingDprY)} is below the requested minimum ${input.minimumEffectiveDpr}.`);
769
- }
770
- if (input.devicePixelRatio !== undefined && (input.effectiveBackingDprX < input.devicePixelRatio * 0.98 || input.effectiveBackingDprY < input.devicePixelRatio * 0.98)) {
771
- warnings.push(`Canvas backing DPR ${round(input.effectiveBackingDprX)}x${round(input.effectiveBackingDprY)} is below devicePixelRatio ${input.devicePixelRatio}; a max-edge clamp or resize mismatch may be reducing effective capture detail.`);
772
- }
773
- if (input.captureDownsamplesCanvas) {
774
- warnings.push(`Screenshot capture DPR ${round(input.effectiveCaptureDprX)}x${round(input.effectiveCaptureDprY)} is below canvas backing DPR ${round(input.effectiveBackingDprX)}x${round(input.effectiveBackingDprY)}; browser capture is downsampling renderer detail.`);
775
- }
776
- if (input.captureUpscalesCanvas) {
777
- warnings.push(`Screenshot capture DPR ${round(input.effectiveCaptureDprX)}x${round(input.effectiveCaptureDprY)} is above canvas backing DPR ${round(input.effectiveBackingDprX)}x${round(input.effectiveBackingDprY)}; screenshot pixels may be upscaled from renderer output.`);
778
- }
779
- if (input.capturesFullCanvas && !input.fullCanvasPixelMatch) {
780
- warnings.push(`Full-canvas screenshot ${input.screenshotWidth}x${input.screenshotHeight} does not match canvas backing ${input.backingWidth}x${input.backingHeight}.`);
781
- }
782
- return warnings;
783
- }
784
-
785
- function createFrameCadenceWarnings(input: RendererFrameCadenceInput & {
786
- readonly targetFrameMs: number;
787
- readonly renderBudgetRatio?: number;
788
- readonly loopBudgetRatio?: number;
789
- readonly frameIntervalBudgetRatio?: number;
790
- readonly readbackBudgetRatio?: number;
791
- readonly captureOverheadFrames?: number;
792
- }): readonly string[] {
793
- const warnings: string[] = [];
794
- if (input.renderBudgetRatio !== undefined && input.renderBudgetRatio > 1) {
795
- warnings.push(`Render work ${round(input.renderBudgetRatio)}x exceeds the ${round(input.targetFrameMs)}ms frame budget.`);
796
- }
797
- if (input.loopBudgetRatio !== undefined && input.loopBudgetRatio > 1) {
798
- warnings.push(`Total loop work ${round(input.loopBudgetRatio)}x exceeds the ${round(input.targetFrameMs)}ms frame budget.`);
799
- }
800
- if (input.frameIntervalBudgetRatio !== undefined && input.frameIntervalBudgetRatio > 1.25) {
801
- warnings.push(`Observed frame interval ${round(input.frameIntervalBudgetRatio)}x exceeds the target cadence; capture may land on a stalled frame.`);
802
- }
803
- if (input.readbackBudgetRatio !== undefined && input.readbackBudgetRatio > 0.5) {
804
- warnings.push(`Readback cost ${round(input.readbackBudgetRatio)}x of the frame budget can affect capture cadence.`);
805
- }
806
- if (input.captureOverheadFrames !== undefined && input.captureOverheadFrames > 1) {
807
- warnings.push(`Screenshot capture overhead spans ${round(input.captureOverheadFrames)} frame budgets; visual review captures may include stall artifacts.`);
808
- }
809
- return warnings;
810
- }
811
-
812
- function assertPositiveInteger(value: number, name: string): void {
813
- if (!Number.isInteger(value) || value <= 0) {
814
- throw new Error(`${name} must be a positive integer.`);
815
- }
816
- }
817
-
818
- function assertNonNegativeFinite(value: number, name: string): void {
819
- if (!Number.isFinite(value) || value < 0) {
820
- throw new Error(`${name} must be a finite non-negative number.`);
821
- }
822
- }
823
-
824
- function assertPositiveFinite(value: number, name: string): void {
825
- if (!Number.isFinite(value) || value <= 0) {
826
- throw new Error(`${name} must be a finite positive number.`);
827
- }
828
- }
829
-
830
- function nearlyEqual(left: number, right: number): boolean {
831
- return Math.abs(left - right) <= 0.001;
832
- }
833
-
834
- function round(value: number): number {
835
- return Number(value.toFixed(4));
836
- }