TemporalFilterArrayResources PrepareTemporalFilterArrayResources(HDCamera hdCamera, RTHandle noisyBuffer, RTHandle distanceBuffer, RTHandle validationBuffer, RTHandle historyBuffer, RTHandle validationHistoryBuffer, RTHandle distanceHistorySignal, RTHandle outputBuffer, RTHandle outputDistanceSignal) { TemporalFilterArrayResources tfaResources = new TemporalFilterArrayResources(); // Input buffers tfaResources.depthStencilBuffer = m_SharedRTManager.GetDepthStencilBuffer(); tfaResources.normalBuffer = m_SharedRTManager.GetNormalBuffer(); tfaResources.velocityBuffer = TextureXR.GetBlackTexture(); tfaResources.historyDepthTexture = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Depth); tfaResources.historyNormalTexture = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Normal); tfaResources.noisyBuffer = noisyBuffer; tfaResources.distanceBuffer = distanceBuffer; tfaResources.motionVectorBuffer = m_SharedRTManager.GetMotionVectorsBuffer(); // Temporary buffers tfaResources.validationBuffer = validationBuffer; // InOut buffers tfaResources.historyBuffer = historyBuffer; tfaResources.validationHistoryBuffer = validationHistoryBuffer; tfaResources.distanceHistorySignal = distanceHistorySignal; // Output buffers tfaResources.outputBuffer = outputBuffer; tfaResources.outputDistanceSignal = outputDistanceSignal; return(tfaResources); }
// Denoiser variant when history is stored in an array and the validation buffer is separate public void DenoiseBuffer(CommandBuffer cmd, HDCamera hdCamera, RTHandle noisyBuffer, RTHandle historyBuffer, RTHandle validationHistoryBuffer, RTHandle velocityBuffer, RTHandle outputBuffer, int sliceIndex, Vector4 channelMask, RTHandle distanceBuffer, RTHandle distanceHistorySignal, RTHandle outputDistanceSignal, Vector4 distanceChannelMask, bool distanceBased, bool singleChannel = true, float historyValidity = 1.0f) { // If we do not have a depth and normal history buffers, we can skip right away var historyDepthBuffer = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Depth); var historyNormalBuffer = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.Normal); // Request the intermediate buffer we need RTHandle validationBuffer = m_RenderPipeline.GetRayTracingBuffer(InternalRayTracingBuffers.R0); TemporalFilterArrayParameters tfaParams = PrepareTemporalFilterArrayParameters(hdCamera, distanceBased, singleChannel, historyValidity, sliceIndex, channelMask, distanceChannelMask); TemporalFilterArrayResources tfaResources = PrepareTemporalFilterArrayResources(hdCamera, noisyBuffer, distanceBuffer, validationBuffer, historyBuffer, validationHistoryBuffer, distanceHistorySignal, outputBuffer, outputDistanceSignal); ExecuteTemporalFilterArray(cmd, tfaParams, tfaResources); }
public TemporalDenoiserArrayOutputData DenoiseBuffer(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthBuffer, TextureHandle normalBuffer, TextureHandle motionVectorBuffer, TextureHandle historyValidationBuffer, TextureHandle noisyBuffer, RTHandle historyBuffer, TextureHandle distanceBuffer, RTHandle distanceHistorySignal, TextureHandle velocityBuffer, RTHandle validationHistoryBuffer, int sliceIndex, Vector4 channelMask, Vector4 distanceChannelMask, bool distanceBased, bool singleChannel, float historyValidity) { TemporalDenoiserArrayOutputData resultData = new TemporalDenoiserArrayOutputData(); using (var builder = renderGraph.AddRenderPass <TemporalFilterArrayPassData>("TemporalDenoiser", out var passData, ProfilingSampler.Get(HDProfileId.TemporalFilter))) { // Cannot run in async builder.EnableAsyncCompute(false); // Fetch all the resources passData.parameters = PrepareTemporalFilterArrayParameters(hdCamera, distanceBased, singleChannel, historyValidity, sliceIndex, channelMask, distanceChannelMask); // Input buffers passData.depthStencilBuffer = builder.ReadTexture(depthBuffer); passData.normalBuffer = builder.ReadTexture(normalBuffer); passData.motionVectorBuffer = builder.ReadTexture(motionVectorBuffer); passData.velocityBuffer = builder.ReadTexture(velocityBuffer); passData.noisyBuffer = builder.ReadTexture(noisyBuffer); passData.distanceBuffer = distanceBased ? builder.ReadTexture(distanceBuffer) : renderGraph.defaultResources.blackTextureXR; passData.validationBuffer = builder.ReadTexture(historyValidationBuffer); // History buffers passData.historyBuffer = builder.ReadWriteTexture(renderGraph.ImportTexture(historyBuffer)); passData.validationHistoryBuffer = builder.ReadWriteTexture(renderGraph.ImportTexture(validationHistoryBuffer)); passData.distanceHistorySignal = distanceBased ? builder.ReadWriteTexture(renderGraph.ImportTexture(distanceHistorySignal)) : renderGraph.defaultResources.blackTextureXR; // Output textures passData.outputBuffer = builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Temporal Filter Output" })); passData.outputDistanceSignal = distanceBased ? builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, enableRandomWrite = true, name = "Temporal Filter Distance output" })) : new TextureHandle(); builder.SetRenderFunc( (TemporalFilterArrayPassData data, RenderGraphContext ctx) => { TemporalFilterArrayResources resources = new TemporalFilterArrayResources(); resources.depthStencilBuffer = data.depthStencilBuffer; resources.normalBuffer = data.normalBuffer; resources.motionVectorBuffer = data.motionVectorBuffer; resources.velocityBuffer = data.velocityBuffer; resources.noisyBuffer = data.noisyBuffer; resources.distanceBuffer = data.distanceBuffer; resources.validationBuffer = data.validationBuffer; resources.historyBuffer = data.historyBuffer; resources.validationHistoryBuffer = data.validationHistoryBuffer; resources.distanceHistorySignal = data.distanceHistorySignal; resources.outputBuffer = data.outputBuffer; resources.outputDistanceSignal = data.outputDistanceSignal; ExecuteTemporalFilterArray(ctx.cmd, data.parameters, resources); }); resultData.outputSignal = passData.outputBuffer; resultData.outputSignalDistance = passData.outputDistanceSignal; } return(resultData); }
static void ExecuteTemporalFilterArray(CommandBuffer cmd, TemporalFilterArrayParameters tfaParams, TemporalFilterArrayResources tfaResources) { if (tfaResources.historyDepthTexture == null || tfaResources.historyNormalTexture == null) { HDUtils.BlitCameraTexture(cmd, tfaResources.noisyBuffer, tfaResources.historyBuffer); HDUtils.BlitCameraTexture(cmd, tfaResources.noisyBuffer, tfaResources.outputBuffer); if (tfaParams.distanceBasedDenoiser) { HDUtils.BlitCameraTexture(cmd, tfaResources.distanceBuffer, tfaResources.distanceHistorySignal); HDUtils.BlitCameraTexture(cmd, tfaResources.distanceBuffer, tfaResources.outputDistanceSignal); } return; } // Evaluate the dispatch parameters int tfTileSize = 8; int numTilesX = (tfaParams.texWidth + (tfTileSize - 1)) / tfTileSize; int numTilesY = (tfaParams.texHeight + (tfTileSize - 1)) / tfTileSize; // First of all we need to validate the history to know where we can or cannot use the history signal // Bind all the input buffers cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.validateHistoryKernel, HDShaderIDs._DepthTexture, tfaResources.depthStencilBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.validateHistoryKernel, HDShaderIDs._HistoryDepthTexture, tfaResources.historyDepthTexture); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.validateHistoryKernel, HDShaderIDs._NormalBufferTexture, tfaResources.normalBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.validateHistoryKernel, HDShaderIDs._HistoryNormalTexture, tfaResources.historyNormalTexture); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.validateHistoryKernel, HDShaderIDs._CameraMotionVectorsTexture, tfaResources.motionVectorBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.validateHistoryKernel, HDShaderIDs._VelocityBuffer, tfaResources.velocityBuffer); // Bind the constants cmd.SetComputeFloatParam(tfaParams.temporalFilterCS, HDShaderIDs._HistoryValidity, tfaParams.historyValidity); cmd.SetComputeFloatParam(tfaParams.temporalFilterCS, HDShaderIDs._PixelSpreadAngleTangent, tfaParams.pixelSpreadTangent); // Bind the output buffer cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.validateHistoryKernel, HDShaderIDs._ValidationBufferRW, tfaResources.validationBuffer); // Evaluate the validity cmd.DispatchCompute(tfaParams.temporalFilterCS, tfaParams.validateHistoryKernel, numTilesX, numTilesY, tfaParams.viewCount); // Now that we have validated our history, let's accumulate cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccKernel, HDShaderIDs._DenoiseInputTexture, tfaResources.noisyBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccKernel, HDShaderIDs._HistoryBuffer, tfaResources.historyBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccKernel, HDShaderIDs._HistoryValidityBuffer, tfaResources.validationHistoryBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccKernel, HDShaderIDs._DepthTexture, tfaResources.depthStencilBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccKernel, HDShaderIDs._CameraMotionVectorsTexture, tfaResources.motionVectorBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccKernel, HDShaderIDs._ValidationBuffer, tfaResources.validationBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccKernel, HDShaderIDs._VelocityBuffer, tfaResources.velocityBuffer); // Bind the constants cmd.SetComputeIntParam(tfaParams.temporalFilterCS, HDShaderIDs._DenoisingHistorySlice, tfaParams.sliceIndex); cmd.SetComputeVectorParam(tfaParams.temporalFilterCS, HDShaderIDs._DenoisingHistoryMask, tfaParams.channelMask); // Bind the output buffer cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccKernel, HDShaderIDs._DenoiseOutputTextureRW, tfaResources.outputBuffer); // Combine with the history cmd.DispatchCompute(tfaParams.temporalFilterCS, tfaParams.temporalAccKernel, numTilesX, numTilesY, tfaParams.viewCount); // Make sure to copy the new-accumulated signal in our history buffer cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.copyHistoryKernel, HDShaderIDs._DenoiseInputTexture, tfaResources.outputBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.copyHistoryKernel, HDShaderIDs._DenoiseOutputTextureRW, tfaResources.historyBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.copyHistoryKernel, HDShaderIDs._ValidityOutputTextureRW, tfaResources.validationHistoryBuffer); cmd.SetComputeIntParam(tfaParams.temporalFilterCS, HDShaderIDs._DenoisingHistorySlice, tfaParams.sliceIndex); cmd.SetComputeVectorParam(tfaParams.temporalFilterCS, HDShaderIDs._DenoisingHistoryMask, tfaParams.channelMask); cmd.DispatchCompute(tfaParams.temporalFilterCS, tfaParams.copyHistoryKernel, numTilesX, numTilesY, tfaParams.viewCount); if (tfaParams.distanceBasedDenoiser) { // Bind the input buffers cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccSingleKernel, HDShaderIDs._DenoiseInputTexture, tfaResources.distanceBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccSingleKernel, HDShaderIDs._HistoryBuffer, tfaResources.distanceHistorySignal); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccSingleKernel, HDShaderIDs._HistoryValidityBuffer, tfaResources.validationHistoryBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccSingleKernel, HDShaderIDs._DepthTexture, tfaResources.depthStencilBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccSingleKernel, HDShaderIDs._ValidationBuffer, tfaResources.validationBuffer); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccSingleKernel, HDShaderIDs._VelocityBuffer, tfaResources.velocityBuffer); // Bind the constant inputs cmd.SetComputeIntParam(tfaParams.temporalFilterCS, HDShaderIDs._DenoisingHistorySlice, tfaParams.sliceIndex); cmd.SetComputeVectorParam(tfaParams.temporalFilterCS, HDShaderIDs._DenoisingHistoryMask, tfaParams.distanceChannelMask); // Bind the output buffers cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.temporalAccSingleKernel, HDShaderIDs._DenoiseOutputTextureRW, tfaResources.outputDistanceSignal); // Dispatch the temporal accumulation cmd.DispatchCompute(tfaParams.temporalFilterCS, tfaParams.temporalAccSingleKernel, numTilesX, numTilesY, tfaParams.viewCount); // Make sure to copy the new-accumulated signal in our history buffer cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.copyHistoryNoValidityKernel, HDShaderIDs._DenoiseInputTexture, tfaResources.outputDistanceSignal); cmd.SetComputeTextureParam(tfaParams.temporalFilterCS, tfaParams.copyHistoryNoValidityKernel, HDShaderIDs._DenoiseOutputTextureRW, tfaResources.distanceHistorySignal); cmd.SetComputeIntParam(tfaParams.temporalFilterCS, HDShaderIDs._DenoisingHistorySlice, tfaParams.sliceIndex); cmd.SetComputeVectorParam(tfaParams.temporalFilterCS, HDShaderIDs._DenoisingHistoryMask, tfaParams.distanceChannelMask); cmd.DispatchCompute(tfaParams.temporalFilterCS, tfaParams.copyHistoryNoValidityKernel, numTilesX, numTilesY, tfaParams.viewCount); } }