浏览代码

First pass at refactoring and speeding up depth & color pyramids

/main
Thomas 6 年前
当前提交
7ffc71c9
共有 12 个文件被更改,包括 252 次插入189 次删除
  1. 6
      com.unity.render-pipelines.core/CoreRP/Textures/DepthBits.cs
  2. 4
      com.unity.render-pipelines.high-definition/HDRP/Camera/HDCameraFrameHistoryType.cs
  3. 82
      com.unity.render-pipelines.high-definition/HDRP/Material/GGXConvolution/RuntimeFilterIBL.cs
  4. 2
      com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDCustomSamplerId.cs
  5. 93
      com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDRenderPipeline.cs
  6. 4
      com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDStringConstants.cs
  7. 4
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/ApplyDistorsion.compute
  8. 6
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramidProcessor.cs
  9. 41
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/ColorPyramid.compute
  10. 62
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/DepthPyramid.compute
  11. 126
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/MipGenerator.cs
  12. 11
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/MipGenerator.cs.meta

6
com.unity.render-pipelines.core/CoreRP/Textures/DepthBits.cs


using System.Collections.Generic;
using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering
{
public enum DepthBits

Depth16 = 16,
Depth24 = 24
Depth24 = 24,
Depth32 = 32
}
}

4
com.unity.render-pipelines.high-definition/HDRP/Camera/HDCameraFrameHistoryType.cs


using UnityEngine.Serialization;
DepthPyramid,
ColorPyramid,
VolumetricLighting,
Count
}

82
com.unity.render-pipelines.high-definition/HDRP/Material/GGXConvolution/RuntimeFilterIBL.cs


using UnityEngine.Rendering;
using System;
using System.Collections.Generic;
namespace UnityEngine.Experimental.Rendering.HDPipeline

Matrix4x4[] m_faceWorldToViewMatrixMatrices = new Matrix4x4[6];
BufferPyramidProcessor m_BufferPyramidProcessor;
List<RenderTexture> m_PlanarColorMips = new List<RenderTexture>();
MipGenerator m_MipGenerator;
public IBLFilterGGX(RenderPipelineResources renderPipelineResources, BufferPyramidProcessor processor)
public IBLFilterGGX(RenderPipelineResources renderPipelineResources, MipGenerator mipGenerator)
m_BufferPyramidProcessor = processor;
m_MipGenerator = mipGenerator;
}
public bool IsInitialized()

{
CoreUtils.Destroy(m_GgxConvolveMaterial);
CoreUtils.Destroy(m_GgxIblSampleData);
for (var i = 0; i < m_PlanarColorMips.Count; ++i)
m_PlanarColorMips[i].Release();
m_PlanarColorMips.Clear();
}
void FilterCubemapCommon(CommandBuffer cmd,

public void FilterPlanarTexture(CommandBuffer cmd, Texture source, RenderTexture target)
{
var lodCount = Mathf.Max(Mathf.FloorToInt(Mathf.Log(Mathf.Min(source.width, source.height), 2f)), 0);
for (var i = 0; i < lodCount - 0; ++i)
{
var width = target.width >> (i + 1);
var height = target.height >> (i + 1);
var rtHash = HashRenderTextureProperties(
width,
height,
target.depth,
target.format,
target.sRGB ? RenderTextureReadWrite.sRGB : RenderTextureReadWrite.Linear
);
var lodIsMissing = i >= m_PlanarColorMips.Count;
RenderTexture rt = null;
var createRT = lodIsMissing
|| (rt = m_PlanarColorMips[i]) == null
|| rtHash != HashRenderTextureProperties(
rt.width, rt.height, rt.depth, rt.format, rt.sRGB
? RenderTextureReadWrite.sRGB
: RenderTextureReadWrite.Linear
);
if (createRT && rt)
rt.Release();
if (createRT)
{
rt = new RenderTexture(
width,
height,
target.depth,
target.format,
target.sRGB ? RenderTextureReadWrite.sRGB : RenderTextureReadWrite.Linear
);
rt.enableRandomWrite = true;
rt.name = "Planar Convolution Tmp RT";
rt.hideFlags = HideFlags.HideAndDontSave;
rt.Create();
}
if (lodIsMissing)
m_PlanarColorMips.Add(rt);
else if (createRT)
m_PlanarColorMips[i] = rt;
}
m_BufferPyramidProcessor.RenderColorPyramid(
new RectInt(0, 0, source.width, source.height),
cmd,
source,
target,
m_PlanarColorMips,
lodCount
);
cmd.Blit(source, target);
m_MipGenerator.RenderColorGaussianPyramid(cmd, new Vector2Int(source.width, source.height), target);
}
// Filters MIP map levels (other than 0) with GGX using multiple importance sampling.

m_GgxConvolveMaterial.SetTexture("_MarginalRowDensities", marginalRowCdf);
FilterCubemapCommon(cmd, source, target, m_faceWorldToViewMatrixMatrices);
}
int HashRenderTextureProperties(
int width,
int height,
int depth,
RenderTextureFormat format,
RenderTextureReadWrite sRGB)
{
return width.GetHashCode()
^ height.GetHashCode()
^ depth.GetHashCode()
^ format.GetHashCode()
^ sRGB.GetHashCode();
}
}
}

