From 4590f9a4b84493ae35e40e23eddf870a57556ae8 Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sat, 10 Oct 2026 17:26:50 +0200 Subject: [PATCH 01/10] [Feature] Draw the XR frame through the compositor's rasterization rate maps (foveation) With foveation enabled in the layer configuration, visionOS hands each eye a rasterization rate map and textures of its physical size; the engine ignored the maps, so apps had to keep foveation off, which also forbids a render quality above the platform default. The stereo path now attaches the eye's map to every pass that rasterizes the scene at drawable size and sets the eye's screen-space viewport there; the full-screen passes keep copying physical pixels one to one. SSAO rebuilds view positions from a texel's screen position, and the occlusion culls (mesh, Gaussian chunk, per-splat) move their projected rects into the pyramid's physical layout through the map the pyramid was drawn with, so culling stays on under foveation. The Gaussian fragment takes its offset from the splat centre from a varying rather than from its position. On by default when the drawable provides maps; `.foveatedRendering(.disabled)` ignores them for diagnosis. Kernels rebuilt for every platform. --- Sources/CShaderTypes/ShaderTypes.h | 13 +- .../RenderExtensionModelSurface.swift | 1 + .../Renderer/RenderPasses+MuscleDebug.swift | 1 + .../UntoldEngine/Renderer/RenderPasses.swift | 37 ++++ .../Renderer/RenderResources.swift | 14 +- .../UntoldEngine/Renderer/XRFoveation.swift | 158 ++++++++++++++ .../UntoldEngine/Shaders/BitonicSort.metal | 22 +- .../Shaders/GaussianChunkCull.metal | 9 +- .../Shaders/GaussianChunkPreprocess.metal | 12 +- Sources/UntoldEngine/Shaders/Gaussians.metal | 31 ++- Sources/UntoldEngine/Shaders/HZBCompute.metal | 6 +- Sources/UntoldEngine/Shaders/HZBOcclusion.h | 35 ++++ Sources/UntoldEngine/Shaders/SSAOShader.metal | 21 +- Sources/UntoldEngine/Shaders/ShaderStructs.h | 4 +- .../UntoldEngine/Systems/CullingSystem.swift | 12 +- .../Systems/GaussianChunkCull.swift | 15 ++ .../UntoldEngine/Systems/GaussianSystem.swift | 8 + .../UntoldEngine/Systems/GraphBuilder.swift | 3 + .../Systems/RenderingSystem.swift | 4 + .../Systems/SmallObjectCulling.swift | 5 +- .../UntoldEngineKernels-ios.metallib | Bin 783432 -> 787304 bytes .../UntoldEngineKernels-iossim.metallib | Bin 786840 -> 790680 bytes .../UntoldEngineKernels-tvos.metallib | Bin 783752 -> 787608 bytes .../UntoldEngineKernels-tvossim.metallib | Bin 787080 -> 790936 bytes .../UntoldEngineKernels-xros.metallib | Bin 784248 -> 788200 bytes .../UntoldEngineKernels-xrossim.metallib | Bin 787480 -> 791400 bytes .../UntoldEngineKernels.metallib | Bin 781928 -> 785752 bytes .../Utils/EngineSettingsAPI.swift | 20 ++ Sources/UntoldEngine/Utils/Globals.swift | 22 ++ Sources/UntoldEngineXR/UntoldEngineXR.swift | 75 ++++++- .../GaussianChunkCullTest.swift | 2 +- .../GaussianChunkLevelTest.swift | 2 +- .../GaussianPagingTest.swift | 3 +- .../GaussianScreenWeightedQuotaTest.swift | 3 +- .../XRFoveationTests.swift | 196 ++++++++++++++++++ docs/API/UsingEngineAPI.md | 11 + docs/Architecture/xrRenderingSystem.md | 9 + 37 files changed, 707 insertions(+), 47 deletions(-) create mode 100644 Sources/UntoldEngine/Renderer/XRFoveation.swift create mode 100644 Tests/UntoldEngineRenderTests/XRFoveationTests.swift diff --git a/Sources/CShaderTypes/ShaderTypes.h b/Sources/CShaderTypes/ShaderTypes.h index 599d73072..40bcd4b90 100644 --- a/Sources/CShaderTypes/ShaderTypes.h +++ b/Sources/CShaderTypes/ShaderTypes.h @@ -559,6 +559,8 @@ typedef enum{ ssaoPassFrustumIndex, ssaoPassReverseZIndex, ssaoPassProjScaleIndex, + ssaoPassRateMapDataIndex, // rasterization_rate_map_data of the eye's rate map (XR foveation; a never-read placeholder otherwise) + ssaoPassRateMapSizesIndex, // float4: the map's screen size in xy, the depth texture's size in zw; x <= 0 when there is no map }SSAOBufferIndices; typedef enum{ @@ -767,7 +769,9 @@ typedef enum{ hzbCullPassViewportIndex, hzbCullPassMipCountIndex, hzbCullPassReverseZIndex, - hzbCullPassOcclusionBiasIndex + hzbCullPassOcclusionBiasIndex, + hzbCullPassRateMapDataIndex, // rasterization_rate_map_data the pyramid was drawn through (XR foveation; a never-read placeholder otherwise) + hzbCullPassRateMapSizesIndex // float4: the map's screen size in xy, the pyramid's base size in zw; x <= 0 when there is no map }HZBOcclusionCullingBufferIndices; typedef enum{ @@ -800,6 +804,8 @@ typedef enum{ gaussianCullHZBReverseZIndex, gaussianCullHZBOcclusionBiasIndex, gaussianCullHZBValidIndex, + gaussianCullHZBRateMapDataIndex, // rasterization_rate_map_data the pyramid was drawn through (XR foveation; a never-read placeholder otherwise) + gaussianCullHZBRateMapSizesIndex, // float4: the map's screen size in xy, the pyramid's base size in zw; x <= 0 when there is no map }GaussianDepthBufferIndices; typedef enum{ @@ -1034,7 +1040,8 @@ typedef struct{ uint32_t uniformQuotas; // GaussianDebugOptions.disableScreenWeightedQuotas: screenArea = splatCount, the uniform quota rule uint32_t paged; // 0: every record resident; 1: a paged entity (the cull writes the demand table and lists resident ranks only, the fused pass reads the page pool); 2: demand only (a warming tier: write the demand word and return) uint32_t rangeCount; // entries of ranges[] (gaussianChunkCullRangesIndex, GaussianChunkTreeCull); a thread whose chunkIndex falls in none of them skips the per-chunk test. 0 (GaussianDebugOptions.disableTreeSkip, or a file without a tree) skips the check entirely, as before the tree was wired in -}GaussianChunkCullConstants; // 192 bytes (176 + rangeCount, padded to the struct's 16-byte alignment) + simd_float4 hzbRateMapSizes; // the rasterization rate map the HZB was drawn through (XR foveation): its screen size in xy, the pyramid's base size in zw; x <= 0 when there is none and the rate map buffer is a never-read placeholder +}GaussianChunkCullConstants; // 208 bytes (180 + hzbRateMapSizes at 192, padded to the struct's 16-byte alignment) /// One span of GaussianChunkTreeCull.visibleChunkRanges (Swift): chunk indices [firstChunk, /// firstChunk + chunkCount) the tree walk could not rule out this frame. Every chunk still gets @@ -1062,6 +1069,7 @@ typedef enum{ gaussianChunkCullLevelStateIndex = 11, // GaussianChunkLevelState[chunkCount], persistent, written by gaussianComputeChunkQuotas (a never-read stand-in without coarse levels) gaussianChunkCullLevelConstantsIndex = 12, // GaussianChunkLevelConstants (setBytes); hasCoarse = 0 keeps every path as it was gaussianChunkCullRangesIndex = 13, // GaussianChunkCullRange[rangeCount] (setBytes; a never-read stand-in when rangeCount == 0) + gaussianChunkCullRateMapDataIndex = 14, // rasterization_rate_map_data the HZB was drawn through (XR foveation; read only when hzbRateMapSizes.x > 0, a placeholder otherwise) }GaussianChunkCullBufferIndices; typedef enum{ @@ -1299,6 +1307,7 @@ typedef enum{ gaussianChunkPreprocessCoarseTableIndex, // 17: GaussianChunkDecodeConstants[levelCount × chunkCount], the coarse rows, level-major gaussianChunkPreprocessLevelStateIndex, // 18: GaussianChunkLevelState[chunkCount] as gaussianComputeChunkQuotas left it this frame gaussianChunkPreprocessLevelConstantsIndex, // 19: GaussianChunkLevelConstants (setBytes) + gaussianChunkPreprocessRateMapDataIndex, // 20: rasterization_rate_map_data the HZB was drawn through (XR foveation; read only when the cull constants' hzbRateMapSizes.x > 0, a placeholder otherwise) }GaussianChunkPreprocessBufferIndices; typedef enum{ diff --git a/Sources/UntoldEngine/Renderer/RenderExtensionModelSurface.swift b/Sources/UntoldEngine/Renderer/RenderExtensionModelSurface.swift index 83f2deaba..e80f6d21e 100644 --- a/Sources/UntoldEngine/Renderer/RenderExtensionModelSurface.swift +++ b/Sources/UntoldEngine/Renderer/RenderExtensionModelSurface.swift @@ -258,6 +258,7 @@ public extension RenderPassContext { renderEncoder.label = label renderEncoder.pushDebugGroup(label) + applyXRFoveationViewport(renderEncoder) renderEncoder.setRenderPipelineState(pipelineState) renderEncoder.setDepthStencilState(pipeline.depthState) diff --git a/Sources/UntoldEngine/Renderer/RenderPasses+MuscleDebug.swift b/Sources/UntoldEngine/Renderer/RenderPasses+MuscleDebug.swift index 3cdeef819..544c16366 100644 --- a/Sources/UntoldEngine/Renderer/RenderPasses+MuscleDebug.swift +++ b/Sources/UntoldEngine/Renderer/RenderPasses+MuscleDebug.swift @@ -155,6 +155,7 @@ public extension RenderPasses { } renderEncoder.label = "Muscle Debug Pass" renderEncoder.pushDebugGroup("Muscle Debug Pass") + applyXRFoveationViewport(renderEncoder) renderEncoder.setRenderPipelineState(pipelineState) // The cages live under the skin, so never depth-test them. In visionOS // mixed immersion the compositor drops pixels that wrote no depth, so diff --git a/Sources/UntoldEngine/Renderer/RenderPasses.swift b/Sources/UntoldEngine/Renderer/RenderPasses.swift index a6810cc66..ed9e340ea 100644 --- a/Sources/UntoldEngine/Renderer/RenderPasses.swift +++ b/Sources/UntoldEngine/Renderer/RenderPasses.swift @@ -1076,6 +1076,7 @@ public enum RenderPasses { } renderEncoder.label = "Grid Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Grid Pass") @@ -1167,6 +1168,7 @@ public enum RenderPasses { } renderEncoder.label = "Sky Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Sky Pass") @@ -1237,6 +1239,7 @@ public enum RenderPasses { } renderEncoder.label = "Environment Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Environment Pass") @@ -1835,6 +1838,7 @@ public enum RenderPasses { } renderEncoder.label = "Model Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Model Pass") @@ -2102,6 +2106,7 @@ public enum RenderPasses { } renderEncoder.label = "Batched Model Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Batched Model Pass") renderEncoder.setRenderPipelineState(modelPipeline.pipelineState!) @@ -2342,6 +2347,10 @@ public enum RenderPasses { renderEncoder.label = "G-Buffer + Light Pass (TBDR)" renderEncoder.pushDebugGroup("G-Buffer + Light Pass (TBDR)") + // Through the eye's rasterization rate map when there is one (XR foveation): the + // geometry in the map's screen space, the light quad over the whole of it, the + // G-buffer read back from the tile under each fragment either way. + applyXRFoveationViewport(renderEncoder) // What every draw of the pass shares, read once. let pass = OpaquePassState(cameraComponent: cameraComponent) @@ -2800,6 +2809,14 @@ public enum RenderPasses { var projScale = simd_float2(renderInfo.perspectiveSpace.columns.0.x, renderInfo.perspectiveSpace.columns.1.y) renderEncoder.setFragmentBytes(&projScale, length: MemoryLayout.stride, index: Int(ssaoPassProjScaleIndex.rawValue)) + // The eye's rasterization rate map (XR foveation): the depth was drawn through it, so + // the view positions are rebuilt from where its texels sit on screen, not in the texture. + bindRateMap( + renderInfo.xrFoveation?.rateMapData, + toFragmentsOf: renderEncoder, + dataIndex: Int(ssaoPassRateMapDataIndex.rawValue), + sizesIndex: Int(ssaoPassRateMapSizesIndex.rawValue) + ) // set the draw command renderEncoder.drawIndexedPrimitivesTracked( @@ -3000,6 +3017,14 @@ public enum RenderPasses { var projScale = simd_float2(renderInfo.perspectiveSpace.columns.0.x, renderInfo.perspectiveSpace.columns.1.y) renderEncoder.setFragmentBytes(&projScale, length: MemoryLayout.stride, index: Int(ssaoPassProjScaleIndex.rawValue)) + // The eye's rasterization rate map (XR foveation): the depth was drawn through it, so + // the view positions are rebuilt from where its texels sit on screen, not in the texture. + bindRateMap( + renderInfo.xrFoveation?.rateMapData, + toFragmentsOf: renderEncoder, + dataIndex: Int(ssaoPassRateMapDataIndex.rawValue), + sizesIndex: Int(ssaoPassRateMapSizesIndex.rawValue) + ) // SSAO properties renderEncoder.setFragmentBytes(&SSAOParams.shared.radius, length: MemoryLayout.stride, index: Int(ssaoPassRadiusIndex.rawValue)) @@ -3619,6 +3644,7 @@ public enum RenderPasses { } renderEncoder.label = "Transparency Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Transparency Pass") renderEncoder.setRenderPipelineState(transparencyPipeline.pipelineState!) @@ -4034,6 +4060,9 @@ public enum RenderPasses { descriptor.depthAttachment.texture = depthTexture descriptor.depthAttachment.loadAction = .load descriptor.depthAttachment.storeAction = .store + // The depth was drawn through the eye's rasterization rate map when there is one + // (XR foveation); so is what this pass adds to it. + descriptor.rasterizationRateMap = renderInfo.xrFoveation?.rateMap guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { handleError(.renderPassCreationFailed, "Mesh Occluder Shell Pass") @@ -4047,6 +4076,7 @@ public enum RenderPasses { } renderEncoder.label = "Mesh Occluder Shell Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Mesh Occluder Shell Pass") renderEncoder.setRenderPipelineState(pipelineState) renderEncoder.setDepthStencilState(pipeline.depthState) @@ -4172,6 +4202,9 @@ public enum RenderPasses { descriptor.depthAttachment.texture = depthTexture descriptor.depthAttachment.loadAction = .load descriptor.depthAttachment.storeAction = .store + // The depth was drawn through the eye's rasterization rate map when there is one + // (XR foveation); so is what this pass adds to it. + descriptor.rasterizationRateMap = renderInfo.xrFoveation?.rateMap guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { handleError(.renderPassCreationFailed, "Wireframe Occlusion Depth Pass") @@ -4185,6 +4218,7 @@ public enum RenderPasses { } renderEncoder.label = "Wireframe Occlusion Depth Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Wireframe Occlusion Depth Pass") renderEncoder.setRenderPipelineState(pipelineState) renderEncoder.setDepthStencilState(pipeline.depthState) @@ -4369,6 +4403,7 @@ public enum RenderPasses { } renderEncoder.label = "Wireframe Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Wireframe Pass") renderEncoder.setRenderPipelineState(wireframePipelineState) @@ -4749,6 +4784,7 @@ public enum RenderPasses { } renderEncoder.label = "Spatial Debug Bounds Pass" + applyXRFoveationViewport(renderEncoder) renderEncoder.pushDebugGroup("Spatial Debug Bounds Pass") renderEncoder.setRenderPipelineState(spatialDebugPipeline.pipelineState!) @@ -4897,6 +4933,7 @@ public enum RenderPasses { } renderEncoder.label = "Gaussian Pass" + applyXRFoveationViewport(renderEncoder) renderInfo.gaussianCoverageWritten = true renderEncoder.pushDebugGroup("Gaussian Pass") diff --git a/Sources/UntoldEngine/Renderer/RenderResources.swift b/Sources/UntoldEngine/Renderer/RenderResources.swift index d30c80743..b75ead173 100644 --- a/Sources/UntoldEngine/Renderer/RenderResources.swift +++ b/Sources/UntoldEngine/Renderer/RenderResources.swift @@ -87,6 +87,10 @@ public struct RenderInfo { /// shadingCameraPosition so each eye gets its own view vector (specular highlights, /// Fresnel), while streaming, LOD and culling keep the head-centre camera position. public var xrEyeCameraPosition: simd_float3? + /// The rasterization rate map of the eye being drawn (visionOS foveation), with the + /// viewport and the decoder data that go with it; nil when the frame is drawn uniformly. + /// `viewPort` stays the size of the textures, the map's physical size. See XRFoveation.swift. + public var xrFoveation: XRFoveationFrame? } /// Where an eye is, from its view matrix (the inverse of the eye's camera transform). @@ -176,6 +180,9 @@ public struct BufferResources { var reduceScanCapacity: Int = 0 /// Whether a frame with more bounding boxes than the scan takes was reported. var reportedReduceScanOverflow: Bool = false + + /// Bound where a shader declares a rasterization rate map it will not read (XRFoveation.swift). + var rateMapPlaceholder: MTLBuffer? } public struct TripleBufferResources { @@ -328,9 +335,14 @@ public struct HZBPyramidFrame: Sendable { public var viewProjection: simd_float4x4 /// Where that frame's camera stood, in world space. public var cameraPosition: simd_float3 + /// The rasterization rate map that frame was drawn through (XR foveation), nil when it was + /// drawn uniformly: the pyramid is laid out in the map's physical space, so a screen rect or + /// point the test projects must go through the map before the pyramid is sampled there. + public var rateMapData: XRRasterizationRateMapData? - public init(viewProjection: simd_float4x4, cameraPosition: simd_float3) { + public init(viewProjection: simd_float4x4, cameraPosition: simd_float3, rateMapData: XRRasterizationRateMapData? = nil) { self.viewProjection = viewProjection self.cameraPosition = cameraPosition + self.rateMapData = rateMapData } } diff --git a/Sources/UntoldEngine/Renderer/XRFoveation.swift b/Sources/UntoldEngine/Renderer/XRFoveation.swift new file mode 100644 index 000000000..ab5c7eb60 --- /dev/null +++ b/Sources/UntoldEngine/Renderer/XRFoveation.swift @@ -0,0 +1,158 @@ +// +// XRFoveation.swift +// UntoldEngine +// +// Variable-rate rasterization in XR. With foveation enabled in its layer configuration, the +// visionOS compositor hands the engine, per eye and per frame, a rasterization rate map and +// colour and depth textures of the map's physical size — smaller than the screen the eye +// sees. The GPU draws through the map, dense where the eyes look and coarse in the periphery, +// and the compositor unwarps the texture on the way to the display; a layer configured this +// way also accepts a render quality above the platform default, which a uniform layer does not. +// +// What this asks of the renderer: every pass that rasterizes scene geometry at drawable size +// attaches the eye's map to its descriptor and sets its viewport in the map's screen space +// (`applyXRFoveationToSceneRenderPassDescriptors`, `applyXRFoveationViewport`). The full-screen +// passes that follow — SSAO, post-processing, anti-aliasing, the output transform into the +// compositor's texture — read and write the physical textures one pixel to one and never see +// the map; it is already baked into the layout of what they copy. Two kinds of shader do have +// to know: one that turns a texel's position back into a direction in space (SSAO rebuilds view +// positions from depth) and the occlusion culls, which project boxes and splats to the screen +// and sample a depth pyramid that is laid out in the map's physical space. Both decode the +// map's parameters (`rasterization_rate_map_decoder`, bound by `bindRateMap`), and the pyramid +// carries the map it was drawn through into the next frame's culls (`HZBPyramidFrame`). +// +// Copyright (C) Untold Engine Studios +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +import Metal +import simd + +/// A rasterization rate map's parameter data in a buffer the shaders decode, with the two sizes +/// a decode needs. Immutable once made, so it can travel with the depth pyramid built through +/// it (`HZBPyramidFrame.rateMapData`) into the culls of the frame after. +public final class XRRasterizationRateMapData: @unchecked Sendable { + /// The map's parameters, as `copyParameterData(buffer:offset:)` wrote them at offset 0. + public let buffer: MTLBuffer + /// The map's screen size in pixels: the space viewports and clip-space positions live in. + public let screenSize: simd_float2 + /// The size in pixels of the textures drawn through the map (layer 0). + public let physicalSize: simd_float2 + + public init(buffer: MTLBuffer, screenSize: simd_float2, physicalSize: simd_float2) { + self.buffer = buffer + self.screenSize = screenSize + self.physicalSize = physicalSize + } + + /// Copies `rateMap`'s parameters into `buffer`, which must be shared and at least + /// `rateMap.parameterDataSizeAndAlign.size` bytes long; nil when it is shorter. + public convenience init?(rateMap: MTLRasterizationRateMap, buffer: MTLBuffer) { + let size = rateMap.parameterDataSizeAndAlign.size + guard size > 0, buffer.length >= size else { return nil } + rateMap.copyParameterData(buffer: buffer, offset: 0) + let screen = rateMap.screenSize + let physical = rateMap.physicalSize(layer: 0) + self.init( + buffer: buffer, + screenSize: simd_float2(Float(screen.width), Float(screen.height)), + physicalSize: simd_float2(Float(physical.width), Float(physical.height)) + ) + } + + /// What the shaders bind next to the buffer: the screen size in xy, the physical size in + /// zw. A zero x is the "no map" word (`rateMapSizes(nil)`). + public var sizes: simd_float4 { + simd_float4(screenSize.x, screenSize.y, physicalSize.x, physicalSize.y) + } +} + +/// The rate map of the eye being drawn, as `UntoldEngineXR` hands it to the renderer for each +/// eye of each frame (`renderInfo.xrFoveation`); nil when the frame is drawn uniformly — the +/// layer configured without foveation, the simulator, or `.foveatedRendering(.disabled)`. +public struct XRFoveationFrame { + public let rateMap: MTLRasterizationRateMap + /// The eye's viewport in the map's screen space (`view.textureMap.viewport`), which every + /// encoder drawing through the map sets explicitly: the default is the physical texture's. + public let viewport: MTLViewport + public let rateMapData: XRRasterizationRateMapData + + public init(rateMap: MTLRasterizationRateMap, viewport: MTLViewport, rateMapData: XRRasterizationRateMapData) { + self.rateMap = rateMap + self.viewport = viewport + self.rateMapData = rateMapData + } + + public var screenSize: simd_float2 { + rateMapData.screenSize + } + + public var physicalSize: simd_float2 { + rateMapData.physicalSize + } +} + +/// Attaches the current eye's rate map to the descriptors of the passes that rasterize the scene +/// at drawable size — the G-buffer + light pass, the deferred colour the transparency, wireframe +/// and debug passes draw into, the environment, sky or grid background, the splats and the +/// gizmos — or detaches it when the frame has none. The full-screen passes keep their +/// descriptors untouched: they copy physical pixels one to one. Called for every eye once its +/// graph is built, since a rebuild may have recreated the descriptors. +func applyXRFoveationToSceneRenderPassDescriptors() { + let rateMap = renderInfo.xrFoveation?.rateMap + renderInfo.offscreenRenderPassDescriptor?.rasterizationRateMap = rateMap + renderInfo.deferredRenderPassDescriptor?.rasterizationRateMap = rateMap + renderInfo.environmentRenderPassDescriptor?.rasterizationRateMap = rateMap + renderInfo.gaussianRenderPassDescriptor?.rasterizationRateMap = rateMap + renderInfo.gizmoRenderPassDescriptor?.rasterizationRateMap = rateMap +} + +/// Sets the eye's screen-space viewport on an encoder that draws through the rate map; nothing +/// outside foveated XR, where the default viewport, the texture's own size, is the right one. +@inline(__always) +func applyXRFoveationViewport(_ encoder: MTLRenderCommandEncoder) { + guard let foveation = renderInfo.xrFoveation else { return } + encoder.setViewport(foveation.viewport) +} + +/// The sizes word of a map, or the "no map" word the shaders test for. +@inline(__always) +func rateMapSizes(_ data: XRRasterizationRateMapData?) -> simd_float4 { + data?.sizes ?? .zero +} + +/// The rate map the current depth pyramid was drawn through, for the culls that sample it. +@inline(__always) +func hzbPyramidRateMapData() -> XRRasterizationRateMapData? { + renderInfo.hzbFrame?.rateMapData +} + +/// Binds a map's parameters and sizes to a kernel, or a placeholder and the "no map" word when +/// there is none: Metal wants every declared buffer bound, and the kernels read the parameters +/// only when `sizes.x > 0`. +func bindRateMap(_ data: XRRasterizationRateMapData?, to encoder: MTLComputeCommandEncoder, dataIndex: Int, sizesIndex: Int) { + var sizes = rateMapSizes(data) + encoder.setBuffer(data?.buffer ?? rateMapPlaceholderBuffer(), offset: 0, index: dataIndex) + encoder.setBytes(&sizes, length: MemoryLayout.stride, index: sizesIndex) +} + +/// The fragment-stage form of `bindRateMap(_:to:dataIndex:sizesIndex:)`. +func bindRateMap(_ data: XRRasterizationRateMapData?, toFragmentsOf encoder: MTLRenderCommandEncoder, dataIndex: Int, sizesIndex: Int) { + var sizes = rateMapSizes(data) + encoder.setFragmentBuffer(data?.buffer ?? rateMapPlaceholderBuffer(), offset: 0, index: dataIndex) + encoder.setFragmentBytes(&sizes, length: MemoryLayout.stride, index: sizesIndex) +} + +/// A small shared buffer bound wherever a shader declares a rate map it will not read. +private func rateMapPlaceholderBuffer() -> MTLBuffer? { + if let buffer = bufferResources.rateMapPlaceholder { + return buffer + } + guard let device = renderInfo.device else { return nil } + let buffer = device.makeBuffer(length: 256, options: .storageModeShared) + buffer?.label = "Rate Map Placeholder" + bufferResources.rateMapPlaceholder = buffer + return buffer +} diff --git a/Sources/UntoldEngine/Shaders/BitonicSort.metal b/Sources/UntoldEngine/Shaders/BitonicSort.metal index 7b04e7c53..babdf2d4e 100644 --- a/Sources/UntoldEngine/Shaders/BitonicSort.metal +++ b/Sources/UntoldEngine/Shaders/BitonicSort.metal @@ -19,6 +19,7 @@ #include "../../CShaderTypes/ShaderTypes.h" #include "ShaderStructs.h" #include "ShadersUtils.h" +#include "HZBOcclusion.h" using namespace metal; @@ -73,14 +74,18 @@ kernel void gaussianFinalizeVisibleSet( // (one thread per resident splat, head-centre view) and gaussianChunkDecodePreprocess // (GaussianChunkPreprocess.metal, one threadgroup per visible chunk, either eye) so the two // paths keep exactly the same splats: centre inside the guard-banded clip volume, then -// optionally not behind the previous frame's HZB. +// optionally not behind the previous frame's HZB. `hzbRateMap` and `hzbRateMapSizes` are the +// rasterization rate map the pyramid was drawn through, if any (HZBOcclusion.h): the centre's +// screen UV is moved into the pyramid's physical layout before the sample. inline bool gaussianClipCentrePassesCull( float4 centerClip, float clipGuardBand, uint hzbReverseZ, float hzbOcclusionBias, uint hzbValid, - texture2d hzbDepthPyramid) + texture2d hzbDepthPyramid, + constant rasterization_rate_map_data *hzbRateMap, + float4 hzbRateMapSizes) { if (centerClip.w <= 0.0f) return false; @@ -100,6 +105,9 @@ inline bool gaussianClipCentrePassesCull( // source of truth for partial occlusion. if (hzbValid != 0u) { float2 uv = float2(ndc.x * 0.5f + 0.5f, 1.0f - (ndc.y * 0.5f + 0.5f)); + if (hzbRateMapActive(hzbRateMapSizes)) { + uv = hzbScreenUVToPhysicalUV(hzbRateMap, hzbRateMapSizes, uv); + } float splatDepth = clamp(centerClip.z / centerClip.w, 0.0f, 1.0f); constexpr sampler pointSampler(coord::normalized, address::clamp_to_edge, filter::nearest); float hzbDepth = hzbDepthPyramid.sample(pointSampler, uv, level(0)).x; @@ -120,12 +128,14 @@ inline bool gaussianSplatPassesCull( uint hzbReverseZ, float hzbOcclusionBias, uint hzbValid, - texture2d hzbDepthPyramid) + texture2d hzbDepthPyramid, + constant rasterization_rate_map_data *hzbRateMap, + float4 hzbRateMapSizes) { float4 centerClip = uniforms.projectionMatrix * uniforms.modelViewMatrix * float4(position, 1.0f); - return gaussianClipCentrePassesCull(centerClip, clipGuardBand, hzbReverseZ, hzbOcclusionBias, hzbValid, hzbDepthPyramid); + return gaussianClipCentrePassesCull(centerClip, clipGuardBand, hzbReverseZ, hzbOcclusionBias, hzbValid, hzbDepthPyramid, hzbRateMap, hzbRateMapSizes); } // One thread per resident splat: the whole-buffer cull for entities without a chunk table @@ -141,11 +151,13 @@ kernel void gaussianFrustumCull( constant uint &hzbReverseZ [[buffer(gaussianCullHZBReverseZIndex)]], constant float &hzbOcclusionBias [[buffer(gaussianCullHZBOcclusionBiasIndex)]], constant uint &hzbValid [[buffer(gaussianCullHZBValidIndex)]], + constant rasterization_rate_map_data *hzbRateMap [[buffer(gaussianCullHZBRateMapDataIndex)]], + constant float4 &hzbRateMapSizes [[buffer(gaussianCullHZBRateMapSizesIndex)]], texture2d hzbDepthPyramid [[texture(gaussianCullHZBDepthPyramidTextureIndex)]], uint index [[thread_position_in_grid]]) { if (index >= numOfSplats) return; - if (!gaussianSplatPassesCull(splats[index].position, uniforms, clipGuardBand, hzbReverseZ, hzbOcclusionBias, hzbValid, hzbDepthPyramid)) return; + if (!gaussianSplatPassesCull(splats[index].position, uniforms, clipGuardBand, hzbReverseZ, hzbOcclusionBias, hzbValid, hzbDepthPyramid, hzbRateMap, hzbRateMapSizes)) return; uint writeIndex = atomic_fetch_add_explicit(visibleCount, 1u, memory_order_relaxed); visibleIndices[writeIndex] = index; diff --git a/Sources/UntoldEngine/Shaders/GaussianChunkCull.metal b/Sources/UntoldEngine/Shaders/GaussianChunkCull.metal index 49e4e3a2a..0d1602f75 100644 --- a/Sources/UntoldEngine/Shaders/GaussianChunkCull.metal +++ b/Sources/UntoldEngine/Shaders/GaussianChunkCull.metal @@ -93,6 +93,8 @@ static inline bool gaussianBoxPassesClipPlanes( // the HZB. The occlusion test is the mesh cull's (HZBOcclusion.h): the box's screen rect at the // mip that covers it, 5x5 samples, nearest box depth against the farthest sample plus the bias. // `area` is the box's clipped screen area in this view, 0 when the view rejects or occludes it. +// `hzbRateMap` is the rasterization rate map the pyramid was drawn through when it was +// (params.hzbRateMapSizes, HZBOcclusion.h): the rect is moved into the pyramid's layout. static inline bool gaussianChunkVisibleInView( const float3 boxMin, const float3 boxMax, @@ -100,6 +102,7 @@ static inline bool gaussianChunkVisibleInView( constant GaussianChunkCullConstants ¶ms, const uint hzbValid, texture2d hzbDepthPyramid, + constant rasterization_rate_map_data *hzbRateMap, thread float &area) { if (!gaussianBoxPassesClipPlanes(boxMin, boxMax, viewProjection, params.clipGuardBand, area)) { @@ -116,6 +119,7 @@ static inline bool gaussianChunkVisibleInView( if (!projectAABBToScreenRect(0.5f * (boxMin + boxMax), 0.5f * (boxMax - boxMin), viewProjection, reverseZ, uvMin, uvMax, nearDepth)) { return true; } + hzbRemapRectToPhysical(hzbRateMap, params.hzbRateMapSizes, uvMin, uvMax); if (hzbRectIsOccluded(hzbDepthPyramid, uvMin, uvMax, nearDepth, params.viewport, params.hzbMipCount, reverseZ, params.hzbOcclusionBias)) { area = 0.0f; return false; @@ -189,6 +193,7 @@ kernel void gaussianChunkCull( const device GaussianChunkLevelState *levelState [[buffer(gaussianChunkCullLevelStateIndex)]], constant GaussianChunkLevelConstants &lvl [[buffer(gaussianChunkCullLevelConstantsIndex)]], const device GaussianChunkCullRange *ranges [[buffer(gaussianChunkCullRangesIndex)]], + constant rasterization_rate_map_data *hzbRateMap [[buffer(gaussianChunkCullRateMapDataIndex)]], texture2d hzbDepthPyramid [[texture(gaussianChunkCullHZBDepthPyramidTextureIndex)]], uint chunkIndex [[thread_position_in_grid]]) { @@ -227,9 +232,9 @@ kernel void gaussianChunkCull( const uint hzbValidForView0 = params.viewCount > 1u ? 0u : params.hzbValid; float area0 = 0.0f; float area1 = 0.0f; - const bool keep0 = gaussianChunkVisibleInView(boxMin, boxMax, params.viewProjection0, params, hzbValidForView0, hzbDepthPyramid, area0); + const bool keep0 = gaussianChunkVisibleInView(boxMin, boxMax, params.viewProjection0, params, hzbValidForView0, hzbDepthPyramid, hzbRateMap, area0); const bool keep1 = params.viewCount > 1u - ? gaussianChunkVisibleInView(boxMin, boxMax, params.viewProjection1, params, params.hzbValid, hzbDepthPyramid, area1) + ? gaussianChunkVisibleInView(boxMin, boxMax, params.viewProjection1, params, params.hzbValid, hzbDepthPyramid, hzbRateMap, area1) : false; const bool seen = keep0 || keep1; const float area = clamp(max(keep0 ? area0 : 0.0f, keep1 ? area1 : 0.0f), kGaussianScreenAreaMin, limit * limit); diff --git a/Sources/UntoldEngine/Shaders/GaussianChunkPreprocess.metal b/Sources/UntoldEngine/Shaders/GaussianChunkPreprocess.metal index c55a82bad..790b4435a 100644 --- a/Sources/UntoldEngine/Shaders/GaussianChunkPreprocess.metal +++ b/Sources/UntoldEngine/Shaders/GaussianChunkPreprocess.metal @@ -60,16 +60,17 @@ inline bool gaussianChunkSplatPassesCull( float3 position, constant Uniforms &uniforms, constant GaussianChunkCullConstants ¶ms, - texture2d hzbDepthPyramid) + texture2d hzbDepthPyramid, + constant rasterization_rate_map_data *hzbRateMap) { if (params.viewCount <= 1u) { - return gaussianSplatPassesCull(position, uniforms, params.clipGuardBand, params.hzbReverseZ, params.hzbOcclusionBias, params.hzbValid, hzbDepthPyramid); + return gaussianSplatPassesCull(position, uniforms, params.clipGuardBand, params.hzbReverseZ, params.hzbOcclusionBias, params.hzbValid, hzbDepthPyramid, hzbRateMap, params.hzbRateMapSizes); } const float4 local = float4(position, 1.0f); - if (gaussianClipCentrePassesCull(params.viewProjection0 * local, params.clipGuardBand, params.hzbReverseZ, params.hzbOcclusionBias, 0u, hzbDepthPyramid)) { + if (gaussianClipCentrePassesCull(params.viewProjection0 * local, params.clipGuardBand, params.hzbReverseZ, params.hzbOcclusionBias, 0u, hzbDepthPyramid, hzbRateMap, params.hzbRateMapSizes)) { return true; } - return gaussianClipCentrePassesCull(params.viewProjection1 * local, params.clipGuardBand, params.hzbReverseZ, params.hzbOcclusionBias, params.hzbValid, hzbDepthPyramid); + return gaussianClipCentrePassesCull(params.viewProjection1 * local, params.clipGuardBand, params.hzbReverseZ, params.hzbOcclusionBias, params.hzbValid, hzbDepthPyramid, hzbRateMap, params.hzbRateMapSizes); } kernel void gaussianChunkDecodePreprocess( @@ -93,6 +94,7 @@ kernel void gaussianChunkDecodePreprocess( const device GaussianChunkDecodeConstants *coarseTable [[buffer(gaussianChunkPreprocessCoarseTableIndex)]], const device GaussianChunkLevelState *levelState [[buffer(gaussianChunkPreprocessLevelStateIndex)]], constant GaussianChunkLevelConstants &lvl [[buffer(gaussianChunkPreprocessLevelConstantsIndex)]], + constant rasterization_rate_map_data *hzbRateMap [[buffer(gaussianChunkPreprocessRateMapDataIndex)]], texture2d hzbDepthPyramid [[texture(gaussianChunkPreprocessHZBDepthPyramidTextureIndex)]], uint chunkSlot [[threadgroup_position_in_grid]], uint localIndex [[thread_position_in_threadgroup]], @@ -161,7 +163,7 @@ kernel void gaussianChunkDecodePreprocess( // bit-identical to what the whole-buffer path loaded, and the covariance and colour // pass through half precision the way EncodedGaussianSplat stores them. const float3 centerLocal = mix(aabbMin, aabbMax, gaussianUnpack11_10_11(record.x)); - if (!gaussianChunkSplatPassesCull(centerLocal, uniforms, cull, hzbDepthPyramid)) { + if (!gaussianChunkSplatPassesCull(centerLocal, uniforms, cull, hzbDepthPyramid, hzbRateMap)) { continue; } diff --git a/Sources/UntoldEngine/Shaders/Gaussians.metal b/Sources/UntoldEngine/Shaders/Gaussians.metal index 9f5d06d78..e97b846c2 100644 --- a/Sources/UntoldEngine/Shaders/Gaussians.metal +++ b/Sources/UntoldEngine/Shaders/Gaussians.metal @@ -621,15 +621,6 @@ inline float calcPowerFromConic(float3 conic, float2 d) 2.0f * conic.y * d.x * d.y); } -inline float2 calcScreenSpaceDelta(float2 pixelPos, - float2 centerPixel, - float projYSign) -{ - float2 d = pixelPos - centerPixel; - d.y *= projYSign; - return d; -} - typedef struct { half4 color [[raster_order_group(0)]]; @@ -693,20 +684,20 @@ vertex GaussianOutData vertexGaussianTBDRShader( return out; } - const float projYSign = -1.0f; - float2 centerNDC = centerClip.xy / centerClip.w; - float2 centerUV = centerNDC * float2(0.5f, 0.5f * projYSign) + 0.5f; - out.coordxy = centerUV * viewport; - out.conic = record.conicAndOpacity.xyz; // Tight, rotated quad along the ellipse's true principal axes (see // computeInverseCovarianceConic) instead of an axis-aligned bounding box. The axes live - // in the pixel frame of the conic (y down, as coordxy and the fragment's position), while - // NDC y points up: the y offset flips sign on the way, or a tilted splat's quad is the - // mirror image of its ellipse and the fragment falloff gets clipped to their overlap. + // in the pixel frame of the conic (y down), while NDC y points up: the y offset flips + // sign on the way, or a tilted splat's quad is the mirror image of its ellipse and the + // fragment falloff gets clipped to their overlap. The offset itself goes to the fragment + // as a varying: interpolated across the quad it is the fragment's own offset from the + // centre in the conic's frame, whatever the rasterizer did to the quad's pixels — under + // a rasterization rate map (XR foveation) the fragment's position is in the physical + // texture, not on the screen the centre was projected to. float2 pixelOffset = quad.x * record.axes.xy + quad.y * record.axes.zw; float2 ndcOffset = pixelOffset * float2(2.0f, -2.0f) / viewport; + out.pixelDelta = pixelOffset; out.position = centerClip; out.position.xy += ndcOffset * centerClip.w; out.color = record.color.xyz; @@ -745,8 +736,10 @@ fragment GaussianTBDRFragmentStore fragmentGaussianTBDRShader( // (gaussianAdaptiveSigma sigma out) — has negligible alpha. Rejecting those tail fragments // here means they never pay for the depth-texture read at all, on top of never reaching // the blend math below. - const float projYSign = 1.0f; - float2 d = calcScreenSpaceDelta(in.position.xy, in.coordxy, projYSign); + // The fragment's offset from the splat's centre in the conic's pixel frame, from the + // quad's corners (see vertexGaussianTBDRShader) rather than from in.position, which a + // rasterization rate map (XR foveation) places in the physical texture, not on screen. + float2 d = in.pixelDelta; float power = calcPowerFromConic(in.conic, d); float falloff = exp(power); diff --git a/Sources/UntoldEngine/Shaders/HZBCompute.metal b/Sources/UntoldEngine/Shaders/HZBCompute.metal index 9cfea93a4..0ad63f72d 100644 --- a/Sources/UntoldEngine/Shaders/HZBCompute.metal +++ b/Sources/UntoldEngine/Shaders/HZBCompute.metal @@ -80,6 +80,8 @@ kernel void hzbCullVisibleEntities( constant uint &mipCount [[buffer(hzbCullPassMipCountIndex)]], constant uint &reverseZ [[buffer(hzbCullPassReverseZIndex)]], constant float &occlusionBias [[buffer(hzbCullPassOcclusionBiasIndex)]], + constant rasterization_rate_map_data *rateMap [[buffer(hzbCullPassRateMapDataIndex)]], + constant float4 &rateMapSizes [[buffer(hzbCullPassRateMapSizesIndex)]], texture2d hzbDepthPyramid [[texture(hzbCullPassDepthPyramidTextureIndex)]], uint tid [[thread_position_in_grid]] ) { @@ -99,7 +101,9 @@ kernel void hzbCullVisibleEntities( return; } - // Shared with the Gaussian chunk cull — see HZBOcclusion.h. + // Shared with the Gaussian chunk cull — see HZBOcclusion.h. A pyramid drawn through a + // rasterization rate map (XR foveation) holds the rect elsewhere than its screen UV. + hzbRemapRectToPhysical(rateMap, rateMapSizes, uvMin, uvMax); bool isOccluded = hzbRectIsOccluded(hzbDepthPyramid, uvMin, uvMax, nearDepth, viewport, mipCount, reverseZ != 0u, occlusionBias); if (!isOccluded) { uint dst = atomic_fetch_add_explicit(outVisibleCount, 1u, memory_order_relaxed); diff --git a/Sources/UntoldEngine/Shaders/HZBOcclusion.h b/Sources/UntoldEngine/Shaders/HZBOcclusion.h index 0e7c2dcb1..550428736 100644 --- a/Sources/UntoldEngine/Shaders/HZBOcclusion.h +++ b/Sources/UntoldEngine/Shaders/HZBOcclusion.h @@ -80,6 +80,41 @@ static inline bool projectAABBToScreenRect( return true; } +/// The rasterization rate map a depth pyramid was drawn through, when its frame was (visionOS +/// foveation): `rateMapSizes.xy` is the map's screen size and `.zw` the pyramid's base size, in +/// pixels, and `rateMapSizes.x <= 0` says there is none, in which case `rateMap` is a placeholder +/// that is never read. Such a pyramid is not laid out over the screen the boxes above project +/// to — dense where the eyes look, sparse in the periphery — so a screen UV must be moved to +/// where the map put it before the pyramid is sampled there. +static inline bool hzbRateMapActive(const float4 rateMapSizes) { + return rateMapSizes.x > 0.0f && rateMapSizes.z > 0.0f; +} + +static inline float2 hzbScreenUVToPhysicalUV( + constant rasterization_rate_map_data *rateMap, + const float4 rateMapSizes, + const float2 uv +) { + rasterization_rate_map_decoder decoder(*rateMap); + const float2 physical = decoder.map_screen_to_physical_coordinates(uv * rateMapSizes.xy); + return clamp(physical / rateMapSizes.zw, 0.0f, 1.0f); +} + +/// Moves a screen rect from `projectAABBToScreenRect` into the pyramid's physical layout; the +/// map is monotonic along each axis, so the two corners are enough. Nothing without a map. +static inline void hzbRemapRectToPhysical( + constant rasterization_rate_map_data *rateMap, + const float4 rateMapSizes, + thread float2 &uvMin, + thread float2 &uvMax +) { + if (!hzbRateMapActive(rateMapSizes)) { + return; + } + uvMin = hzbScreenUVToPhysicalUV(rateMap, rateMapSizes, uvMin); + uvMax = hzbScreenUVToPhysicalUV(rateMap, rateMapSizes, uvMax); +} + /// True when the rect `uvMin..uvMax` whose nearest depth is `nearDepth` lies behind the HZB /// everywhere it is sampled. The mip is the one whose texel spans the rect; a 5x5 grid across /// the rect keeps porous occluders (window frames, glass assemblies) from falsely culling what diff --git a/Sources/UntoldEngine/Shaders/SSAOShader.metal b/Sources/UntoldEngine/Shaders/SSAOShader.metal index d93b867ab..7df4249a8 100644 --- a/Sources/UntoldEngine/Shaders/SSAOShader.metal +++ b/Sources/UntoldEngine/Shaders/SSAOShader.metal @@ -34,6 +34,19 @@ static float3 reconstructViewPos(float2 uv, float linearDepth, float2 projScale) return float3(xy, linearDepth); } +// The screen UV a depth texel was projected to: its own UV, unless the eye was drawn through +// a rasterization rate map (XR foveation, rateMapSizes.x > 0: the map's screen size in xy, the +// depth texture's size in zw). Such a texture is dense where the eyes look and sparse in the +// periphery, so a view position rebuilt from the texel's own UV would bend the geometry there +// and shade false creases; the map's decoder says where the texel sits on screen. +static float2 screenUVOfTexel(float2 uv, constant rasterization_rate_map_data *rateMap, float4 rateMapSizes) { + if (rateMapSizes.x <= 0.0 || rateMapSizes.z <= 0.0) { + return uv; + } + rasterization_rate_map_decoder decoder(*rateMap); + return decoder.map_physical_to_screen_coordinates(uv * rateMapSizes.zw) / rateMapSizes.xy; +} + fragment float4 fragmentSSAOShader(VertexCompositeOutput vertexOut [[stage_in]], depth2d depthTexture [[texture(ssaoDepthTextureIndex)]], constant float &radius [[buffer(ssaoPassRadiusIndex)]], @@ -43,7 +56,9 @@ fragment float4 fragmentSSAOShader(VertexCompositeOutput vertexOut [[stage_in]], constant float2 &viewPort [[buffer(ssaoPassViewPortIndex)]], constant float2 &frustumPlanes [[buffer(ssaoPassFrustumIndex)]], constant bool &reverseZ [[buffer(ssaoPassReverseZIndex)]], - constant float2 &projScale [[buffer(ssaoPassProjScaleIndex)]] + constant float2 &projScale [[buffer(ssaoPassProjScaleIndex)]], + constant rasterization_rate_map_data *rateMap [[buffer(ssaoPassRateMapDataIndex)]], + constant float4 &rateMapSizes [[buffer(ssaoPassRateMapSizesIndex)]] ) { if (!enabled){ @@ -62,7 +77,7 @@ fragment float4 fragmentSSAOShader(VertexCompositeOutput vertexOut [[stage_in]], float2 texelSize = 1.0 / max(viewPort, float2(1.0)); float pixelRadius = clamp(radius * 220.0 / max(centerDepth, 0.001), 2.0, 48.0); - float3 centerPosition = reconstructViewPos(vertexOut.uvCoords, centerDepth, projScale); + float3 centerPosition = reconstructViewPos(screenUVOfTexel(vertexOut.uvCoords, rateMap, rateMapSizes), centerDepth, projScale); // No normal G-buffer is available here — normalMap/positionMap are memoryless // (TBDR tile-only) in normal rendering and can't be bound to a later, separate // pass. Derive the surface normal from the depth buffer itself via screen-space @@ -94,7 +109,7 @@ fragment float4 fragmentSSAOShader(VertexCompositeOutput vertexOut [[stage_in]], } float sampleLinearDepth = linearizeDepth(sampleRawDepth, frustumPlanes.x, frustumPlanes.y, reverseZ); - float3 samplePosition = reconstructViewPos(sampleUV, sampleLinearDepth, projScale); + float3 samplePosition = reconstructViewPos(screenUVOfTexel(sampleUV, rateMap, rateMapSizes), sampleLinearDepth, projScale); float3 toSample = samplePosition - centerPosition; float sampleDistance = length(toSample); if (sampleDistance < 1e-5) { diff --git a/Sources/UntoldEngine/Shaders/ShaderStructs.h b/Sources/UntoldEngine/Shaders/ShaderStructs.h index 8a5d939c1..db6a59375 100644 --- a/Sources/UntoldEngine/Shaders/ShaderStructs.h +++ b/Sources/UntoldEngine/Shaders/ShaderStructs.h @@ -187,10 +187,10 @@ typedef struct{ float3 cov2; float3 conic; float3 color; - float2 coordxy; + float2 pixelDelta; // the vertex's offset from the splat's centre in the conic's pixel frame (y down) float alpha; bool valid; - + }GaussianOutData; // Cascaded Shadow Maps: 3 cascades shared between both eyes in XR. diff --git a/Sources/UntoldEngine/Systems/CullingSystem.swift b/Sources/UntoldEngine/Systems/CullingSystem.swift index 040abdb5d..4f62bbd92 100644 --- a/Sources/UntoldEngine/Systems/CullingSystem.swift +++ b/Sources/UntoldEngine/Systems/CullingSystem.swift @@ -548,6 +548,14 @@ func executeHZBOcclusionCulling( computeEncoder.setBytes(&mipCount, length: MemoryLayout.stride, index: Int(hzbCullPassMipCountIndex.rawValue)) computeEncoder.setBytes(&reverseZFlag, length: MemoryLayout.stride, index: Int(hzbCullPassReverseZIndex.rawValue)) computeEncoder.setBytes(&occlusionBias, length: MemoryLayout.stride, index: Int(hzbCullPassOcclusionBiasIndex.rawValue)) + // The rasterization rate map the pyramid's frame was drawn through (XR foveation): the + // rects are moved into the pyramid's physical layout before it is sampled. + bindRateMap( + pyramidFrame.rateMapData, + to: computeEncoder, + dataIndex: Int(hzbCullPassRateMapDataIndex.rawValue), + sizesIndex: Int(hzbCullPassRateMapSizesIndex.rawValue) + ) computeEncoder.setTexture(hzbDepthPyramid, index: Int(hzbCullPassDepthPyramidTextureIndex.rawValue)) let tew = pipelineState.threadExecutionWidth @@ -1257,9 +1265,11 @@ extension HZBPyramidFrame { let cameraComponent = scene.get(component: CameraComponent.self, for: camera) else { return nil } let view = SceneRootTransform.shared.effectiveViewMatrix(cameraComponent.viewSpace) + // In stereo the last eye drawn: its view, projection and rate map alike. return HZBPyramidFrame( viewProjection: simd_mul(renderInfo.perspectiveSpace, view), - cameraPosition: eyePosition(ofView: view) + cameraPosition: eyePosition(ofView: view), + rateMapData: renderInfo.xrFoveation?.rateMapData ) } } diff --git a/Sources/UntoldEngine/Systems/GaussianChunkCull.swift b/Sources/UntoldEngine/Systems/GaussianChunkCull.swift index 93c307986..bf425a541 100644 --- a/Sources/UntoldEngine/Systems/GaussianChunkCull.swift +++ b/Sources/UntoldEngine/Systems/GaussianChunkCull.swift @@ -1033,6 +1033,9 @@ func gaussianChunkCullConstants( constants.hzbValid = hzbValid ? 1 : 0 constants.hzbReverseZ = renderInfo.reverseZEnabled ? 1 : 0 constants.hzbMipCount = UInt32(max(0, renderInfo.hzbMipCount)) + // The rasterization rate map the pyramid was drawn through (XR foveation), only with a + // pyramid to sample: the "no map" word otherwise, and the kernels never touch the buffer. + constants.hzbRateMapSizes = hzbValid ? rateMapSizes(hzbPyramidRateMapData()) : .zero constants.forceAllVisible = forceAllVisible ? 1 : 0 constants.uniformQuotas = uniformQuotas ? 1 : 0 constants.paged = paged @@ -1255,6 +1258,12 @@ private func encodeGaussianChunkCullDispatch( } else { encoder.setBytes(&gpuRanges, length: MemoryLayout.stride * gpuRanges.count, index: Int(gaussianChunkCullRangesIndex.rawValue)) } + // The pyramid's rate map (XR foveation), read only when the constants' hzbRateMapSizes say so. + encoder.setBuffer( + hzbPyramidRateMapData()?.buffer ?? chunkTable.constantsBuffer, + offset: 0, + index: Int(gaussianChunkCullRateMapDataIndex.rawValue) + ) encoder.setTexture(hzbTexture, index: Int(gaussianChunkCullHZBDepthPyramidTextureIndex.rawValue)) let tew = pipelines.cull.threadExecutionWidth let block = max(min(256, pipelines.cull.maxTotalThreadsPerThreadgroup) / tew * tew, tew) @@ -1530,6 +1539,12 @@ func encodeGaussianChunkDecodePreprocess( encoder.setBuffer(inputs.levels?.coarseTable ?? inputs.chunkTable.constantsBuffer, offset: 0, index: Int(gaussianChunkPreprocessCoarseTableIndex.rawValue)) encoder.setBuffer(inputs.levels?.levelState ?? inputs.chunkTable.constantsBuffer, offset: 0, index: Int(gaussianChunkPreprocessLevelStateIndex.rawValue)) encoder.setBytes(&inputs.levelConstants, length: MemoryLayout.stride, index: Int(gaussianChunkPreprocessLevelConstantsIndex.rawValue)) + // The pyramid's rate map (XR foveation), read only when the cull constants' hzbRateMapSizes say so. + encoder.setBuffer( + hzbPyramidRateMapData()?.buffer ?? inputs.chunkTable.constantsBuffer, + offset: 0, + index: Int(gaussianChunkPreprocessRateMapDataIndex.rawValue) + ) encoder.setTexture(inputs.hzbTexture, index: Int(gaussianChunkPreprocessHZBDepthPyramidTextureIndex.rawValue)) let threads = threadsPerThreadgroup ?? gaussianChunkPreprocessThreadsPerThreadgroup(chunkTable: inputs.chunkTable, pipelineState: pipelineState) diff --git a/Sources/UntoldEngine/Systems/GaussianSystem.swift b/Sources/UntoldEngine/Systems/GaussianSystem.swift index f80679111..13e4d3882 100644 --- a/Sources/UntoldEngine/Systems/GaussianSystem.swift +++ b/Sources/UntoldEngine/Systems/GaussianSystem.swift @@ -128,6 +128,14 @@ private func bindGaussianSplatCullInputs( encoder.setBytes(&inputs.hzbReverseZ, length: MemoryLayout.stride, index: Int(gaussianCullHZBReverseZIndex.rawValue)) encoder.setBytes(&inputs.hzbOcclusionBias, length: MemoryLayout.stride, index: Int(gaussianCullHZBOcclusionBiasIndex.rawValue)) encoder.setBytes(&inputs.hzbValid, length: MemoryLayout.stride, index: Int(gaussianCullHZBValidIndex.rawValue)) + // The rasterization rate map the pyramid was drawn through (XR foveation), with a pyramid + // to sample; the "no map" word otherwise. + bindRateMap( + inputs.hzbValid != 0 ? hzbPyramidRateMapData() : nil, + to: encoder, + dataIndex: Int(gaussianCullHZBRateMapDataIndex.rawValue), + sizesIndex: Int(gaussianCullHZBRateMapSizesIndex.rawValue) + ) encoder.setTexture(hzbTexture, index: Int(gaussianCullHZBDepthPyramidTextureIndex.rawValue)) } diff --git a/Sources/UntoldEngine/Systems/GraphBuilder.swift b/Sources/UntoldEngine/Systems/GraphBuilder.swift index df194fc4a..925d60dea 100644 --- a/Sources/UntoldEngine/Systems/GraphBuilder.swift +++ b/Sources/UntoldEngine/Systems/GraphBuilder.swift @@ -949,6 +949,9 @@ func makeSceneRenderTargetAccess( return nil } encoder.label = label + // The copied descriptor carries the eye's rasterization rate map (XR foveation); the + // viewport that goes with it is the eye's, not the texture's. + applyXRFoveationViewport(encoder) return encoder } } diff --git a/Sources/UntoldEngine/Systems/RenderingSystem.swift b/Sources/UntoldEngine/Systems/RenderingSystem.swift index 42da9e94d..8d121dfc6 100644 --- a/Sources/UntoldEngine/Systems/RenderingSystem.swift +++ b/Sources/UntoldEngine/Systems/RenderingSystem.swift @@ -170,6 +170,10 @@ func UpdateXRRenderingSystem(commandBuffer: MTLCommandBuffer, passDescriptor: MT do { let graph = try buildExecutableGameModeGraph() + // The eye's rasterization rate map (visionOS foveation) on the passes that draw the + // scene, after the build: a rebuild may have recreated their descriptors. + applyXRFoveationToSceneRenderPassDescriptors() + #if ENGINE_STATS_ENABLED let encodeStart = shouldRecordStatsInThisCallback ? CACurrentMediaTime() : 0.0 #endif diff --git a/Sources/UntoldEngine/Systems/SmallObjectCulling.swift b/Sources/UntoldEngine/Systems/SmallObjectCulling.swift index c37c72b0e..2f8241454 100644 --- a/Sources/UntoldEngine/Systems/SmallObjectCulling.swift +++ b/Sources/UntoldEngine/Systems/SmallObjectCulling.swift @@ -57,10 +57,13 @@ struct SmallObjectCulling { guard let viewPort, viewPort.y > 0, projection.columns.3.w == 0, projection.columns.1.y > 0 else { return nil } + // Pixels of the screen the eye sees: under a rasterization rate map (XR foveation) the + // textures are smaller than that screen, and a size in their pixels would cull early. + let screenHeight = renderInfo.xrFoveation?.screenSize.y ?? viewPort.y return SmallObjectCulling( cameraPosition: SceneRootTransform.shared.effectiveCameraPosition(cameraComponent.localPosition), minimumPixels: pixels, - viewportHeight: viewPort.y, + viewportHeight: screenHeight, tanHalfFovY: 1 / projection.columns.1.y ) } diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib index c6a09d92204a0b5fbc5221a510449dfd3f2c8a7d..a8f903cb37d0370cca3cf66e03023bfa01625a5f 100644 GIT binary patch delta 39703 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 S7CM_6mf=&*hQGiQ*ZnUg{hIFp delta 36436 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
S1d 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 HE}i^;)<&Yk delta 36534 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 V%+6!rSmoqgrmVSTo2R4he*m@Ix&;6L diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-tvos.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-tvos.metallib index f006582828f29adb1c548ad926d2f36eb4efad84..fb5072e2b7e418afa548f89a32d7cb69e507f5cf 100644 GIT binary patch delta 39679 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 delta 36429 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 WbUth~Uq&bUSQv3W_ho(<`Tqb~!l8Bm delta 36588 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

xd%}to6aqbu8dF0?xJ_?2@^F(xviQo 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 diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xros.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xros.metallib index d81cb37beae3f60106ad710e03c96290cb566678..fc1714a18bb795aaf0ad17f6d256825ed738bc7c 100644 GIT binary patch delta 41354 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

p#>rer2OHgd+6l(exjZhv(3e z(9IFUvHA4zD(n2da9y`LzTC5=J2oAngMfPzGYfhuF4cI<$omV9@kO%%{yf+5SLR>2 zid`D=?HU7|yH29QK+PBQS5!`Hc!07^0m&JJ$TEDmo;>0HoRP!zh3ukkGY>hfupdoM zs+v>d60VuZ*T2}5AgXBy*F-D22MpZ-rR9?N=qncIN{cTXYKEL>_DSetu8F+T=e)HK za;&~JkYi>Rz<}ag#8AJpAH9lsj5pNi_?aX)vm=_=*;(ZrE8hP{uV-;VXY%_8N;CS) zvSNQ}oY$Thv1K-#?LP@#?e8)3c-8JfnIPtB`3DO-OSYew^Im7t*CFe&rMDC3JwCSD zwchIY*16!#d;e6_e7DZVe9>3FZc2Y6@i?i@dk{uk#4Ca0~b97ta8x$Z&YqZ4)9dW}C3b-#vLEyEl6A1>z&-Apd&OXttJ zdLX1TtyKGS0PUT6L)E4O@);|e7W~nw^p#|VZp(=)7s?OLiZbsgJ2H2@XG`{M#mOsN zn>-*d>b}|eG!;(0vlhB*h_vJbNowbzy}xMcw&f5-STVmR$* zzh5Q}`AKs|Y?NLqkqrf_zjA<+e|4*a?^*GXkku_MscB*c*OKY=NEM)fcqgi)=BKN| zhKu8~S-#uL#6`~|OKd+~5ylI9(a&S_(|5&3R}gqC>IyILMWp>l;XUV6dnCQoF#Kbi ztqtACl`rxqe{Q=Vn~6>n=&P!B4Y7KWf_Z{%k`mlzOFjvtiteaF^lVB_y;w+iO3bgR zgpGXpcGi&mBZ>rIL916C1+bEZxTp5_IR1NrUGX0y9VF^|80`(Rt1feeiqJUMxy7YX zt-SkJc7dwUQ_zqO$6^#%@2&Ie-USUd+pUf0Y8|*44c9i_oPJfpav984PyGys5M{`D z`nTaaVsdlCxKGs{eW38p8z-Y2RFiY6(*fqx;>D`?iT9_@tQ=2&Umm{+uUtZ93$KOC zCo8P11Hv?z$nl4*F>N)>rG?+DvKPE!xL_GG8|S~~a7V_p!F9qNp_UTmQNaaozoh2C z0qW0mVOc5YIuIQxvZ$p^+?D3gX~UW=3)!Cul#1YP=@kY2WFh->@8|^WpRdN=2Mq`s z-+XO&YF-J^JHu{Sl4X=cvhW`*)2x@OQa|av7EZg!w2E}R;8Rhp61~I6qM7t=X{(}a z&c{kfm0Kx8I%z{Q?}AMhkE2fG)W8+TVBvsS~0R;U(?BNILMc z_78j7IhkH{40=2P>H+mbLmQ)43w}?LCOPw$gxI$tv(!la`=N5yTa~dny0G)~doqS? z^D<8r&CO|kZl=X?F{RM7o4}^r=kb)1Hp^NoUlridm{VH z!mnA=N9clmk|{GbwTWQm&l%0P`2pN`5274$m$Cl6%XqM;uo^mlaG6nK;wFq9H2 zhuV4AzqnCmYdaXq93F6vs=}_UPpY_zyqH8g{UzqcAE|hK=dkY6&>E)tCW-itUmUH&KhXXm7Kc%lTub{r`*Ju z2jsVRi^HYl#Wj<>%=l_Q$_(rxFGP4Zd97|9$WWxd9M`{Gl^xTdJ$+N;-YdFNi!_5T z$JMY{t$9q2YyH;~dh{Om%U_b}9ER}z9@OWW!TaZ>FQ;^vo3ds)lqaJ zJ;aadpQb7|J5?N^{qTeO)Kr^K<746Rm@BgB_=M|`xA!cZtK$}JnEr=ujf(-Ay0YiS zkomol3B1iZ{V!dC3pr1-CBaBr_VO*EwkAG=-XkrM)$?%LbMTQ%E;$3*d5$?*!Qixt zR6+Yv^&0hXg~LvwR1QPfE4aT;Y%5O^0mYOKJUC~Nva#pchhuumS9cqvILtkT5o-6B zPSR`2q2-N(J`ZAAdAG~CnKc335t%GTkNAWJA9Vp=V(Q)901I*s0rQB87(Qoff4h@;i&uotDsai@)| z>hSF1+uNCqdY!`nNmAqCD}*bNp^E)0(6H?$acy*Uw|RUrmgibpGq*Y>6$a654+Wp*xiy>hi)_AU zoaoV9@MX=-0(sO3DJ^8bcs5;Fu@CgakwzposdcI3KCgPNCwEF&xd*pSM?rP^f-G>&k#|IOm$WV7WAhJo7;k0p1EAdQG8MYG7QqKdLNbHujDe!#Wlt%uo zNsdF2-_^|5IA4#duzJ#k^Akpu(jRLKjPtq&uKE|@m={RFUD8xFP9w%SCE+_gS*yXje8qmW=~!b1chPoz&*ZS`3blM1tZ`q_!QGl& zfA3vN9yWdVa2M8U%NU~%WZ7M=?JiYTS#iJ#&3Zf^J}UTI#z~{kmD!rO>n=6uc{Nsv z+=m?>41brOt%muA|8@2o@#=pET?1IZ@ zE^_!h6>yy3`_yl9r0zTE2=4YfO(fqI|PnobDM_k!z&Q1TXkMn4K2q8N0%pemXf~s+Nb{ z0M+DaX5D~w`JBUjevyh}LQtAcVN4ecUHkM#P(@IcPUDnnre!;+h%~1>Plye)IIqb< zelm}Pwc-wYNjBI1vfbMYMjs4>TR;*;Z4f= z8jMpcA(VGLpo{I*cG5O-dO~SxFo-N@1Dh=6zb|Sz_zjU*qCU&1H{bn0RBb{gQdF$n zr57mwrkVhD1G{|lP8v|TBj`8#THfD%rel~gvCDUboa-)+tuhDNn{G#c!j5Kc+U$6M zVqS9duy2Rw?A70XGq1?1N(f_s*GtM1xf%JDUk6+N<$L^7ObIKDf4f^4QvA8kf3%ji zL%Ipw4~snLD=+%YmrP=QA$oT1p^^G7G4&UQ)iiO3TTh#OQpy)7{y>N6!AjoNyM-3{ z*-6Z=M1KLCu3?qacKIKY~q9MOnLbQp#5aQwPnW!@5<*?RN{+@e8Bu1@ej;a_j{Xa<=uV&+l3rAn3Mp z-&6%Y=kUbjFxTLXX70YI8mgL zOmHz=-AhCpZWK(-3gqn%Sj{_nH>zoFN5pb`#oqSZHcEv2^8(L?pnTIrT|NEhbGbs3 zdBsI;k4tUap{@_9k$0o?i$%f9OZKu`b5bi8VTXA$&Yu*XKE9gw;oZX8B~PN6oubV1 z4~x#k7dX|(8}i!t%bPoWlsf(OL)jPE=cZb4hxaE=+p(UJxABOhHg-AQzwZVE1`qx+ zMHI?ELDVjwr;yf6A&^H`&<-f5NwV#5bm6EK85>O>_|Z1_xFf5jjogVEmypOimd4P( zw$G@(^`9#!5nzfC(IiCl^SyTm`1c0(-W%Zmvr}>e$%9L}(zc%fA>8Vx0ks%qTuxs+ z<_l5+5a)mncX%V8J}!qvThs~m@UWRvfSpg9iUp4S?TdO?hhAu~suEQbh9cV}qZ<3k zVfXctD>nMal2+b~EVb3s0Go^sHrOgPctVtb)k-RSEf>qfxl!~bUYm@VQ=T{oi90T1 z8G+1wu<4>&oj{4NVfce^CG^L|J1Xnbsj1o#@x@v820mB< zz^29*m<5{4fHi5x29HD|DzD2G$|GJD*qfx5hd_aqsK7Z&wr~^dlVtctCA;n@gDl!m zJf`Rqd}R&WR&EVNe2_1FK$R=O$&$q$V=%3m4ZQ{hpGO6!7&&!vJCqMVabDKnVRC*% z6B5TT&%ng-ygOpES~T)WuGX%n3lGqM`EmlzQNhuq9q|*9g=G4Usj4DbEuRim{Y+LR zabC*gk(hVx7=!sQe5JzKRxY1Oc1kbp`}nEAQzodL{!|lI(NHS`I&2!Sd*d+>&-~cu z4GV}&i2W8n$sm3CGenI8kUvpPzw$0OgUy!n_zj=;dD|NoJO(dgirP9C@Cp+H^q)Li z^IjU2Y-XYVtIeeDq7%Y)uoaRBpq*;^)D53gCTo5OGviziUiqz3HOlc|d1nkeziO%A=F04~;=xdxS3RVGLv&JxI*AYrvST7y5CV z!lS#~+y^8G)-S^QsIsP{4qrem<3P(py}^#!x1*>LV2^SdPCxNe2)7c1Tawamyt|#a z>vxYq?PEaA8&E5-qt^0}Zbxln>$@=0|3M?2qVRj$ z!%l&{|JyznHjEd44+IL zB80aM(CH%09z;}IumR^OWvs7Y0_zsi4SrMnhdKrDBkWIv4GG|`+eQBv1W%U@6-T!9 zbI7@-+&`wJQh`z#Y%A9sM$o(I=L=tG$T6o+8&kb17Q@$pr6W;~gh3+g=#gzQveB9a zV;X&Vo?3Gh8oe1cI;Cd3FsHj*E`*+IcpqltRFqrbVr~;9bOf6VW6n(?%aFf5ri}i1 zYU~u0aRNbaa%pON#1Z%5 zj4-!Dt)aHUO@-0+T33v%6=YVQL9IQg)>@aQ_Gb?ET6=s0MZy#{{b}K* z;YzoSt#lTK_d|bm>_Xio|59lrN~KykWhg!Dk^fMY-!mAbLF&NqRrId%M6^cz>~i8d zkW++s%b7!a)F$p?BulZf*n6S zadZrVws@c?+K})z5|fBDHxN0M0Dc3^0n`DZf{GiWgqo;X8=o$clIUP-$Ds3Aq1JQ) zI#~#vD8c0$KXdHp*v6pKAY=%u90#(^u>^^aYU9)4{<=H{of;4|6#_b~yAe9p?+`kh zv4IEeM|MMBlZ#d?_8iuLHH}l4(NAdP5|=jq)t1NmGK6X;kTD@~2xW@=&x{-PCBXVO zggG(#Y1S`NV~+s!DujB9Z5lJ$z6R7B9Wygdxhg5s;Y))gC^VPbPQz=!jd_m^((l=m z^inn%d}+QU9^~|o9^d%lI>$b7K}+xz@>8c`_*c*}Vi1X2F3-2b@0em=E%QGdQ=iRM zshS0A&U3Q9+ONL=@3QDq`)EunsnZz3%gzJYeY42^?AO6+IRIvJsY>pq^j{{kioY8* zAls%`fDN>}_|SsfVLb&W-fE>5*j+!u|2?-3AwePY6Q z2)g%u1YIovXw7B>-8Wwp4E(#kLIw2}(3uC- z7o>JF1>G2koJg94D)T;$1%PsLwgaiLQWiuZuTVxd>kc-~6chs!9J>f29uS1Q#~-}sk83oPAK7Y3f1zG0_(g2YoqUk%}??1p@tDSY~9 zF?|A1?Ge(?0Vk`+yp#&Vi*R|Q;_MuqtV|4h{VNjOIuTgfdL;(*$OVo25fMd0xO74f@#4sS~wws!9`=FLE~Z}iOGV9DIt!YLuz|xiYOE-=;jFM z>16+tAu(X%pun4;-`)9ixx`(}(n{PTxs5U@@`+H8?I4pJl5n#f8ejmNV1F^Jkwgwl z3=E5x%srY?i^hkL93peks3gC2kpmSWy&wk|Aa6YKIsf}kiNT?wr=>)mw!LXeEH{f9 zeCcc^Z@=G9$gGcYG`r&uo11;7G1CY}uV(tu>|U95T!>0^G{bf|g#p1xHa<`C*keSC7v?ZN8wka9x;A^5r)jD8^OaWJ)#uOyfWyhtq%0$E{#cMpc|x63Sb81r4Vd{`=N zY?u2f`$&=D?`83BotfdAkGYbFSjQcp;#o)rsq?L%B70X-xUKBRLX|dBjO`p1Xg0Hj zDpDRf^LTynRyC*AK(;MG#y+REdK19KL&Ti(YPmP!=l8N}A*?LQJIlU6Zn;FdxN2>L z*%KWB$(+vAaOxS5QaXKV;jlm&nhHE;9ITM=T@8T?+zF8=`ADNGv4gXdXpdqoRo7TJ za6~aeqdz_2SVaj|PLHHjIY1?*BDtk7UMU!zEEI3p3o2Q#7gRaI@ld4m=o1NgVkDpN z!GpzX&Mh2U`2x{UBR@elz?`-h!W_7gVGjCv-1FR}eD0J!Z2>T130d@Biw^k{ut~3U zIBAxdqrtO4KZJGjAsTsQO~UxNs%BN9+8G6_EK8UJCxU;7kn;eZOJjJWhOXm6tc)RJ z7{3l8IGCON?GYRduE-MnX@{>>;ldhxb+a__}-<3in`_oSXf? zVQZ5;3Se!*w%dt>lpD6eB`nh=SmS%#0h5&Q9yhBJW>qtVX0>yd)F+d!Cq$Kiw~vOd zCDNwQ6QEmytl`#grtbWZw;S{vZ;~Wd#z=ik2U>l5PgZ!^@mY^(;UtNy#ssr8K$AjO z+rOr=YttS7>To_szEG1i4+ud+3}o}w#E&8OsIfy2q#asqsTM@nN3+$t?y~r7pOhbk zJ;!3xPJok*Oz*H;Q}IjnyWs#?V#|v2mvEY;d7kd$Wyix&fR5nJ_55hm z!Rg7E_pf_{vl_fy(_Fb7vcbI&UuC0f?FPTKS;3#m34jz+2#~SKb8V7oSB!AxKi-wX zo2Dy`DpB5V0W$VNWISW3dacFl6*B(psTZ7)Hh9%Ww${|+Ylo@Wf0R}!p`%nRM^x-P z`b2`B*r_d-y=cCRgs1^kYc>;*P7C<_il?ks3}h*3)CPH;N3> zeaSpvnGz)6_2S4LAlzQ?dLh&<^=ss7w!lpJj@NVrw&JhDloOhnTWx#;@ih6q6NHi6 z(sadu`4cFr;f@*o*F>#soH}~qbD368|97SDdHOf9=3vD=y*&!ah(brI!tYmzLXrkb zC_gJAf^PXXZohwJJ1m>FYx!gllDDGni{A z>s8@e{)v#@y+_CoCmFr*2|Nd5?IPs5hX(&y@Ft24od*BmTSwVnP{fTyEv!dR;ZFbn zC~_iVevkpZoe6sR9I_~Zbu$NPr>O)AMsgbJLRVw~hz!h;`*vgrKXOI+$U?pn@{s}i z$aN(D0^}nD_L1vI{v*gotk%eNB>zvyN1tA}QYnt4LAnz(1lm|2Bn{H*z#u(>7WF^d zqR0N9ZPAlVd;{Ch^mQ7Q^Zy+*#lys<(IfW@cX4+trqSU)qi!(`=P9ZEZlo=GC}aPY z*WNVsXXD>9GAR%qvF_U(+>y>~Uqqo88C27YHCS*Re+~XQ72CDnstI89GF6JVO&c2N z0@h+r{p;zB)gg7f0(=1TkCdp^6y+8q<`!(qOxzr`DsKYmh&}3MZe74SycnzdXg%&o zb6g62B%mjf98{pmT8PKGO{QpM-RV?b83lO+OxH@vg19sjcOyQHt3_JgET^7!=;*q< zjrhk9lMr9fpB$%CYj@;OEUEf;6CW&77EgnG;D0t2n|Y;D4j~ zI0MG#=?KfXg)F^cr1-6ATLm&mv&Sw_u0=00IU#mcNhN@1^}k0zlH zvhZo{gOm=LrCe#wzUfTi_Xh}jmHo6n`d{$K#T9eKlC+vVE%PX`{QH3wYde{=inT0m z=0&lj+jgOy8I$M9HXinO&33>2h@G`4*my? zIsv?XZ{kd<>)D1^QBC!~GXoh#z@9GnuZh&5#(V!?CX(qNT6|$$fDZqfO6_NuEN*lk z6R!jx0EZK+)zt`93WWMU_5Rn3zw05VM<> zv@meq{+QR@SL7*$B~b|yZevGmnM9JOytHRVfP||lQTaHCp0K!@y<}LWujrDm;}c)R z%m()m2Q-po9v7?_m!-7Q1C9u0dgA8WEUxS{|I(f}qT}`?{0Bu{eGS6Y(nv=D|E_y} zoz+04bxh!zZvGRz&bBDmm=sG{69`@7i1EFRH2If-3BGlW-O~RaMZy>fU!#m8Bir;o zN6R*rPlF&XFC(hrt`v@9tztMN&}2#)8K~8gf?!{brE2^M;(1aqBx(pbkFbo8kL?Ha8Ne%W<4D@TJ7 z!H2$4fJYyHe_4}5o~R~aXK3zJody*KA4+6-d|0yyBh7bT+Fdv3LTFSO0Px_y-KzH> z`xZ`D!;J|3Qz%LlDa6Ce`M(3RPD@l$=xWMKFam`3uq$JCK?uU_(SH-7cdQ&V*`wu%p$GKpVr?2TX2Apk$Dyr5taz|{%CrOq%xh z6$F`nZsM>ook?EK_MoTurgjd;BiT!S=+c=5ythnUzcal}if>s?41?90NU2-(Ez3rY z`M(DcDYQp?9lnr(Ud!KRy760(PapUL!`+ksR-pT$Pz6 z!ME8Sj#Sle_3X!LUnkZ{bhqt~N~yzG3_n^g(Iv9sr6Swzkta5*rwwbu-F(_b2ep8o zU(uEk{I;p^ZIrdI`?Omsw8Elo_H4>k`D6$%@ev?wWBN`QMp)x_MB^u0n8b{ZxfEH$ zx!l3|vX5iqIdw~%dK6ASNE&(U&s0v)tiP$*$xMjiFdUNgm8h()htzD`Md^Jp)B7UC zaLDuqtHc_sI~k=RobI+r?zTkZ_J-AMCFVXRN`s+zY?Ou^6rELwEkiLH+%@iRTHW^{ z%f86{oat|o;auZ}!?Si^`zsGME^vVPCZI1Q8L3G?TJ&~`Vi8#6t#&MfT^m($NCa{x znXKPO7yFGB+;I*|p9YW#oaN$^u=S)cN(9Dkwm)9{>t80@cdV$lyd>_}h%wtst2QQ| zUCCpcWjFHeQCkN&Af@V?)GjWI4=D=*`@3%BoO9?pMFEA=WPktJ1@J-At7^ECR&BG| zKY=9W>jeCcJyb;TG84a%=DXkcC*LGp#pas6`kobK`r3t7V(R;noq?i6=()ixy)cbu zh)fsv(WX}m|Iql|%WSqe589lolbg89rr#Nsx?7M{PZ*_iJlO=T6Ua`ZC zHm8p^vsyS;>-Q+LS?MyUbPg-oZ`<*1y4c*5UckDO*=Tl}u-Dlek5!az?UYnE&FyK# z<$k|qg7Z!91N#X{={`~EUS6q@QcCpgaFnMMDCRc=&eaC~kr|js4IHxi#nS!H%BMQ) z4{_MnyJIiQ!8pJqIwe(lD5yjk7#lJ^(EW%?9- zlXRf5L_J*Pm=d?5PCtMrf|k@{3MfgL!GFD~3{-?-48>D~X_!-kjYgaIr|zbnBAP5} zP$ht`O^HurK{0_OEV-igC|SI!(X&sbw<3)-o>>FxFpk(&O#*OzQegt`p7M|;#D%Nx zyQ1a;C)W32kfcV`;HOI_1DGDN2&P4kU(e#e{%MT%2N5*9S?rV+q9V7Zc#cm zfyg8d=@bXNyCcid?sIY~K`I&Rc8Huh)$x@RvRRsN*wPm%U`yX1V#Ai+*A?&)v8|Fe zwGW6Np5SH>ZyAV>wY55KsgI$-fN4p8aY9?8=l~5i^k1VuqI*=9;=P}WCN^smRAw4@ z1g)Wk`$(!#>{nKw*-at>JaveJBxdG=!+y(Ya9SQfx+jgb?NByZQV?3l9S7ym^mUnB zc`JiUf8v)Q+LXz)+87X;HrXFyq2dZwcP3Z7m&s+rLuD^^PzF(C8;CttRx9QaKlr2w z)UZ%&0D}mekM0RT!38cKWq~^N0~Ye9FR3UclzXghR0157uB`N_0Y9U|ebh+XCG+0H zx*_j#_O=k0#3KDvd_|RRpLr`9J)=veY|v(m)Qf^zc=~r`Viw_A(sxC}BcAT~I|$e( zfnU(u30)u|X_P{D{tn%_sZmM??%L|~m!wryn;_-QjngZ&o&;UcUJ<029r6b-H-xee zoVSi*XV^t~0VTiZkXI%YB_l_=1%Kna#7nNooHYx;l7X5EKf2U*7a7fsyG!(YADHaa zYwtILo+UZ+a{QCQ!r(NU~A-i zJPHuaJRlk$@$Dv?-#;AV`#_KcL~#~2QdV!Z)N36G2QApZf+<{VoQ?1XEzY(M$(!ml z5CV@9)8p9`rz(vGBGHD+qZM7OvO1+g0HRctpd??Z1jUP1UXOmcQU=G#DjA@MEvN?* z8A~Sv@8%)hOFr5vt=vKf4YlEBpGXFs&3Z-`=xmk?+9Uh*r0T^2qJ!aufe^}vY@I(oub29pUsiN@`#_Q!EE9yiaGK&W zgEp>gW{5W1+3^?6yB63v8+~EtYz(o=<}^mArGbzAYf@|EGVn|aYX-60MU?KK4cc=^ zmXVdZh#n@dX?o(qN-LOfBp{e~xU+DRHO(hRbGzx#1J1f`i$mb}i#|EL_NGcf>->TV z-`i{sCm?4Nyr8thO4DTXWD#1%Dev zq<=vUq_vr^r)_XE@wFdP8{nN zDmXtS~&SUETi-4$n2`3V(`)VmCh=%=M_wWtQ07jH3 z@wJi?1-?$L5rODoP0enx*;)ef3LzIvusU#G{1D80m}#J&VulN7>6lAl0mvlR6VLki zj?8)#k019@{7AI?*1TrqcFFt#Xt5w3ybM^Z$&ywPJ5$CCz>8t}iSRE#`#cb4CI)H}em(Ib&N&GzFxjlXE15k^ z^s!xuaaC$spWhx9yFuDvL@5dBR$E&MzNz<_m(nJ*H^eC@C`gM3#O}zPqh0Cvk&^S3 z43pTybgPMXcTn7(I;!L3Zs63KM@Dj?(u?C*;A^>&{7jtjeKT`Ums8X#_)0)fbrl&} zyhFFRBAYdBX+^fAINJwIzg|mc_&~^Xi?hYgBa-)m>z+6XWG3<0;3U^VEYIPP#)}a| zKOj;x$Q<+w75<)8%M|f42Wn6T_kfJc2->IdqK-UoQYicnuT3w;Kps+}yeJmx@0KiK zsU4|Vc1h^+J>kmI<3T)A=b{r^_(n^jG i^+T3P9mnyh>tD$Uq?(LxQCX(jGFnVsN+w5g=zjo|oE!82 delta 37490 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�B54ZU7H7H5==ENB|ph2AReSbL3pC5Wffy>DN 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 T>)pd?2l;zBEr-l& diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xrossim.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xrossim.metallib index bcd5eba842d532bd6ea1607c20640e403f59394f..86b58685bc5853a2165b2a5301da59c4e43563b8 100644 GIT binary patch delta 41340 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 delta 37522 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%0D=Pt@ICpY3 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 diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels.metallib index 37cee1e055bdf35bd712aed1f78b75425f919406..b4bc92f89e9f00f7c56cf061d7a3d0f208a52462 100644 GIT binary patch delta 39323 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 Bool { + xrFoveatedRenderingEnabled +} + public enum RenderResourceQuery { case texture(String) } diff --git a/Sources/UntoldEngine/Utils/Globals.swift b/Sources/UntoldEngine/Utils/Globals.swift index 1a92d1f3a..1e5b0c5cf 100644 --- a/Sources/UntoldEngine/Utils/Globals.swift +++ b/Sources/UntoldEngine/Utils/Globals.swift @@ -1103,6 +1103,7 @@ private final class RuntimeGlobalsStore: @unchecked Sendable { private var activeEntityValue: EntityID = .invalid private var enableEngineMetricsValue: Bool = false private var bypassPostProcessingValue: Bool = false + private var xrFoveatedRenderingEnabledValue: Bool = true private var antiAliasingModeValue: AntiAliasingMode = .fxaa private var renderDebugViewModeValue: RenderDebugViewMode = .lit private var pomQualitySettingsValue: POMQualitySettings = .platformDefault @@ -1594,6 +1595,20 @@ private final class RuntimeGlobalsStore: @unchecked Sendable { } } + var xrFoveatedRenderingEnabled: Bool { + get { + lock.lock() + let value = xrFoveatedRenderingEnabledValue + lock.unlock() + return value + } + set { + lock.lock() + xrFoveatedRenderingEnabledValue = newValue + lock.unlock() + } + } + var antiAliasingMode: AntiAliasingMode { get { lock.lock() @@ -2093,6 +2108,13 @@ public var bypassPostProcessing: Bool { set { RuntimeGlobalsStore.shared.bypassPostProcessing = newValue } } +/// Whether the XR frame draws through the rasterization rate maps the compositor provides +/// (visionOS foveation), the default. See `RenderingProperty.foveatedRendering`. +public var xrFoveatedRenderingEnabled: Bool { + get { RuntimeGlobalsStore.shared.xrFoveatedRenderingEnabled } + set { RuntimeGlobalsStore.shared.xrFoveatedRenderingEnabled = newValue } +} + /// Selects the active anti-aliasing pass inserted after the look pass. public enum AntiAliasingMode: Sendable { case none diff --git a/Sources/UntoldEngineXR/UntoldEngineXR.swift b/Sources/UntoldEngineXR/UntoldEngineXR.swift index b32d7c122..5417ce751 100644 --- a/Sources/UntoldEngineXR/UntoldEngineXR.swift +++ b/Sources/UntoldEngineXR/UntoldEngineXR.swift @@ -69,6 +69,15 @@ // Reuse render pass descriptors to avoid allocation churn (2 eyes × 90 FPS = 180 allocs/sec) private let passDescriptorLeft = MTLRenderPassDescriptor() private let passDescriptorRight = MTLRenderPassDescriptor() + + // Foveation: the parameter data of each eye's rasterization rate map, copied every frame + // (the maps follow the gaze) into a ring one slot deeper than the frames in flight — + // the depth pyramid built on a frame carries its last eye's data into the culls of the + // frame after (HZBPyramidFrame.rateMapData), which may still run when this frame's + // slot comes round again with only the usual in-flight depth. + private var rateMapParameterBuffers: [[MTLBuffer?]] = Array(repeating: [nil, nil], count: maxInFlightCommandBuffers + 1) + private var rateMapFrameCounter = 0 + private var loggedFoveationState: Bool? private let spatialGestureRecognizer = XRSpatialGestureRecognizer() private let xrEnvironmentLightingSystem = XREnvironmentLightingSystem() private var runtimeLightingModeObserverId: UUID? @@ -756,6 +765,57 @@ spatialGestureRecognizer.resetAllSpatialInteractionTracking() } + /// The rasterization rate map the compositor made for a view, as the renderer draws + /// through it, or nil when the frame is drawn uniformly: the layer configured without + /// foveation (no maps; also the simulator) or `setRendering(.foveatedRendering(.disabled))`. + /// The map's parameters go into this frame's slot of the ring for the shaders that decode + /// them; the viewport is the view's in the map's screen space. + private func makeFoveationFrame( + drawable: LayerRenderer.Drawable, + viewport: MTLViewport, + viewIndex: Int, + slot: Int + ) -> XRFoveationFrame? { + let rateMaps = drawable.rasterizationRateMaps + let available = xrFoveatedRenderingEnabled && viewIndex < rateMaps.count && viewIndex < stereoEyeCount + if loggedFoveationState != available { + loggedFoveationState = available + if available { + let rateMap = rateMaps[viewIndex] + let screen = rateMap.screenSize + let physical = rateMap.physicalSize(layer: 0) + print("✓ XR foveation: drawing through the compositor's rasterization rate maps, screen \(screen.width)×\(screen.height), textures \(physical.width)×\(physical.height) per eye") + } else if rateMaps.isEmpty { + print("XR foveation off: the layer provides no rasterization rate maps (isFoveationEnabled is false, or the simulator); drawing uniformly") + } else { + print("XR foveation off by setting (.foveatedRendering(.disabled)); the layer's rate maps are ignored and the picture will be warped") + } + } + guard available else { return nil } + + let rateMap = rateMaps[viewIndex] + let sizeAndAlign = rateMap.parameterDataSizeAndAlign + let align = max(1, sizeAndAlign.align) + let length = max(16, (sizeAndAlign.size + align - 1) / align * align) + if rateMapParameterBuffers[slot][viewIndex].map({ $0.length < length }) ?? true { + let buffer = renderInfo.device.makeBuffer(length: length, options: .storageModeShared) + buffer?.label = "XR Rate Map Parameters eye \(viewIndex) slot \(slot)" + rateMapParameterBuffers[slot][viewIndex] = buffer + } + guard let buffer = rateMapParameterBuffers[slot][viewIndex], + let data = XRRasterizationRateMapData(rateMap: rateMap, buffer: buffer) + else { + Logger.logWarning(message: "XR foveation: could not copy the rate map parameters for eye \(viewIndex); drawing this eye uniformly") + return nil + } + if let texture = drawable.colorTextures.indices.contains(viewIndex) ? drawable.colorTextures[viewIndex] : nil, + Int(data.physicalSize.x) != texture.width || Int(data.physicalSize.y) != texture.height + { + Logger.logWarning(message: "XR foveation: eye \(viewIndex) rate map physical size \(data.physicalSize) differs from its texture \(texture.width)×\(texture.height)") + } + return XRFoveationFrame(rateMap: rateMap, viewport: viewport, rateMapData: data) + } + func executeXRSystemPass(frame _: LayerRenderer.Frame, drawable: LayerRenderer.Drawable, loading: Bool) { // Wait for available command buffer slot to prevent unbounded memory growth let semaphoreWaitStart = CACurrentMediaTime() @@ -781,8 +841,12 @@ let renderTotalStart = CACurrentMediaTime() #endif renderInfo.currentInFlightFrameSlot = acquireUniformFrameSlot() + let rateMapSlot = rateMapFrameCounter % rateMapParameterBuffers.count + rateMapFrameCounter += 1 - // Update viewport to match actual drawable size (per-eye texture dimensions) + // Update viewport to match actual drawable size (per-eye texture dimensions). With + // foveation on, that is the rate map's physical size: every texture of the frame is + // allocated at it, while viewports and clip space live in the map's screen size. if let firstColorTexture = drawable.colorTextures.first { let actualViewPort = simd_float2(Float(firstColorTexture.width), Float(firstColorTexture.height)) if renderInfo.viewPort != actualViewPort { @@ -867,6 +931,15 @@ } renderInfo.currentEye = viewIndex + // The eye's rasterization rate map (foveation), for the passes that draw the + // scene; the final pass into the compositor's textures copies physical pixels + // one to one and keeps passDescriptor without it. + renderInfo.xrFoveation = makeFoveationFrame( + drawable: drawable, + viewport: view.textureMap.viewport, + viewIndex: viewIndex, + slot: rateMapSlot + ) #if ENGINE_STATS_ENABLED let encodeStart = CACurrentMediaTime() diff --git a/Tests/UntoldEngineRenderTests/GaussianChunkCullTest.swift b/Tests/UntoldEngineRenderTests/GaussianChunkCullTest.swift index 481e6b99c..82bf2b0c3 100644 --- a/Tests/UntoldEngineRenderTests/GaussianChunkCullTest.swift +++ b/Tests/UntoldEngineRenderTests/GaussianChunkCullTest.swift @@ -1095,7 +1095,7 @@ final class GaussianChunkCullTest: BaseRenderSetup { XCTAssertEqual(constants.hzbOcclusionBias, gaussianCullHZBOcclusionBias) XCTAssertEqual(constants.uniformQuotas, 0, "the weighted quotas are the default") XCTAssertEqual(gaussianChunkCullConstants(chunkTable: table, modelMatrix: world.space, viewMatrix: matrix_identity_float4x4, hzbValid: false, uniformQuotas: true).uniformQuotas, 1) - XCTAssertEqual(MemoryLayout.stride, 192) + XCTAssertEqual(MemoryLayout.stride, 208) XCTAssertEqual(MemoryLayout.stride, 16) XCTAssertEqual(MemoryLayout.stride, 48) XCTAssertEqual(MemoryLayout.stride, 48) diff --git a/Tests/UntoldEngineRenderTests/GaussianChunkLevelTest.swift b/Tests/UntoldEngineRenderTests/GaussianChunkLevelTest.swift index f80387fc7..ae60e1d9e 100644 --- a/Tests/UntoldEngineRenderTests/GaussianChunkLevelTest.swift +++ b/Tests/UntoldEngineRenderTests/GaussianChunkLevelTest.swift @@ -1888,7 +1888,7 @@ final class GaussianChunkLevelTest: BaseRenderSetup { XCTAssertEqual(MemoryLayout.stride, 16) XCTAssertEqual(MemoryLayout.offset(of: \.coarseAvailable), 12) XCTAssertEqual(MemoryLayout.stride, 32) - XCTAssertEqual(MemoryLayout.stride, 192) + XCTAssertEqual(MemoryLayout.stride, 208) XCTAssertEqual(MemoryLayout.stride, 48) XCTAssertEqual(MemoryLayout.stride, 64) XCTAssertEqual(MemoryLayout.stride, 48) diff --git a/Tests/UntoldEngineRenderTests/GaussianPagingTest.swift b/Tests/UntoldEngineRenderTests/GaussianPagingTest.swift index 158a67565..d26e253ac 100644 --- a/Tests/UntoldEngineRenderTests/GaussianPagingTest.swift +++ b/Tests/UntoldEngineRenderTests/GaussianPagingTest.swift @@ -1784,9 +1784,10 @@ final class GaussianPagingTest: BaseRenderSetup { XCTAssertEqual(MemoryLayout.offset(of: \.frameIndex), 8) XCTAssertEqual(MemoryLayout.offset(of: \.fadeFrames), 12) XCTAssertEqual(MemoryLayout.offset(of: \.debugMode), 16) - XCTAssertEqual(MemoryLayout.stride, 192) + XCTAssertEqual(MemoryLayout.stride, 208) XCTAssertEqual(MemoryLayout.offset(of: \.paged), 172) XCTAssertEqual(MemoryLayout.offset(of: \.rangeCount), 176) + XCTAssertEqual(MemoryLayout.offset(of: \.hzbRateMapSizes), 192) XCTAssertEqual(gaussianChunkCullResidencyIndex.rawValue, 8) XCTAssertEqual(gaussianChunkCullDemandIndex.rawValue, 9) XCTAssertEqual(gaussianChunkPreprocessResidencyIndex.rawValue, 13) diff --git a/Tests/UntoldEngineRenderTests/GaussianScreenWeightedQuotaTest.swift b/Tests/UntoldEngineRenderTests/GaussianScreenWeightedQuotaTest.swift index 953c6758c..3e61dce6f 100644 --- a/Tests/UntoldEngineRenderTests/GaussianScreenWeightedQuotaTest.swift +++ b/Tests/UntoldEngineRenderTests/GaussianScreenWeightedQuotaTest.swift @@ -320,7 +320,8 @@ final class GaussianScreenWeightedQuotaTest: BaseRenderSetup { /// The shared layouts the kernels and the readbacks depend on. func testLayoutsArePinned() { - XCTAssertEqual(MemoryLayout.stride, 192) + XCTAssertEqual(MemoryLayout.stride, 208) + XCTAssertEqual(MemoryLayout.offset(of: \.hzbRateMapSizes), 192) XCTAssertEqual(MemoryLayout.stride, 16) XCTAssertEqual(MemoryLayout.stride, 48) XCTAssertEqual(MemoryLayout.stride, 48) diff --git a/Tests/UntoldEngineRenderTests/XRFoveationTests.swift b/Tests/UntoldEngineRenderTests/XRFoveationTests.swift new file mode 100644 index 000000000..432c06a13 --- /dev/null +++ b/Tests/UntoldEngineRenderTests/XRFoveationTests.swift @@ -0,0 +1,196 @@ +// +// XRFoveationTests.swift +// UntoldEngine +// +// Drawing through a rasterization rate map (visionOS foveation, XRFoveation.swift): the map's +// parameter data the shaders decode, which pass descriptors carry the map and which do not, +// and the occlusion cull sampling a pyramid drawn through a map where the map put the rect, +// not where the rect's screen UV falls in the texture. +// +// Copyright (C) Untold Engine Studios +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +import CShaderTypes +import Metal +import simd +@testable import UntoldEngine +import XCTest + +@MainActor +final class XRFoveationTests: BaseRenderSetup { + private let screen = 256 + + override func initializeAssets() {} + + override func tearDown() async throws { + renderInfo.xrFoveation = nil + applyXRFoveationToSceneRenderPassDescriptors() + try await super.tearDown() + } + + // MARK: - Helpers + + /// A map over a 256-pixel-square screen whose right half is drawn at a quarter of the rate + /// of its left half, so the physical texture is narrower than the screen and a screen + /// position in the right half lands at a different texel than its UV says. + private func makeRateMap() throws -> MTLRasterizationRateMap { + let device = try XCTUnwrap(renderInfo.device) + guard device.supportsRasterizationRateMap(layerCount: 1) else { + throw XCTSkip("this GPU has no rasterization rate maps") + } + let descriptor = MTLRasterizationRateMapDescriptor(screenSize: MTLSize(width: screen, height: screen, depth: 1)) + let layer = MTLRasterizationRateLayerDescriptor(sampleCount: MTLSize(width: 2, height: 1, depth: 1)) + layer.horizontal[0] = 1.0 + layer.horizontal[1] = 0.25 + layer.vertical[0] = 1.0 + descriptor.setLayer(layer, at: 0) + descriptor.label = "XRFoveationTests" + return try XCTUnwrap(device.makeRasterizationRateMap(descriptor: descriptor)) + } + + private func makeRateMapData(_ rateMap: MTLRasterizationRateMap) throws -> XRRasterizationRateMapData { + let device = try XCTUnwrap(renderInfo.device) + let buffer = try XCTUnwrap(device.makeBuffer(length: rateMap.parameterDataSizeAndAlign.size, options: .storageModeShared)) + return try XCTUnwrap(XRRasterizationRateMapData(rateMap: rateMap, buffer: buffer)) + } + + // MARK: - Tests + + func testRateMapDataCarriesTheSizesAndParameters() throws { + let rateMap = try makeRateMap() + let data = try makeRateMapData(rateMap) + + let physical = rateMap.physicalSize(layer: 0) + XCTAssertEqual(data.screenSize, simd_float2(Float(screen), Float(screen))) + XCTAssertEqual(data.physicalSize, simd_float2(Float(physical.width), Float(physical.height))) + XCTAssertLessThan(physical.width, screen, "a quarter-rate half narrows the physical texture") + XCTAssertEqual(data.sizes, simd_float4(Float(screen), Float(screen), Float(physical.width), Float(physical.height))) + XCTAssertEqual(rateMapSizes(nil), .zero, "the word the shaders read as 'no map'") + + let bytes = UnsafeRawBufferPointer(start: data.buffer.contents(), count: rateMap.parameterDataSizeAndAlign.size) + XCTAssertTrue(bytes.contains { $0 != 0 }, "the map's parameters were copied") + + let short = try XCTUnwrap(renderInfo.device.makeBuffer(length: 4, options: .storageModeShared)) + XCTAssertNil(XRRasterizationRateMapData(rateMap: rateMap, buffer: short), "a buffer too short for the parameters is refused") + } + + func testScenePassesCarryTheRateMapAndScreenPassesDoNot() throws { + let rateMap = try makeRateMap() + let data = try makeRateMapData(rateMap) + let viewport = MTLViewport(originX: 0, originY: 0, width: Double(screen), height: Double(screen), znear: 0, zfar: 1) + + renderInfo.xrFoveation = XRFoveationFrame(rateMap: rateMap, viewport: viewport, rateMapData: data) + applyXRFoveationToSceneRenderPassDescriptors() + + XCTAssertTrue(renderInfo.offscreenRenderPassDescriptor.rasterizationRateMap === rateMap, "the G-buffer + light pass draws through the map") + XCTAssertTrue(renderInfo.deferredRenderPassDescriptor.rasterizationRateMap === rateMap, "transparency, wireframe and debug draw through the map") + XCTAssertTrue(renderInfo.environmentRenderPassDescriptor.rasterizationRateMap === rateMap, "the background draws through the map") + XCTAssertTrue(renderInfo.gaussianRenderPassDescriptor.rasterizationRateMap === rateMap, "the splats draw through the map") + XCTAssertNil(renderInfo.sceneCompositeRenderPassDescriptor.rasterizationRateMap, "the composite copies physical pixels one to one") + XCTAssertNil(renderInfo.ssaoRenderPassDescriptor.rasterizationRateMap, "SSAO reads the physical depth one to one") + XCTAssertNil(renderInfo.postProcessRenderPassDescriptor?.rasterizationRateMap, "post-processing copies physical pixels one to one") + + renderInfo.xrFoveation = nil + applyXRFoveationToSceneRenderPassDescriptors() + XCTAssertNil(renderInfo.offscreenRenderPassDescriptor.rasterizationRateMap, "a uniform frame detaches the map") + XCTAssertNil(renderInfo.deferredRenderPassDescriptor.rasterizationRateMap) + XCTAssertNil(renderInfo.environmentRenderPassDescriptor.rasterizationRateMap) + XCTAssertNil(renderInfo.gaussianRenderPassDescriptor.rasterizationRateMap) + } + + /// A box in the right half of the screen, in front of a pyramid that holds an occluder only + /// where the map put that half. Read where the box's screen UV falls in the texture, the + /// pyramid shows background and the box is kept; moved through the map, the rect lies on + /// the occluder and the box is dropped. + func testOcclusionCullSamplesThePyramidWhereTheRateMapPutTheRect() throws { + let rateMap = try makeRateMap() + let data = try makeRateMapData(rateMap) + let device = try XCTUnwrap(renderInfo.device) + let physical = rateMap.physicalSize(layer: 0) + + // The box: NDC x in 0.5…0.9 — screen pixels 192…243 of 256 — a sliver of y, at depth 0.5. + let box = VisibleEntity(center: simd_float4(0.7, 0, 0.5, 1), halfExtent: simd_float4(0.2, 0.05, 0, 0), index: 1, version: 1) + // Where the rect's left edge lands in the texture by Metal's own mapping, against where + // its screen UV (0.75) would be read without the map. + let mappedMinX = rateMap.physicalCoordinates(screenCoordinates: MTLCoordinate2D(x: 192, y: 128), layer: 0).x + let unmappedMinX = 0.75 * Float(physical.width) + XCTAssertGreaterThan(mappedMinX, unmappedMinX + 2, "the quarter-rate half moves the rect to the right in the texture") + + // One mip: an occluder (0.9, near in reverse-Z) from just before the mapped rect to the + // right edge, background (0) everywhere else. + let occluderStart = max(0, Int(mappedMinX.rounded(.down)) - 1) + let pyramidDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .r32Float, width: physical.width, height: physical.height, mipmapped: false) + pyramidDescriptor.usage = [.shaderRead] + pyramidDescriptor.storageMode = .managed + let pyramid = try XCTUnwrap(device.makeTexture(descriptor: pyramidDescriptor)) + var row = [Float](repeating: 0, count: physical.width) + for x in occluderStart ..< physical.width { + row[x] = 0.9 + } + var texels = [Float]() + texels.reserveCapacity(physical.width * physical.height) + for _ in 0 ..< physical.height { + texels.append(contentsOf: row) + } + texels.withUnsafeBytes { bytes in + pyramid.replace( + region: MTLRegionMake2D(0, 0, physical.width, physical.height), + mipmapLevel: 0, + withBytes: bytes.baseAddress!, + bytesPerRow: physical.width * MemoryLayout.stride + ) + } + + // The frame state the cull reads, restored afterwards. + let savedViewPort = renderInfo.viewPort + let savedValid = renderInfo.hzbIsValid + let savedFrame = renderInfo.hzbFrame + let savedMipCount = renderInfo.hzbMipCount + let savedReverseZ = renderInfo.reverseZEnabled + let savedPyramid = textureResources.hzbDepthPyramid + defer { + renderInfo.viewPort = savedViewPort + renderInfo.hzbIsValid = savedValid + renderInfo.hzbFrame = savedFrame + renderInfo.hzbMipCount = savedMipCount + renderInfo.reverseZEnabled = savedReverseZ + textureResources.hzbDepthPyramid = savedPyramid + } + renderInfo.viewPort = simd_float2(Float(physical.width), Float(physical.height)) + renderInfo.hzbIsValid = true + renderInfo.hzbMipCount = 1 + renderInfo.reverseZEnabled = true + textureResources.hzbDepthPyramid = pyramid + + func survivors(rateMapData: XRRasterizationRateMapData?) throws -> Int { + renderInfo.hzbFrame = HZBPyramidFrame(viewProjection: matrix_identity_float4x4, cameraPosition: .zero, rateMapData: rateMapData) + var candidate = box + var candidateCount: UInt32 = 1 + let inputVisibility = try XCTUnwrap(device.makeBuffer(bytes: &candidate, length: MemoryLayout.stride, options: .storageModeShared)) + let inputCount = try XCTUnwrap(device.makeBuffer(bytes: &candidateCount, length: MemoryLayout.stride, options: .storageModeShared)) + let outputVisibility = try XCTUnwrap(device.makeBuffer(length: MemoryLayout.stride, options: .storageModeShared)) + let outputCount = try XCTUnwrap(device.makeBuffer(length: MemoryLayout.stride, options: .storageModeShared)) + + let commandBuffer = try XCTUnwrap(renderInfo.commandQueue.makeCommandBuffer()) + let ran = executeHZBOcclusionCulling( + commandBuffer, + cameraPosition: .zero, + dispatchCount: 1, + inputVisibilityBuffer: inputVisibility, + inputVisibleCountBuffer: inputCount, + outputVisibilityBuffer: outputVisibility, + outputVisibleCountBuffer: outputCount + ) + XCTAssertTrue(ran, "the pyramid is valid and the camera has not moved") + commandBuffer.commit() + commandBuffer.waitUntilCompleted() + return Int(outputCount.contents().load(as: UInt32.self)) + } + + XCTAssertEqual(try survivors(rateMapData: nil), 1, "read at its screen UV, the rect sees background and the box is kept") + XCTAssertEqual(try survivors(rateMapData: data), 0, "moved through the map, the rect lies on the occluder and the box is dropped") + } +} diff --git a/docs/API/UsingEngineAPI.md b/docs/API/UsingEngineAPI.md index 7889c439f..19b17b9c1 100644 --- a/docs/API/UsingEngineAPI.md +++ b/docs/API/UsingEngineAPI.md @@ -82,6 +82,17 @@ setRendering(.occlusionCullingMaxCameraStep(0.5)) getOcclusionCullingMaxCameraStep() ``` +On visionOS, a layer configured with `isFoveationEnabled` hands the engine a rasterization +rate map per eye, and the engine draws through it by default: dense where the eyes look, +coarse in the periphery, and the only configuration in which the compositor accepts a +`maxRenderQuality` above the platform default. Disabling it in such a layer is a diagnostic +(the frame is drawn uniformly into textures the compositor still unwarps): + +```swift +setRendering(.foveatedRendering(.disabled)) +getFoveatedRenderingEnabled() +``` + ## PostFX Use `setPostFX` for individual post-processing and SSAO settings: diff --git a/docs/Architecture/xrRenderingSystem.md b/docs/Architecture/xrRenderingSystem.md index b4c3059ae..bba8ca2d3 100644 --- a/docs/Architecture/xrRenderingSystem.md +++ b/docs/Architecture/xrRenderingSystem.md @@ -167,6 +167,15 @@ The compositor provides the exact asymmetric projection for each eye. This accou - `renderInfo.currentEye = viewIndex` — tells uniform uploads which eye's matrices to use - The base pass mode: `.mixed` immersion omits the base pass (camera passthrough is the background), `.full` immersion renders the skybox +**Foveation (rasterization rate maps).** With `isFoveationEnabled` in the app's `CompositorLayerConfiguration`, the compositor hands each eye a `MTLRasterizationRateMap` and colour/depth textures of the map's *physical* size, smaller than the *screen* the eye sees; the GPU draws through the map (dense where the eyes look, coarse in the periphery) and the compositor unwarps the texture for the display. It is also the only configuration in which the compositor accepts a `maxRenderQuality` above the platform default. The engine supports it as follows (`XRFoveation.swift`, on by default, `setRendering(.foveatedRendering(.disabled))` to ignore the maps for diagnosis): + +- `executeXRSystemPass` makes an `XRFoveationFrame` per eye (`renderInfo.xrFoveation`): the map, the eye's viewport in the map's screen space (`view.textureMap.viewport`), and the map's parameter data copied into a ring of shared buffers for the shaders. `renderInfo.viewPort` stays the texture size, the physical size, so every sizeable resource is allocated at it. +- After the graph is built, `applyXRFoveationToSceneRenderPassDescriptors` attaches the map to the descriptors of the passes that rasterize the scene at drawable size (G-buffer + light, the deferred colour that transparency/wireframe/debug draw into, environment/sky/grid, splats, gizmos), and each of those encoders sets the eye's viewport (`applyXRFoveationViewport`): the default viewport is the texture's size, which would draw the scene at a fraction of the screen. The full-screen passes (SSAO, post-processing, anti-aliasing, the output transform into the compositor's texture) keep plain descriptors: they copy physical pixels one to one and the layout is already the map's. +- Two kinds of shader decode the map (`rasterization_rate_map_decoder`): SSAO, which rebuilds view positions from a depth texel's UV and must use the texel's *screen* position; and the occlusion culls (`hzbCullVisibleEntities`, `gaussianChunkCull`, the per-splat test), which project boxes and splats to screen UV and sample a pyramid laid out in physical space — the rect or point goes through the map first (`HZBOcclusion.h`). The pyramid carries the map it was drawn through into the next frame's culls (`HZBPyramidFrame.rateMapData`). +- The Gaussian fragment takes its offset from the splat centre from a varying rather than from `[[position]]`, which the rate map places in the physical texture. Fragment position is physical everywhere else too, which is what every one-to-one texture read wants; `SmallObjectCulling` measures its pixel threshold against the screen height. + +Without foveation (the layer configured without it, the simulator), `drawable.rasterizationRateMaps` is empty and the frame is drawn uniformly exactly as before. + ### 3c. HZB Pyramid (built once after both eyes) ```swift From 444c30892039aea50343aa93a5465e091238f5a3 Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sat, 10 Oct 2026 18:34:14 +0200 Subject: [PATCH 02/10] [Bugfix] Query the frame's drawables with queryDrawables on visionOS 26 A layer configured with foveation or a render quality aborts the app when the frame is queried with the single-drawable queryDrawable() ("BUG IN CLIENT: called cp_frame_query_drawable() which does not support setting render quality or fovea"). The frame now takes the drawable array on visionOS 26 (the old call on visionOS 2), presents every drawable, and draws the scene into a capture drawable only while its textures match the frame's resources; otherwise it is presented cleared rather than reallocating every sizeable resource twice a frame. --- Sources/UntoldEngineXR/UntoldEngineXR.swift | 147 ++++++++++++++------ docs/Architecture/xrRenderingSystem.md | 4 +- 2 files changed, 107 insertions(+), 44 deletions(-) diff --git a/Sources/UntoldEngineXR/UntoldEngineXR.swift b/Sources/UntoldEngineXR/UntoldEngineXR.swift index 5417ce751..c2f48bebe 100644 --- a/Sources/UntoldEngineXR/UntoldEngineXR.swift +++ b/Sources/UntoldEngineXR/UntoldEngineXR.swift @@ -78,6 +78,7 @@ private var rateMapParameterBuffers: [[MTLBuffer?]] = Array(repeating: [nil, nil], count: maxInFlightCommandBuffers + 1) private var rateMapFrameCounter = 0 private var loggedFoveationState: Bool? + private var loggedCaptureTargetSkip = false private let spatialGestureRecognizer = XRSpatialGestureRecognizer() private let xrEnvironmentLightingSystem = XREnvironmentLightingSystem() private var runtimeLightingModeObserverId: UUID? @@ -625,64 +626,79 @@ } } - // 9. Encode any drawing commands that depend on the device position or orientation - guard let drawable = frame.queryDrawable() else { + // 9. Encode any drawing commands that depend on the device position or orientation. + // visionOS 26 hands a frame one drawable per target (the built-in display, and a + // capture target while the view is recorded or streamed); a layer with foveation + // or a render quality set aborts the app if the single-drawable query is used. + let drawables: [LayerRenderer.Drawable] + if #available(visionOS 26.0, *) { + drawables = frame.queryDrawables() + } else { + drawables = frame.queryDrawable().map { [$0] } ?? [] + } + guard !drawables.isEmpty else { #if ENGINE_STATS_ENABLED renderer.finalizeXRStatsAndMonitors(frameStartTime: xrFrameStartTime) #else renderer.finalizeXRStatsAndMonitors(frameStartTime: 0.0) #endif - // queryDrawable() can fail during shutdown/teardown; in that case the + // No drawables (shutdown/teardown, or the compositor cancelled the frame): the // frame is already invalid and endSubmission() must not be called. shouldEndSubmission = false return } - // 10. Fetch the predicted device anchor from ARKit using the frameTiming information, and - // apply the anchor to your frame - let presentationInstant = drawable.frameTiming.presentationTime - let presentationTimeCA: TimeInterval = compositorInstantToCATime(presentationInstant) - var deviceAnchor = queryDeviceAnchorIfTrackingRunning(atTimestamp: presentationTimeCA) - - // If predicted-time query misses, retry at "now" to reduce one-frame anchor gaps. - if deviceAnchor == nil { - let nowTimestamp = CACurrentMediaTime() - if let retryAnchor = queryDeviceAnchorIfTrackingRunning(atTimestamp: nowTimestamp) { - deviceAnchor = retryAnchor - } - } - - // Use current anchor if valid, otherwise fall back to last valid anchor. - // This prevents "Presenting a drawable without a device anchor" while maintaining - // stable rendering. We must always present the drawable once we have it. - if let anchor = deviceAnchor { - if missingAnchorFrameCount > 0 { - print("✓ XR device anchor recovered after \(missingAnchorFrameCount) missing frame(s)") - } - missingAnchorFrameCount = 0 - lastValidDeviceAnchor = anchor - drawable.deviceAnchor = anchor - } else if let cachedAnchor = lastValidDeviceAnchor { - missingAnchorFrameCount += 1 - if shouldLogAnchorDiagnostics() { - printXRAnchorDiagnostics(message: "XR device anchor missing; using cached anchor") - } - drawable.deviceAnchor = cachedAnchor - } else { - missingAnchorFrameCount += 1 - if shouldLogAnchorDiagnostics() { - printXRAnchorDiagnostics(message: "XR device anchor missing; no cached anchor available") - } - } - // Note: If we have no cached anchor either, drawable.deviceAnchor remains nil - // and the render loop will skip rendering but still present (required by compositor) - // Re-check loading state right before render pass to catch any mutations that started // after our initial snapshot. This provides a second layer of protection against races. let loadingNow = AssetLoadingGate.shared.isLoadingAny let effectiveLoading = loading || loadingNow - executeXRSystemPass(frame: frame, drawable: drawable, loading: effectiveLoading) + for drawable in drawables { + // 10. Fetch the predicted device anchor from ARKit using the frameTiming information, and + // apply the anchor to your frame + let presentationInstant = drawable.frameTiming.presentationTime + let presentationTimeCA: TimeInterval = compositorInstantToCATime(presentationInstant) + var deviceAnchor = queryDeviceAnchorIfTrackingRunning(atTimestamp: presentationTimeCA) + + // If predicted-time query misses, retry at "now" to reduce one-frame anchor gaps. + if deviceAnchor == nil { + let nowTimestamp = CACurrentMediaTime() + if let retryAnchor = queryDeviceAnchorIfTrackingRunning(atTimestamp: nowTimestamp) { + deviceAnchor = retryAnchor + } + } + + // Use current anchor if valid, otherwise fall back to last valid anchor. + // This prevents "Presenting a drawable without a device anchor" while maintaining + // stable rendering. We must always present the drawable once we have it. + if let anchor = deviceAnchor { + if missingAnchorFrameCount > 0 { + print("✓ XR device anchor recovered after \(missingAnchorFrameCount) missing frame(s)") + } + missingAnchorFrameCount = 0 + lastValidDeviceAnchor = anchor + drawable.deviceAnchor = anchor + } else if let cachedAnchor = lastValidDeviceAnchor { + missingAnchorFrameCount += 1 + if shouldLogAnchorDiagnostics() { + printXRAnchorDiagnostics(message: "XR device anchor missing; using cached anchor") + } + drawable.deviceAnchor = cachedAnchor + } else { + missingAnchorFrameCount += 1 + if shouldLogAnchorDiagnostics() { + printXRAnchorDiagnostics(message: "XR device anchor missing; no cached anchor available") + } + } + // Note: If we have no cached anchor either, drawable.deviceAnchor remains nil + // and the render loop will skip rendering but still present (required by compositor) + + if drawsScene(into: drawable) { + executeXRSystemPass(frame: frame, drawable: drawable, loading: effectiveLoading) + } else { + presentCleared(drawable) + } + } #if ENGINE_STATS_ENABLED renderer.finalizeXRStatsAndMonitors(frameStartTime: xrFrameStartTime) #else @@ -690,6 +706,51 @@ #endif } + /// Whether the scene is drawn into a drawable. The built-in display always; another + /// target (a capture of the view for recording or streaming) only while its textures are + /// the size the frame's resources are allocated at — every sizeable resource is sized + /// to one viewport, and a second size would reallocate them twice a frame. + private func drawsScene(into drawable: LayerRenderer.Drawable) -> Bool { + if #available(visionOS 26.0, *), drawable.target != .builtIn, + let texture = drawable.colorTextures.first, + renderInfo.viewPort != simd_float2(Float(texture.width), Float(texture.height)) + { + if !loggedCaptureTargetSkip { + loggedCaptureTargetSkip = true + print("XR: a \(texture.width)×\(texture.height) capture drawable differs from the \(Int(renderInfo.viewPort.x))×\(Int(renderInfo.viewPort.y)) frame resources; presenting it cleared") + } + return false + } + return true + } + + /// Presents a drawable with its colour cleared (the immersion mode's alpha) and its depth + /// cleared, without drawing the scene: the compositor wants every drawable it handed out + /// presented. + private func presentCleared(_ drawable: LayerRenderer.Drawable) { + guard let commandBuffer = renderInfo.commandQueue.makeCommandBuffer() else { return } + commandBuffer.label = "XR Cleared Drawable" + for viewIndex in drawable.views.indices + where viewIndex < drawable.colorTextures.count && viewIndex < drawable.depthTextures.count + { + let descriptor = MTLRenderPassDescriptor() + descriptor.colorAttachments[0].texture = drawable.colorTextures[viewIndex] + descriptor.colorAttachments[0].loadAction = .clear + descriptor.colorAttachments[0].storeAction = .store + descriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: Double(getAlphaForImmersionMode())) + descriptor.depthAttachment.texture = drawable.depthTextures[viewIndex] + descriptor.depthAttachment.loadAction = .clear + descriptor.depthAttachment.storeAction = .store + descriptor.depthAttachment.clearDepth = 0.0 + if viewIndex < drawable.rasterizationRateMaps.count { + descriptor.rasterizationRateMap = drawable.rasterizationRateMaps[viewIndex] + } + commandBuffer.makeRenderCommandEncoder(descriptor: descriptor)?.endEncoding() + } + drawable.encodePresent(commandBuffer: commandBuffer) + commandBuffer.commit() + } + private func updateSpatialInputState() { spatialGestureRecognizer.updateSpatialInputState() } diff --git a/docs/Architecture/xrRenderingSystem.md b/docs/Architecture/xrRenderingSystem.md index bba8ca2d3..03aa402da 100644 --- a/docs/Architecture/xrRenderingSystem.md +++ b/docs/Architecture/xrRenderingSystem.md @@ -100,6 +100,8 @@ defer { frame.endSubmission() } The `defer` is important: `endSubmission()` **must** be called even if rendering fails partway through. If it isn't called, the compositor stalls. The `defer` guarantees this regardless of how the function exits. +**Drawables.** On visionOS 26 the frame is queried with `frame.queryDrawables()`, which returns one drawable per target: the built-in display, plus a capture target while the view is being recorded or streamed. A layer configured with foveation or a render quality aborts the app ("BUG IN CLIENT: called cp_frame_query_drawable() which does not support setting render quality or fovea") if the older single-drawable `queryDrawable()` is used, which the engine still calls on visionOS 2. An empty array means the compositor cancelled the frame: it is left without `endSubmission()`. Every drawable is presented; the scene is drawn into the built-in one and into a capture drawable only while its textures are the size the frame's resources are allocated at — otherwise it is presented cleared, since every sizeable resource is sized to one viewport and a second size would reallocate them twice a frame. + ### 2e. Device Anchor Acquisition ```swift @@ -229,7 +231,7 @@ Selection rays update from interaction events, not continuously as the user look ├─ frame.endUpdate() ├─ wait(until: optimalInputTime) (sleep until compositor deadline) ├─ frame.startSubmission() - ├─ queryDrawable() (get per-eye textures) + ├─ queryDrawables() (one drawable per target; the old single query aborts a foveated layer) ├─ queryDeviceAnchor() → fallback chain → drawable.deviceAnchor = anchor │ └─ executeXRSystemPass() From 9ed204af6b7d5b4d0b6c09d818f934334ae0cabc Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sat, 10 Oct 2026 18:46:43 +0200 Subject: [PATCH 03/10] [Bugfix] Leave the render target size to the attachments while a rate map is attached Under a rasterization rate map Metal reads a descriptor's renderTargetWidth and renderTargetHeight, like the viewport, in screen pixels. The scene descriptors carried the physical texture size there, which clipped every foveated frame to the top-left physical-size corner of the screen: on the headset a screen-fixed rectangle, different in each eye, outside which the board vanished. The attached descriptors now leave the size at 0 (the attachments' own) and get the texture size back when the map is detached; the eye's viewport is taken from the map's screen size. --- .../UntoldEngine/Renderer/RenderPasses.swift | 4 +-- .../UntoldEngine/Renderer/XRFoveation.swift | 34 ++++++++++++++++--- Sources/UntoldEngineXR/UntoldEngineXR.swift | 12 +++++-- .../XRFoveationTests.swift | 8 +++++ docs/Architecture/xrRenderingSystem.md | 2 +- 5 files changed, 50 insertions(+), 10 deletions(-) diff --git a/Sources/UntoldEngine/Renderer/RenderPasses.swift b/Sources/UntoldEngine/Renderer/RenderPasses.swift index ed9e340ea..c12b69184 100644 --- a/Sources/UntoldEngine/Renderer/RenderPasses.swift +++ b/Sources/UntoldEngine/Renderer/RenderPasses.swift @@ -4062,7 +4062,7 @@ public enum RenderPasses { descriptor.depthAttachment.storeAction = .store // The depth was drawn through the eye's rasterization rate map when there is one // (XR foveation); so is what this pass adds to it. - descriptor.rasterizationRateMap = renderInfo.xrFoveation?.rateMap + attachXRFoveation(renderInfo.xrFoveation?.rateMap, to: descriptor) guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { handleError(.renderPassCreationFailed, "Mesh Occluder Shell Pass") @@ -4204,7 +4204,7 @@ public enum RenderPasses { descriptor.depthAttachment.storeAction = .store // The depth was drawn through the eye's rasterization rate map when there is one // (XR foveation); so is what this pass adds to it. - descriptor.rasterizationRateMap = renderInfo.xrFoveation?.rateMap + attachXRFoveation(renderInfo.xrFoveation?.rateMap, to: descriptor) guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { handleError(.renderPassCreationFailed, "Wireframe Occlusion Depth Pass") diff --git a/Sources/UntoldEngine/Renderer/XRFoveation.swift b/Sources/UntoldEngine/Renderer/XRFoveation.swift index ab5c7eb60..ee345707d 100644 --- a/Sources/UntoldEngine/Renderer/XRFoveation.swift +++ b/Sources/UntoldEngine/Renderer/XRFoveation.swift @@ -102,15 +102,39 @@ public struct XRFoveationFrame { /// graph is built, since a rebuild may have recreated the descriptors. func applyXRFoveationToSceneRenderPassDescriptors() { let rateMap = renderInfo.xrFoveation?.rateMap - renderInfo.offscreenRenderPassDescriptor?.rasterizationRateMap = rateMap - renderInfo.deferredRenderPassDescriptor?.rasterizationRateMap = rateMap - renderInfo.environmentRenderPassDescriptor?.rasterizationRateMap = rateMap - renderInfo.gaussianRenderPassDescriptor?.rasterizationRateMap = rateMap - renderInfo.gizmoRenderPassDescriptor?.rasterizationRateMap = rateMap + for descriptor in [ + renderInfo.offscreenRenderPassDescriptor, + renderInfo.deferredRenderPassDescriptor, + renderInfo.environmentRenderPassDescriptor, + renderInfo.gaussianRenderPassDescriptor, + renderInfo.gizmoRenderPassDescriptor, + ] { + guard let descriptor else { continue } + attachXRFoveation(rateMap, to: descriptor) + } +} + +/// Attaches a rate map to a descriptor whose attachments are physical-size textures, or +/// detaches it. A descriptor's render target size is read in *screen* pixels while a map is +/// attached (measured: a target size equal to the physical size clips the scene to the +/// top-left physical-size corner of the screen), so the size is left at 0 — Metal then takes +/// the attachments' own size — and put back to the texture size without a map, which is what +/// `createRenderPassDescriptor` sets and the memoryless attachments rely on. +func attachXRFoveation(_ rateMap: MTLRasterizationRateMap?, to descriptor: MTLRenderPassDescriptor) { + descriptor.rasterizationRateMap = rateMap + if rateMap != nil { + descriptor.renderTargetWidth = 0 + descriptor.renderTargetHeight = 0 + } else if let viewPort = renderInfo.viewPort, descriptor.renderTargetWidth == 0 { + descriptor.renderTargetWidth = Int(viewPort.x) + descriptor.renderTargetHeight = Int(viewPort.y) + } } /// Sets the eye's screen-space viewport on an encoder that draws through the rate map; nothing /// outside foveated XR, where the default viewport, the texture's own size, is the right one. +/// (Measured: a viewport of the physical size under a map clips the scene the same way a +/// physical-size render target does; the map's screen size covers the whole texture.) @inline(__always) func applyXRFoveationViewport(_ encoder: MTLRenderCommandEncoder) { guard let foveation = renderInfo.xrFoveation else { return } diff --git a/Sources/UntoldEngineXR/UntoldEngineXR.swift b/Sources/UntoldEngineXR/UntoldEngineXR.swift index c2f48bebe..5cec2ad71 100644 --- a/Sources/UntoldEngineXR/UntoldEngineXR.swift +++ b/Sources/UntoldEngineXR/UntoldEngineXR.swift @@ -845,7 +845,7 @@ let rateMap = rateMaps[viewIndex] let screen = rateMap.screenSize let physical = rateMap.physicalSize(layer: 0) - print("✓ XR foveation: drawing through the compositor's rasterization rate maps, screen \(screen.width)×\(screen.height), textures \(physical.width)×\(physical.height) per eye") + print("✓ XR foveation: drawing through the compositor's rasterization rate maps, screen \(screen.width)×\(screen.height), textures \(physical.width)×\(physical.height) per eye; view texture map viewport \(viewport.originX),\(viewport.originY) \(viewport.width)×\(viewport.height)") } else if rateMaps.isEmpty { print("XR foveation off: the layer provides no rasterization rate maps (isFoveationEnabled is false, or the simulator); drawing uniformly") } else { @@ -874,7 +874,15 @@ { Logger.logWarning(message: "XR foveation: eye \(viewIndex) rate map physical size \(data.physicalSize) differs from its texture \(texture.width)×\(texture.height)") } - return XRFoveationFrame(rateMap: rateMap, viewport: viewport, rateMapData: data) + // The eye's viewport in the map's screen space. In the dedicated layout the view + // is the whole texture, so it is the map's screen size at the origin; the view's own + // texture map viewport is logged above for the day another layout needs it. + let screenViewport = MTLViewport( + originX: 0, originY: 0, + width: Double(data.screenSize.x), height: Double(data.screenSize.y), + znear: 0, zfar: 1 + ) + return XRFoveationFrame(rateMap: rateMap, viewport: screenViewport, rateMapData: data) } func executeXRSystemPass(frame _: LayerRenderer.Frame, drawable: LayerRenderer.Drawable, loading: Bool) { diff --git a/Tests/UntoldEngineRenderTests/XRFoveationTests.swift b/Tests/UntoldEngineRenderTests/XRFoveationTests.swift index 432c06a13..208f709be 100644 --- a/Tests/UntoldEngineRenderTests/XRFoveationTests.swift +++ b/Tests/UntoldEngineRenderTests/XRFoveationTests.swift @@ -92,10 +92,18 @@ final class XRFoveationTests: BaseRenderSetup { XCTAssertNil(renderInfo.sceneCompositeRenderPassDescriptor.rasterizationRateMap, "the composite copies physical pixels one to one") XCTAssertNil(renderInfo.ssaoRenderPassDescriptor.rasterizationRateMap, "SSAO reads the physical depth one to one") XCTAssertNil(renderInfo.postProcessRenderPassDescriptor?.rasterizationRateMap, "post-processing copies physical pixels one to one") + // A render target size is read in screen pixels under a map: the physical size would + // clip the scene to the top-left corner of the screen, so the size is left to the + // attachments while the map is attached. + XCTAssertEqual(renderInfo.offscreenRenderPassDescriptor.renderTargetWidth, 0) + XCTAssertEqual(renderInfo.deferredRenderPassDescriptor.renderTargetHeight, 0) + XCTAssertEqual(renderInfo.sceneCompositeRenderPassDescriptor.renderTargetWidth, Int(renderInfo.viewPort.x), "a screen pass keeps its texture-size target") renderInfo.xrFoveation = nil applyXRFoveationToSceneRenderPassDescriptors() XCTAssertNil(renderInfo.offscreenRenderPassDescriptor.rasterizationRateMap, "a uniform frame detaches the map") + XCTAssertEqual(renderInfo.offscreenRenderPassDescriptor.renderTargetWidth, Int(renderInfo.viewPort.x), "and puts the texture-size target back") + XCTAssertEqual(renderInfo.deferredRenderPassDescriptor.renderTargetHeight, Int(renderInfo.viewPort.y)) XCTAssertNil(renderInfo.deferredRenderPassDescriptor.rasterizationRateMap) XCTAssertNil(renderInfo.environmentRenderPassDescriptor.rasterizationRateMap) XCTAssertNil(renderInfo.gaussianRenderPassDescriptor.rasterizationRateMap) diff --git a/docs/Architecture/xrRenderingSystem.md b/docs/Architecture/xrRenderingSystem.md index 03aa402da..19ffdc1e0 100644 --- a/docs/Architecture/xrRenderingSystem.md +++ b/docs/Architecture/xrRenderingSystem.md @@ -172,7 +172,7 @@ The compositor provides the exact asymmetric projection for each eye. This accou **Foveation (rasterization rate maps).** With `isFoveationEnabled` in the app's `CompositorLayerConfiguration`, the compositor hands each eye a `MTLRasterizationRateMap` and colour/depth textures of the map's *physical* size, smaller than the *screen* the eye sees; the GPU draws through the map (dense where the eyes look, coarse in the periphery) and the compositor unwarps the texture for the display. It is also the only configuration in which the compositor accepts a `maxRenderQuality` above the platform default. The engine supports it as follows (`XRFoveation.swift`, on by default, `setRendering(.foveatedRendering(.disabled))` to ignore the maps for diagnosis): - `executeXRSystemPass` makes an `XRFoveationFrame` per eye (`renderInfo.xrFoveation`): the map, the eye's viewport in the map's screen space (`view.textureMap.viewport`), and the map's parameter data copied into a ring of shared buffers for the shaders. `renderInfo.viewPort` stays the texture size, the physical size, so every sizeable resource is allocated at it. -- After the graph is built, `applyXRFoveationToSceneRenderPassDescriptors` attaches the map to the descriptors of the passes that rasterize the scene at drawable size (G-buffer + light, the deferred colour that transparency/wireframe/debug draw into, environment/sky/grid, splats, gizmos), and each of those encoders sets the eye's viewport (`applyXRFoveationViewport`): the default viewport is the texture's size, which would draw the scene at a fraction of the screen. The full-screen passes (SSAO, post-processing, anti-aliasing, the output transform into the compositor's texture) keep plain descriptors: they copy physical pixels one to one and the layout is already the map's. +- After the graph is built, `applyXRFoveationToSceneRenderPassDescriptors` attaches the map to the descriptors of the passes that rasterize the scene at drawable size (G-buffer + light, the deferred colour that transparency/wireframe/debug draw into, environment/sky/grid, splats, gizmos), and each of those encoders sets the eye's viewport (`applyXRFoveationViewport`) in the map's screen space. Under a map, Metal reads a descriptor's `renderTargetWidth/Height` and the viewport in *screen* pixels (measured on a Mac GPU, and seen on the headset as a screen-fixed rectangle outside which nothing was drawn), so the attached descriptors leave the target size at 0 — the attachments' own size — and get it back when the map is detached. The full-screen passes (SSAO, post-processing, anti-aliasing, the output transform into the compositor's texture) keep plain descriptors: they copy physical pixels one to one and the layout is already the map's. - Two kinds of shader decode the map (`rasterization_rate_map_decoder`): SSAO, which rebuilds view positions from a depth texel's UV and must use the texel's *screen* position; and the occlusion culls (`hzbCullVisibleEntities`, `gaussianChunkCull`, the per-splat test), which project boxes and splats to screen UV and sample a pyramid laid out in physical space — the rect or point goes through the map first (`HZBOcclusion.h`). The pyramid carries the map it was drawn through into the next frame's culls (`HZBPyramidFrame.rateMapData`). - The Gaussian fragment takes its offset from the splat centre from a varying rather than from `[[position]]`, which the rate map places in the physical texture. Fragment position is physical everywhere else too, which is what every one-to-one texture read wants; `SmallObjectCulling` measures its pixel threshold against the screen height. From baed0e4adc75f2474a90ee4e74f0d7f9f44c91a7 Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sat, 10 Oct 2026 19:26:39 +0200 Subject: [PATCH 04/10] [Feature] Temporal anti-aliasing (.taa and .msaaTaa) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The projection is jittered by a sub-pixel Halton offset before each frame's graph is built, and a resolve pass after the look pass blends the frame with the eye's history, reprojected through the depth buffer and the two frames' unjittered view-projections and clipped to the colour box of the pixel's neighbourhood. Sub-pixel detail a single sample flickers on — thin wires, fine normal maps, the periphery of a foveated frame where a texel spans several screen pixels — averages out over frames. Under a rasterization rate map the reprojection goes physical → screen → world → previous screen → previous physical through both frames' maps. Camera motion is handled; moving objects rely on the clip. Kernels rebuilt for every platform. --- Sources/CShaderTypes/ShaderTypes.h | 32 +++ .../Renderer/Pipelines/RenderPipeLines.swift | 15 + .../Pipelines/RenderPipelineType.swift | 1 + .../Renderer/RenderInitializer.swift | 4 +- .../Renderer/TemporalAntiAliasing.swift | 258 ++++++++++++++++++ .../UntoldEngine/Renderer/UntoldEngine.swift | 2 + .../UntoldEngine/Renderer/XRFoveation.swift | 2 +- .../UntoldEngine/Scenes/SceneSerializer.swift | 10 + Sources/UntoldEngine/Shaders/TAAShader.metal | 157 +++++++++++ .../Systems/RenderingSystem.swift | 9 + .../UntoldEngineKernels-ios.metallib | Bin 787304 -> 798780 bytes .../UntoldEngineKernels-iossim.metallib | Bin 790680 -> 802220 bytes .../UntoldEngineKernels-tvos.metallib | Bin 787608 -> 799084 bytes .../UntoldEngineKernels-tvossim.metallib | Bin 790936 -> 802476 bytes .../UntoldEngineKernels-xros.metallib | Bin 788200 -> 799692 bytes .../UntoldEngineKernels-xrossim.metallib | Bin 791400 -> 802940 bytes .../UntoldEngineKernels.metal | 1 + .../UntoldEngineKernels.metallib | Bin 785752 -> 797260 bytes Sources/UntoldEngine/Utils/Globals.swift | 9 +- .../RenderGraphBuilderTest.swift | 2 +- .../TemporalAntiAliasingTests.swift | 146 ++++++++++ docs/API/UsingEngineAPI.md | 3 + docs/Architecture/renderingSystem.md | 5 +- 23 files changed, 650 insertions(+), 6 deletions(-) create mode 100644 Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift create mode 100644 Sources/UntoldEngine/Shaders/TAAShader.metal create mode 100644 Tests/UntoldEngineRenderTests/TemporalAntiAliasingTests.swift diff --git a/Sources/CShaderTypes/ShaderTypes.h b/Sources/CShaderTypes/ShaderTypes.h index 40bcd4b90..64900862a 100644 --- a/Sources/CShaderTypes/ShaderTypes.h +++ b/Sources/CShaderTypes/ShaderTypes.h @@ -1363,6 +1363,38 @@ typedef enum{ fxaaPassSplatCoverageTextureIndex = 1 }FXAATextureIndices; +// MARK: - Temporal anti-aliasing (TAAShader.metal) + +/// The resolve's inputs: the eye's unjittered matrices for this frame and the frame its +/// history holds, and the rasterization rate maps of both when the frames were foveated +/// (XR): the history is laid out in its own frame's physical space, so a pixel goes +/// physical → screen → world → previous screen → previous physical before the history is read. +typedef struct { + matrix_float4x4 invViewProjection; // this frame, unjittered, scene root included + matrix_float4x4 prevViewProjection; // the history's frame, unjittered, scene root included + simd_float4 rateMapSizes; // this frame's map: screen size xy, physical size zw; x <= 0 when drawn uniformly + simd_float4 prevRateMapSizes; // the history frame's map, same layout + simd_float2 physicalSize; // the colour, depth and history textures' size in pixels + float historyWeight; // share of the clipped history in the output (0.9) + uint32_t historyValid; // 0 on the first frame, after a resize or a mode change: the output is the current frame + uint32_t reverseZ; + uint32_t pad0; + uint32_t pad1; + uint32_t pad2; +} TAAConstants; // 176 bytes + +typedef enum{ + taaPassConstantsIndex = 0, // TAAConstants + taaPassRateMapDataIndex, // rasterization_rate_map_data of this frame (read only when rateMapSizes.x > 0; a placeholder otherwise) + taaPassPrevRateMapDataIndex // rasterization_rate_map_data of the history's frame (read only when prevRateMapSizes.x > 0) +}TAABufferIndices; + +typedef enum{ + taaPassColorTextureIndex = 0, // this frame's look output + taaPassHistoryTextureIndex, // the previous resolve of this eye + taaPassDepthTextureIndex // this frame's opaque depth +}TAATextureIndices; + typedef enum{ smaaPassTexelSizeIndex, smaaPassEdgeThresholdIndex, diff --git a/Sources/UntoldEngine/Renderer/Pipelines/RenderPipeLines.swift b/Sources/UntoldEngine/Renderer/Pipelines/RenderPipeLines.swift index 7fc744d59..2a7b78b46 100644 --- a/Sources/UntoldEngine/Renderer/Pipelines/RenderPipeLines.swift +++ b/Sources/UntoldEngine/Renderer/Pipelines/RenderPipeLines.swift @@ -963,6 +963,20 @@ public func InitFXAAPipeline() -> RenderPipeline? { ) } +/// The temporal resolve: the look output and the eye's history into the anti-aliasing +/// texture and the eye's next history, two colour targets of the look format. +public func InitTAAPipeline() -> RenderPipeline? { + CreatePipeline( + vertexShader: "vertexTAAShader", + fragmentShader: "fragmentTAAShader", + vertexDescriptor: createPostProcessVertexDescriptor(), + colorFormats: [renderInfo.colorPipeline.working.lookOutput, renderInfo.colorPipeline.working.lookOutput], + depthFormat: .invalid, + depthEnabled: false, + name: "TAA Pipeline" + ) +} + public func InitFXAAEdgeDebugPipeline() -> RenderPipeline? { CreatePipeline( vertexShader: "vertexFXAAShader", @@ -1176,6 +1190,7 @@ public func DefaultPipeLines() -> [(RenderPipelineType, RenderPipelineInitBlock) (.look, InitLookPipeline), (.fxaa, InitFXAAPipeline), (.fxaaEdgeDebug, InitFXAAEdgeDebugPipeline), + (.taa, InitTAAPipeline), (.smaaEdges, InitSMAAEdgesPipeline), (.smaaBlendWeights, InitSMAABlendWeightsPipeline), (.smaaNeighborhood, InitSMAANeighborhoodPipeline), diff --git a/Sources/UntoldEngine/Renderer/Pipelines/RenderPipelineType.swift b/Sources/UntoldEngine/Renderer/Pipelines/RenderPipelineType.swift index 0d935727f..809870e47 100644 --- a/Sources/UntoldEngine/Renderer/Pipelines/RenderPipelineType.swift +++ b/Sources/UntoldEngine/Renderer/Pipelines/RenderPipelineType.swift @@ -57,6 +57,7 @@ public extension RenderPipelineType { static let outputTransform: RenderPipelineType = "outputTransform" static let fxaa: RenderPipelineType = "fxaa" static let fxaaEdgeDebug: RenderPipelineType = "fxaaEdgeDebug" + static let taa: RenderPipelineType = "taa" static let smaaEdges: RenderPipelineType = "smaaEdges" static let smaaBlendWeights: RenderPipelineType = "smaaBlendWeights" static let smaaNeighborhood: RenderPipelineType = "smaaNeighborhood" diff --git a/Sources/UntoldEngine/Renderer/RenderInitializer.swift b/Sources/UntoldEngine/Renderer/RenderInitializer.swift index b7e38243d..e831ee3e0 100644 --- a/Sources/UntoldEngine/Renderer/RenderInitializer.swift +++ b/Sources/UntoldEngine/Renderer/RenderInitializer.swift @@ -118,11 +118,11 @@ func requestedOpaqueSampleCount() -> Int { return 1 #else switch antiAliasingMode { - case .msaa: + case .msaa, .msaaTaa: let preferredSampleCount = 4 guard let device = renderInfo.device else { return 1 } return device.supportsTextureSampleCount(preferredSampleCount) ? preferredSampleCount : 1 - case .none, .fxaa, .smaa: + case .none, .fxaa, .smaa, .taa: return 1 } #endif diff --git a/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift new file mode 100644 index 000000000..382895d51 --- /dev/null +++ b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift @@ -0,0 +1,258 @@ +// +// TemporalAntiAliasing.swift +// UntoldEngine +// +// Temporal anti-aliasing: the projection is jittered by a sub-pixel amount each frame, and +// the resolve pass after the look pass blends the frame with the eye's reprojected, clipped +// history (TAAShader.metal). Sub-pixel detail a single sample flickers on — thin wires, fine +// normal maps, the periphery of a foveated frame where a pixel spans several screen pixels — +// averages out over frames. The reprojection follows the camera through the depth buffer; +// what moves on its own is covered by the neighbourhood clip, not by motion vectors. +// +// State is per eye (XR renders the two eyes through the same passes): a history texture +// ping-pong, the unjittered view-projection of the frame the history holds, and that frame's +// rasterization rate map when it was foveated — the history is laid out in that map's +// physical space, so the resolve maps through both frames' maps. +// +// Copyright (C) Untold Engine Studios +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +import CShaderTypes +import Metal +import simd + +/// Tunables of the temporal resolve. +public final class TAAParams: @unchecked Sendable { + public static let shared = TAAParams() + private let lock = NSLock() + private var historyWeightValue: Float = 0.9 + + /// The share of the (clipped) history in each resolved pixel: higher converges further + /// and reacts slower. Clamped to [0, 0.98]; the default is 0.9. + public var historyWeight: Float { + get { lock.withLock { historyWeightValue } } + set { lock.withLock { historyWeightValue = min(max(newValue, 0), 0.98) } } + } +} + +/// Sub-pixel offsets, in pixels, of the Halton (2, 3) sequence centred on the pixel: eight +/// of them, so the average over a short window sits at the pixel centre. +let taaJitterSequence: [simd_float2] = (1 ... 8).map { index in + func halton(_ index: Int, _ base: Int) -> Float { + var result: Float = 0 + var fraction: Float = 1 + var i = index + while i > 0 { + fraction /= Float(base) + result += fraction * Float(i % base) + i /= base + } + return result + } + return simd_float2(halton(index, 2) - 0.5, halton(index, 3) - 0.5) +} + +/// Whether a mode runs the temporal resolve. +extension AntiAliasingMode { + var isTemporal: Bool { + switch self { + case .taa, .msaaTaa: + return true + case .none, .fxaa, .smaa, .msaa: + return false + } + } +} + +final class TemporalAntiAliasing: @unchecked Sendable { + static let shared = TemporalAntiAliasing() + + /// What one eye carries from frame to frame. + struct EyeHistory { + var textures: [MTLTexture] = [] + var readIndex = 0 + var viewProjection = matrix_identity_float4x4 + var rateMapData: XRRasterizationRateMapData? + var valid = false + } + + private(set) var eyes: [EyeHistory] = [EyeHistory(), EyeHistory()] + private var jitterIndex = 0 + /// The jitter currently added to `renderInfo.perspectiveSpace`, in NDC, so it can be + /// taken out before the next one goes in (the macOS projection persists across frames). + private(set) var appliedJitter = simd_float2.zero + /// The jitter of this frame in pixels of the screen, for diagnostics and tests. + private(set) var currentJitterPixels = simd_float2.zero + + private var eyeIndex: Int { + renderInfo.isXRStereoMode ? min(max(renderInfo.currentEye, 0), 1) : 0 + } + + /// The projection was set afresh (a resize, a new eye): nothing of the old jitter is in it. + func projectionDidChange() { + appliedJitter = .zero + } + + /// Before a frame's graph is built: takes last frame's jitter out of the projection and + /// puts this frame's in — or just takes it out when the mode is not temporal. The offset + /// lives in the projection's third column: for a perspective projection, whose clip w is + /// the view-space depth, it shifts every point by a constant amount in NDC. + func applyJitter() { + var projection = renderInfo.perspectiveSpace + projection.columns.2.x -= appliedJitter.x + projection.columns.2.y -= appliedJitter.y + appliedJitter = .zero + currentJitterPixels = .zero + + if antiAliasingMode.isTemporal, let screen = screenSize(), screen.x > 0, screen.y > 0 { + let pixels = taaJitterSequence[jitterIndex % taaJitterSequence.count] + jitterIndex += 1 + let ndc = simd_float2(2 * pixels.x / screen.x, 2 * pixels.y / screen.y) + projection.columns.2.x += ndc.x + projection.columns.2.y += ndc.y + appliedJitter = ndc + currentJitterPixels = pixels + } + renderInfo.perspectiveSpace = projection + } + + /// The size of the screen the projection maps to: the rate map's under foveation, the + /// textures' otherwise. + private func screenSize() -> simd_float2? { + if let foveation = renderInfo.xrFoveation { + return foveation.screenSize + } + return renderInfo.viewPort + } + + /// This frame's projection without its jitter. + var unjitteredProjection: simd_float4x4 { + var projection = renderInfo.perspectiveSpace + projection.columns.2.x -= appliedJitter.x + projection.columns.2.y -= appliedJitter.y + return projection + } + + /// Forgets every eye's history: the next resolve of each eye outputs its frame as is. + func invalidateHistory() { + for index in eyes.indices { + eyes[index].valid = false + } + } + + /// The eye's history textures at the current viewport, made or remade when needed (a + /// remake invalidates the history). + private func historyTextures(for eye: Int) -> [MTLTexture]? { + let width = max(1, Int(renderInfo.viewPort.x)) + let height = max(1, Int(renderInfo.viewPort.y)) + if eyes[eye].textures.count == 2, eyes[eye].textures[0].width == width, eyes[eye].textures[0].height == height { + return eyes[eye].textures + } + guard let device = renderInfo.device else { return nil } + var textures: [MTLTexture] = [] + for slot in 0 ..< 2 { + guard let texture = createTexture( + device: device, + label: "TAA History Eye \(eye) \(slot)", + pixelFormat: renderInfo.colorPipeline.working.lookOutput, + width: width, + height: height, + usage: [.shaderRead, .renderTarget], + storageMode: .private + ) else { return nil } + textures.append(texture) + } + eyes[eye].textures = textures + eyes[eye].readIndex = 0 + eyes[eye].valid = false + return textures + } + + /// The resolve: the look output and the eye's history into the anti-aliasing texture and + /// the eye's other history texture, then the frame's matrices and map become the history's. + func encodeResolve(_ commandBuffer: MTLCommandBuffer) { + guard let source = textureResources.lookTexture, + let destination = textureResources.antiAliasingTexture, + let depth = textureResources.depthMap, + let pipeline = PipelineManager.shared.renderPipelinesByType[.taa], + pipeline.success, + let pipelineState = pipeline.pipelineState, + let camera = CameraSystem.shared.activeCamera, + let cameraComponent = scene.get(component: CameraComponent.self, for: camera) + else { + handleError(.renderPassCreationFailed, "TAA Pass: missing texture, pipeline or camera") + return + } + let eye = eyeIndex + guard let textures = historyTextures(for: eye) else { + handleError(.renderPassCreationFailed, "TAA Pass: history textures") + return + } + let readTexture = textures[eyes[eye].readIndex] + let writeTexture = textures[1 - eyes[eye].readIndex] + + let view = SceneRootTransform.shared.effectiveViewMatrix(cameraComponent.viewSpace) + let viewProjection = simd_mul(unjitteredProjection, view) + let currentRateMap = renderInfo.xrFoveation?.rateMapData + var constants = TAAConstants() + constants.invViewProjection = simd_inverse(viewProjection) + constants.prevViewProjection = eyes[eye].viewProjection + constants.rateMapSizes = rateMapSizes(currentRateMap) + constants.prevRateMapSizes = rateMapSizes(eyes[eye].rateMapData) + constants.physicalSize = simd_float2(Float(source.width), Float(source.height)) + constants.historyWeight = TAAParams.shared.historyWeight + constants.historyValid = eyes[eye].valid ? 1 : 0 + constants.reverseZ = renderInfo.reverseZEnabled ? 1 : 0 + + let descriptor = MTLRenderPassDescriptor() + descriptor.colorAttachments[0].texture = destination + descriptor.colorAttachments[0].loadAction = .dontCare + descriptor.colorAttachments[0].storeAction = .store + descriptor.colorAttachments[1].texture = writeTexture + descriptor.colorAttachments[1].loadAction = .dontCare + descriptor.colorAttachments[1].storeAction = .store + + guard let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { + handleError(.renderPassCreationFailed, "TAA Pass") + return + } + encoder.label = "TAA Pass" + encoder.pushDebugGroup("TAA Pass") + encoder.setRenderPipelineState(pipelineState) + encoder.waitForFence(renderInfo.fence, before: .fragment) + encoder.setVertexBuffer(bufferResources.quadVerticesBuffer, offset: 0, index: 0) + encoder.setVertexBuffer(bufferResources.quadTexCoordsBuffer, offset: 0, index: 1) + encoder.setFragmentTexture(source, index: Int(taaPassColorTextureIndex.rawValue)) + encoder.setFragmentTexture(readTexture, index: Int(taaPassHistoryTextureIndex.rawValue)) + encoder.setFragmentTexture(depth, index: Int(taaPassDepthTextureIndex.rawValue)) + encoder.setFragmentBytes(&constants, length: MemoryLayout.stride, index: Int(taaPassConstantsIndex.rawValue)) + // The maps' sizes are in the constants; the shader reads a map's parameters only when + // its sizes say there is one, so a placeholder stands in for a uniform frame. + let placeholder = rateMapPlaceholderBuffer() + encoder.setFragmentBuffer(currentRateMap?.buffer ?? placeholder, offset: 0, index: Int(taaPassRateMapDataIndex.rawValue)) + encoder.setFragmentBuffer(eyes[eye].rateMapData?.buffer ?? placeholder, offset: 0, index: Int(taaPassPrevRateMapDataIndex.rawValue)) + encoder.drawIndexedPrimitivesTracked( + type: .triangle, + indexCount: 6, + indexType: .uint16, + indexBuffer: bufferResources.quadIndexBuffer!, + indexBufferOffset: 0 + ) + encoder.updateFence(renderInfo.fence, after: .fragment) + encoder.popDebugGroup() + encoder.endEncoding() + + eyes[eye].readIndex = 1 - eyes[eye].readIndex + eyes[eye].viewProjection = viewProjection + eyes[eye].rateMapData = currentRateMap + eyes[eye].valid = true + } +} + +/// The graph's temporal resolve pass, in the slot FXAA or SMAA otherwise take. +let taaRenderPass: RenderPasses.RenderPassExecution = { commandBuffer in + TemporalAntiAliasing.shared.encodeResolve(commandBuffer) +} diff --git a/Sources/UntoldEngine/Renderer/UntoldEngine.swift b/Sources/UntoldEngine/Renderer/UntoldEngine.swift index df278b6fa..6028b5519 100644 --- a/Sources/UntoldEngine/Renderer/UntoldEngine.swift +++ b/Sources/UntoldEngine/Renderer/UntoldEngine.swift @@ -727,6 +727,7 @@ public class UntoldRenderer: NSObject, MTKViewDelegate { : matrixPerspectiveRightHand(fovyRadians: degreesToRadians(degrees: fov), aspectRatio: aspect, nearZ: near, farZ: far) renderInfo.perspectiveSpace = projectionMatrix + TemporalAntiAliasing.shared.projectionDidChange() let viewPortSize: simd_float2 = simd_make_float2(Float(size.width), Float(size.height)) renderInfo.viewPort = viewPortSize @@ -830,6 +831,7 @@ public class UntoldRenderer: NSObject, MTKViewDelegate { eyeIndex: Int ) { renderInfo.perspectiveSpace = projectionMatrix + TemporalAntiAliasing.shared.projectionDidChange() guard let camera = CameraSystem.shared.activeCamera, let cameraComponent = scene.get(component: CameraComponent.self, for: camera) else { handleError(.noActiveCamera) diff --git a/Sources/UntoldEngine/Renderer/XRFoveation.swift b/Sources/UntoldEngine/Renderer/XRFoveation.swift index ee345707d..1ce4ebde4 100644 --- a/Sources/UntoldEngine/Renderer/XRFoveation.swift +++ b/Sources/UntoldEngine/Renderer/XRFoveation.swift @@ -170,7 +170,7 @@ func bindRateMap(_ data: XRRasterizationRateMapData?, toFragmentsOf encoder: MTL } /// A small shared buffer bound wherever a shader declares a rate map it will not read. -private func rateMapPlaceholderBuffer() -> MTLBuffer? { +func rateMapPlaceholderBuffer() -> MTLBuffer? { if let buffer = bufferResources.rateMapPlaceholder { return buffer } diff --git a/Sources/UntoldEngine/Scenes/SceneSerializer.swift b/Sources/UntoldEngine/Scenes/SceneSerializer.swift index 53e026d6a..a64765261 100644 --- a/Sources/UntoldEngine/Scenes/SceneSerializer.swift +++ b/Sources/UntoldEngine/Scenes/SceneSerializer.swift @@ -117,6 +117,8 @@ enum AntiAliasingModeData: String, Codable { case fxaa case smaa case msaa + case taa + case msaaTaa } struct FXAAData: Codable { @@ -1384,6 +1386,10 @@ public func serializeScene() -> SceneData { antiAliasingModeData = .smaa case .msaa: antiAliasingModeData = .msaa + case .taa: + antiAliasingModeData = .taa + case .msaaTaa: + antiAliasingModeData = .msaaTaa } sceneData.antiAliasing = AntiAliasingData( mode: antiAliasingModeData, @@ -1696,6 +1702,10 @@ public func deserializeScene( antiAliasingMode = .smaa case .msaa: antiAliasingMode = .msaa + case .taa: + antiAliasingMode = .taa + case .msaaTaa: + antiAliasingMode = .msaaTaa } FXAAParams.shared.subpixelQuality = antiAliasing.fxaa.subpixelQuality diff --git a/Sources/UntoldEngine/Shaders/TAAShader.metal b/Sources/UntoldEngine/Shaders/TAAShader.metal new file mode 100644 index 000000000..3ab536515 --- /dev/null +++ b/Sources/UntoldEngine/Shaders/TAAShader.metal @@ -0,0 +1,157 @@ +// +// TAAShader.metal +// UntoldEngine +// +// Temporal anti-aliasing resolve. The frame was drawn with the projection jittered by a +// sub-pixel amount (TemporalAntiAliasing.swift); this pass blends the jittered frame with the +// eye's history, reprojected through the depth buffer and the two frames' unjittered +// view-projections, after clipping the history to the colour range of the pixel's 3×3 +// neighbourhood so that what moved or was uncovered does not ghost. Over frames the jitter +// averages sub-pixel detail — thin wires, fine normal maps — that a single sample flickers on. +// +// Under a rasterization rate map (XR foveation) the colour, depth and history textures are in +// physical space, not the screen the geometry was projected to, and each frame's map differs: +// a pixel is mapped physical → screen (this frame's map) → world → screen (previous frame, +// previous matrices) → physical (the history frame's map) before the history is sampled. +// +// Copyright (C) Untold Engine Studios +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include +#include "../../CShaderTypes/ShaderTypes.h" +#include "ShaderStructs.h" +using namespace metal; + +vertex VertexCompositeOutput vertexTAAShader(VertexCompositeIn in [[stage_in]]) { + VertexCompositeOutput out; + out.position = float4(float3(in.position), 1.0); + out.uvCoords = in.uvCoords; + return out; +} + +struct TAAFragmentOut { + float4 color [[color(0)]]; + float4 history [[color(1)]]; +}; + +// Luma-chroma space for the neighbourhood clip: a box in YCoCg hugs the local colours more +// tightly than one in RGB, so less ghosting gets through on moving edges. +static inline float3 taaRGBToYCoCg(float3 c) { + return float3(0.25 * c.r + 0.5 * c.g + 0.25 * c.b, + 0.5 * c.r - 0.5 * c.b, + -0.25 * c.r + 0.5 * c.g - 0.25 * c.b); +} + +static inline float3 taaYCoCgToRGB(float3 c) { + return float3(c.x + c.y - c.z, c.x + c.z, c.x - c.y - c.z); +} + +// Moves `history` towards `current` until it lies inside the box [lo, hi]: the direction the +// history came from is kept, only its distance is cut, which avoids the colour shifts a plain +// clamp introduces (Karis 2014). +static inline float3 taaClipToBox(float3 lo, float3 hi, float3 current, float3 history) { + const float3 center = 0.5 * (hi + lo); + const float3 extent = 0.5 * (hi - lo) + 1e-4; + const float3 offset = history - center; + const float3 unit = abs(offset / extent); + const float maxUnit = max(unit.x, max(unit.y, unit.z)); + return maxUnit > 1.0 ? center + offset / maxUnit : history; +} + +// Where a texel of this frame's textures sits on the screen, in pixels. +static inline float2 taaScreenFromPhysical(float2 physical, float4 sizes, constant rasterization_rate_map_data *rateMap) { + if (sizes.x <= 0.0) { + return physical; + } + rasterization_rate_map_decoder decoder(*rateMap); + return decoder.map_physical_to_screen_coordinates(physical); +} + +// Where a screen position of the history's frame sits in the history texture, in pixels. +static inline float2 taaPhysicalFromScreen(float2 screen, float4 sizes, constant rasterization_rate_map_data *rateMap) { + if (sizes.x <= 0.0) { + return screen; + } + rasterization_rate_map_decoder decoder(*rateMap); + return decoder.map_screen_to_physical_coordinates(screen); +} + +fragment TAAFragmentOut fragmentTAAShader( + VertexCompositeOutput in [[stage_in]], + texture2d colorTexture [[texture(taaPassColorTextureIndex)]], + texture2d historyTexture [[texture(taaPassHistoryTextureIndex)]], + depth2d depthTexture [[texture(taaPassDepthTextureIndex)]], + constant TAAConstants &taa [[buffer(taaPassConstantsIndex)]], + constant rasterization_rate_map_data *rateMap [[buffer(taaPassRateMapDataIndex)]], + constant rasterization_rate_map_data *prevRateMap [[buffer(taaPassPrevRateMapDataIndex)]] +) { + constexpr sampler linearSampler(min_filter::linear, mag_filter::linear, mip_filter::none, address::clamp_to_edge); + constexpr sampler pointSampler(min_filter::nearest, mag_filter::nearest, mip_filter::none, address::clamp_to_edge); + + const float2 uv = in.uvCoords; + const float2 texel = 1.0 / max(taa.physicalSize, float2(1.0)); + const float4 current = colorTexture.sample(pointSampler, uv); + + TAAFragmentOut out; + if (taa.historyValid == 0u) { + out.color = current; + out.history = current; + return out; + } + + // The colour range of the 3×3 neighbourhood, in YCoCg. + float3 lo = float3(1e9); + float3 hi = float3(-1e9); + for (int y = -1; y <= 1; ++y) { + for (int x = -1; x <= 1; ++x) { + const float3 c = taaRGBToYCoCg(colorTexture.sample(pointSampler, uv + float2(x, y) * texel).rgb); + lo = min(lo, c); + hi = max(hi, c); + } + } + + // This pixel's position in space, from its depth. A background texel (the clear value) + // is pushed just off the clear plane so an infinite-far projection still inverts. + float depth = depthTexture.sample(pointSampler, uv); + depth = (taa.reverseZ != 0u) ? max(depth, 1e-5) : min(depth, 1.0 - 1e-5); + const float2 physical = in.position.xy; + const float2 screen = taaScreenFromPhysical(physical, taa.rateMapSizes, rateMap); + const float2 screenSize = taa.rateMapSizes.x > 0.0 ? taa.rateMapSizes.xy : taa.physicalSize; + const float2 ndc = float2(screen.x / screenSize.x * 2.0 - 1.0, 1.0 - screen.y / screenSize.y * 2.0); + float4 world = taa.invViewProjection * float4(ndc, depth, 1.0); + if (abs(world.w) < 1e-12) { + out.color = current; + out.history = current; + return out; + } + world /= world.w; + + // Where it was on the previous frame's screen, then in the history texture. + const float4 prevClip = taa.prevViewProjection * world; + if (prevClip.w <= 0.0) { + out.color = current; + out.history = current; + return out; + } + const float2 prevNdc = prevClip.xy / prevClip.w; + const float2 prevScreenSize = taa.prevRateMapSizes.x > 0.0 ? taa.prevRateMapSizes.xy : taa.physicalSize; + const float2 prevScreen = float2((prevNdc.x * 0.5 + 0.5) * prevScreenSize.x, (1.0 - (prevNdc.y * 0.5 + 0.5)) * prevScreenSize.y); + const float2 prevPhysical = taaPhysicalFromScreen(prevScreen, taa.prevRateMapSizes, prevRateMap); + const float2 historyUV = prevPhysical * texel; + if (any(historyUV < 0.0) || any(historyUV > 1.0)) { + out.color = current; + out.history = current; + return out; + } + + const float4 history = historyTexture.sample(linearSampler, historyUV); + const float3 clipped = taaYCoCgToRGB(taaClipToBox(lo, hi, taaRGBToYCoCg(current.rgb), taaRGBToYCoCg(history.rgb))); + const float3 blended = mix(current.rgb, clipped, taa.historyWeight); + const float alpha = mix(current.a, history.a, taa.historyWeight); + out.color = float4(blended, alpha); + out.history = out.color; + return out; +} diff --git a/Sources/UntoldEngine/Systems/RenderingSystem.swift b/Sources/UntoldEngine/Systems/RenderingSystem.swift index 8d121dfc6..c3cf56889 100644 --- a/Sources/UntoldEngine/Systems/RenderingSystem.swift +++ b/Sources/UntoldEngine/Systems/RenderingSystem.swift @@ -94,6 +94,8 @@ func UpdateRenderingSystem(in view: MTKView) { commandBuffer.label = "Rendering Command Buffer" do { + // This frame's sub-pixel jitter (temporal anti-aliasing), before anything reads the projection. + TemporalAntiAliasing.shared.applyJitter() let graph = try buildExecutableGameModeGraph() #if ENGINE_STATS_ENABLED @@ -168,6 +170,8 @@ func UpdateXRRenderingSystem(commandBuffer: MTLCommandBuffer, passDescriptor: MT commandBuffer.label = "XR Rendering Command Buffer" do { + // This eye's sub-pixel jitter (temporal anti-aliasing), before anything reads the projection. + TemporalAntiAliasing.shared.applyJitter() let graph = try buildExecutableGameModeGraph() // The eye's rasterization rate map (visionOS foveation) on the passes that draw the @@ -260,6 +264,7 @@ let gameModeReservedPassIDs: Set = [ "look", "fxaa", "fxaaEdgeDebug", + "taa", "smaaEdges", "smaaBlendWeights", "smaaNeighborhood", @@ -530,6 +535,10 @@ private func buildGameModeGraphWithCompilation() throws -> CompiledRenderGraphRe let fxaaPass = RenderPass(id: "fxaa", dependencies: [lookPass.id], execute: fxaaRenderPass) builder.addPass(fxaaPass) outputDependency = fxaaPass.id + case .taa, .msaaTaa: + let taaPass = RenderPass(id: "taa", dependencies: [lookPass.id], execute: taaRenderPass) + builder.addPass(taaPass) + outputDependency = taaPass.id case .smaa: let smaaEdgesPass = RenderPass(id: "smaaEdges", dependencies: [lookPass.id], execute: smaaEdgesRenderPass) builder.addPass(smaaEdgesPass) diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib index a8f903cb37d0370cca3cf66e03023bfa01625a5f..c0ddbef697ca02b0caabb00b6f5fde00066f82a7 100644 GIT binary patch delta 6447 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 diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-iossim.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-iossim.metallib index 45a8b9c159b278b9d090fa299b56b58dfeb09a61..fdad47de73f9bc140fa1d292fa69ac416a8d25bc 100644 GIT binary patch delta 6450 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 P=Um$rm(G@|CSUzu?>leJ delta 1627 zcmY+^Urbw790%~*Zo=)oOIFTN2M^1@#lbBdl<|M#Pg`N4X=fMiwi1WyG>b6Bm1OF4 zfi*ex2NRf}#U-+3Syr={uxKKS4-VZ!O-uw$w9|)ae9*%=-y36-bI;B1 z^ZlKB@40Q~{|-#e1bU)&B<#}MTA`+m6lt0^<=rBVniiKwP5Zh-om6+KxyDd);t4gc zZBlbrx0++uOnEZ2*wa={ryll_zrv>9%YAgQ;uJe0F0=9Ja;rJhOd($}y=od1wGOcq zI0jBUD)~T(m+n~I>=SStJbpy*i)JeDu~XFTGqDVg0(gW)iW| zQMvfBHiPa}_R@_?9}WATBHQnE2WA94MBd%q>=wF4(Ura`yMA>Uv~{0OAMB2?RYb-S zNv@KsYKZ-S@|4s0lk7ZDV$i2mJ!~DE2IuZcesYIF?bS!wUGOY8P(TxVis_5$7wC>( zH!>)vELrXiJkMMn^?a8>nNCT61Wq##C<{uTkYseQ$#t)8(#JJnR)owlGQo2q<0Jo` zZdL+XaoQIJ4Y4wmZ=;;QE>~4gpwr{EHnR}PA(Hy$f06G*qy~{SXYn-|8TKNTty9tVZIr9)=ONgijy^F0L@^tg_XVyLl))$p3<6V8LC= z^5Ns$g+I*8uw=cmvyYtM9#|HZ4=FP`j`1ScGAtW&jM0Z3QCB39jN9PJ&pSDM)ZI>8sF*b>@S&aLZ grtN~acaF@SFA$?p3|$P*((HL7_si1qnEB(vzgj^_Gynhq diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-tvos.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-tvos.metallib index fb5072e2b7e418afa548f89a32d7cb69e507f5cf..9119a8f04ee85b23b849aec3ae5d542ac1e75189 100644 GIT binary patch delta 6456 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 ds!;A)eJXk#sR%v+N9J9vS+8PV{VzZ5a}fXl delta 1626 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 A{r~^~ delta 1627 zcmY+^ZD?Cn7zgl^c583$6->@S+kO~JeQR=?wdq>>vh^j6?TDJxTY9&pxVjAA)@|Lo zv9aoC2})T-#MI|QD;CWVq19Tu4b}-F5fxSt>_Bjv`w+jiD4OX9w+{nv&-q`(z`5u0 z{Ql3m_nw<%@qT3XK3&J2b$*0H?swl*4EEO_b9p=Z2kfkcwuKu9zmh{e+Ls)+YF{rmi`P*xHm_ z{9va}|I`lAx3wlsgkK;#>?nqvyhexLecWd;~4vXJJB#TJo z7J2H%`L8I?qMTlroqbh0U8)=88{ix`cUSWB+jZ)yKfv#R=fTA?n%-GS-`5|f+hI*# zMmcKA@=)X$_juLwT?LKqk@R=uH1~q?p!6$}^d3I5;MWXVYKU<^GS`q{87E^>c;^7G z0FPsUeUZy^uslHv0b_Qau=E{`mj+m zeDFx0@<&@n#3A%nx@*6vQFUX8erU19Ff0Jeoz9( zlz1O*!IvLWzWIyzVE2%?08hcKpz>m;m>HYbAEsy9V`2fJv>R&C`S`bqm7P)_y#rxi=1+A>{YP}%fO=K-qcZX9X18aEh;NCahmDcPw%vA zde-gx?!D+6w5>xkW>LxirqYYi!}PgR&!L`ShJ2!*yKQj?SD1HK@fmVU_r^|&d$46# zphj6Sc1U>euXz<_H7h&!)XTyP%fkvWWqQv+;fGy=<@;UZ^hr-rRKeHa#iNGY#k$^v zsD|BuWiqOFb2qN^?iV3=0nR>?ez|4O>GI3JBp1rwoU_l**&b(}v#XK2pwuEZzx!0#*bS!2u6zd%$$zyJUM diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xros.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xros.metallib index fc1714a18bb795aaf0ad17f6d256825ed738bc7c..6f8e3281883ba5811e6e4225068acfd2a0f31446 100644 GIT binary patch delta 6504 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 delta 1636 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 diff --git a/Sources/UntoldEngine/Utils/Globals.swift b/Sources/UntoldEngine/Utils/Globals.swift index 1e5b0c5cf..19fbe4bb7 100644 --- a/Sources/UntoldEngine/Utils/Globals.swift +++ b/Sources/UntoldEngine/Utils/Globals.swift @@ -2121,10 +2121,17 @@ public enum AntiAliasingMode: Sendable { case fxaa case smaa case msaa + /// Temporal: the projection jittered by a sub-pixel amount each frame and the frame + /// blended with its reprojected history after the look pass (TemporalAntiAliasing.swift). + /// Averages the sub-pixel detail a single sample flickers on; moving objects rely on the + /// neighbourhood clip, not on motion vectors. + case taa + /// 4× MSAA on the G-buffer and the temporal resolve on top. + case msaaTaa var usesPostLookPass: Bool { switch self { - case .fxaa, .smaa: + case .fxaa, .smaa, .taa, .msaaTaa: return true case .none, .msaa: return false diff --git a/Tests/UntoldEngineRenderTests/RenderGraphBuilderTest.swift b/Tests/UntoldEngineRenderTests/RenderGraphBuilderTest.swift index 315dcf741..382ba9cd7 100644 --- a/Tests/UntoldEngineRenderTests/RenderGraphBuilderTest.swift +++ b/Tests/UntoldEngineRenderTests/RenderGraphBuilderTest.swift @@ -1530,7 +1530,7 @@ final class RenderGraphBuilderTest: BaseRenderSetup { for environmentEnabled in [false, true] { renderEnvironment = environmentEnabled - for mode in [AntiAliasingMode.none, .fxaa, .smaa, .msaa] { + for mode in [AntiAliasingMode.none, .fxaa, .smaa, .msaa, .taa, .msaaTaa] { antiAliasingMode = mode try captureGraphPassIDs() } diff --git a/Tests/UntoldEngineRenderTests/TemporalAntiAliasingTests.swift b/Tests/UntoldEngineRenderTests/TemporalAntiAliasingTests.swift new file mode 100644 index 000000000..695b0232a --- /dev/null +++ b/Tests/UntoldEngineRenderTests/TemporalAntiAliasingTests.swift @@ -0,0 +1,146 @@ +// +// TemporalAntiAliasingTests.swift +// UntoldEngine +// +// The temporal resolve (TemporalAntiAliasing.swift, TAAShader.metal): the jitter sequence, +// the jitter going into and out of the projection, and the resolve of a still scene settling +// to a stable image that stays close to the un-anti-aliased frame. +// +// Copyright (C) Untold Engine Studios +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +import simd +@testable import UntoldEngine +import XCTest + +@MainActor +final class TemporalAntiAliasingTests: BaseRenderSetup { + private var camera: EntityID = 0 + private var savedMode: AntiAliasingMode = .fxaa + + override func setUp() async throws { + try await super.setUp() + savedMode = antiAliasingMode + } + + override func tearDown() async throws { + antiAliasingMode = savedMode + TemporalAntiAliasing.shared.applyJitter() + TemporalAntiAliasing.shared.invalidateHistory() + destroyAllEntities() + try await super.tearDown() + } + + override func initializeAssets() { + camera = createEntity() + createGameCamera(entityId: camera) + CameraSystem.shared.activeCamera = camera + cameraLookAt(entityId: camera, eye: simd_float3(0, 1, 4), target: .zero, up: simd_float3(0, 1, 0)) + let box = createEntity() + setEntityMeshDirect(entityId: box, meshes: BasicPrimitives.createCube(extent: 1.0), assetName: "Box") + translateTo(entityId: box, position: simd_float3(0, 0.5, 0)) + let slab = createEntity() + setEntityMeshDirect(entityId: slab, meshes: BasicPrimitives.createCube(extent: 1.0), assetName: "Slab") + scaleTo(entityId: slab, scale: simd_float3(4, 0.05, 0.05)) + translateTo(entityId: slab, position: simd_float3(0, 1.6, -1)) + } + + // MARK: - Helpers + + private func drawFrame() { + renderer.draw(in: renderer.metalView) + renderInfo.lastCommandBuffer?.waitUntilCompleted() + } + + /// The anti-aliasing output as floats, RGBA per pixel. + private func readAntiAliasingOutput() throws -> [Float] { + let texture = try XCTUnwrap(textureResources.antiAliasingTexture) + XCTAssertEqual(texture.pixelFormat, .rgba16Float) + var halves = [UInt16](repeating: 0, count: texture.width * texture.height * 4) + halves.withUnsafeMutableBytes { bytes in + texture.getBytes(bytes.baseAddress!, bytesPerRow: texture.width * 8, from: MTLRegionMake2D(0, 0, texture.width, texture.height), mipmapLevel: 0) + } + return halves.map { Float(Float16(bitPattern: $0)) } + } + + private func meanAbsoluteDifference(_ a: [Float], _ b: [Float]) -> Float { + var total: Float = 0 + for i in 0 ..< min(a.count, b.count) { + total += abs(a[i] - b[i]) + } + return total / Float(max(1, min(a.count, b.count))) + } + + // MARK: - Tests + + func testJitterSequenceIsSubPixelAndCentred() { + XCTAssertEqual(taaJitterSequence.count, 8) + var mean = simd_float2.zero + for offset in taaJitterSequence { + XCTAssertLessThanOrEqual(abs(offset.x), 0.5) + XCTAssertLessThanOrEqual(abs(offset.y), 0.5) + mean += offset + } + mean /= Float(taaJitterSequence.count) + XCTAssertLessThan(abs(mean.x), 0.1, "the offsets average near the pixel centre") + XCTAssertLessThan(abs(mean.y), 0.1) + XCTAssertEqual(Set(taaJitterSequence.map { "\($0.x),\($0.y)" }).count, 8, "eight distinct offsets") + } + + func testJitterGoesIntoAndOutOfTheProjection() { + antiAliasingMode = .fxaa + TemporalAntiAliasing.shared.applyJitter() + let base = renderInfo.perspectiveSpace + + antiAliasingMode = .taa + TemporalAntiAliasing.shared.applyJitter() + let jittered = renderInfo.perspectiveSpace + let pixels = TemporalAntiAliasing.shared.currentJitterPixels + XCTAssertNotEqual(pixels, .zero) + XCTAssertEqual(jittered.columns.2.x - base.columns.2.x, 2 * pixels.x / renderInfo.viewPort.x, accuracy: 1e-6) + XCTAssertEqual(jittered.columns.2.y - base.columns.2.y, 2 * pixels.y / renderInfo.viewPort.y, accuracy: 1e-6) + XCTAssertEqual(jittered.columns.0, base.columns.0) + XCTAssertEqual(jittered.columns.1, base.columns.1) + XCTAssertEqual(jittered.columns.3, base.columns.3) + XCTAssertEqual(TemporalAntiAliasing.shared.unjitteredProjection, base, "the unjittered projection is the base one") + + TemporalAntiAliasing.shared.applyJitter() + XCTAssertNotEqual(renderInfo.perspectiveSpace.columns.2.x, jittered.columns.2.x, "the next frame takes the next offset, not a sum") + + antiAliasingMode = .fxaa + TemporalAntiAliasing.shared.applyJitter() + XCTAssertEqual(renderInfo.perspectiveSpace, base, "leaving the temporal mode leaves the projection as it was") + } + + func testResolveSettlesOnAStillSceneCloseToTheSingleSampleFrame() throws { + antiAliasingMode = .none + for _ in 0 ..< 2 { + drawFrame() + } + // The look output is what the output pass shows without a post-look pass. + let lookTexture = try XCTUnwrap(textureResources.lookTexture) + var reference = [UInt16](repeating: 0, count: lookTexture.width * lookTexture.height * 4) + reference.withUnsafeMutableBytes { bytes in + lookTexture.getBytes(bytes.baseAddress!, bytesPerRow: lookTexture.width * 8, from: MTLRegionMake2D(0, 0, lookTexture.width, lookTexture.height), mipmapLevel: 0) + } + let single = reference.map { Float(Float16(bitPattern: $0)) } + XCTAssertGreaterThan(single.max() ?? 0, 0.01, "the scene draws something") + + antiAliasingMode = .taa + TemporalAntiAliasing.shared.invalidateHistory() + for _ in 0 ..< 10 { + drawFrame() + } + let settled = try readAntiAliasingOutput() + drawFrame() + let next = try readAntiAliasingOutput() + + XCTAssertFalse(settled.contains { $0.isNaN || $0.isInfinite }, "no NaN or infinity in the resolve") + XCTAssertLessThan(meanAbsoluteDifference(settled, next), 0.004, "a still scene no longer changes between frames") + XCTAssertLessThan(meanAbsoluteDifference(settled, single), 0.02, "the resolve stays close to the single-sample frame: no drift, no smear") + XCTAssertGreaterThan(meanAbsoluteDifference(settled, single), 0, "and is not the single-sample frame") + } +} diff --git a/docs/API/UsingEngineAPI.md b/docs/API/UsingEngineAPI.md index 19b17b9c1..c50b7e613 100644 --- a/docs/API/UsingEngineAPI.md +++ b/docs/API/UsingEngineAPI.md @@ -18,7 +18,10 @@ Existing direct APIs such as `LODConfig.shared`, `SSAOParams.shared`, `antiAlias setRendering(.antiAliasing(.fxaa)) setRendering(.antiAliasing(.smaa)) setRendering(.antiAliasing(.msaa)) +setRendering(.antiAliasing(.taa)) // temporal: jittered frames blended with their reprojected history +setRendering(.antiAliasing(.msaaTaa)) // 4× MSAA on the G-buffer plus the temporal resolve setRendering(.antiAliasing(.none)) +TAAParams.shared.historyWeight = 0.9 // share of the history in each resolved pixel (0…0.98) setRendering(.debugView(.lit)) setRendering(.debugView(.depth)) diff --git a/docs/Architecture/renderingSystem.md b/docs/Architecture/renderingSystem.md index 9aac362fc..0bd58eaf7 100644 --- a/docs/Architecture/renderingSystem.md +++ b/docs/Architecture/renderingSystem.md @@ -332,10 +332,13 @@ After the look pass, the graph inserts an anti-aliasing pass whose topology depe |---|---|---| | `.fxaa` | `fxaa` | `look → fxaa → outputTransform` | | `.smaa` | `smaaEdges`, `smaaBlendWeights`, `smaaNeighborhood` | `look → smaaEdges → smaaBlendWeights → smaaNeighborhood → outputTransform` | -| `.none` | *(none)* | `look → outputTransform` | +| `.taa`, `.msaaTaa` | `taa` | `look → taa → outputTransform` (`.msaaTaa` also draws the G-buffer at 4 samples, like `.msaa`) | +| `.none`, `.msaa` | *(none)* | `look → outputTransform` | **FXAA** is a single-pass screen-space filter that attenuates aliased edges using local luma contrast. +**TAA** (temporal anti-aliasing, `TemporalAntiAliasing.swift`, `TAAShader.metal`) jitters the projection by a sub-pixel Halton offset before each frame's graph is built (`applyJitter`, in the projection's third column, so the offset is a constant NDC shift; the previous frame's offset is taken out first) and, after the look pass, blends the frame with the eye's history: each pixel is reprojected through the depth buffer and the unjittered view-projections of this frame and the history's, the history colour is clipped to the YCoCg box of the pixel's 3×3 neighbourhood (so what moved or was uncovered does not ghost), and the two are mixed with `TAAParams.shared.historyWeight` (0.9). The resolve writes the anti-aliasing texture and the eye's next history texture in one pass (two colour targets); the history is per eye, ping-ponged, and invalidated by a resize or a mode change. Under a foveated XR frame the textures are in physical space and each frame's rate map differs, so the reprojection goes physical → screen → world → previous screen → previous physical through both maps, and the jitter is measured in screen pixels. Camera motion is handled; objects moving on their own rely on the clip, since there are no motion vectors yet. + **SMAA** (Subpixel Morphological Anti-Aliasing) is a three-pass chain: 1. **Edge detection** (`smaaEdges`) — identifies aliased edges from the look texture using luma and chroma gradients. Also detects diagonal patterns. 2. **Blend-weight calculation** (`smaaBlendWeights`) — computes per-pixel blend weights from the SMAA area and search look-up textures, accounting for corner patterns. From 98763750619a79bafd233d97368a82a23ca392dc Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sat, 10 Oct 2026 23:08:58 +0200 Subject: [PATCH 05/10] [Patch] TAA: variance clipping and a history weight that follows the rate map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pixel-thin feature — a wire, a line of text — is rasterized in some jittered frames and not others, and a min/max box of a frame that missed it clipped it out of the history, so it flickered at distance; the clip box is now the 3×3 mean ± clipGamma (1.25) standard deviations. Under foveation a spot the gaze has just moved onto has a history from the periphery, coarser than the new frame, which showed as a shadow fading over twenty frames; the history's weight is cut by the ratio of the two maps' local rates. Kernels rebuilt. --- Sources/CShaderTypes/ShaderTypes.h | 2 +- .../Renderer/TemporalAntiAliasing.swift | 11 ++++++ Sources/UntoldEngine/Shaders/TAAShader.metal | 36 ++++++++++++++---- .../UntoldEngineKernels-ios.metallib | Bin 798780 -> 799180 bytes .../UntoldEngineKernels-iossim.metallib | Bin 802220 -> 802620 bytes .../UntoldEngineKernels-tvos.metallib | Bin 799084 -> 799484 bytes .../UntoldEngineKernels-tvossim.metallib | Bin 802476 -> 802876 bytes .../UntoldEngineKernels-xros.metallib | Bin 799692 -> 800092 bytes .../UntoldEngineKernels-xrossim.metallib | Bin 802940 -> 803340 bytes .../UntoldEngineKernels.metallib | Bin 797260 -> 797660 bytes docs/API/UsingEngineAPI.md | 1 + 11 files changed, 42 insertions(+), 8 deletions(-) diff --git a/Sources/CShaderTypes/ShaderTypes.h b/Sources/CShaderTypes/ShaderTypes.h index 64900862a..7b138ce6b 100644 --- a/Sources/CShaderTypes/ShaderTypes.h +++ b/Sources/CShaderTypes/ShaderTypes.h @@ -1378,9 +1378,9 @@ typedef struct { float historyWeight; // share of the clipped history in the output (0.9) uint32_t historyValid; // 0 on the first frame, after a resize or a mode change: the output is the current frame uint32_t reverseZ; + float clipGamma; // the clip box is the 3×3 mean ± clipGamma × standard deviation (1.25) uint32_t pad0; uint32_t pad1; - uint32_t pad2; } TAAConstants; // 176 bytes typedef enum{ diff --git a/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift index 382895d51..0a256d00b 100644 --- a/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift +++ b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift @@ -29,6 +29,7 @@ public final class TAAParams: @unchecked Sendable { public static let shared = TAAParams() private let lock = NSLock() private var historyWeightValue: Float = 0.9 + private var clipGammaValue: Float = 1.25 /// The share of the (clipped) history in each resolved pixel: higher converges further /// and reacts slower. Clamped to [0, 0.98]; the default is 0.9. @@ -36,6 +37,15 @@ public final class TAAParams: @unchecked Sendable { get { lock.withLock { historyWeightValue } } set { lock.withLock { historyWeightValue = min(max(newValue, 0), 0.98) } } } + + /// How far the history may stray from a pixel's 3×3 neighbourhood: the clip box is the + /// neighbourhood's mean ± this many standard deviations. Lower rejects ghosting sooner, + /// higher keeps pixel-thin features (wires, text) through the frames that miss them. + /// Clamped to [0.5, 3]; the default is 1.25. + public var clipGamma: Float { + get { lock.withLock { clipGammaValue } } + set { lock.withLock { clipGammaValue = min(max(newValue, 0.5), 3) } } + } } /// Sub-pixel offsets, in pixels, of the Halton (2, 3) sequence centred on the pixel: eight @@ -204,6 +214,7 @@ final class TemporalAntiAliasing: @unchecked Sendable { constants.prevRateMapSizes = rateMapSizes(eyes[eye].rateMapData) constants.physicalSize = simd_float2(Float(source.width), Float(source.height)) constants.historyWeight = TAAParams.shared.historyWeight + constants.clipGamma = TAAParams.shared.clipGamma constants.historyValid = eyes[eye].valid ? 1 : 0 constants.reverseZ = renderInfo.reverseZEnabled ? 1 : 0 diff --git a/Sources/UntoldEngine/Shaders/TAAShader.metal b/Sources/UntoldEngine/Shaders/TAAShader.metal index 3ab536515..10086b2a7 100644 --- a/Sources/UntoldEngine/Shaders/TAAShader.metal +++ b/Sources/UntoldEngine/Shaders/TAAShader.metal @@ -102,16 +102,24 @@ fragment TAAFragmentOut fragmentTAAShader( return out; } - // The colour range of the 3×3 neighbourhood, in YCoCg. - float3 lo = float3(1e9); - float3 hi = float3(-1e9); + // The colour box of the 3×3 neighbourhood, in YCoCg: the mean ± γ·σ (variance clipping, + // Salvi 2016) rather than the hard min/max. A feature a pixel wide — a wire, a line of + // text — is rasterized in some jittered frames and not others; a min/max box of a frame + // that missed it excludes its colour and the clip wipes it from the history, so it flickers. + // The statistical box still reaches towards it through the frames that miss it. + float3 m1 = float3(0.0); + float3 m2 = float3(0.0); for (int y = -1; y <= 1; ++y) { for (int x = -1; x <= 1; ++x) { const float3 c = taaRGBToYCoCg(colorTexture.sample(pointSampler, uv + float2(x, y) * texel).rgb); - lo = min(lo, c); - hi = max(hi, c); + m1 += c; + m2 += c * c; } } + const float3 mean = m1 / 9.0; + const float3 sigma = sqrt(max(m2 / 9.0 - mean * mean, 0.0)); + const float3 lo = mean - taa.clipGamma * sigma; + const float3 hi = mean + taa.clipGamma * sigma; // This pixel's position in space, from its depth. A background texel (the clear value) // is pushed just off the clear plane so an infinite-far projection still inverts. @@ -147,10 +155,24 @@ fragment TAAFragmentOut fragmentTAAShader( return out; } + // Under foveation the history may be coarser here than this frame: the spot was in the + // periphery of the previous map (one texel spanning several screen pixels) and the gaze + // has moved onto it. Trusting such a history at full weight shows the sharp frame with a + // blurry shadow that fades over twenty frames; its weight is cut by how much coarser it + // was, measured from the two maps' local rates (texels per screen pixel). + float weight = taa.historyWeight; + if (taa.rateMapSizes.x > 0.0 || taa.prevRateMapSizes.x > 0.0) { + const float2 screenStep = taaScreenFromPhysical(physical + float2(1.0, 1.0), taa.rateMapSizes, rateMap) - screen; + const float currentRate = 1.0 / max(max(abs(screenStep.x), abs(screenStep.y)), 1e-3); + const float2 prevStep = taaPhysicalFromScreen(prevScreen + float2(1.0, 1.0), taa.prevRateMapSizes, prevRateMap) - prevPhysical; + const float prevRate = max(max(abs(prevStep.x), abs(prevStep.y)), 1e-3); + weight *= saturate(prevRate / currentRate); + } + const float4 history = historyTexture.sample(linearSampler, historyUV); const float3 clipped = taaYCoCgToRGB(taaClipToBox(lo, hi, taaRGBToYCoCg(current.rgb), taaRGBToYCoCg(history.rgb))); - const float3 blended = mix(current.rgb, clipped, taa.historyWeight); - const float alpha = mix(current.a, history.a, taa.historyWeight); + const float3 blended = mix(current.rgb, clipped, weight); + const float alpha = mix(current.a, history.a, weight); out.color = float4(blended, alpha); out.history = out.color; return out; diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib index c0ddbef697ca02b0caabb00b6f5fde00066f82a7..fa632500af558b7f11f53dbbb76c0663b891d854 100644 GIT binary patch delta 3788 zcmZXW4OkOb)`0K)FqzB@FbN<*0!)Zv#6Tw?g4?>=30AN_xBL6AM-{^WQ#-Kss|C-JId1>u> ze!7k6`|7=w8I1eFm#-G1>P=&rmzzzG=Kp*>2|BsfX2Thb<>^*gLTu|=qZRWN&e{{k zN^D~7to>}>F3eOqYg75#F|IOX%UfT`{}sj`pj!=#7q+Gs{1S5=n;r8lmW#jBGBK@} z3m(J3dqG%}UARBH5P^b1!Jyz!!k`dPBv42wQYchUb|HNw0d;b%uN5bwk&>SDa$1cL zS|Awg4~w5Zi4}?q&=pU;^XCp_>s@ zANKunH^AM{=Yq^cxE=33ouUJ%9{hOWn9Qg|fN+qJPylcu{K@2_D8VWS72e*@hLZ@i~W5^qw&;}@q;UGFb`|0EuW<} zq6&Qp*Wh8OMb)2aX1#;ZTUh;c&@1N-dzd|)RA(o(*-dl;`t?p?tC@PWlWK_{G^U<0 z-X*#P>UForqjmJB4qBBX=)yDo$`L~vbcYQIqtG=fM?FE;li&-E`aDeABBv+La-qM6 zIw267Sn4-irGNeY);2*Y>TGB%s@X4^E+TVchR2j6suwyJFOALY>pb^n zU<&%IsJ}-=6VYRd69{On{GWmFJtzQC_!HW|>#d!9UoV@!^z=+=r z46Hqu#SK#!G%j}4#c%f>d3$pAmcD?YZar&sKQ054JOI1lmXmu*_Rt8j$R3_Tu8e<# zm1jG-dE0rz3ZKd581&$(mKv!sLlR}TN5Fst81SHYu$oRLE|u1rqRPZSRMRUg4KG(n zkC~;%svE)wR!ARZ-^wi=QK(2_lOtlc>AGj`N$cFIgtW#KT>l2M z%S`p?5fhV*_X6S^^SFg&imN{71%xlU^3niDxb5SFJ&1mqk-21CrC10_o(7aM#gy9Y5xSqbP_mmFns;p^D2A-H` zDyq*-H%y&y3;ud*nVnNuMm@_;qYEO>vXli-J9)_+{zVp^?2Pe&AuLSDxX$)sis1}J zfpBe^;5O$uB2D~d4)^E_Boadci^U`;@jZH`7(67qj_68F!8+(9$+BVH1%oMKCu1dO zg~K{k)=B$9W%0@1?j#UxZ~vltn?-YLpuz|mRrpteM^o=t^qXmg(>8UJ75oZY3$1X? z+RD5{{H`FC%_z>>rasUyNDg{G3RYr9Lyk9lh?(AxaS~QI2Z0sF zWQ_`C0coqX2%aa~tlD9@QcWxm*46~(Y_xFnIozwiWQ?|rCDkzhWa+<+EE;&IEq`^9 zTT@1QRx-I`_0%Ncw4)3{t6;hiBvX?)!US~Us0Y@g(RL* zqmQ%GWsJ4DL5CwLMH3RKu zc9*c`wqgYNxWQ1zCEP=54AalPVv-)KIPhkUlu~SH>PTQa73Ji0WFD^=gwvb~y3cXo zaB$i!1M^;~L*?9m$gN`iPc7VnrhPM>{*(`T z8>@F&l1RUELuZ@GVf9HwcQOa(x{c|NsTbdZbK}Yt#^jVD60SydcOLjibMP2kjfjgl zf}3Ol@$xS#@e#H>{?kWVE5z z*+i~4PBiQ6*b-h(PkOmDw}r7f!x?LO zN>uXUjCHGcrS5#K?+2(3z}4`YY-!uSx2Ti58h*Cp>wYa(9JV522QqVxX^D>56#t{U z5+k!sJLfy#T~TFlOuq_V1lv7@j(?uTEwq0frjTA@iR-f<;KxY|nWo^k3P==|`aiP&`+_*}H>`+y=7&fw1tDIX`aoWc#T?Lo?8&^}*Gwtjspggn ziMJ~g-|C3hWx$S6!|apA-_q4_Z6t9)HB(07drcGZ#8NWKYsTF52(R5PQo`{4WjRUK>|@xEpP+9YhP zvn@tNbjV@TSe8-8wGY9jk^I9;ZAvxr_d6m&{LY9E$PCYsGdiy;vEK=M;FoKXd+}S% z2tIRF<|&@Ccwwnh%1B$IE6{OJojTA_y%EG{E%L#ZyeU)M(4169hTMj zJ-E|)x;eS{&dt-SGe0p~k`ewBmh=#a4gmPO27b}Rxf|3A*q26kC_Sr{ORZlF9vPtA z<3rN?1#c>!X6Gzl#r>pf1BW%Fyvdy8J{&w!6N9$r>_D$Hq!nnDWmd<#NAi>*;$4d8 zRNlgmNBtsVH)+0~WRmp_wnWvh+Ol*?wJNljkS|09Q-7{$01KMh^;M;pJLJf!*&Q5D z36h_+%vt^d7!59Ej15;Q^sMQ|V%4uo`w|N1@;=@8!sc@&Hf=@4(Z&qF%I zPu}Mt?e~j!1p0C5Z($BO*7i0guDKyyCN4`QDbZo2%S0iU3==1A(5#rNlZ1(%c2JD? zm!p_Yqyq-*sI#)yh=JVLx^qvwmyt)(Iko9HO9Ub=z(iyKR>}>yf<)rn~3tJ?G2+-S7VY zfB$py-{kgx&3)kGq)Unx=OO?FVgRh+0Dx@nfb>b!`IpXRlXYs}^FM_DZtCGbSZlu> zYCf}a?t1*l&VP;0j<`DSCoLkW5Fn?-TxyP~etQc8u005I$9 zPYbu7$MS{Nb(EnnR7Gsy?Vs*nVI%B3QQIBj6vC%a`;VUZ^sfW`1O@)o*r8~-J41uW z5(YPQ0_GDstk$*zLy`cSS8mtg+7^_}Me^aEb+~Q`Jo~d z9xVV04&!S}MawU=3+rE`Y$j_lrT{oxKmyC@U|-R;Lh&{zK|vAFc#+GoKl@}BK(zn> z1_A(>W#Mvp)u>1t5GHc32lTnYc=Z1g?oPXgFz^co=0L1D8t9XrJ9-Zg04W4O8xUQz zS-Jf3sw#k+;amX$01r1N*QRCzl!vqbZv1mvb1XmrRD_vrP=FGs zJD_0j3(-*600pO;uu2;gY7ebf<0rXpjzkmtxkDa?OsCIiTcDg6*~WDn$bA91!Y`Yh zemVXer+4;qc570*hwkx^r#i@Vyr0&Y()GUn^6c{+q#=Guy6n2T9gTcykhack@22~b ziara;m(JFwkw@2WVG^p+)hB#=&T}LWYAo@hbalIL%72ArMt?K$C}9k3LM(r>ww zT%M$MB*ulNw0ovrawnelB;{>osB<0UjhH?(sT~!IFKS8Cc}BclOP%f@E4AX^YsvGR zxQY)YHon+R9^@*ZFqjTGj1rv0s+?<-iz7hJ@P&zbJG5tgqIPM5%7QmpsH)j zOH>GwTpBuqki;xz4$f{-#Bb$v3vcsQhs%vC>ur+UIB|r%Gz>aSgAQ|rW7SlgsK;2t zM;L{x)zm_hiW>`XU2M-E@St45>^=XT4{{+=nyxMx45ropLWJmPaayDUVKw-)A!J<0Co70ai(fHkF4}@k5rWurtbU zr8LaIweQe7c=BB>!qb^}7Z6>f4Gdkh!*rf2cWLvxNK8x@f$PpNSDmHMu2?a)U|Or5 zTcmAZvkC|+65EQ&vqwh7m9Ui!qIE9nlmr<_*2_OY=NN#xI~2(>yHjk1c=c(Ffcd}k z=g;-$|BXT1qs`wCQl*9I72$)3#>fZiEfoLA^lR!&Ix|&C>r^DW>Q0j`**spSE3qrs z)9##0)~GsEZAYgKxaY$9U2Lw8Vh1f_O-lNl8HugS2}2-f&zmh1{JQ3njt^^LhMU~- zx^Y=I(}$*+6pvW7uL+Sps-*J_luEQ9+{zEjE1lAn+{C$=9%;lWCnRT&;r_Z45m+}C z-oVQ832TkX>|WwP68ojHU?9&#tkaSgaj&*FH_|#Rx6$`G^7243HfPAT$ly|!5Xh7C z0=&~X=1sv4;=97$o~F?@GB`C}jUD6A!!6SnijrhVMdNVY$tn0aTbgBBp_H|$&>ZGr z32g!O8eAD~=m>e>)hbN%M&zNFk-o(0vu-0bs~HoG|F~cc;rZ}6@)bjUYoFw>(_DCu z-GLO>>-OIc$kjjjgromM&glfv`J%E zWpI5Gc&G_36Kzq1()fepCFXipMlWNUdfDYm=#jhQh;a?RE|p_?OpR{hTVocQMESRC znX&Ln`QPf0?fy&Qjd6LIvECG2x?z~0FYrF;og7*C_xP|}CCZ1bej z?Y>{dfBMB|xW_lsA#baQ2w8jo>YB?nFPIK_H|7F5t>6B9&sEmyh+$ndu&tTX7Wb;h zEiP-b=vD{#b&WHhiS@U*Wlf;PFNxA#R{l?mgP60E{tX`abEtBD(vOuWqV6;ytIRo5 z^B{MOKfc?w?7%{9AJgMyt)`Bc5~6$SuN|*zB;0lGz%PK9y-$S0Za$|R^UAu{693fn zG3I?`KB*%|#Ed<&0DpE^4jbOopd{{Da>1h#qGy+rv5(8J7jdPv7r;B0>x!+8^ff)j zK(6=2UP&AD)(;RNRGOEG(e0wrA&kRMK^!uC? z4qQQFG!c+0;2)-cyakg)Lpu+`|M;H);UB?uKaUWunW@)JFd;Yv;kV;(5b*%K1NjpW zK^xRZpyp2(v_bvn$NoVZ)RSNte*d5i>hqxPFBjT10TNtT`gkE|gL*O4qhLVL2KDO4 zde8>-rpI}jgwa@bz0ZZ56^oaaPE|BoblzT_QpV^|L=lQKVq9 RQ!|BRITG4+*-k~i^&hflau)yq diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-iossim.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-iossim.metallib index fdad47de73f9bc140fa1d292fa69ac416a8d25bc..7ef786317d588d424fed9716a974e49af420972b 100644 GIT binary patch delta 3781 zcmZ9O3tSUtw!r7bWHK|rgog|gU_vlP40OUn&}vD-L+!Q-mRj50+VH50>nk8yx>_>{ z0YMRhpp*8}HTb%=)fUthZ0&6l(6HNdOV_qbZ{0Sa?e)5SK!2{6-FnIW5=^(hJHI(O z=ls9(y-vP4GiQI~ugvl>k5@cqfFT5uK+t{}1VPISyJ8+eoOcG+#p~5tY^d^F#1qgm zkd4o=U~$ zH*)<&2VSpvy2%2P3ogP3jVoT(AJJ?T@9n0V%x6A@2ndECU8vPX3yS!S#akdu06qr< zf{eJ!o{@LQ6)A)O7J@#AUH6Zb$wM#$0U(5!kO&pMzO-`k{}1@dv0@{H1!FiMa|4p= z-&_hII%qQlF+m3LsBzV5?v?;3B_%K=+{O! z{TbzgYYA=!Tscts5+d%+0tgyKf+R&8Fdz#C>l>+ih*IXw_9~&4tr>>KwYy zNxs3O1N|QLSq}~86pi_qf*kpW8E28W)z@in4*3RD5|h{DjQSgoo+pp&(s$WDu(umd zKbPGXI8SMzGtK{0;G`YC(OZA+02zZMcp9^_4+z~hZLO~_^{_v67^l$J{9gy+fA0)E;>PC?OA!V}+3#ALzI4FcXhRmo}^Dia#}6826c zxD@gcMf{Q_?<^5>&u8bqU2d%#U7&gVPgmc3YsBFy#+!n ztxBj`Hq6sInP(HozsifBY&PUc^yPiJ5A=;2)r|m`G>eZkQEKxSFXw)=yENP}zncIF>D?MhC9&2oi99}y!^5|A}-|>adR1HtXKH`o^LJp5JzL6G-s>+~R zf@Kd>I@=tMVB}rfqtLtASM=%|NJK|=l_^d^%$x0#Tw!u=W48*c##jY`Z?;G6Hr{a0 zKWUlYkeu1B!gO!ZyG-Pu4mQ&H*bszYpx2ujx}xDLUV!)cg7ZG$C~&c;$wjAgBbS^Ak1E+NorskU*fdEC9?46-o#97CERawjjj!@t6Sot-s2 zG>S$D**BOWl=Wq^CBnxm1edAE9&O~`=PVC=}PK!V0oqinF40#r}TFvTP!?gyeU4eZgxYexz)?=br zhjr#ABLrA$7sWc~Yq77s7)DPCLVQdbl1)$~ft@0{^!(8Ji~=ySUK*{|FO!haO^+qQZRvyi?$+}-%Vz1v?8T$BV?vyro4VQptT9A zQo212b9)Lug_c++TAk)pBH(zwzsG2|_$8t%jRSpMhOBkU+*_b;Vhw9ZQc%_VrLw@-F2>eh5ny)tYfaT`3 zD6Qu~Htm(;Z9|R@;u*tKr`Cop;dRusm&f!F&-H!l(V!I(tD@@R z*$Z@6T-4^IpPiL>nf1P7fgPL`MK(u!6yP9O@3C6`0E3ySzy_3+USseZb0Fv^N=xaE z(7)vJm$n#3{AvTExsTGObS`q_pUC}RC#uL_O#N&h^0XoBRws#LcuTTq`@<6=Rmpc9sj(o2~vd>;-;QC$zTv zw3xx+i`jtYwf_^k(|x8ht>VtjGi!4`H<{C5{&R+KUh1} zy;i=|a(m?HFzK2cl@>3&B!7;Xw{i`)Y~XngZBt#MPja7(9Bqn6dJF22kJ>UzH1cYT z{p!&od6;;YVg+@#u;a16jM`0@9t<+g_(!^8Ti0w|I-^(h5!lc zF#iK!c|gKC%x53)unzMaFeMGz!aB?g0S}H3v^ivi8_GaK0%!>9F#q)f9@b&L5AawJ zAJ$>s^?-+Un4f&W!#WTUe|v~pFMSD&5rg)8g^HE8r7Oh9T!Iw24ysx-t|lVHsXG)S zMlX{@h#Sw5wAk4}<%y>vrFlf<_7}5uXK&VamtTz+M;R*QVZgUjHdfkV%XVEiIB4m^7Q1~gQy2Cmm~LnG&V2d)=XbvI zoo~*3Cv&cjac#eG(q$``<{$tCVgRbb0RU|a4oerJ%-0<&CTrDITmF`wA$#U4^tYmr ze`H19_vEtTr!Q8%+J5dQ{gjAz)ys09e3k&byrEv(hAA?shVYoEhNp5Y7+5i(M{>$B zu6RQ4)9u9CpP$fV?hBatrJ$BJoXuT}wI8Dzv}p+qv-8$q{Dp}*Uz$`9GU>?;ALXsU zoHql|HZQ+wUOoa1g@!@Hp@l#bK@&qGph=*So%8ak!bDUdZ+K&6Ec#bbLs8Fj0$WbK zD+0i*wLdN_T#Mxivh9?q}1=9byDINyk}xdwYNj>khrK zzR+fYhYLT#3kHs5$6oyb4Q&4|$SIZkvg-cPv^x~zCT2TcPlMX+?> zY9ZG|t(1b+F9X>DX9Y`D#Qrj|@PiedDy+SR(55dT+@m6#^Q^$^B2Y%8BFt>90+c}R zfI#mDQz6&{L6eKHN^2ErH?33Sr@1bUL=(K+5jR7o(r5Wbh!Y}Pxh_3>@zY=TFX)RjyIZM`%D`{Ap$nR4;aM87ijjnm*8M9~$ zL+a%P2RQ6Wa^py)Tiv9cW=H$QpUS=F%eKs`SXOseR-bNxm%EH+4lrFbsvdH~pJDf1 z#Mz7p;dhZJ!Ll%9azv|v+-xA*z@!l{DgEyB*@My%!Sx;~ON!cMiF(l$bpVmMwXzk( zC6~5VELJ5|oQa;nR;_V=I<)4y4~Oo3diz$sq*rK0BrLLBP+ldYCd)oXVqTFfX{gXN zP?=i;3)-uM=GjCf9{xQdZ#Yop4xIrzF#<14_TP{!A>2kO)i1LLiyLjebiMDMLQO`V z%c$OhR&EJ9{Vm`8n$34k61h1YZHY(z_aoU302CKvA!j&~PNlvUd!oEHX2E@RC`NFJ9Dpu5OtTaRz zg{La10+Zy_X342C$*DaxpX7PJW+AuzpZR}%}glJ1y*iOTMWg6^^vRlcu zGjaZHdWV60her(bJiHT#F4201Ub(|`fh%+Jd7UICrdNU+O<~SzOQBt{YIIS|2_3hD zuVvHo2`e)F1SZcK8WC5(R@RF)IH@xdq%TP)zlvt)fx0UcNjJNaZH4%r7L0)TzxC(O z@#lY9FYe~^HihiuVR}V)KcX=j0`(S(e`LIxYLnJXRnS@$$*#FmuT3(KS8Ge`3bw_S zec2jSjjHWvOrL8$tl!Dz_$apDGFq>s&zq6y)!AVP)a(VbWkTQ3T-F-G8kxa*m%Msh z*2VOqDJI1jtM=6+(yh^ zSsr1nG?`t?97uv!Dhn<&FcBMg@)GXhdvYSJgK`@^%#m06lCX>c+Y-G~T|yuW=|y-) z)2JsIdj;Pc_EwCBuVZj(d=GY#LytDjC=eyekn+00>eEy3adv&WX_ZpeszS4whb6QH z)M#*JoW4EefrnR^=*`GO4e6o`m1`LjjsLi)h;YCE4Ed72=0vaLXp_0{9=ii6 zuF)PeMBPGc+K2nj4p#{yl2cAG$!@3{jB+%x>j`J^bdK$Y%MLfybgO4`Z5k#p#Rhmb+q!aSgsRiM(#&k51@^9BT zv*23U{c2>p|5A9OogQYiCs~`SA0+6D2A}j!wk-TRd{C|u<-yi+ihd6Frtr%-ndYJ0 z_dER651-&3-AsqPwLBtZ-S7uRS1MPVj(9fb06N8M|5Nt|tkn_CIxAsYGc6X^nnx`z zYqe8w%3GbabO-_n^Q7A;rI@3`x$0`YYx_#MV2<jOLkm@LHUL$egvP50F)~Lz@SeFV`A;tQU4!#;M+h0@G?|V?1;htbo0lY7RsGy zv?c;d#l+JMya|)2;5ZYS|NTD`n*R&V`*nn{_RrL7CYTVMf#&z)@FU^?cpK`+pap%9 z4?*Tn7xY2?^P~8n5AsA&gFF**f4R^X1w?RS`J;)T5AtHjqu_#|5Ar>ac+dxV z{i8hf!u>jGon$v$3Qw#Z6N-l=3xv=#f)q~FQzb<4w!O1=rEJj%N(Yr8j6~p4p*2*J z=2s$N!M{nd(4K`!g!&>pL~vwcl4FM{F}h`&z-3{P!onmvRQUM^B0{(yDv=2L!X(nIIXC88EN{P5xDMs7 z1^v35W&3iL!9WloC=d)t7!VwY1PB2{3WV&-Sw>AM5eL`)hq5FjQqumxl~=|7HPmH1 z9TN1mmEuz`qJ`qXTB@WpuDr+jF^8zw!SQN%IJ=qaw8)D2{c+{6^Ap)T?7~OMDZ(Aw zV;S?H-q*Ws{Ehj5j@VaMgTiSLTVS&3F`WZp3s&38Z7^G4w3TB>-%IN#28&0O#C`km zv=?p~IZ#;eL9(EoMQckQq2k5H4OE@^57`i+1DpW@K|E?Ks*k-sAA&jH5kMfw0rMwU z9(>G%azOwGVHVU-Hd`v$3}FxeT#y-Ym;KdZM=pfupr0oEN2-j4U=FY!6Iu^%h!DV{ z>mZOJ@EL*FXWzKCMxujg;2}Y_7NUPYvqlaU4#fPpur_NPW&$xnFiePp^3!@>e*n^h z7+sLLXs9V1saHopP%j`#u`~sa>YLn15vW*w6Hg8!$QsBjs!UWmoZMGzqL!kv%8lzy z%gZ-yDmRr^@j$eq{uM+czP+6)li{BR(?YxzDp3=^5hP-Fn?xzqgoDqNL(O&ZK4t<;LeS5Rv z^b7Hx6@Q^uYHH25)0z=hSI#xLX>wuhZOxo_5O@n}UkQ3u++jDptDEfZCO5e7Zisrb z8{cFif8R~E#d{2CXAKYVUV(hm<#wmr2h%(j#VE4i?4V*)p8?zveZm-U4T>>$&~+#H zf}=h+-LcT&jx!Go_K_z9d_6fKi0}A1h`b#5ddsvMGF7{_D!jof z6|dlaa=Er{_Thm`eD6sK9lM4+E#RkJ+mD#&wOy@k56x2^ws;DIs}Diu_CdEW?#F$VqVP1 zxMEcGdiUa`v00b9FI)=DKwcAd|0JWsqQ{k!aJz1wCwvz;lTq07>4Ar7saU^@QfW3o zh^0{tRmz5VdOPz{Ecq8j!7u6!*%Ezem+pOi?aP{4fD7xz4|Y)+^JlLwzP`Cx*mURl z&#n@t@BQCwX@)R8#r(nAC^bQl*r-O}j4%QFh7wG5A3|&@pj~8IRUu7NR2O( zS&id~+no{abXaRp{m1Y3=ch_%wFX(x%#qGotlX>y8_#>VxEk-; zbDg_lL|bFYpffS0(pb`%w@5#I!X@|{EtNKoHIKQUJcFc0o?}QeL~iFLU-Cy8aA#)? zj}D_@Lgp=|A7w`}*+Su?Ck2-&-yUh?uW^`LS16I_6BslmL4obk(PhvRvRkmW!WgWB zR+1ze(GKX15!-1CPO)~&bY(Z?3zfwuf4dup)B6V(Hd@V^yF=9ms9A;G7u=dgKRalm zSci4`4kP$kYa7Kn=WIp35_=#>WwY!>>-2|O8qVczkQ1#IWR~T|^SnCjj$pxOHN-@# z8=vj}1S3F&b74?nRMyNY3JGhyS#ZD5VM!m6E7bV%U~P@iytQVIx`26gR}InD@x(g% zpA7Za(S<`#bQG*AacL?E_X>JB=5tPa)6qlN`p9z$T3ri+QGOHpzr3~6@kkM#rhvD$ zj5k^pn4hi6t$~%N)yQ+qOeJlpZPH?JN{L1?<<)U!+5^vcnL~To{M;EhYzJeev2VRQ z2=m~(&+l&^mR{5y=yVFDpR=RzCr$bWF5x@4PCxV7DWmjQ^?^&dQj%TM(v`q;vsJ_` zIGJZXV48!aF53?r4ooP2QR=xNxm>XBc8j?~<2(TL2 z+kN1s=HM}~8XgyM$SI9Rro2uFg#TZ~qgDCYSA*fkXOUD8o_GKPdpA*|{RjU)mjZjY ztF}phr&BTJbYwCypBSsiO`4Qm$y*y|p0|*#Vyg`qcpP!Ggo;MK{pK+IXc?NLF?N9M zW;dvaC@(`}4(L8{ zXFcp|#*}YW^D6}9=UbI;b;WBlLC2`0_sZh$Y8$u?0v}M#Rub4A<7E6qYd!?*eS3_I zGH7q7du11il!EC>qjDn8%VXw$S(#$dZJp8h1b}V);c;4?f zfaVeJYsG<0fYv(KVpMpS95jt5GaI zbbucC_tK<(>~1TJ&EAl?%cjj z!RCgTFNPI$dxzbfAkTkF)oQ#b*hiG-J#MC1+&FC%smriV$U7@wytsN(=qAcq|77&wwgEf>#QsVZ^RJpvbtC!~?$ZLK6s zytPFdF6MTkyjW64Vd5!NnoX2%-o0pN=6Y@Wbx(}gm_WyhU(`_w@%z7$3F2FI6eThi U0uxCar4?`GAaq}mjY>ZEUvHHZj{pDw delta 3454 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 JwPfr&{{v!YcEtby diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-tvossim.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-tvossim.metallib index add3446fbac41e4955abedbd88bbd98d3d90bc96..73537e42741f00636f4ca247a0f10bc50421c6f6 100644 GIT binary patch delta 3773 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 LJ#fZBVZZw)TsajA delta 3450 zcmZ9O4OA0X7J%POhGa4`&>^4<5=cT&!jG5$3MwrL0krj}!P2d5QA0q5N-c<3{LL?a zHVaYIp{>@S=+TvJL2a>H*(M<+bQ>#eY0LJwZt$SX_7~j#aL!uTmtcB!_nmWd@B7}p z_ucc(eJ^v}py>WpE?8H*HV*+P-~rGa4glzW?1WMR!#tJjX4VB$U-5T8b$hSQ zd+qj?XNoRO_N2XFm+AWBm)*Zx@$S0(r=G)sQqgIqPvOPRDs{QFaBgeO4&YsMx z;n2D{d%wDlW8XPv6ZtQ33g-!J+V>5PeyNq#^}P5VilII3E2Ix39H^lp>Han1?+=eq^2lTif`9iK0Cb8j9avL(?E!w4WCaQezo(ne-3+b5`5m;Bks7nNP!3w zM=E;({V^5RWZum|k^z%nZBb#$4wT8)T1qjLDP&;og1%F=q!?RJ%|lmqU3g;tQU-^o z3b%DohS;Og#UEZ~zkHcA>&eDY1EApo7FhNIW~)0p14DorqJcX3e)AoG0|WqN zfWa)1rw@)eV*ug@bGbVZdDn(^ocjNS-+h?LQwDs{K=3v|T`bx98b=JUA_!noI5I$E z@z}1<;l|L(5I}*A54<}GaKry>{P{;~_W{iBBZdNimTPcxjjrqPRG$_1J+_yO;~;Of z8#hTqaAJ4QA-3TFnM%-D_$IHI>k%M*KZNpXk-oG;WIsYxmzK++D4?XXQ;{4Qn_wV| z1>pQwfz&{50&AuC!D=2WGNaM#?_r4kD+ueQxFgF13{D)Sxl-J~SjC_WavKC1KZu54 zI|OzoZW36VXt>}U-mF$8sXWW@Gp-NWn7f(4UYjTG(i#TiGR?>to z^AxddvcV;@s}@+$5#FaFui>hB<#kSudmv|6{is)d64^XIV+y#FoTz3&iC&H@k zB2jG5Gn{!5=e0zImgokLOoB(U@5ZH#2`1Uj>x3{RYL78$pEK$ZB6O*Q8%oQr?5KTQ zno@fl0Ok-(>*_W;H-4n}*$P3GxE769^ zuruE%J6|{ZF7P8OvQhaL0Ap8JNSS_g*`d2HTEUmIvonLZlE$XCFjDP}EKiEg%Jl+G z8P^~zN$;K$smsMO$)dOf}7c#{0e8%rE!;iyAKZ$BhhS?WwGr z+HT}V-R&Hn9}E4smf3M_YERX>F)w*eya$ct>3>bes_=OTn34lf*Y`II8G@vghc3eT zF>C3g%R0mfJLRg?x3wml!-+{+%>2A~UWBDQ3_8R@hZSsSBN@+i>l(BXI(BIzxmwRZ zUBN$H%|Bh=5<2kYwEKxF=8!9KqfV_9#F$EyjfXHH<_xw>ISf^#dY!|Jr7#s#o5s&A!Q7h%e`sNGuP z9VMcrvamkDy+Ubds(82llDyiXEa)RRJgOMnw1+vGjYSsm#_3hDC)M&bN-L9Hh?|hO zlN?db_$03uwz7u1)j^)+Bf}|b(RFmW2FM0Nk!*uA)m((tcX4o-{~Le)Jb(V*X?SjB z!S;|kB}^|4A3+p4ZJ^#F-hJAuXx6I?WG$tV5=_aRHdTsYwpmqX5i?!R+^eRjW>jWD zV~3q9VEqmz&qp#N#_2W*bVOFt;1jG#qnZI1s?E6T{bz^+nwFD8{Nr{*(LH82QreT9>HvF9gDJcFy*+TG)~UAVb~FSOD{tn3WN=*s4AUJqL=XwI3)D! z=A`xUiNok(r3o!`YJr{-OnQ9CtiobXD5R|MnA4Se$G5~Z*6fSLXFIkUj%jVi>L!~b zUJOHZy3`-@(gtB@bUAa+n4rPoZiipXCg1NNJK%2I=&=3S{77`lV+YWEw`p-<*^-KY zyI%Wq=|bo)dIiAZr(3QmLx&xFSiDVwwy;VGtxrWKMQVJXE<3)S|3U7y==n0HoLQ?& zwEmMVcue;=@Btbm%Fg zIF!PsPL~;49GQc(e!(?|FVQV>#^bXJY-^gFcI#W6_}98@G@0~o*Rg1IfAx3G$S(h- z@WePg^z>k=Dnm1dQxhU6z)w|u9piH4=ldl;4gmor2OH{ zw298wM1*Xa_+az3hUfLiJQaC>O7~ixb$`H^Y%z?Z0k$>WWptK2Y;oavqiR#YzNxSm z&~g42H*OBJ_*HKDKFNQzIEcCM$iKmiKZi8;NA+}>IO}0h5>p0lag0j=1_rU)$p}wAH@2{`3(~%P<~7 zrhDiZ)nO_fySzaaC*`gV+{(=-y{d4lkxRx(PjCLDK$`1y(NP;7q0^W2rT z7jz$u@sRbx<;Ds330-7ZuX0fLk%|lwX%u=gdl&ji%i^XbSa!`gb|&Ka)*8HeE{X7a z+UGtJ(Y(HD`MAW(ML3=5bpbqkJ$o%PoI>>)| z=pWQUo(#+I`v-N9uY}xRF4UU?MsQ*M!-b#@@>0m7U_ej@dHq8k)Ir|%Fi#tMqmA5x z*TYbFV!bTAhFrz&w~^&|>CU}rd(tZvEOLZg&T1kt0lO`XpXs-_Z2u&mJfS1FC$?Z1 z>&vD1tnUcP3#r_hwkLyCq*8J0+mm<%>+rAqIe{eDAC8cZwv&~iec4Az?9KlGXiRsT diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xros.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xros.metallib index 6f8e3281883ba5811e6e4225068acfd2a0f31446..71735086a239c57405427567ac80922740130a67 100644 GIT binary patch delta 3761 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 Hv)=w+%l#Sv delta 3442 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 diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xrossim.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xrossim.metallib index 032f2156362e95d0a07ad55bbe3f92fb025c39f7..9bf9b02141f2b3e6a0db5d50f596e7840a6c568a 100644 GIT binary patch delta 3761 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 H{?>m10L*`h diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels.metallib index f16de9a3af04a718323a6615db984347ddcadcc8..9166f6f9ed2db10b99295b729f1545baa77eb75c 100644 GIT binary patch delta 3745 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 B2QL5s delta 3392 zcmYk83se(l7J&bGkW6LPw^~7|t1GQgt=QA{GzmyJD=KYi%l3F|@SxSc7TemgTMz7?Xu6$~n|tr~-+TXi z{&W9HZhgu14|38a`FRuRcMtzpznSLG*Z#aDYvoG>;N(q>`gY7XgK7$ojc$4&!-{cPPwdf*a?G&u ziM=uqhz|fX05<^oT%YOyrT{qf zkpRikE`#oHi)KoMX@k<0n~l6VfFJot0L_mV!70Ym{A0R@0&glpS=v?R;|_b`A! zQ2_b@yQ1pa3t~PH^#6@V?|R_I@WB4G@hsf~gaI(d;x7j*lYuk_C%>5jK#{epbrU7W zkPCu)3zdj=>=zzvp^_1%D{3n>7o*Dxia01*C@I3Bb*NgXEvNFO;LKNnN`SM0JQcC8 zOe~yyn~WCZA0lDsSDdiyfq0S`6v9=fn?MaB6=9iNuK*h%XmJxZX}v=2p)=L^DXyC% z(P{nM5f4M^=(qT0h^IxK;kpfEbpV(9v8Bb26V7p&E&ZIsrfK)kJs$FO2dTsRX}vDf z*I%~ad+fd&7;ZM%24Mz$WLPW zP)$237GLDa^Ne^qPqlTB6}4-`8vSy^4o!x?a=lo;VJpcEqg5Vti++j&9Ta~m@3&mC z&;Jlx(9^wOAoIC??h-nGsGCOBBOds5-*XpnwIbefng1i4sh}94po5qcb;d{*8_9O? z%qVy!?QY!6Vd*F@E*7*>f=$kf-f4|~)g8Sbk$Lp86$OPCH&-lDO|Li|GnK7bkX!icQTk64=6BFaT1kd0P*Rd+&^*P?@rg~97FcgX`vObhgKxLPHCl!KBFA7a0Br$o+;n~fKgsq%D z_qNgIbh&Y5on4X+`Qg**5X_YCHm&VwR4RHfmd3`e#^IVyW&+Z~IF`W-?wuHHAt;-#XRbvZdk7sg=`Fb`jhp-`W$1(YWkx_94oN9w; zy^A_6K?bI0%0EQs8i2Yx6iKtVlkLm#-E9~F>wo93pW(0nSA)2R&)yhP$;0xB@Igdt zG6woxF8+z>*VdZ#7OH~Qt4Mauoksn1%S5fd(4k=4-07EW(Y2`BfyNHF=fVD6Y=)0w z2d!g`O8T4yiK|TyL!ix`w^*OpH?^1a#;|5)xX~@Iose}ieQ1hVG0v)ejfix-g3dBf zD$&Aln{ilP(IS0`dvb2(ajiJHRdV(O?(cgV0{h0o>seVgVXHD*+)JFuw0@~9m}q1o z*7M{=+{^c7MB0YscKSX?UKyB<%^k8YHn`M<1o9VpA>P?C=1s;9<9ov1iPiEA3{Fk# z#!hhP(dMbSB8?0wZy2sU6@^c*MQP?$O4%6|n$A2fq^+P%iz^ch9U%|ByuwTuBagj| zbQhbMb{naBg)!6kPYc%)o{wK7Uo+Gl?~@#Du`IvG?m!Ca^wq}bTZmo%c<)>HYlKnB zNtc*p*EbADJDb@e!c`E*u{|*DP)l7WOYIM&_37zSlT&F{i(hjonTfU2mc}Oypfh+I zn&UPCGc6tU`j82&qa`7Su8+svp7cAuS+?O?Uo0`vyxwxe=(LvAI9>4ym})X5|B^AY z7p6`wV((cK3K?X0$}(K+l-vTS;c{Hv+>u0sW4uC z5Wwcg>aOsi11L9wK>xq%qhk2Y!@s#LB|0uMFGWu~o)P#S-Dvd~iJ zO6_ILQ?9stNj-9RJTalg*U#jb9&>}6_|}w$YAFA9&55}mmHkkQZ1-OZZ;Z>!jP)k# zb%tSre%I)e-bt5*e~%B#RibP-S}xI}@ctBjDJRoDcKH5)zxm-Z?&-~R%FmQXgsi)N zb?ud^m(54K#TkH3>36K|xyss{F|4Z!jy2O}b+36k;<7VV{VM_crnV)UiSv)Rb!}k8 zFNsoKRsLzjLCo1_eh1_J8mjbPGRF!P(RUh=HJ0=#S_9G8&GdL#o4F&V zkm%m}$HeO!2zRYJ@CFdG_la;g&F7S3URn1#;x}y{W2r9nNuB8;W^CC)eC4nl4!pTu zN!+t$fbl}2XHN^`n2=$caHXvmz&n@WirXFOYh1)YJJT2UQOcmVZh#1(QoKxz{s5hV zzq>*orxN7`ZspqJ{rd2FXk#tzIs*>xP+yZ@p!KSE06hB>t$dQi$UlhmxlTB zY`O!ZzIwavdZ~RI?kdex;4yd)0Mmqm{ZzC$lXTtblVl}briHACmqqiPn@rb+#mG|G zTwS3P_D*fLL;E5fIpc2=WSu1nTie# zx_%TPw3?|m%rGCEhT_)~@F5ZaxB%^Ep#*i1k3bd#4ss1_-5(#+K|UXH ze|J!?4H&_NrB4@vI>-wkkA?|B9pt;8@}Lg##;0`}1+A4@C)o*8;Q^h)1m$HiNBG)G z6%hqn_sraxQlb@pXYj>>29cx+FIGsxg|d87B-~s{N`;LkDohxQrlSS1ostPRR>Fm4 OcIvsVgLZ29+5Z81uW63} diff --git a/docs/API/UsingEngineAPI.md b/docs/API/UsingEngineAPI.md index c50b7e613..a57fe68bb 100644 --- a/docs/API/UsingEngineAPI.md +++ b/docs/API/UsingEngineAPI.md @@ -22,6 +22,7 @@ setRendering(.antiAliasing(.taa)) // temporal: jittered frames blended with setRendering(.antiAliasing(.msaaTaa)) // 4× MSAA on the G-buffer plus the temporal resolve setRendering(.antiAliasing(.none)) TAAParams.shared.historyWeight = 0.9 // share of the history in each resolved pixel (0…0.98) +TAAParams.shared.clipGamma = 1.25 // clip box = 3×3 mean ± γσ: lower rejects ghosts sooner, higher keeps pixel-thin features setRendering(.debugView(.lit)) setRendering(.debugView(.depth)) From 551e8b48aeee10922b067c619f324789146314f5 Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sat, 10 Oct 2026 23:13:41 +0200 Subject: [PATCH 06/10] [Chores] Log the temporal resolve's parameters once --- Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift index 0a256d00b..c505cd2ca 100644 --- a/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift +++ b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift @@ -96,6 +96,7 @@ final class TemporalAntiAliasing: @unchecked Sendable { private(set) var appliedJitter = simd_float2.zero /// The jitter of this frame in pixels of the screen, for diagnostics and tests. private(set) var currentJitterPixels = simd_float2.zero + private var loggedResolve = false private var eyeIndex: Int { renderInfo.isXRStereoMode ? min(max(renderInfo.currentEye, 0), 1) : 0 @@ -201,6 +202,11 @@ final class TemporalAntiAliasing: @unchecked Sendable { handleError(.renderPassCreationFailed, "TAA Pass: history textures") return } + if !loggedResolve { + loggedResolve = true + let foveated = renderInfo.xrFoveation != nil ? "rate-map reprojection, rate-weighted history" : "uniform reprojection" + print("✓ TAA resolve: \(source.width)×\(source.height), history weight \(TAAParams.shared.historyWeight), clip gamma \(TAAParams.shared.clipGamma) (variance clip), \(foveated)") + } let readTexture = textures[eyes[eye].readIndex] let writeTexture = textures[1 - eyes[eye].readIndex] From 271edfd3f6252981f4a4fc1657efda825c48e0f8 Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sat, 10 Oct 2026 23:33:22 +0200 Subject: [PATCH 07/10] [Patch] TAA: keep depth-less pixels, Catmull-Rom history, moving-map and moving-camera tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pixel at the clear depth — the background pass, a transparent quad drawn over passthrough — has no position to reproject from; fetched from the far plane its history ghosted or wiped it under a moving camera (the HUD pill and label flickered on and off). Such a pixel now keeps its own frame. The history is sampled with a Catmull-Rom filter (nine bilinear taps), which resampling every frame smears less than bilinear. The rate map on renderInfo.xrFoveation now also goes on the scene passes of the macOS path, so the foveated resolve is testable on a Mac: the new tests draw a still scene through a rate map whose dense zone jumps every frame, and move the camera, in both temporal modes; the residuals sit at the held-still floor. Kernels rebuilt. --- Sources/UntoldEngine/Shaders/TAAShader.metal | 48 ++++- .../Systems/RenderingSystem.swift | 3 + .../UntoldEngineKernels-ios.metallib | Bin 799180 -> 799820 bytes .../UntoldEngineKernels-iossim.metallib | Bin 802620 -> 803244 bytes .../UntoldEngineKernels-tvos.metallib | Bin 799484 -> 800124 bytes .../UntoldEngineKernels-tvossim.metallib | Bin 802876 -> 803500 bytes .../UntoldEngineKernels-xros.metallib | Bin 800092 -> 800716 bytes .../UntoldEngineKernels-xrossim.metallib | Bin 803340 -> 803980 bytes .../UntoldEngineKernels.metallib | Bin 797660 -> 798284 bytes .../TemporalAntiAliasingTests.swift | 167 ++++++++++++++++++ 10 files changed, 213 insertions(+), 5 deletions(-) diff --git a/Sources/UntoldEngine/Shaders/TAAShader.metal b/Sources/UntoldEngine/Shaders/TAAShader.metal index 10086b2a7..f348b7302 100644 --- a/Sources/UntoldEngine/Shaders/TAAShader.metal +++ b/Sources/UntoldEngine/Shaders/TAAShader.metal @@ -79,6 +79,37 @@ static inline float2 taaPhysicalFromScreen(float2 screen, float4 sizes, constant return decoder.map_screen_to_physical_coordinates(screen); } +// The history at a fractional position, Catmull-Rom filtered with nine bilinear taps (Jimenez +// 2016): resampling the history every frame with a bilinear filter smears it a little more +// each time, which under a moving head or a moving rate map shows as a soft halo that settles +// only when everything stands still; the cubic keeps it sharp. +static inline float4 taaSampleHistory(texture2d history, sampler linearSampler, float2 uv, float2 size) { + const float2 texel = 1.0 / size; + const float2 position = uv * size; + const float2 center = floor(position - 0.5) + 0.5; + const float2 f = position - center; + const float2 w0 = f * (-0.5 + f * (1.0 - 0.5 * f)); + const float2 w1 = 1.0 + f * f * (-2.5 + 1.5 * f); + const float2 w2 = f * (0.5 + f * (2.0 - 1.5 * f)); + const float2 w3 = f * f * (-0.5 + 0.5 * f); + const float2 w12 = w1 + w2; + const float2 offset12 = w2 / w12; + const float2 uv0 = (center - 1.0) * texel; + const float2 uv3 = (center + 2.0) * texel; + const float2 uv12 = (center + offset12) * texel; + float4 result = float4(0.0); + result += history.sample(linearSampler, float2(uv0.x, uv0.y)) * w0.x * w0.y; + result += history.sample(linearSampler, float2(uv12.x, uv0.y)) * w12.x * w0.y; + result += history.sample(linearSampler, float2(uv3.x, uv0.y)) * w3.x * w0.y; + result += history.sample(linearSampler, float2(uv0.x, uv12.y)) * w0.x * w12.y; + result += history.sample(linearSampler, float2(uv12.x, uv12.y)) * w12.x * w12.y; + result += history.sample(linearSampler, float2(uv3.x, uv12.y)) * w3.x * w12.y; + result += history.sample(linearSampler, float2(uv0.x, uv3.y)) * w0.x * w3.y; + result += history.sample(linearSampler, float2(uv12.x, uv3.y)) * w12.x * w3.y; + result += history.sample(linearSampler, float2(uv3.x, uv3.y)) * w3.x * w3.y; + return max(result, 0.0); +} + fragment TAAFragmentOut fragmentTAAShader( VertexCompositeOutput in [[stage_in]], texture2d colorTexture [[texture(taaPassColorTextureIndex)]], @@ -121,10 +152,17 @@ fragment TAAFragmentOut fragmentTAAShader( const float3 lo = mean - taa.clipGamma * sigma; const float3 hi = mean + taa.clipGamma * sigma; - // This pixel's position in space, from its depth. A background texel (the clear value) - // is pushed just off the clear plane so an infinite-far projection still inverts. - float depth = depthTexture.sample(pointSampler, uv); - depth = (taa.reverseZ != 0u) ? max(depth, 1e-5) : min(depth, 1.0 - 1e-5); + // This pixel's position in space, from its depth. A texel at the clear depth has none: + // nothing opaque was drawn there — the background, or a transparent quad over it — and + // reprojecting it from the far plane would fetch the wrong history and ghost or wipe it + // under a moving camera; such a pixel keeps its own frame. + const float depth = depthTexture.sample(pointSampler, uv); + const bool cleared = (taa.reverseZ != 0u) ? (depth <= 1e-6) : (depth >= 1.0 - 1e-6); + if (cleared) { + out.color = current; + out.history = current; + return out; + } const float2 physical = in.position.xy; const float2 screen = taaScreenFromPhysical(physical, taa.rateMapSizes, rateMap); const float2 screenSize = taa.rateMapSizes.x > 0.0 ? taa.rateMapSizes.xy : taa.physicalSize; @@ -169,7 +207,7 @@ fragment TAAFragmentOut fragmentTAAShader( weight *= saturate(prevRate / currentRate); } - const float4 history = historyTexture.sample(linearSampler, historyUV); + const float4 history = taaSampleHistory(historyTexture, linearSampler, historyUV, taa.physicalSize); const float3 clipped = taaYCoCgToRGB(taaClipToBox(lo, hi, taaRGBToYCoCg(current.rgb), taaRGBToYCoCg(history.rgb))); const float3 blended = mix(current.rgb, clipped, weight); const float alpha = mix(current.a, history.a, weight); diff --git a/Sources/UntoldEngine/Systems/RenderingSystem.swift b/Sources/UntoldEngine/Systems/RenderingSystem.swift index c3cf56889..b0a3d6d0a 100644 --- a/Sources/UntoldEngine/Systems/RenderingSystem.swift +++ b/Sources/UntoldEngine/Systems/RenderingSystem.swift @@ -97,6 +97,9 @@ func UpdateRenderingSystem(in view: MTKView) { // This frame's sub-pixel jitter (temporal anti-aliasing), before anything reads the projection. TemporalAntiAliasing.shared.applyJitter() let graph = try buildExecutableGameModeGraph() + // A rasterization rate map set on renderInfo.xrFoveation (the foveation tests + // draw through one on the Mac) goes on the scene passes here as in XR. + applyXRFoveationToSceneRenderPassDescriptors() #if ENGINE_STATS_ENABLED let encodeStart = CACurrentMediaTime() diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib index fa632500af558b7f11f53dbbb76c0663b891d854..c9d2f5dc587631dab3840830dc74ca7bdf2ad5bd 100644 GIT binary patch delta 4534 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 delta 3829 zcmZXX3s_TEwt)9}aB`A!gp=?(K!6iMF(B9z5W!BpB;g_UVX=d)_0H7r(7{J5Dn2@O z%t;6kN-DviNjo|XR;_Jy8qiyy)iw!8m`bNO+Fsh)X+Z1r_6hx*UZ&%a*$JlY_f5WU zWv%t^wby=}y;n}gKIg}-^Rfr4AJ8EH1tI`UQUJi1x=Z$7DE~?C!|_@blJZdz^Ot2U z>-gK<^x#+Ttjwo9=f8Zp8dYwZEV$IEf3WPA>qy|{?48=v7{gO`X=AmjLcds_AvT&!Gy|H`#!U7FxL@M(Ha4 znWP%T^`SHYKYKMZOPCMsd#>lo|1p22quZLBFeC@CWsPPnu5qGl*;;dr8DY!x<{BJ@ z`?{J1;86d}I&uTDz=Y(2Y_NvWXp@Bz2a@MPy#Yt=ns1A*zFJlmB8`06B4Bo z0W0Ci@ackBi-xs`wdxu^y53~tV$lsgw|o>gYWt1nsr`uK{>_v$IbifeXTNfA!vZ2S zX#hAL)3?-d-J7XK!(l=LXvpVVHv;p$?z`v{vtxoM5)UpdrA7AxvEPS^BO3Oc(+`CA?{F|Br+QnK7Ku@Ux6LYX@%vGBm0toX|rH ziuVV9wHx3b=yPGFCp@-y)@P{!ssTSAIKCh@4Imt3BoqLg2!A}|_bX$B@LWQRfj0rz zCb+8NDVU22ku)fd*)7x#yqafbLf6b%4x0#!=#cY1y>YK*s)l0C+En`%P1@kj`Br$TsT&KRRA zpnF`BS9z@0?Ngoh(MUn*_!v`MAb&6CG#a<^3hghDyb8)?h0U($FL|s_a%h*f%lxj* zsyq2u%J9lh==)TA4WH&%QC3sKwR>sFqP?H0=Dla3m%Vp=*sJFbdFefFiQ6sN;vw9C zdeu!l(I|P@E$K=b*5#bm-6Hw~$*Uf(H`nIN88*tt(d^Sc`M5R@x?|eZ3FzwN6W*}v zO$~%w175m&k<*)`Kkw_8yeJTx7|CWX=Ba7PZ*7wCw90)v_M&9t^s_#dOPg#)uZj+) zk9oRHN&9+uNrR2(0e?5%5*2V?2co|PF*AJ3t*V#;`iv*~d%hV+218$OG(H6y8$8<` zGfh+i;&CXJi{cVDNKOjGNsnY2#7qmn{ANQ{T2z#K0&26el+}o45Z!*!NkPj>3 zmo9yCsbfiBe$gANP1{HB%6;(97ytOclZ(H8_la&n?ogZ1L{!!0(7%l&#E(tN#}&`H zmn=&x7<8X~J=6t#+M)Sg5=X>MrcEQjzWuEs!yXh~G5pco&|zK%1$QE+ko&qd(r)DF zW<4%cDM6iB!yo49OgX}C0jSXeiFAmkcQU_DlzbvDThpQ|6lquYXx`QCeO$E{;_?k@l!V}jY{p$$X_^;r%^YOtJ zHTuE6o#!(~8ay;8+z3Y1hk=Q+7&y{2TZHkb=ICWXDkKTLt@oxq^y#JRGq)~;jFc@f zzqy3LwX+yB-tKKp+2%j|=FIM`gCRp{Kcn+JA_X%%0K4I0GgiFx#U2XDF)zp>SEf9` z$cmg?<~Cki8PJ<-!(Lp`)hyQKi(<{@Xc&+R0~~QrQGYa?*Q&0eQ3vvC8{-sY!d#E& zJhS9;{6lFWlMX_|DcuuX8hRq`JoY7?9=2ZA( z$(_-SqOTZzq+@L$TKgJ(Ohet&cx%VhO~yPrA5TluS6NCHYiD2d2tkXn&djkB-sPvz zg)wIsi2+D<@}e*J=NWJz|FrJzQ7lTxzs3w;>{vcqE?iwMcp6J>F?#+IhkG^UB9S)L zz+myIa(s`5t_Jr?uOaGMeRv<#q73Pn`n*;jy^}T)6l*ii*14%bWLpBVH{Ar1JK$Sn zF{y40HRym)ZfMz4c*&a_E42aRY!VP(kt+QYu2BO9mF@qoJmz{ z4lpr?y4kmeO-R~FCHe?+yN)*QZCB$+R+UOLiB#*v-irs6kuDp>V$&TKb(@o5I<4(4%02k7sX1 z^S+r{{J06N@alnqmQDKuNKkDSvMOk62JZEhd;pf3CM~XXGU(jk?$+Ck0g=O#!NIN` z-QtIpOK!lfN%gEQBddypqe=SQ9UrKkeE|+eBt;)|iQ~{2zrh7y{9kJCt}iVd3CHUn zMi;{P^bP*U}N@`L{iuyy5guGsvJCFJHnl!-fN1va+riJw}Cwb7qZRZTQ-P>@ag{ zXWLTX6FKM4)fQAul60Tm6FXHRmmZIrOji=+@PsfTg={Q;?J8cbKGzcX5h_FQA$Ux- z8oJx|Rk^t<3(oX>?aRfgqbj3!AaiHwuDIw;DL*?b@lw-m=Up~ z{+ZBOT8pvb5r(+-lb277YJ@-u_KemgN3vxC}#N z9TOJDHkykR!gbgcH9|{})d_IE^EG6PTj^zeeAxB|xP%$@=xF6p4uUcX4NC|Wj&?aGJov$zoqDN*`81Uu!t=y4OST!tt|pL(J!+^5*@c-Xk#0KUXW2#DkULI+FIEqn{!-t#W(Idq>(97+4<+<`YqwV71Qh9{BffCZ8w|O!XfES@14<(`_d;qf0 zAGe5(@IOIT2qmH;eC`g9=m;->FVdkmd#DXzBhpX;8$ts_bc9zyo(OqFNBD2<@Q9A^ z{gB7P_=t}1t~)%UgTa{j6(7ITaNKdhOsyCH7WS24-EU%!)t`u$JC^5=635mSs?yQ1 pM#3GQq8LYsS`_7AS}BwL;;_`gF2JK5F6cS7CZlwJaT^tP=HFjp8u$PJ diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-iossim.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-iossim.metallib index 7ef786317d588d424fed9716a974e49af420972b..0b10937d2e7703a6162d6cf83baf3c613fde5cd8 100644 GIT binary patch delta 4523 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 delta 3830 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 delta 3834 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 Xs3@W9+#d0|_Q}Ikf5l!g{`!9a+CLgK delta 3834 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 a)U>{MQ>i=HD(!W5ZD_Xm?UAu;duC+d*;%mz_ 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 E2Tl$*2mk;8 diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xrossim.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xrossim.metallib index 9bf9b02141f2b3e6a0db5d50f596e7840a6c568a..922880d9acb4ccdc94c5aa10c7734f8ecc298059 100644 GIT binary patch delta 4485 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 delta 3919 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%0Dw#5k;$^ z8RS)=jfUILpXzQo?IYh8BvNKWn?29n$E+v5LJBx01jCM6T0gi<9*&27r^vWsbt}g9 z9`Y-Adgh7wyOj&{qVjqNS{1MWo{~)thmjd=leegfaw)MuPC{umQ<6{fJ9I8RBC$4t=yj#OLiKX)>RCj8^t@L*qM0&b4+MoiovH-y+O7?eRIP zb3@C8z!pI#Gem6W+=+Jn-86Xm8Y4D$Zn)i`h;Cvg+N+;&>hO1wC__!O8yW=NH+Wi< z;bv{TEpoz?7jCyJqYYHJeW^aW=9m~px9Fa@1|zmiv?t+FX6Hnre~uL|mgRle+UIP& zJ%bZ;^WE_v%E}xEXGsKf!zb9H0GRP2N&KNaT;t*EYpLW z@kw69tZ3mnrKdQfoJnxr^-FeJ>WqaOtg1!d#W=!BHrh!2v93^s zzXacp55Hk7x}DZ7IefCE?Z!xts}KXY8>Z$mFx}@8v%DXcII(Afg-=hY?%!S#U&)Je z+Y8l#9a7!)?6V1~;VeJByan4KE81RKXbZ-;g1rd7)7izQ(PH&+e3!B4S!-e4ckxlA zC|bk9#}A^6W}-a{i!!UBR~ThpfUghv=`*q(lp$LI%njAbVyqIf-=ge!|jL+w&kVzl5S-Q8fCmK z5mjqn4Q$Ybu&NFVx}2pE8|zLK*IwpEE!Rw6y1+OlOKim8+dma+;1lAXRV*Z@!AAY2 zGBPYT{RdC{P&z{2kh~q1xpg=l`9(GM%kg~J%tu@b;wy&{L~TUqJulrfBR6$p1&u=h zCS(M6H>8K#m(#It27C7o>UEi{q-=!lmcH*|*!cNqcy^B1#5GSA{k61NFaBGpRfvC! zd#}GlcZOKeRPl|{VVbyAs(4VJJk6<-ya$C<;s+GLrd8Afcb!f?D+8yK?erF!7I~iB zO=|c`QA=Sz^&0zG=#VJ`JyN+H{j}w-4@=}WyZggKB6$L-UW`?4yM`T~^Y1Co67>@! zlBGrc@^9&IX#X7NiY<$$75)}g5q=yzH#*k#BH`C|Kx z&>?GK9C>hCX7yUOuJ^h-t2L~dh3r|wYuNR@r_?W<(9owniau#Z{&C6d?E-)e6uebJ zMuFddqL9m;7kM%(*$l5ZiC>227*96xbD-~p64SA(A~6qu zSD>8>C7}~|Kg80ZBy<8l53vj=37x>dgjgDsgihd-5L*ZZYCdix1`6PHD>jhO3H(ur z!ySTzPT+MA&w_YDC-4{V;0c|;4?;Y)(S)9vDVp8!Yj*|`IuY>R9sE6y)=oYt5nwEQ z#M2^=qF-9&`O;1<_k52?NRK^<$Ud}Mn(BE3CsI9^w@NZRGuNfK=LrXC_q>cqvOMBO Mk{@t2lIHGz0FUn!I{*Lx delta 3829 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 diff --git a/Tests/UntoldEngineRenderTests/TemporalAntiAliasingTests.swift b/Tests/UntoldEngineRenderTests/TemporalAntiAliasingTests.swift index 695b0232a..2420bc1db 100644 --- a/Tests/UntoldEngineRenderTests/TemporalAntiAliasingTests.swift +++ b/Tests/UntoldEngineRenderTests/TemporalAntiAliasingTests.swift @@ -115,6 +115,172 @@ final class TemporalAntiAliasingTests: BaseRenderSetup { XCTAssertEqual(renderInfo.perspectiveSpace, base, "leaving the temporal mode leaves the projection as it was") } + /// A rate map over the window whose dense column sits at `denseColumn` of four; the + /// three other columns are drawn at a quarter of the rate. Every column layout has the + /// same physical size, as the compositor's gaze-following maps do. + private func makeRateMap(denseColumn: Int) throws -> MTLRasterizationRateMap { + let device = try XCTUnwrap(renderInfo.device) + guard device.supportsRasterizationRateMap(layerCount: 1) else { + throw XCTSkip("this GPU has no rasterization rate maps") + } + let descriptor = MTLRasterizationRateMapDescriptor(screenSize: MTLSize(width: windowWidth, height: windowHeight, depth: 1)) + let layer = MTLRasterizationRateLayerDescriptor(sampleCount: MTLSize(width: 4, height: 1, depth: 1)) + for column in 0 ..< 4 { + layer.horizontal[column] = column == denseColumn ? 1.0 : 0.25 + } + layer.vertical[0] = 1.0 + descriptor.setLayer(layer, at: 0) + return try XCTUnwrap(device.makeRasterizationRateMap(descriptor: descriptor)) + } + + private func makeFoveationFrame(_ rateMap: MTLRasterizationRateMap) throws -> XRFoveationFrame { + let device = try XCTUnwrap(renderInfo.device) + let buffer = try XCTUnwrap(device.makeBuffer(length: rateMap.parameterDataSizeAndAlign.size, options: .storageModeShared)) + let data = try XCTUnwrap(XRRasterizationRateMapData(rateMap: rateMap, buffer: buffer)) + let viewport = MTLViewport(originX: 0, originY: 0, width: Double(windowWidth), height: Double(windowHeight), znear: 0, zfar: 1) + return XRFoveationFrame(rateMap: rateMap, viewport: viewport, rateMapData: data) + } + + /// Reads a physical-size texture of the look format as floats. + private func readFloats(_ texture: MTLTexture) -> [Float] { + var halves = [UInt16](repeating: 0, count: texture.width * texture.height * 4) + halves.withUnsafeMutableBytes { bytes in + texture.getBytes(bytes.baseAddress!, bytesPerRow: texture.width * 8, from: MTLRegionMake2D(0, 0, texture.width, texture.height), mipmapLevel: 0) + } + return halves.map { Float(Float16(bitPattern: $0)) } + } + + /// The headset's situation: a still scene drawn through a rate map whose dense zone moves + /// every frame, as a gaze-following map does. The history of each frame is laid out in the + /// previous map's physical space; reprojected through both maps it must land where this + /// frame's map puts the same point, or the resolve shows the scene with a displaced copy. + func testResolveStaysStableWhileTheRateMapsDenseZoneMoves() throws { + let maps = try [makeRateMap(denseColumn: 0), makeRateMap(denseColumn: 3)] + let physical = maps[0].physicalSize(layer: 0) + guard physical.width == maps[1].physicalSize(layer: 0).width, physical.height == maps[1].physicalSize(layer: 0).height else { + throw XCTSkip("the two layouts got different physical sizes on this GPU") + } + XCTAssertLessThan(physical.width, windowWidth, "three quarter-rate columns narrow the texture") + let frames = try maps.map { try makeFoveationFrame($0) } + + // Draw into textures of the physical size, through the maps, like a foveated eye. + let savedViewPort = renderInfo.viewPort + defer { + renderInfo.xrFoveation = nil + renderInfo.viewPort = savedViewPort + renderer.initSizeableResources() + TemporalAntiAliasing.shared.invalidateHistory() + } + renderInfo.viewPort = simd_float2(Float(physical.width), Float(physical.height)) + renderer.initSizeableResources() + + // The single-sample frame in the first map's layout. + antiAliasingMode = .none + renderInfo.xrFoveation = frames[0] + for _ in 0 ..< 2 { + drawFrame() + } + let single = try readFloats(XCTUnwrap(textureResources.lookTexture)) + XCTAssertGreaterThan(single.max() ?? 0, 0.01, "the scene draws something through the map") + + // The same frame in the second layout differs a lot from the first: the test can tell + // the layouts apart, so a history mapped through the wrong one would be caught. + renderInfo.xrFoveation = frames[1] + drawFrame() + let singleOther = try readFloats(XCTUnwrap(textureResources.lookTexture)) + let layoutDifference = meanAbsoluteDifference(single, singleOther) + XCTAssertGreaterThan(layoutDifference, 0.002, "the two layouts place the scene differently in the texture") + + // Temporal, with the dense zone jumping every frame, ending on the first layout. + antiAliasingMode = .taa + TemporalAntiAliasing.shared.invalidateHistory() + for frame in 0 ..< 12 { + renderInfo.xrFoveation = frames[(frame + 1) % 2] + drawFrame() + } + let resolved = try readFloats(XCTUnwrap(textureResources.antiAliasingTexture)) + + // The floor: the resolve of the first layout held still differs from the single-sample + // frame by the jitter's averaging and the history filter alone. + TemporalAntiAliasing.shared.invalidateHistory() + renderInfo.xrFoveation = frames[0] + for _ in 0 ..< 12 { + drawFrame() + } + let still = try readFloats(XCTUnwrap(textureResources.antiAliasingTexture)) + let floor = meanAbsoluteDifference(still, single) + + XCTAssertFalse(resolved.contains { $0.isNaN || $0.isInfinite }) + let resolveDifference = meanAbsoluteDifference(resolved, single) + print("TAA moving-map test: resolve differs from the single-sample frame by \(resolveDifference), held still by \(floor), the other layout by \(layoutDifference)") + XCTAssertLessThan(resolveDifference, floor + 0.1 * layoutDifference, "the history reprojected through the moving maps lands where this frame's map puts the scene: resolve differs by \(resolveDifference), held still by \(floor), the other layout by \(layoutDifference)") + } + + /// A camera that moves a little every frame, as a head does: the history is reprojected + /// through the depth buffer and the two view-projections, and the resolve at the final + /// pose must match the single-sample frame at that pose rather than drag the earlier poses + /// along as a shadow. + func testResolveFollowsAMovingCameraWithoutAShadow() throws { + func pose(_ frame: Int) -> simd_float3 { + simd_float3(0.03 * Float(frame), 1 + 0.01 * Float(frame), 4 - 0.02 * Float(frame)) + } + let frameCount = 12 + + antiAliasingMode = .none + cameraLookAt(entityId: camera, eye: pose(0), target: .zero, up: simd_float3(0, 1, 0)) + drawFrame() + drawFrame() + let first = try readFloats(XCTUnwrap(textureResources.lookTexture)) + cameraLookAt(entityId: camera, eye: pose(frameCount - 1), target: .zero, up: simd_float3(0, 1, 0)) + drawFrame() + drawFrame() + let last = try readFloats(XCTUnwrap(textureResources.lookTexture)) + let motion = meanAbsoluteDifference(first, last) + XCTAssertGreaterThan(motion, 0.002, "the camera's path moves the scene in the frame") + + for mode in [AntiAliasingMode.taa, .msaaTaa] { + antiAliasingMode = mode + TemporalAntiAliasing.shared.invalidateHistory() + for frame in 0 ..< frameCount { + cameraLookAt(entityId: camera, eye: pose(frame), target: .zero, up: simd_float3(0, 1, 0)) + drawFrame() + } + let moved = try readAntiAliasingOutput() + TemporalAntiAliasing.shared.invalidateHistory() + for _ in 0 ..< frameCount { + drawFrame() + } + let held = try readAntiAliasingOutput() + print("TAA moving-camera \(mode): resolve differs from the final pose's frame by \(meanAbsoluteDifference(moved, last)), held still by \(meanAbsoluteDifference(held, last)), the first pose by \(motion)") + } + + antiAliasingMode = .taa + TemporalAntiAliasing.shared.invalidateHistory() + for frame in 0 ..< frameCount { + cameraLookAt(entityId: camera, eye: pose(frame), target: .zero, up: simd_float3(0, 1, 0)) + drawFrame() + } + let resolved = try readAntiAliasingOutput() + let shadow = meanAbsoluteDifference(resolved, last) + + // The floor: the resolve held still at the final pose. + TemporalAntiAliasing.shared.invalidateHistory() + for _ in 0 ..< frameCount { + drawFrame() + } + let stillResolved = try readAntiAliasingOutput() + let floor = meanAbsoluteDifference(stillResolved, last) + print("TAA moving-camera test: resolve differs from the final pose's frame by \(shadow), held still by \(floor), the first pose by \(motion)") + if let dump = ProcessInfo.processInfo.environment["UNTOLD_TAA_DUMP"] { + let texture = try XCTUnwrap(textureResources.antiAliasingTexture) + for (name, pixels) in [("single", last), ("moving", resolved), ("still", stillResolved)] { + let data = pixels.withUnsafeBufferPointer { Data(buffer: $0) } + try data.write(to: URL(fileURLWithPath: dump).appendingPathComponent("\(name)_\(texture.width)x\(texture.height).f32")) + } + } + XCTAssertLessThan(shadow, floor + 0.1 * motion, "the resolve follows the camera: it differs from the final pose's frame by \(shadow), held still by \(floor), the first pose differs by \(motion)") + } + func testResolveSettlesOnAStillSceneCloseToTheSingleSampleFrame() throws { antiAliasingMode = .none for _ in 0 ..< 2 { @@ -139,6 +305,7 @@ final class TemporalAntiAliasingTests: BaseRenderSetup { let next = try readAntiAliasingOutput() XCTAssertFalse(settled.contains { $0.isNaN || $0.isInfinite }, "no NaN or infinity in the resolve") + print("TAA still test: frame to frame \(meanAbsoluteDifference(settled, next)), resolve vs single-sample \(meanAbsoluteDifference(settled, single))") XCTAssertLessThan(meanAbsoluteDifference(settled, next), 0.004, "a still scene no longer changes between frames") XCTAssertLessThan(meanAbsoluteDifference(settled, single), 0.02, "the resolve stays close to the single-sample frame: no drift, no smear") XCTAssertGreaterThan(meanAbsoluteDifference(settled, single), 0, "and is not the single-sample frame") From edb7f83da658a01c72267024bbbc49ae2ef105b7 Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sun, 11 Oct 2026 00:08:38 +0200 Subject: [PATCH 08/10] [Chores] TAA: a jitter scale for diagnosis (TAAParams.jitterScale) --- .../UntoldEngine/Renderer/TemporalAntiAliasing.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift index c505cd2ca..4cce9dde9 100644 --- a/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift +++ b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift @@ -30,6 +30,15 @@ public final class TAAParams: @unchecked Sendable { private let lock = NSLock() private var historyWeightValue: Float = 0.9 private var clipGammaValue: Float = 1.25 + private var jitterScaleValue: Float = 1 + + /// Scales the sub-pixel jitter: 1 is the full half-pixel sequence, 0 draws every frame + /// from the pixel centre (the resolve still runs, as a diagnostic of what the jitter + /// itself changes). Clamped to [0, 1]. + public var jitterScale: Float { + get { lock.withLock { jitterScaleValue } } + set { lock.withLock { jitterScaleValue = min(max(newValue, 0), 1) } } + } /// The share of the (clipped) history in each resolved pixel: higher converges further /// and reacts slower. Clamped to [0, 0.98]; the default is 0.9. @@ -119,7 +128,7 @@ final class TemporalAntiAliasing: @unchecked Sendable { currentJitterPixels = .zero if antiAliasingMode.isTemporal, let screen = screenSize(), screen.x > 0, screen.y > 0 { - let pixels = taaJitterSequence[jitterIndex % taaJitterSequence.count] + let pixels = taaJitterSequence[jitterIndex % taaJitterSequence.count] * TAAParams.shared.jitterScale jitterIndex += 1 let ndc = simd_float2(2 * pixels.x / screen.x, 2 * pixels.y / screen.y) projection.columns.2.x += ndc.x From 0e1c7ae9804886e796a42e1cf68358017992618c Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sun, 11 Oct 2026 11:59:03 +0200 Subject: [PATCH 09/10] [Bugfix] XR: a capture drawable does not advance the temporal history or the depth pyramid On visionOS 26 a frame carries a second drawable while the view is recorded or streamed. The engine drew the scene into it as into the built-in display, so each eye's temporal history and the occlusion pyramid were overwritten from the capture's pose on every frame: the display's next resolve read a history that alternated between its own pose and the capture's, and thin objects blinked while recording. A secondary drawable now resolves its frame as is and leaves the history, the matrices, the map and the pyramid to the built-in display. The frame's drawable count is logged when it changes. --- .../Renderer/TemporalAntiAliasing.swift | 13 ++++++-- Sources/UntoldEngineXR/UntoldEngineXR.swift | 31 ++++++++++++++++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift index 4cce9dde9..67c73969b 100644 --- a/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift +++ b/Sources/UntoldEngine/Renderer/TemporalAntiAliasing.swift @@ -86,8 +86,8 @@ extension AntiAliasingMode { } } -final class TemporalAntiAliasing: @unchecked Sendable { - static let shared = TemporalAntiAliasing() +public final class TemporalAntiAliasing: @unchecked Sendable { + public static let shared = TemporalAntiAliasing() /// What one eye carries from frame to frame. struct EyeHistory { @@ -106,6 +106,10 @@ final class TemporalAntiAliasing: @unchecked Sendable { /// The jitter of this frame in pixels of the screen, for diagnostics and tests. private(set) var currentJitterPixels = simd_float2.zero private var loggedResolve = false + /// False while a secondary target is drawn (XR: a capture drawable of a recording or a + /// stream, seen from its own pose): the resolve outputs the frame as is and leaves the + /// eye's history, matrices and map untouched for the built-in display's next frame. + public var historyUpdatesEnabled = true private var eyeIndex: Int { renderInfo.isXRStereoMode ? min(max(renderInfo.currentEye, 0), 1) : 0 @@ -230,7 +234,7 @@ final class TemporalAntiAliasing: @unchecked Sendable { constants.physicalSize = simd_float2(Float(source.width), Float(source.height)) constants.historyWeight = TAAParams.shared.historyWeight constants.clipGamma = TAAParams.shared.clipGamma - constants.historyValid = eyes[eye].valid ? 1 : 0 + constants.historyValid = eyes[eye].valid && historyUpdatesEnabled ? 1 : 0 constants.reverseZ = renderInfo.reverseZEnabled ? 1 : 0 let descriptor = MTLRenderPassDescriptor() @@ -271,6 +275,9 @@ final class TemporalAntiAliasing: @unchecked Sendable { encoder.popDebugGroup() encoder.endEncoding() + // A secondary target wrote the spare history texture, which the next primary resolve + // overwrites anyway; the one it reads, and the frame's matrices and map, are untouched. + guard historyUpdatesEnabled else { return } eyes[eye].readIndex = 1 - eyes[eye].readIndex eyes[eye].viewProjection = viewProjection eyes[eye].rateMapData = currentRateMap diff --git a/Sources/UntoldEngineXR/UntoldEngineXR.swift b/Sources/UntoldEngineXR/UntoldEngineXR.swift index 5cec2ad71..3e98fb7ae 100644 --- a/Sources/UntoldEngineXR/UntoldEngineXR.swift +++ b/Sources/UntoldEngineXR/UntoldEngineXR.swift @@ -79,6 +79,7 @@ private var rateMapFrameCounter = 0 private var loggedFoveationState: Bool? private var loggedCaptureTargetSkip = false + private var loggedDrawableCount = 0 private let spatialGestureRecognizer = XRSpatialGestureRecognizer() private let xrEnvironmentLightingSystem = XREnvironmentLightingSystem() private var runtimeLightingModeObserverId: UUID? @@ -647,6 +648,16 @@ shouldEndSubmission = false return } + if drawables.count != loggedDrawableCount { + loggedDrawableCount = drawables.count + let targets = drawables.map { drawable -> String in + if #available(visionOS 26.0, *) { + return drawable.target == .builtIn ? "built-in" : "capture" + } + return "built-in" + } + print("XR: \(drawables.count) drawable(s) per frame (\(targets.joined(separator: ", ")))") + } // Re-check loading state right before render pass to catch any mutations that started // after our initial snapshot. This provides a second layer of protection against races. @@ -694,7 +705,14 @@ // and the render loop will skip rendering but still present (required by compositor) if drawsScene(into: drawable) { - executeXRSystemPass(frame: frame, drawable: drawable, loading: effectiveLoading) + // A capture drawable (a recording or a stream of the view) is drawn from + // its own pose, so it must not advance the frame-to-frame state the + // built-in display relies on: the temporal history and the depth pyramid. + var primary = true + if #available(visionOS 26.0, *) { + primary = drawable.target == .builtIn + } + executeXRSystemPass(frame: frame, drawable: drawable, loading: effectiveLoading, primary: primary) } else { presentCleared(drawable) } @@ -885,7 +903,9 @@ return XRFoveationFrame(rateMap: rateMap, viewport: screenViewport, rateMapData: data) } - func executeXRSystemPass(frame _: LayerRenderer.Frame, drawable: LayerRenderer.Drawable, loading: Bool) { + func executeXRSystemPass(frame _: LayerRenderer.Frame, drawable: LayerRenderer.Drawable, loading: Bool, primary: Bool = true) { + TemporalAntiAliasing.shared.historyUpdatesEnabled = primary + defer { TemporalAntiAliasing.shared.historyUpdatesEnabled = true } // Wait for available command buffer slot to prevent unbounded memory growth let semaphoreWaitStart = CACurrentMediaTime() let firstWaitResult = commandBufferSemaphore.wait(timeout: .now() + .milliseconds(100)) @@ -1026,8 +1046,11 @@ // Build the HZB depth pyramid once after both eyes are rendered. // In stereo mode the mono pyramid (from the last eye rendered) is used - // for both per-eye VP occlusion tests in executeFrustumCulling. - buildHZBDepthPyramid(commandBuffer) + // for both per-eye VP occlusion tests in executeFrustumCulling. A capture + // drawable's depth is seen from its own pose and does not replace it. + if primary { + buildHZBDepthPyramid(commandBuffer) + } drawable.encodePresent(commandBuffer: commandBuffer) From 5cea34ce396e34c59e4503cf99c053406bf592a2 Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Sun, 11 Oct 2026 15:35:22 +0200 Subject: [PATCH 10/10] [Bugfix] TAA: take the rate ratio on the axis where the history is coarsest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A rate map is coarser in one axis than the other wherever its rows and columns differ, and Metal quantizes the requested rates, so a frame can be 0.6 texels per screen pixel in y where the history's frame was 0.25. The history weight was scaled by a ratio taken from the larger step of the two axes and judged such frames equal in rate, keeping a history 2.4× coarser at full weight: its blurred edge overrode the frame's and a thin object lost its edge rows on alternate frames (a headset HUD strip blinked at the one distance where it sat on such a zone). The ratio is now per axis, the smaller taken. The moving-map test now draws a map coarse in both axes and asserts, with the jitter off, that no lit pixel loses its colour to a history drawn through the other map. Kernels rebuilt. --- Sources/UntoldEngine/Shaders/TAAShader.metal | 14 ++++-- .../UntoldEngineKernels-ios.metallib | Bin 799820 -> 799916 bytes .../UntoldEngineKernels-iossim.metallib | Bin 803244 -> 803340 bytes .../UntoldEngineKernels-tvos.metallib | Bin 800124 -> 800220 bytes .../UntoldEngineKernels-tvossim.metallib | Bin 803500 -> 803596 bytes .../UntoldEngineKernels-xros.metallib | Bin 800716 -> 800812 bytes .../UntoldEngineKernels-xrossim.metallib | Bin 803980 -> 804060 bytes .../UntoldEngineKernels.metallib | Bin 798284 -> 798380 bytes .../TemporalAntiAliasingTests.swift | 43 ++++++++++++------ 9 files changed, 39 insertions(+), 18 deletions(-) diff --git a/Sources/UntoldEngine/Shaders/TAAShader.metal b/Sources/UntoldEngine/Shaders/TAAShader.metal index f348b7302..74e81c8e2 100644 --- a/Sources/UntoldEngine/Shaders/TAAShader.metal +++ b/Sources/UntoldEngine/Shaders/TAAShader.metal @@ -200,11 +200,15 @@ fragment TAAFragmentOut fragmentTAAShader( // was, measured from the two maps' local rates (texels per screen pixel). float weight = taa.historyWeight; if (taa.rateMapSizes.x > 0.0 || taa.prevRateMapSizes.x > 0.0) { - const float2 screenStep = taaScreenFromPhysical(physical + float2(1.0, 1.0), taa.rateMapSizes, rateMap) - screen; - const float currentRate = 1.0 / max(max(abs(screenStep.x), abs(screenStep.y)), 1e-3); - const float2 prevStep = taaPhysicalFromScreen(prevScreen + float2(1.0, 1.0), taa.prevRateMapSizes, prevRateMap) - prevPhysical; - const float prevRate = max(max(abs(prevStep.x), abs(prevStep.y)), 1e-3); - weight *= saturate(prevRate / currentRate); + // Texels per screen pixel of each frame, per axis: a map is coarser in one axis than + // the other wherever its rows and columns differ, so the ratio is taken on the axis + // where the history is coarsest relative to this frame. + const float2 screenStep = abs(taaScreenFromPhysical(physical + float2(1.0, 1.0), taa.rateMapSizes, rateMap) - screen); + const float2 currentRate = 1.0 / max(screenStep, float2(1e-3)); + const float2 prevStep = abs(taaPhysicalFromScreen(prevScreen + float2(1.0, 1.0), taa.prevRateMapSizes, prevRateMap) - prevPhysical); + const float2 prevRate = max(prevStep, float2(1e-3)); + const float2 ratio = prevRate / currentRate; + weight *= saturate(min(ratio.x, ratio.y)); } const float4 history = taaSampleHistory(historyTexture, linearSampler, historyUV, taa.physicalSize); diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-ios.metallib index c9d2f5dc587631dab3840830dc74ca7bdf2ad5bd..e079f3c35108a2bc37796a01d43ca04878375099 100644 GIT binary patch delta 3233 zcmYk84OA0X7RP5M!(=iu>Lg+v!$*b$Aw(BLz>ikkB!GygbsMd^w6*O>5V!RUMXic7 zlMgURG(p@Bezj4ti!1FxMQL}jCIJO2o?`3ny4Ko2Y0LJwEx0}1bPp%lmtc0y;m*DH zcmMP5}U?{KzU>GnlFdUc!7|}Vun7o~WRH_7d3$E(?RXKSJ&bdiV z-e)hf;|>nrXU5ojTAK$eF8TXNg(HFAwxpEqztH4`4j$HADutZu>wfcx!p>P0WDY8S zX!T9b`s1N%lQ0CV5(KeY5x1`#TXmsJ*!c$Ovv3f~M=>x6;xM0w`1N}WAjAMc5Dg51 zfWBm|@`WS_W+u+j61t8LxmpWr;1~@D6J#Dv%sEgsP zQOtXzIQ^`)(A%$d*febcswY64ZYOfle#)3z80@diKi5u}(wF5Xf2wXn5|`egY|pfH zQ+=A1e@$2{n^&kKj#OAS(V07P)hB~B=d=U|)mqcBTy_z6td@YLXfsWoZ6|Ig^&y%zL@d5&AkNX^Z3eQXov1R1FM(7m z-oZuFt(>?smcGfysuo_HYx;o0){hcjXtn?lsX0dN@! zd;|MV!o6FQd$%5EoNy*q#y;^Uh(tq6=+s~Yab0HOUrx|8@OA*}0hOI0<^cCfcC6;lL#ciW= zTr+tV4=6x+{J_kv+}BTixv(kY-T^4aA4PfOKvc3n2-#S*tvhxzj)8kwCZ^fX#R~9_ zVo@ns(MMDJT<9bqr4if>a>L7pCnd zyQEU_545Q?VOU=_z@*{W27@rPn=BADiXRD?d&sOQZyBb*^UAoyH2kS>8uqjB+8%Ny z3MyP@BY~i4_kzVXsr@u=Y#((m=xgNWc#uh> z@2+#EYi^n^tFS)MY*4Y?t19p)FQT6rYE?y;1D+OEVa2h^rl892^e>Ojc}X(Al$A3U zc1T}G^L>oXo2tT=#8jLqqd@z3yNqG$Wt^!#GTWbLI*-ee@Y?!%&h0G?WUS1da+L$!thBxtg%pNiiBn91jaRd|FKhs<85K2;P_Nj>`2!*G}>A9DX~3%KQ2$ZWOhu@fOTlUIz}{PI@fz-aMF zrTUQaKPMGcx}!8?r&d>caLg8(qT_yCuC!Bi0i_B%0REwNto@W~Na}Mobm30ESIND3XRRmhAnpL)>Ktoc;5n+bJ`Rt&4Z^WLI5K7>^#8933t> z*f-Is6>e}!2#y8Pat?bVE)8byLX_5H?Msh^obLOvj=}nf(>T$q>){P&tMPc3dQ1VHA0K(VXT&ppdKSvCQ)*qtPF)=vB(P1& zuo>@Z<)F+VcOeAgC1*KyBCewHWjvWt6f#$44(WTfXq&D7gj0_ZAv5oYB#We7#M{n# z3+QN8hIc8|vM_VF9(2nHx-n^(!NJ!o{>7R<)s=>hf{r7fFahtZ|Ls#>F4(7)vCkTe zEhh=meTWXbVKn@?)W0&+%M`TFG2;avd1*evAZxSL=%C)x z>&t}uyg7U%*-p2SsR<#o49u>Z?zovOI_q%U0OOq5maW1{Vz0(K_j~-bD{Vy5b51Y}~0rGjjS2t)G0@pMxS-`ei23B9|Txr-wcteBP=3W$M?@-`ptr0QGGw zWYHwF2Yl?cz+OHm+_RFGU|jInNV%d-0$A*~4jhzDgGeSi%q9RY0yZWzUO|$C*1cj1 z9v8-JE1w3nxG!I>We+^Nz;L(Z3eVjjd%pV9> z9OP?~dLRL7G#3??e<@icEYjeFu(6grBfRn*A%1&@1Qm|Hgc5>RBuNk+t|l0PqR~9z q8X}pCuid;md#CR89D)7@pC)9V5Kk7ob!34MPKC2ORr|=S_x}r$ delta 3130 zcmY*b4O|oF8Gr9CUM{&qkBE9ez=QA+KB`ARX{&8WP(E6^rl_6mY>j}}PFg^eQHAAl zfCNPnM0;p;3x2Fj=})YzXw^0ZCb7m9{k5B2I}MDk=-LfB+r|~c-UQQj`Q4M}`Tw8) z``nZFp1WN4ZO%Q;g+8^qK#u?vNC6N+0RRPUp<1-(*6G4|y2Qi--~1u`i$ZR&{#;RY z=hK@cHy+=yX;tH$_ZOkHkL+5S@YIS`&l7-aZ`Hkp*)(K(Xw-uCHF`5<%%6!T^p#k} z+L?Gq_BPB@G84;Jlw={ijUcUZr!hdgol`gHdFA#`bCcc)CdvnrvPjq zZ)JKr0}$4~lzq(Knjs@Bz_}C%%1kOgf{PX}=WYmC@?u+X1l6@-xw*ISY;N z)0dIoqT=|+cwFDQa?*>1mVO#23pfF+RuP>xsaWYj;^lvZnC~Z08W;Cek!q8=pAcf* zT!WsKr&C8+o0G~;qB^+&gS;Wh&F#}~fb?-=ho4ry>8FWgKfPC;F8P4UR(Cm*-C3#K zoctu0?Qqi>>5@NDLuceC!OH6y1CuSz8N0d8ROinw~G{AT6@RLs@uc|DueVL2x)0`MF3Vv&jzwJ9QL`q zv;sGsnt02pw(BAqga}u5^aUaM7}_gUEOa}%gz(yo@v%G#0{1O(eiw4Sw3gu9x|477(*#A3} zU*NBL;2|#GMh>-aea{gBFaYLC)};DJ+h3yFD{RM`qmYHa2ki5 zdNCc{p!Ello6k;Gmz|3&AA0>f3?9*ck}N^X=AnJ_Ye))7ITn&YG)ETDdow%OxC%~} zH)<4Yu6{|(fqI!4LmjW7?u&CWgQ_vtq<{Qjb+i z|0Ay7PA1K%HOxVl78%20i21%4{5w(HPR2{j(fpw3*iNblv$WAf<%ZRW|J+VyvY(ls zlvGhQv}-__Jv@oxn^+%n2=iK*j2uGfj~EyAJIIP(n8|++r(oK%4bK@I>S6*ZpmHT& z*u6uk^_7x)b52L4Wwp{0a@vNSe59aHbd7l;8Vur=aS~B@rkSUB<_&8#^W24<>w3(Ua zgN|5s`o*N{MT<+amwYRrIpHOY0ZlXzu+Xk|yyT}9A-%8=9^ShDhAa%79I^u_9}_aF ziEpI#z|}z`jNnmU9XHjMEYQ12!b| zTl$~z{~{^VbD3^olq(6L(ZuWCki26?RK6dC_5=h!=>1SpfX&;@exj>?8;KaR7Sj=< zR&yCYZ7~OGV_*buqq|m{Du)s}?PO4)HP6 zs8v_PYyX9Z`WS8|##_Bdv!gv$bF8n1@>o}7`POzy;p%4Xi(_y_*{F3E?qjx&25*bu zr``jEe=~6woJ1F zOYXTWy5a_w=|;}>$m%3TXu^hAmFDf_qcVguxrW%}{DHhhLbHnwW0gg}eF9k}5^w7EMC2)34>tiSU}voa`=| ztUiKQ>l3#XC6s<0$RdfpJQi+0@G+^Q)&&wDvl^lVA5#l29|BkA2F9oaXpjSxrq^}g z%gc-~oWi)8z1A4IOVAy*XlElZR-O<{{WIXhw1#}cq7Hh*iu~3xtsI~S<(k@9AEWkI z5rwacT9K8~6`O+k7<;o4kKDbWCdQC&h?B5XIYh3iW?371g)8e%E>0HUGk%jQ#=4y!{?g)C| zD<%ftwbKpL%Iq#leElT=8`6WtHDMlWJ`Lk+c5xN;dxat;-9>lF&$lpa;QpxDHdmU> z?VL#bMzb?Z`mLsj4?Kxaf4+zA7-X@@-pbzrTL!N?s&6 z`F)U|3-!=z0zokG=7U7g2l;m&@BuHjtwNWHwseY>@vw*j+c$}c8yd+k#ao?nQvAys fSekfhC%ICb)kGRZS0g!Fv}3ZozK$j`?5+O+Q|UbH diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-iossim.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-iossim.metallib index 0b10937d2e7703a6162d6cf83baf3c613fde5cd8..34d4ef91141adb7945d46f51330fe9a635936eec 100644 GIT binary patch delta 3218 zcmZXW3se(l7RP5M!(@^fa1v05mzfYAA$l+YeC&#wgdpNpx6#_xZmk;$Xl;G)sI9KY zX7T_6L=z0{;IpA(D@t2blzI+blfVip-NlyfTI;rfQkS#GtzbRfbPp%lFTw2goSl=K zd++c5=eu9NeBYeuvZ@?5m3ZC8wZ$-mKzs;l5J3<`7Pp9h1y@~IKTn%8UDvEKy?nK2 z@AJ9`ty`42U0VYBd21K$gLa3%)E;45*Off;TO9JZ4{JZ*v1-CCN}un3w%E)wJU1Ip z6<70Im9y~y-CiD5GaCy__V5C1EEc=Zl)S{FjuUQeVXixG)n=aOquE-ZP|WdvMb35K zTD5`4+>Ju(veJfSr7$oA7!Mc1v`JR^1{K8m#43+-ATVj2LrQX>nntWnWHiv&FGBt2a@@7u_D{aI50-Cdj_M{x|RI zde7GoS~TSV)2(YdS5a*>gQWr&J`CNF9@W0JXb*?IL0mJ5Xb5H^92f+(!O9McGdF>S zD3GC1HVn}l4h@ZBny3bevTYFAxw9i-5+DFHQRXFC=@;il;dBU&fd37MB;WtP0WYk5 z938L{iVOg*$cVqcf0M^VyTVac0M&1Nt#%rwARYvjo*5> z_Du+7LCye!AOpq@U}k?O*d#A73%Co#NLKH;eZ-Fle6hFv0FjD{vhPKOkkSHemf`K) ze2yN6vk^}`H)A5?Cg@dA==R|jv4fHONu3;hSJ|%=BDurLRzD>yAkS#p0M1Q%PuZ^* z)<f2B=evda%yk86f0lP4Noz() z%P+h7$sxtYzr?K)FV*D>k8U&VqH^{Y$lC)4&ntxnsLq^;709~+2T#vtg&^w)9Bhwd zE#{3_!9AbC>sNHasa|AJmp`S)m)qf2lUc6O|ytqArz_&rph2KRdOwwJf43Y*8r%b zBXHoF%JPRjFKkYg?F)ym%_?SqV$%XkXF6#m>Rc{}l=Lbit^W3V|t)&4~opQ+D^Izxe(2uc!;(MWVy{ zD^1XgbzoU~ciRXOUN{k-jSJG&Qb(4zF_|?=ZP|T;#WmtXrJYtmaXCNHHjw}X3xJ@A zJ5xvWiA4PGDgCCn33d4hEyb}{HC#r?_JcL>1h^5q2Uy<5Idx zbC^Pju!nb5iCk#QT8=5wd{s?j_VRQzOjj%);C^iD+teF6kZahMiEXWS3gT?4C?K+*avv z8C+(j@t8M*32({$tbB2WZpn`pq%^sL-hkxjaWGKRl_2p|ReTQ^2un_Qn^QIt^b6(V zk)os-nmKUhdh#l{O7DP>xOOi6V3KgyS9$caCywoq=nmLMRG%{%H~;GFGH?SGe*}|nrm+)B(R+GH4?e%wtw2;8XL1I$WK2p zMBN!&5C8KUX}QuV1T7Q;pOGVvx&iBGOI!;m{>= zPEx{8sXtrYWDz1dn#F?E9aE)|e(B6=(vgAs{OY@bQj5rX8rODDIhPN$7#6#b_^Ed) z?U{;O#w#*x2s9g$yylS=yD~1JpK0o3C72DK8>8oP!`p-s%V zx}IW(Xp3io3|k#l8T8r3$|u`p8rv>5=o`a}e1-Z8xHz?NGUb3aG&x-tGzL-v>L;q( z*lw|5Dkb17p+fXPebBfI9dr7a5Iu?oje5H}r9SwrHg((y?_$-MHE0}34LGl8ZEDP6 znoZ2I&?L(b8a;OP0$xxia;cx2fJ1b}xbv@jz%9pvMzdLsoeVnZ!cyGgOF1h%G*#N3 zAwQDw?{-OT{xJ%&lFuD*;g}^jC*SaJeTJ2+_h-nkL*NH>W8Lq{#zkIxb02PJ%T776 zQ7^+Qlqf7_CSeh1NRB;)rkv4LE&ZN`>R=v_R{8fIEB2n%i!^Tnv%qh)WST8syc3|Q;t;J0yLt>=P2qfw1X!2idFpX?ca^5dtVY%3|x&wf3>o(TxC zT^S)GK5*6m<%~OZ5QtZI8kpI*mMjvpM0QEgSd}xb9#o=Tmf@3jH6{!iSz9=bC+ZWv zZErMzj>e48z6`lIM7K7AZrK4RCJNCwc$&qYSj!R}QgjM*oV-cLgu4;YZiWtPB>vS^ts5lF*ryUcP}>L#aBHP8>W%1d2)12 zZ5s6Ez(XDt8&0!QUBrU8pivBF*H87_O5=6fY&XC-XKM0fSXuOFoVqvQqa4ynL7zi9 zqV03g%qrYcXWIF?49!*zY0lpKcvyuZpA3ujyp;|$9LfxSKK8U-`BUPzPv6?f`w;c+ z)G=r(IshK_N?K;AyVfi=@WS2O4(vy$YJ)%uZrH z7p&taafaJ)66bXi0aGGSOaY7dFu3qc2;zY^sz@I5F+LCQC4k3#j6d~+$9#;lfRjKU z^D*uKJo3U0{FZ1CE1U#{$dqF~#(SRdn2+&WfJY`8^D+MQ6aF=~u7&uWpczQSyjC^J zZJiXXyYm5Fk%4*5h_>_6As|_|3JT)Cp7-~^< z)pY#2@fEbEb~+X>-HdWvES9u(E?tZE93Wfu1zD}R%br7ZC#G}30tvtVQEE=>#bxEF z_j;6c6c#rX79-FE&`@X?v>DKFXhLWNG!Zm$e_=7XQYBEzTaT`i2|9(X&!7KeKT}Iq zAbA^T8%>SY41x6IV)}}g$V&Rs)dNPpCrJA?{p7PGQB={~c^4-hM^?1{uzW-Pq zsmGFDV|$D{k5;a8*x*sYK?K0HwEg-wb2jn#tK>QB7s&u&BRn(!+7R^-yZd1e%0>w! zO6G&cRaND}I)DL4uu;y8dp#?jZhIIAbN~Pv8USk4Tw0a;w-kV|5ItD%7XR2R4lt0z zpaBp7O!*gqbX*5DdH`=SGO7Xf!R6{PxN$`EVBjq`~d zskABw2)itxZZNRoe5!->_$Xr*bx1vE5;tT8)cXwUAl+$hi_p^dBQ&9k(0j%C*k_bc z+2vCObUEE>@iDd08=wpFvCGu(N%1kT>`KAlq|2w$?OA$>?HYVIz;zp{)|%4S<)?Re z{_t14w!F|G5#O-(i#q^rVoEF24xji&;eBLLI}G9*^CE~&EUi)xrgRH(x_wDKNRHR1 z>eeS8G^n}_H}PJN_!#|(EvMb5s;NW;fWfDa==Q zn(-HuELqa?2wB~~du-YdUa4g|Fr+y3AA%y9PLO~SxBj9df zgjd>8!ro5Ij8116IKgg?YLs>)lEAMf#xY16!ff#WbMp2lkEA~FkBgC@7l)OGP(9tC zjReUXPEBszcshCW@LOkKu*h&-g$Xv!5%eE!ASopKNSuObPA;SO7PhhJHEMn7nAz^} z4`6Bg9U_B4IJ@DlO{AQ#33phjl7xEx)h4o#{o3{zwuP#v z{ex2D$fN*Y&xVu(j3Qhm z9jMtk>a0k?rkKhiAOD7vOhT^k`<-Nl{05S?OWz1miv3VscNyM zdit13;ub&ZBol}q(&l_!;Yl0e?>R};Q=rg3>g3XiskW+ikJ)2mnh$to?9}sFS1J}% z8W;X#7ZfK}GA2Q$i5NQf^v;h$5e`7fKv`3TGZ z*i2@T&hMQ_T?4x&)FkDzc9N-cO~NcmKw~OXOY;Idg7fA0vUt1M#IM~+rdaEd@JVV` z!pu9#zd5hOctQOB3=W>xXr7evrQIE-1-~$P>Yb6}tVgAy^K|3H1Dql%rdnj!fKTgX z%Nor?L8XDtxr1*PKiqX646J?@{w|`Ss$VvD4b8H2sQ7f?rS;y^|VhprQju*qa zM(1xEFgavLW*Duflc(f*%NdE-6Fj z>|(F$9Ume|H{BLGY0Pcg$W1wI(KSkvhn8~#8#%2+AF^0Y$z$%*@eNws5wduagKm9V z_(f*SUGkDsi=Rfq3^nG~*K^wc;PGKbJssmMp$=ne&~1~2>#3l7sV=gO&s?W8o!3YY7C z7Y9CbA1pD+^9}Nha@iZ212k|@BiqjsxIHvWQ{dhm(*?!*drI2nMSJC{!?KQP-CXNP zL?@rkX>nN6h;xb^TzJRt)LR-@rW-lcBifEt2o&pNa?OXT4iTcZ`bYNoTi6WeR7`W) zD|*9RZBSHI$RGM4qTyDuVF&e1wL*^XhWFEhj~g=Y#&?Mh9BFPD_jkJ#7{EQSG?$*~ zx)59COi<*+Uh*k6jmaOa%Z}{iZ^zYj3MFTQQjab1?6lO%bnDOFUfzstk!03s6c%4Z z%h@vFolb9dTcA=N#Kf5)kviNIKT)NUP^2A}6OEH~x0(W7qUJ?E5k zkRB3iw#mYbGU!Gm;VslsU3Ql&TM%a2n?v$leWf8wy8?FA0ZyB=G-P2tvF2)G#>>== z^wo=ueInaJ44(M4SqDBR9&|Am7f+R7$7CVvu+;c2@r%Y!kBd$OB_1tKhn^_Go*bQT zArQYSjkskufUt!a`na8Ln35X1unfm}01GmJ1@#F*_i`G>Ms~p#>H~=+JKs-tiO;wg zHv0Xje`U7NsBWCd{87`W6aJ*B;G(~>z2EMp+lE+lQZ=p_&Y+1qn#Xi;x7ErS?fbZL z;fge0LpinLcPHb{O2ElD8@-XHQGP=Uc@|gh?#Q7}w&op7z|l?-{Cnhg6`_g9CBD`x zNanpoC>4JVJ{HMgW-+wLldppRrU*^u``qMh>q3Ypphf%?97H+*8Bia=F(2cfg**lM zn2+(*ke>(nn2+(>@AEMqi8Y-#0eT}#_Qv1Pk%i*C0~dpOCy45sTj`%Z4| zz2Cia@5`GvFEjO>dgPyK$?A1a<--sH2_eWTfgot)h(wF%M$fICtV|BqZf50JE(_#I40y39qk|fP-dN#jC;Q!sU zJ(<5#Fu7sct};}@Ow$8{T|ie(6H$S*>1@FZ0=1K9(&uJ2Wi8(%aJNjy{JGMmOUugz ztgz_s6J@q2cGrsaf(CHUS9Y6KO4GN zl@l5?-j|Hucb!pf7-49zKwuy_(4L|)W7V!HT{I8&{?#llaoF8+QFIfIq z#lM`o@(|1gbk*?%Jz`cq`-@HcA=CqWnr95=alKrbo(&;7=<&w)mNv;CmY$ZAu|bKRQTM7vNampWsE-uoh|lVp0nUtlN8M`_ z)$w>|7_;s$PHk5k+=FVHMb+UG_xVIEouV9cP^`}}_y;TU-t80_Q&;CCeyr?3Vpk4} zEl+mziU(Bd{uZ@dy2zjry;Wx3MrKszC{O#V-&KnksJ12*%Tadtt6QeMT;R3(t51i$ zBQ@)=oDr|e<5P9O2_9sAhcCX%o7w796>KMo_D<0!2?L0#0}%=@=tS?5!d*I|wNtcP zC%gz;wXl*2yE_?SH}Ag6@=-G@%rU;tVC9pduT%~szE!VmtH~Sp&YRGybXD{Nuh^k# z_AVB+u-Hqa$S5m1pcXtMDx0kJDc$;b8!{~XR5r+VS(o+*^7?x7h78LF)m_NaJH28= zIqm~r6TW+}=QP~EGqHc?3Ca#O)~5Yt-3}Dn~jjDK9Hb*^kl&`-uZFvbzBFa znhL|dYuT2+?%1#?L9sU!x;C9L1v1wE`__X7ss+x06wol(Q2px>+(HLyXngD|v4?le zQv{7$CKou;SQ_`qKzQmjMP#JVR{^8!d>IKgJ+dqem9UU;LCxc+hqqD-s_4w^QNgKbv{yBN>Uf4Qp zywm_~tOd)`9o$QZ;d$dT((&lTr^wfrG}EcO)cT@t7>jGji^|)r(fP%~7~A+vkdO=# z^0SRVs)&5S5#d8_MHP`b>ws<+yr`IomE&`Qa_lG0 zTt%dzuxzTAYpWs@_z_{PS-c{4A9uToSS%dZuR?c=_i>W_1O-oWs{KR-e1to`pGZo% zkd&=EOrk`{Ex4ja&NZhk!BmOfiiS~paS|G$N|y9-clQ(V@G$qE{Y0A356c_%bu=fh zCSp@hC%d|+68t`#rl$I?Juf=RG+wAeYD~lWQ}@Wgj49u##JIfXLJ~|H}^VveD}U z!lV-e?*^d#KhQf!vh?M3Q+Q z9K0Z&6+82ngvVAlPJ&3@N@Kz5j%Fu{ee$UlVn+(<^=a?=3oR0B3$E{+bS@bqI^B&*VD4ynqwqn6+c(y!ZAx=mWKIZO^Q`q=Sxvwhrkc&I?#v~qlV-Id; zi%vPxQ4cN1m8mQ>bkJ-S--=O05-&bfd@C6qa10gIAGN>DCt7P|3&M#5sNd-YQ_3CF z4pgjuLi6ZR8=6=CFj?=sk2|}H8k;}-Q$8ftyh0Z%ilWCNPa~PNMI&3^JcT#+6*=0% zDNL+AL>szmZ`k!_lZ~c2^jCUrRHLPu^pdrTg=4CgXqbglgI2ML#7ZNbTv@x%%k;-i zL?0V3Iy^AlsSR$lM~fI5q?Rz)%aK%n)?Or~=6L7I;{m&KgzxCD583t8y?XB7u(#S#UamhN|Ak|2eH(=2jgEsk->(Miy8;zP>kp7+~6_2htk zTEQP{Ft*Hq_DX8n@nCkpF2izFtU)Vx&AW__J7F|j zB|54#_j@wn0e3bVO0<$4L~>NXBn7kUCA)4W3fgV98=%hFU0DjOh<`Lrjr4g*hkPQs z#~~lm_c$neIc}*nZ{4Fn)3XP3Z6979%tn!`gHoelnL`T)Qv8cjg^z+tZjvhgtYtA)4-<6Nheh?jLl1ICY1F$A>$ODZ@@M*%GW@_-w?iX?DF z)j}~m#Yt?$Tqz6wQzK(8Z*akn;W?bqM)=J!089c2>kt@tDyReA&%%C0NBA7T7Xlv9 z5x(jXkLUdWon91Uv|Y5U3sj#l9_X2&i<8R6FhZ5)(l?wc_jOL~^+x z1WidO)&r*-indg7#mYytVjBXLSg|rcwjbMC7Z|SAwHr9w#+HUX38w9q&;9fKf8Xc# zyySVFyWEX`GUIm`=@ZL}4KO5tL=fbVLJ(BhAk_*2fs-XO^y#U0GW!z#^6^N<=UaBY zd-+Y*0o;3ZU+Jfg#21Dxyl?Qm{zU#$&tMSKSg${UbmZWT(!^Pf%MEsfT|AkO8a5%G zm6Q1n<2D#-95Xr*@775o$(J=A&3_IVtj8PmxfzXf7CwvUS|{rQxw6L73)dhWmm}Jd zS5TW*0D};KKtKpVOaXy{5P`rzh(SoY@(S>=Bmt>tJhm)Fa7fhn;rqYqI#Y^U;Oupz zog{|J`=Hc>0`jUC%ZUHT)d3BDjp5wN&9Yc;L&?#ZIP~Sf;FnvSYtY(Webu|5_9;$<|FpgA~LByMZ)~O=^0icU8FTo}+ zZ@y-iLvR>`%@EWCGe@q@czr4hkw6I}YyhH4nlEh={eOqw-@1y>5DGkS#FqorEX&QQ zgGn%k7Gfiejf0HGPBjNX_rRo!u<*dI-7Kzxge=fB2naHxY#(a(wSpaA2}lyZR0&V- zGHt*ygkSqHn%Y%ajt3EG*=G?q#Bk6u1$M|I;u`{Rn&eZU*&a+lqWp=ixXPyL!MKzG zrrJPDa)?&i<0Fh2#382FB&p6AVD=hT0esZl6vpy5!WdJB@vD*?;Rl3K)#g(V=(5@w z$#KT$9UyaagdY<9rzFRrg;#TX$6P+Ot|9+2-PZfa0NZXTea@7+Dkrto^Ww+orjk5| zOmfrKC256F6IEnk96rg-ya&q4I1G}Tv%-puD=KAr6Waw@?Y{U9ILqr(x9bxQ7}V{C z5%i=-a-2MG&ua0h%gY)3NQYz-E$Y;P*@(89!g7mAbQ(xfw7onc%SC4*wG|9>-LCJ=6QB*Z9}~^7yr0!kF3Nczl3n4RgR3H|NeOu?`W5?BE4Gl!(&A%qaaXp01dxcpv5l_4!9~-*zJPuIZt12CuE38I z6O;C_7bu1Ka$bL?#f1()F34m>S-DkAV_Z&}dAUw<}XWB3g^=y!bA4m?e0Ph$J{zz$r2*+si-L}6?Nk5}S(^bPwG z;TEET^!Lh*gJS}84IQEmAVD{kTYzyr@wa(PC0_npJO1y%OhkL8dZo#$vSM&CQ7HVP zCD@hPIchtSh0jEt+yw6I;qvz z9XO4l`riAEUhZ#|=5zRBWQDw8dlg*r~ex z-V}P``HZWUxvP!yzU2f3ajPklAl-z4j&`38;-8hrbb^l1xcb+wi(>_2{Vfo%k8ru$ zt@E!(>}E4Bt->kz7_Y9v6GYn$bI>^FLB6;Om%}9gVii6crun)mJOg)r?Swa1(<_3t za{hc3o;1@W%8(6cOvQ{mdtg^!wgO!!<;*62tO`%GRluQB#I)F{_Y;1xcyUsJv^k9h zi#L=lCw$4{{iNUrDx29IUfT*pF1|q4jQ*?>#RWutim=D0_0q*P=DvW+KxU02L|^KP zn7#sJd`(=6_|m;!Oe^RlJN;SqT+@&ZYk*g=yCx_DnW8`oz`TZLZ)B7`l+T;=lQt=P zoIOj!zeq%NTqIqTd?Ci|va$L<3QyZ%Md&AEixNin2d~JAkr{jFPxOwr;rJ1^m5d*D z+t;%bPJ5(}!i2s>Y|naDE7J$9HdDf|`>eEDi#mc*gXXeQCo+jx5c3P zVOi4qdpeza#`|r7i)#%Kp;Wrz2Pb{t1NVVKlOo5UNGnOH z((ET82Qj#_8$-F^G)=Dim8dTuY3?X&Q7m{>p+20_I_aBf8w~pt(^)MFrZniBpnK=t z_dE60YMN??&vb})3M~TVsuYFhZFQ>{W^De!27f)B=A4Ln&U(dF<}!n_)S{SwH|$}T z(jf=&d6`myz5@2A1HElXAD6a?_aCXNzwK{#DTNT~0aJ77skV#JUd{!?PT@;F<%VI! zuQq3fNAkCz%x0yEwF9fi9@jl-wNdT*?t6>sgj;0kn>9+SFYIOQ>0nPM2fHUws}7^v z4e8q~%CftWS~xvaM1$prLR8kUdzLUnEdxp!qAJ1m!JuVfGU^$b&=u* zGbw*v(49=Sar%Q!?Nk`#@?)H>XHs0ru3luC(?kxr;XgYk4}pAKu! z73}9z%*IH;gX?%o(AFS?MpID90;;H#a zEMHWO-?PmFd=x~uoB$sz6@t>h%U4)O%P4;aa02jX8Rcbw&jLJJM)}SMJX%KiUcjdV zKPWYkBwF#tgNkSw5gz_k30U*U2w3p$Y@d+#E=y$1h^|9qpE;1?V~82(Bv azK~CI;wJuf4L+4;h2o;FGfq79#D4+KU_;XY diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-tvossim.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-tvossim.metallib index 93f4c02e17fb5870a4c4d77c80cf2e0b9c3d4382..39e74474057ff8a6e1c1877296e95984dc5f6834 100644 GIT binary patch delta 3230 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 delta 3118 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 NBqcq>izN1!{{o@0JU##b diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xros.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels-xros.metallib index add93fedff8f116ff918e7369dc3e6a0f5db2f42..4156f7c1b5dfb8269bf49d27f238906267399c9d 100644 GIT binary patch delta 3179 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 diff --git a/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels.metallib b/Sources/UntoldEngine/UntoldEngineKernels/UntoldEngineKernels.metallib index d7815a225b5aa9ece109d98e4a8f62547aa5b2fb..30dd8e82bad844b84de3d3124d1d595732ddc4da 100644 GIT binary patch delta 3222 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 HoABZH+o{@F zS$3B&vF1F03(|uJDi?YkD<~LeGY@Pd-;zq#rDnLPF3CAN%>-YN${hK_BTBx^LPW5MKiMNXUnLh~Ism z5BU(kAMy*J9(r{!2qoUUp9uL7|NebG==s&lh(CxqSP#GLG|J0QOLF= 6 { + // Lit pixels that lost most of their colour against the single-sample frame of + // this layout: the thin bar's edge rows, where a history coarser than the frame + // on one axis overrode the frame until the rate ratio was taken per axis. A mean + // over the frame would not show it. + let frameResolved = try readFloats(XCTUnwrap(textureResources.antiAliasingTexture)) + let reference = layout == 0 ? single : singleOther + var lost = 0 + for i in stride(from: 0, to: min(frameResolved.count, reference.count), by: 4) where reference[i] + reference[i + 1] + reference[i + 2] > 0.6 { + let sum = frameResolved[i] + frameResolved[i + 1] + frameResolved[i + 2] + if sum < 0.4 * (reference[i] + reference[i + 1] + reference[i + 2]) { + lost += 1 + } + } + XCTAssertEqual(lost, 0, "frame \(frame) in layout \(layout): no lit pixel loses most of its colour to a history drawn through the other map") + } } let resolved = try readFloats(XCTUnwrap(textureResources.antiAliasingTexture)) @@ -271,13 +295,6 @@ final class TemporalAntiAliasingTests: BaseRenderSetup { let stillResolved = try readAntiAliasingOutput() let floor = meanAbsoluteDifference(stillResolved, last) print("TAA moving-camera test: resolve differs from the final pose's frame by \(shadow), held still by \(floor), the first pose by \(motion)") - if let dump = ProcessInfo.processInfo.environment["UNTOLD_TAA_DUMP"] { - let texture = try XCTUnwrap(textureResources.antiAliasingTexture) - for (name, pixels) in [("single", last), ("moving", resolved), ("still", stillResolved)] { - let data = pixels.withUnsafeBufferPointer { Data(buffer: $0) } - try data.write(to: URL(fileURLWithPath: dump).appendingPathComponent("\(name)_\(texture.width)x\(texture.height).f32")) - } - } XCTAssertLessThan(shadow, floor + 0.1 * motion, "the resolve follows the camera: it differs from the final pose's frame by \(shadow), held still by \(floor), the first pose differs by \(motion)") }