2
com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDCustomSamplerId.cs


{
PushGlobalParameters,
CopySetDepthBuffer,
CopyDepthStencilbuffer,
CopyDepthBuffer,
HTileForSSS,
Forward,
RenderSSAO,

93
com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDRenderPipeline.cs


Material m_CopyDepth;
GPUCopy m_GPUCopy;
BufferPyramid m_BufferPyramid;
MipGenerator m_MipGenerator;
IBLFilterGGX m_IBLFilterGGX = null;

RTHandleSystem.RTHandle m_CameraSssDiffuseLightingBuffer;
RTHandleSystem.RTHandle m_CameraDepthStencilBuffer;
RTHandleSystem.RTHandle m_CameraDepthBufferCopy;
RTHandleSystem.RTHandle m_CameraDepthBufferMipChain;
RTHandleSystem.RTHandle m_CameraStencilBufferCopy;
RTHandleSystem.RTHandle m_VelocityBuffer;

m_GPUCopy = new GPUCopy(asset.renderPipelineResources.copyChannelCS);
m_MipGenerator = new MipGenerator(m_Asset);
var bufferPyramidProcessor = new BufferPyramidProcessor(
asset.renderPipelineResources.colorPyramidCS,
asset.renderPipelineResources.depthPyramidCS,

m_MaterialList.ForEach(material => material.Build(asset));
m_IBLFilterGGX = new IBLFilterGGX(asset.renderPipelineResources, bufferPyramidProcessor);
m_IBLFilterGGX = new IBLFilterGGX(asset.renderPipelineResources, m_MipGenerator);
m_LightLoop.Build(asset, m_ShadowSettings, m_IBLFilterGGX);

m_SSSBufferManager.InitSSSBuffers(m_GbufferManager, m_Asset.renderPipelineSettings);
m_NormalBufferManager.InitNormalBuffers(m_GbufferManager, m_Asset.renderPipelineSettings);
m_CameraColorBuffer = RTHandles.Alloc(Vector2.one, filterMode: FilterMode.Point, colorFormat: RenderTextureFormat.ARGBHalf, sRGB: false, enableRandomWrite: true, enableMSAA: true, name: "CameraColor");
m_CameraColorBuffer = RTHandles.Alloc(Vector2.one, filterMode: FilterMode.Point, colorFormat: RenderTextureFormat.ARGBHalf, sRGB: false, enableRandomWrite: true, enableMSAA: true, useMipMap: true, autoGenerateMips: false, name: "CameraColor");
m_CameraDepthStencilBuffer = RTHandles.Alloc(Vector2.one, depthBufferBits: DepthBits.Depth24, colorFormat: RenderTextureFormat.Depth, filterMode: FilterMode.Point, bindTextureMS: true, enableMSAA: true, name: "CameraDepthStencil");
m_CameraDepthStencilBuffer = RTHandles.Alloc(Vector2.one, depthBufferBits: DepthBits.Depth32, colorFormat: RenderTextureFormat.Depth, filterMode: FilterMode.Point, bindTextureMS: true, enableMSAA: true, name: "CameraDepthStencil");
m_CameraDepthBufferCopy = RTHandles.Alloc(Vector2.one, depthBufferBits: DepthBits.Depth24, colorFormat: RenderTextureFormat.Depth, filterMode: FilterMode.Point, bindTextureMS: true, enableMSAA: true, name: "CameraDepthStencilCopy");
m_CameraDepthBufferMipChain = RTHandles.Alloc(Vector2.one, colorFormat: RenderTextureFormat.RFloat, filterMode: FilterMode.Point, sRGB: false, bindTextureMS: true, enableMSAA: true, useMipMap: true, autoGenerateMips: false, enableRandomWrite: true, name: "CameraDepthBufferMipChain");
}
// Technically we won't need this buffer in some cases, but nothing that we can determine at init time.

RTHandles.Release(m_CameraSssDiffuseLightingBuffer);
RTHandles.Release(m_CameraDepthStencilBuffer);
RTHandles.Release(m_CameraDepthBufferCopy);
RTHandles.Release(m_CameraDepthBufferMipChain);
RTHandles.Release(m_CameraStencilBufferCopy);
RTHandles.Release(m_AmbientOcclusionBuffer);

PushGlobalRTHandle(
cmd,
hdCamera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.DepthPyramid),
m_CameraDepthBufferMipChain,
HDShaderIDs._DepthPyramidTexture,
HDShaderIDs._DepthPyramidSize,
HDShaderIDs._DepthPyramidScale

hdCamera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.ColorPyramid),
m_CameraColorBuffer,
HDShaderIDs._ColorPyramidTexture,
HDShaderIDs._ColorPyramidSize,
HDShaderIDs._ColorPyramidScale

bool NeedDepthBufferCopy()
{
// For now we consider all console to be able to read from a bound depth buffer.
return !IsConsolePlatform();
// We always need it for SSR since depth textures do not support MIP maps.
return !IsConsolePlatform()
|| m_Asset.GetFrameSettings().enableRoughRefraction
|| m_Asset.GetFrameSettings().enableSSR;
}
bool NeedStencilBufferCopy()

RTHandleSystem.RTHandle GetDepthTexture()
{
return NeedDepthBufferCopy() ? m_CameraDepthBufferCopy : m_CameraDepthStencilBuffer;
return NeedDepthBufferCopy() ? m_CameraDepthBufferMipChain : m_CameraDepthStencilBuffer;
}
void CopyDepthBufferIfNeeded(CommandBuffer cmd)

if (NeedDepthBufferCopy())
{
using (new ProfilingSample(cmd, "Copy depth-stencil buffer", CustomSamplerId.CopyDepthStencilbuffer.GetSampler()))
using (new ProfilingSample(cmd, "Copy depth buffer", CustomSamplerId.CopyDepthBuffer.GetSampler()))
cmd.CopyTexture(m_CameraDepthStencilBuffer, m_CameraDepthBufferCopy);
// TODO: maybe we don't actually need the top MIP level?
// That way we could avoid making the copy, and build the MIP hierarchy directly.
// The downside is that our SSR tracing accuracy would decrease a little bit.
// But since we never render SSR at full resolution, this may be acceptable.
m_GPUCopy.SampleCopyChannel_xyzw2x(cmd, m_CameraDepthStencilBuffer, m_CameraDepthBufferMipChain, new RectInt(0, 0, m_CurrentWidth, m_CurrentHeight));
}
}
}

// Depth texture is now ready, bind it (Depth buffer could have been bind before if DBuffer is enable)
cmd.SetGlobalTexture(HDShaderIDs._CameraDepthTexture, GetDepthTexture());
RenderDepthPyramid(hdCamera, cmd, renderContext, FullScreenDebugMode.DepthPyramid);
RenderDepthPyramid(hdCamera, cmd, FullScreenDebugMode.DepthPyramid);
// TODO: In the future we will render object velocity at the same time as depth prepass (we need C++ modification for this)
// Once the C++ change is here we will first render all object without motion vector then motion vector object

// Render pre refraction objects
RenderForward(m_CullResults, hdCamera, renderContext, cmd, ForwardPass.PreRefraction);
RenderColorPyramid(hdCamera, cmd, renderContext, true);
RenderColorPyramid(hdCamera, cmd, true);
// Render all type of transparent forward (unlit, lit, complex (hair...)) to keep the sorting between transparent objects.
RenderForward(m_CullResults, hdCamera, renderContext, cmd, ForwardPass.Transparent);

// Fill depth buffer to reduce artifact for transparent object during postprocess
RenderTransparentDepthPostpass(m_CullResults, hdCamera, renderContext, cmd);
RenderColorPyramid(hdCamera, cmd, renderContext, false);
RenderColorPyramid(hdCamera, cmd, false);
AccumulateDistortion(m_CullResults, hdCamera, renderContext, cmd);
RenderDistortion(hdCamera, cmd, m_Asset.renderPipelineResources);

using (new ProfilingSample(cmd, "ApplyDistortion", CustomSamplerId.ApplyDistortion.GetSampler()))
{
var colorPyramidRT = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.ColorPyramid);
var pyramidScale = m_BufferPyramid.GetPyramidToScreenScale(hdCamera, colorPyramidRT);
var pyramidScale = m_BufferPyramid.GetPyramidToScreenScale(hdCamera, m_CameraColorBuffer);
// Need to account for the fact that the gaussian pyramid is actually rendered inside the camera viewport in a square texture so we mutiply by the PyramidToScreen scale
var size = new Vector4(hdCamera.screenSize.x, hdCamera.screenSize.y, pyramidScale.x / hdCamera.screenSize.x, pyramidScale.y / hdCamera.screenSize.y);

cmd.SetComputeTextureParam(m_applyDistortionCS, m_applyDistortionKernel, HDShaderIDs._ColorPyramidTexture, colorPyramidRT);
cmd.SetComputeTextureParam(m_applyDistortionCS, m_applyDistortionKernel, HDShaderIDs._CameraColorTexture, m_CameraColorBuffer);
cmd.SetComputeTextureParam(m_applyDistortionCS, m_applyDistortionKernel, HDShaderIDs._ColorPyramidTexture, m_CameraColorBuffer);
cmd.SetComputeTextureParam(m_applyDistortionCS, m_applyDistortionKernel, HDShaderIDs._Destination, m_CameraColorBuffer);
cmd.SetComputeVectorParam(m_applyDistortionCS, HDShaderIDs._Size, size);
cmd.DispatchCompute(m_applyDistortionCS, m_applyDistortionKernel, Mathf.CeilToInt(size.x / x), Mathf.CeilToInt(size.y / y), 1);

}
}
void RenderColorPyramid(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext renderContext, bool isPreRefraction)
void RenderColorPyramid(HDCamera hdCamera, CommandBuffer cmd, bool isPreRefraction)
{
if (isPreRefraction)
{

return;
}
// TODO: Move allocation in separate method call in start of the render loop
var cameraRT = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.ColorPyramid)
?? hdCamera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.ColorPyramid, m_BufferPyramid.AllocColorRT);
int lodCount;
using (new ProfilingSample(cmd, "Color Pyramid", CustomSamplerId.ColorPyramid.GetSampler()))
m_BufferPyramid.RenderColorPyramid(hdCamera, cmd, renderContext, m_CameraColorBuffer, cameraRT);
Vector2 pyramidScale = m_BufferPyramid.GetPyramidToScreenScale(hdCamera, cameraRT);
PushFullScreenDebugTextureMip(hdCamera, cmd, cameraRT, m_BufferPyramid.GetPyramidLodCount(new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight)), new Vector4(pyramidScale.x, pyramidScale.y, 0.0f, 0.0f), isPreRefraction ? FullScreenDebugMode.PreRefractionColorPyramid : FullScreenDebugMode.FinalColorPyramid);
using (new ProfilingSample(cmd, "Color Gaussian MIP Chain", CustomSamplerId.ColorPyramid))
{
var size = new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight);
lodCount = m_MipGenerator.RenderColorGaussianPyramid(cmd, size, m_CameraColorBuffer);
}
float scaleX = hdCamera.actualWidth / (float)m_CameraColorBuffer.rt.width;
float scaleY = hdCamera.actualHeight / (float)m_CameraColorBuffer.rt.height;
cmd.SetGlobalTexture(HDShaderIDs._ColorPyramidTexture, m_CameraColorBuffer);
cmd.SetGlobalVector(HDShaderIDs._ColorPyramidSize, new Vector4(hdCamera.actualWidth, hdCamera.actualHeight, 1f / hdCamera.actualWidth, 1f / hdCamera.actualHeight));
cmd.SetGlobalVector(HDShaderIDs._ColorPyramidScale, new Vector4(scaleX, scaleY, lodCount, 0.0f));
PushFullScreenDebugTextureMip(hdCamera, cmd, m_CameraColorBuffer, lodCount, new Vector4(scaleX, scaleY, 0f, 0f), isPreRefraction ? FullScreenDebugMode.PreRefractionColorPyramid : FullScreenDebugMode.FinalColorPyramid);
void RenderDepthPyramid(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext renderContext, FullScreenDebugMode debugMode)
void RenderDepthPyramid(HDCamera hdCamera, CommandBuffer cmd, FullScreenDebugMode debugMode)
if (!hdCamera.frameSettings.enableRoughRefraction)
if (!hdCamera.frameSettings.enableRoughRefraction && !hdCamera.frameSettings.enableSSR)
// TODO: Move allocation in separate method call in start of the render loop
var cameraRT = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.DepthPyramid)
?? hdCamera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.DepthPyramid, m_BufferPyramid.AllocDepthRT);
int lodCount;
using (new ProfilingSample(cmd, "Depth Pyramid", CustomSamplerId.DepthPyramid.GetSampler()))
m_BufferPyramid.RenderDepthPyramid(hdCamera, cmd, renderContext, GetDepthTexture(), cameraRT);
using (new ProfilingSample(cmd, "Depth Buffer MIP Chain", CustomSamplerId.DepthPyramid))
{
var size = new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight);
lodCount = m_MipGenerator.RenderMinDepthPyramid(cmd, size, m_CameraDepthBufferMipChain);
}
Vector2 pyramidScale = m_BufferPyramid.GetPyramidToScreenScale(hdCamera, cameraRT);
PushFullScreenDebugTextureMip(hdCamera, cmd, cameraRT, m_BufferPyramid.GetPyramidLodCount(new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight)), new Vector4(pyramidScale.x, pyramidScale.y, 0.0f, 0.0f), debugMode);
float scaleX = hdCamera.actualWidth / (float)m_CameraDepthBufferMipChain.rt.width;
float scaleY = hdCamera.actualHeight / (float)m_CameraDepthBufferMipChain.rt.height;
cmd.SetGlobalTexture(HDShaderIDs._DepthPyramidTexture, m_CameraDepthBufferMipChain);
cmd.SetGlobalVector(HDShaderIDs._DepthPyramidSize, new Vector4(hdCamera.actualWidth, hdCamera.actualHeight, 1f / hdCamera.actualWidth, 1f / hdCamera.actualHeight));
cmd.SetGlobalVector(HDShaderIDs._DepthPyramidScale, new Vector4(scaleX, scaleY, lodCount, 0.0f));
PushFullScreenDebugTextureMip(hdCamera, cmd, m_CameraDepthBufferMipChain, lodCount, new Vector4(scaleX, scaleY, 0f, 0f), debugMode);
}
void RenderPostProcess(HDCamera hdcamera, CommandBuffer cmd, PostProcessLayer layer)

4
com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDStringConstants.cs


public static readonly int _PixelCoordToViewDirWS = Shader.PropertyToID("_PixelCoordToViewDirWS");
public static readonly int _Size = Shader.PropertyToID("_Size");
public static readonly int _Source4 = Shader.PropertyToID("_Source4");
public static readonly int _Result1 = Shader.PropertyToID("_Result1");
public static readonly int _Source = Shader.PropertyToID("_Source");
public static readonly int _Destination = Shader.PropertyToID("_Destination");
public static readonly int _AtmosphericScatteringType = Shader.PropertyToID("_AtmosphericScatteringType");
public static readonly int _AmbientProbeCoeffs = Shader.PropertyToID("_AmbientProbeCoeffs");

4
com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/ApplyDistorsion.compute


TEXTURE2D(_DistortionTexture);
TEXTURE2D(_ColorPyramidTexture);
RW_TEXTURE2D(float4, _CameraColorTexture);
RW_TEXTURE2D(float4, _Destination);
SamplerState sampler_ColorPyramidTexture;

float mip = (_ColorPyramidScale.z - 1) * clamp(distortionBlur, 0.0, 1.0);
float4 sampled = SAMPLE_TEXTURE2D_LOD(_ColorPyramidTexture, sampler_ColorPyramidTexture, distordedUV, mip);
_CameraColorTexture[dispatchThreadId] = sampled;
_Destination[dispatchThreadId] = sampled;
}

6
com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramidProcessor.cs


)
{
m_ColorPyramidCS = colorPyramidCS;
m_ColorPyramidKernel = m_ColorPyramidCS.FindKernel("KMain");
m_ColorPyramidKernel = m_ColorPyramidCS.FindKernel("KColorGaussian");
m_DepthPyramidCS.FindKernel("KDepthDownSample8"),
m_DepthPyramidCS.FindKernel("KDepthDownSample1")
//m_DepthPyramidCS.FindKernel("KDepthDownSample8"),
//m_DepthPyramidCS.FindKernel("KDepthDownSample1")
};
m_TexturePadding = texturePadding;

41
com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/ColorPyramid.compute


#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch
Texture2D<float4> _Source;
RWTexture2D<float4> _Result;
#pragma kernel KColorGaussian KERNEL_SIZE=8 MAIN_GAUSSIAN=KColorGaussian
#pragma kernel KColorDownsample KERNEL_SIZE=8 MAIN_DOWNSAMPLE=KColorDownsample
RWTexture2D<float4> _Source;
RWTexture2D<float4> _Destination;
float4 _Size;
float4 _Size; // x: src width, y: src height, zw: unused
CBUFFER_END
// 16x16 pixels with an 8x8 center that we will be blurring writing out. Each uint is two color

float4 blurred = BlurPixels(s0, s1, s2, s3, s4, s5, s6, s7, s8);
// Write to the final target
_Result[pixelCoord] = blurred;
_Destination[pixelCoord] = blurred;
#pragma kernel KMain
[numthreads(8, 8, 1)]
void KMain(uint2 groupId : SV_GroupID, uint2 groupThreadId : SV_GroupThreadID, uint2 dispatchThreadId : SV_DispatchThreadID)
[numthreads(KERNEL_SIZE, KERNEL_SIZE, 1)]
void MAIN_GAUSSIAN(uint2 groupId : SV_GroupID, uint2 groupThreadId : SV_GroupThreadID, uint2 dispatchThreadId : SV_DispatchThreadID)
// Downsample the block
float2 offset = float2(threadUL);
float4 p00 = _Source.SampleLevel(sampler_LinearClamp, (offset + 0.5) * _Size.zw, 0.0);
float4 p10 = _Source.SampleLevel(sampler_LinearClamp, (offset + float2(1.0, 0.0) + 0.5) * _Size.zw, 0.0);
float4 p01 = _Source.SampleLevel(sampler_LinearClamp, (offset + float2(0.0, 1.0) + 0.5) * _Size.zw, 0.0);
float4 p11 = _Source.SampleLevel(sampler_LinearClamp, (offset + float2(1.0, 1.0) + 0.5) * _Size.zw, 0.0);
uint2 size = uint2(_Size.xy) - 1u;
float4 p00 = _Source[clamp(threadUL + uint2(0u, 0u), 0u, size)];
float4 p10 = _Source[clamp(threadUL + uint2(1u, 0u), 0u, size)];
float4 p11 = _Source[clamp(threadUL + uint2(1u, 1u), 0u, size)];
float4 p01 = _Source[clamp(threadUL + uint2(0u, 1u), 0u, size)];
// Store the 4 downsampled pixels in LDS
uint destIdx = groupThreadId.x + (groupThreadId.y << 4u);

// Vertically blur the pixels in LDS and write the result to memory
BlurVertically(dispatchThreadId, (groupThreadId.y << 3u) + groupThreadId.x);
}
[numthreads(KERNEL_SIZE, KERNEL_SIZE, 1)]
void KColorDownsample(uint2 dispatchThreadId : SV_DispatchThreadID)
{
uint2 offset = dispatchThreadId * 2u;
uint2 size = uint2(_Size.xy) - 1u;
float4 p00 = _Source[clamp(offset + uint2(0u, 0u), 0u, size)];
float4 p10 = _Source[clamp(offset + uint2(1u, 0u), 0u, size)];
float4 p11 = _Source[clamp(offset + uint2(1u, 1u), 0u, size)];
float4 p01 = _Source[clamp(offset + uint2(0u, 1u), 0u, size)];
_Destination[dispatchThreadId] = (p00 + p01 + p11 + p10) * 0.25;
}

62
com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/DepthPyramid.compute


#include "CoreRP/ShaderLibrary/Common.hlsl"
// ------------------------------------------------
// Algorithm
// ------------------------------------------------
// Downsample a depth texture by taking min value of sampled pixels
// ------------------------------------------------
// Variants
// ------------------------------------------------
#pragma kernel KDepthDownSample8 KERNEL_SIZE=8 KERNEL_NAME=KDepthDownSample8
#pragma kernel KDepthDownSample1 KERNEL_SIZE=1 KERNEL_NAME=KDepthDownSample1
// ------------------------------------------------
// Texture buffers
// ------------------------------------------------
#pragma kernel KDepthDownsample8DualUav KERNEL_SIZE=8 KERNEL_NAME=KDepthDownsample8DualUav
Texture2D<float2> _Source;
RW_TEXTURE2D(float2, _Result);
SamplerState sampler_PointClamp; //TODO: could we use min-sampler instead of using ALU?
RW_TEXTURE2D(float, _Destination);
RW_TEXTURE2D(float, _Source);
// ------------------------------------------------
// Constant buffers
// ------------------------------------------------
float4 _SrcSize;
int2 _RectOffset; // Offset in source texture
float4 _Size; // x: src width, y: src height, zw: unused
// ------------------------------------------------
// Kernel
// ------------------------------------------------
# define MAX_DEPTH(l, r) min(l, r)
# define MAX_DEPTH(l, r) max(l, r)
// Downsample a depth texture by taking the min value of sampled pixels
// The size of the dispatch is (DstMipSize / KernelSize).
void KERNEL_NAME(uint2 groupId : SV_GroupID, uint2 groupThreadId : SV_GroupThreadID, uint2 dispatchThreadId : SV_DispatchThreadID)
void KERNEL_NAME(uint2 dispatchThreadId : SV_DispatchThreadID)
uint2 srcPixelUL = _RectOffset + (dispatchThreadId << 1);
// Offset by 0.5 so sampling get the proper pixels
float2 offset = float2(srcPixelUL) + 0.5;
uint2 srcPixelUL = dispatchThreadId << 1;
#if defined(PLATFORM_SUPPORT_GATHER)
float4 depths = GATHER_RED_TEXTURE2D(_Source, sampler_PointClamp, offset * _SrcSize.zw).wzxy;
#else
float p00 = SAMPLE_TEXTURE2D_LOD(_Source, sampler_PointClamp, (offset) * _SrcSize.zw, 0.0).x;
float p10 = SAMPLE_TEXTURE2D_LOD(_Source, sampler_PointClamp, (offset + float2(1.0, 0.0)) * _SrcSize.zw, 0.0).x;
float p01 = SAMPLE_TEXTURE2D_LOD(_Source, sampler_PointClamp, (offset + float2(0.0, 1.0)) * _SrcSize.zw, 0.0).x;
float p11 = SAMPLE_TEXTURE2D_LOD(_Source, sampler_PointClamp, (offset + float2(1.0, 1.0)) * _SrcSize.zw, 0.0).x;
// '_Source' and '_Destination' are two different MIP levels of the same texture.
// TODO: Use Gather here instead of 4 loads
uint2 size = uint2(_Size.xy) - 1u;
float p00 = _Source[min(srcPixelUL + uint2(0u, 0u), size)];
float p10 = _Source[min(srcPixelUL + uint2(1u, 0u), size)];
float p01 = _Source[min(srcPixelUL + uint2(0u, 1u), size)];
float p11 = _Source[min(srcPixelUL + uint2(1u, 1u), size)];
#endif
float maxDepth = MAX_DEPTH(MAX_DEPTH(depths.x, depths.y), MAX_DEPTH(depths.z, depths.w));
uint2 dstPixel = (_RectOffset >> 1) + dispatchThreadId;
_Result[dstPixel] = float2(minDepth, maxDepth);
_Destination[dispatchThreadId] = minDepth;
#undef MAX_DEPTH

126
com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/MipGenerator.cs


using UnityEngine.Assertions;
using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
using RTHandle = RTHandleSystem.RTHandle;
public class MipGenerator
{
RTHandle m_TempFullscreenTarget;
ComputeShader m_DepthPyramidCS;
ComputeShader m_ColorPyramidCS;
int m_DepthDownsampleKernel;
int m_ColorDownsampleKernel;
int m_ColorGaussianKernel;
public MipGenerator(HDRenderPipelineAsset asset)
{
m_DepthPyramidCS = asset.renderPipelineResources.depthPyramidCS;
m_ColorPyramidCS = asset.renderPipelineResources.colorPyramidCS;
m_DepthDownsampleKernel = m_DepthPyramidCS.FindKernel("KDepthDownsample8DualUav");
m_ColorDownsampleKernel = m_ColorPyramidCS.FindKernel("KColorDownsample");
m_ColorGaussianKernel = m_ColorPyramidCS.FindKernel("KColorGaussian");
}
public void Release()
{
RTHandles.Release(m_TempFullscreenTarget);
m_TempFullscreenTarget = null;
}
// Generates an in-place depth pyramid
// Returns the number of generated mips
// TODO: Mip-mapping depth is problematic for precision at lower mips, generate a packed atlas instead
public int RenderMinDepthPyramid(CommandBuffer cmd, Vector2Int size, RTHandle texture)
{
var cs = m_DepthPyramidCS;
int kernel = m_DepthDownsampleKernel;
int srcMipLevel = 0;
int srcMipWidth = size.x;
int srcMipHeight = size.y;
// TODO: Do it 1x MIP at a time for now. In the future, do 4x MIPs per pass, or even use a single pass.
// Note: Gather() doesn't take a LOD parameter and we cannot bind an SRV of a MIP level,
// and we don't support Min samplers either. So we are forced to perform 4x loads.
while (srcMipWidth >= 2 || srcMipHeight >= 2)
{
int dstMipWidth = Mathf.Max(1, srcMipWidth >> 1);
int dstMipHeight = Mathf.Max(1, srcMipHeight >> 1);
cmd.SetComputeVectorParam(cs, HDShaderIDs._Size, new Vector4(srcMipWidth, srcMipHeight, 0f, 0f));
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._Source, texture, srcMipLevel);
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._Destination, texture, srcMipLevel + 1);
cmd.DispatchCompute(cs, kernel, (dstMipWidth + 7) / 8, (dstMipHeight + 7) / 8, 1);
srcMipLevel++;
srcMipWidth = srcMipWidth >> 1;
srcMipHeight = srcMipHeight >> 1;
}
return srcMipLevel - 1;
}
// Generates an in-place gaussian pyramid
// Returns the number of mips
public int RenderColorGaussianPyramid(CommandBuffer cmd, Vector2Int size, RTHandle texture)
{
return RenderColorGaussianPyramid(cmd, size, texture.rt);
}
// Need this RenderTexture variant because some of the code in HDRP still hasn't switched to
// the RTHandle system :(
public int RenderColorGaussianPyramid(CommandBuffer cmd, Vector2Int size, RenderTexture texture)
{
// Only create the temporary target on-demand in case the game doesn't actually need it
if (m_TempFullscreenTarget == null)
{
m_TempFullscreenTarget = RTHandles.Alloc(
Vector2.one * 0.5f,
filterMode: FilterMode.Bilinear,
colorFormat: RenderTextureFormat.ARGBHalf,
sRGB: false,
enableRandomWrite: true,
useMipMap: false,
enableMSAA: false,
name: "Temp Gaussian Pyramid Target"
);
}
var cs = m_ColorPyramidCS;
int downsampleKernel = m_ColorDownsampleKernel;
int gaussianKernel = m_ColorGaussianKernel;
int srcMipLevel = 0;
int srcMipWidth = size.x;
int srcMipHeight = size.y;
// Note: smaller mips are excluded as we don't need them and the gaussian compute works
// on 8x8 blocks
// TODO: Could be further optimized by merging the smaller mips to reduce the amount of dispatches
while (srcMipWidth >= 2 || srcMipHeight >= 2)
{
int dstMipWidth = Mathf.Max(1, srcMipWidth >> 1);
int dstMipHeight = Mathf.Max(1, srcMipHeight >> 1);
cmd.SetComputeVectorParam(cs, HDShaderIDs._Size, new Vector4(srcMipWidth, srcMipHeight, 0f, 0f));
cmd.SetComputeTextureParam(cs, downsampleKernel, HDShaderIDs._Source, texture, srcMipLevel);
cmd.SetComputeTextureParam(cs, downsampleKernel, HDShaderIDs._Destination, m_TempFullscreenTarget);
cmd.DispatchCompute(cs, downsampleKernel, (dstMipWidth + 7) / 8, (dstMipHeight + 7) / 8, 1);
cmd.SetComputeVectorParam(cs, HDShaderIDs._Size, new Vector4(dstMipWidth, dstMipHeight, 0f, 0f));
cmd.SetComputeTextureParam(cs, gaussianKernel, HDShaderIDs._Source, m_TempFullscreenTarget);
cmd.SetComputeTextureParam(cs, gaussianKernel, HDShaderIDs._Destination, texture, srcMipLevel + 1);
cmd.DispatchCompute(cs, gaussianKernel, (dstMipWidth + 7) / 8, (dstMipHeight + 7) / 8, 1);
srcMipLevel++;
srcMipWidth = srcMipWidth >> 1;
srcMipHeight = srcMipHeight >> 1;
}
return srcMipLevel - 1;
}
}
}

11
com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/MipGenerator.cs.meta


fileFormatVersion: 2
guid: 9fb5527a68d5789439b1caea92b87bdf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存