浏览代码

Merge pull request #1904 from Unity-Technologies/pyramid-rework

Pyramid rework
/main
GitHub 6 年前
当前提交
1d71d3d6
共有 27 个文件被更改,包括 2773 次插入3188 次删除
  1. 998
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1101_Unlit.png
  2. 6
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1101_Unlit.png.meta
  3. 999
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1102_Unlit_Distortion.png
  4. 17
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1102_Unlit_Distortion.png.meta
  5. 998
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1103_Unlit_Distortion_DepthTest.png
  6. 6
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1103_Unlit_Distortion_DepthTest.png.meta
  7. 999
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1205_Lit_Transparent_Refraction.png
  8. 6
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1205_Lit_Transparent_Refraction.png.meta
  9. 998
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1206_Lit_Transparent_Distortion.png
  10. 6
      TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1206_Lit_Transparent_Distortion.png.meta
  11. 6
      com.unity.render-pipelines.core/CoreRP/Textures/DepthBits.cs
  12. 3
      com.unity.render-pipelines.high-definition/CHANGELOG.md
  13. 4
      com.unity.render-pipelines.high-definition/HDRP/Camera/HDCameraFrameHistoryType.cs
  14. 1
      com.unity.render-pipelines.high-definition/HDRP/Lighting/Reflection/PlanarReflectionProbeCache.cs
  15. 83
      com.unity.render-pipelines.high-definition/HDRP/Material/GGXConvolution/RuntimeFilterIBL.cs
  16. 2
      com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDCustomSamplerId.cs
  17. 114
      com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDRenderPipeline.cs
  18. 5
      com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDStringConstants.cs
  19. 9
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/ApplyDistorsion.compute
  20. 58
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/ColorPyramid.compute
  21. 62
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/DepthPyramid.compute
  22. 136
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/MipGenerator.cs
  23. 11
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/MipGenerator.cs.meta
  24. 11
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramid.cs.meta
  25. 176
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramid.cs
  26. 11
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramidProcessor.cs.meta
  27. 236
      com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramidProcessor.cs

998
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1101_Unlit.png
文件差异内容过多而无法显示
查看文件

6
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1101_Unlit.png.meta


fileFormatVersion: 2
guid: a3f1cb86a1e031a44bd3380ab40642cf
guid: c14640e6cd052a54dbedd03d1de4b094
serializedVersion: 6
serializedVersion: 7
mipmaps:
mipMapMode: 0
enableMipMap: 0

edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

999
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1102_Unlit_Distortion.png
文件差异内容过多而无法显示
查看文件

17
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1102_Unlit_Distortion.png.meta


fileFormatVersion: 2
guid: 74ce626098389e144ae57a1c9e1ad613
guid: 63d4d615f7b52154984007cacaf2f082
serializedVersion: 6
serializedVersion: 7
mipmaps:
mipMapMode: 0
enableMipMap: 0

allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []

edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

998
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1103_Unlit_Distortion_DepthTest.png
文件差异内容过多而无法显示
查看文件

6
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1103_Unlit_Distortion_DepthTest.png.meta


fileFormatVersion: 2
guid: 5a59cd7fd9c84cb4ca0f998edbb72442
guid: 1e3e18c578889334ba442b1bdab350d1
serializedVersion: 6
serializedVersion: 7
mipmaps:
mipMapMode: 0
enableMipMap: 0

edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

999
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1205_Lit_Transparent_Refraction.png
文件差异内容过多而无法显示
查看文件

6
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1205_Lit_Transparent_Refraction.png.meta


fileFormatVersion: 2
guid: 5812afd0981a5ff4392f8a3ad2fa1080
guid: 5909ed2ce8074034fa8a856ce381404f
serializedVersion: 6
serializedVersion: 7
mipmaps:
mipMapMode: 0
enableMipMap: 0

edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

998
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1206_Lit_Transparent_Distortion.png
文件差异内容过多而无法显示
查看文件

6
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1206_Lit_Transparent_Distortion.png.meta


fileFormatVersion: 2
guid: b2dd9eeef86426449b5f1a674ab0a5cf
guid: e520e0ec1f31e394fbb8f6b074f6731a
serializedVersion: 6
serializedVersion: 7
mipmaps:
mipMapMode: 0
enableMipMap: 0

edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

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
}
}

3
com.unity.render-pipelines.high-definition/CHANGELOG.md


### Fixed
- Fixed an issue where sometimes the deferred shadow texture would not be valid, causing wrong rendering.
### Changed
- Changed the way depth & color pyramids are built to be faster and better quality, thus improving the look of distortion and refraction.
## [3.3.0-preview]
### Added

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


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

1
com.unity.render-pipelines.high-definition/HDRP/Lighting/Reflection/PlanarReflectionProbeCache.cs


m_ConvolutionTargetTexture.useMipMap = true;
m_ConvolutionTargetTexture.autoGenerateMips = false;
m_ConvolutionTargetTexture.name = CoreUtils.GetRenderTargetAutoName(m_ProbeSize, m_ProbeSize, 1, RenderTextureFormat.ARGBHalf, "PlanarReflectionConvolution", mips: true);
m_ConvolutionTargetTexture.enableRandomWrite = true;
m_ConvolutionTargetTexture.Create();
InitializeProbeBakingStates();

83
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,

FilterCubemapCommon(cmd, source, target, m_faceWorldToViewMatrixMatrices);
}
public void FilterPlanarTexture(CommandBuffer cmd, Texture source, RenderTexture target)
public void FilterPlanarTexture(CommandBuffer cmd, RenderTexture 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
);
m_MipGenerator.RenderColorGaussianPyramid(cmd, new Vector2Int(source.width, source.height), source, 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,

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


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

// 'm_CameraColorBuffer' does not contain diffuse lighting of SSS materials until the SSS pass. It is stored within 'm_CameraSssDiffuseLightingBuffer'.
RTHandleSystem.RTHandle m_CameraColorBuffer;
RTHandleSystem.RTHandle m_CameraColorBufferMipChain;
RTHandleSystem.RTHandle m_CameraDepthBufferCopy;
RTHandleSystem.RTHandle m_CameraDepthBufferMipChain;
RTHandleSystem.RTHandle m_CameraStencilBufferCopy;
RTHandleSystem.RTHandle m_VelocityBuffer;

m_GPUCopy = new GPUCopy(asset.renderPipelineResources.copyChannelCS);
var bufferPyramidProcessor = new BufferPyramidProcessor(
asset.renderPipelineResources.colorPyramidCS,
asset.renderPipelineResources.depthPyramidCS,
m_GPUCopy,
new TexturePadding(asset.renderPipelineResources.texturePaddingCS)
);
m_BufferPyramid = new BufferPyramid(bufferPyramidProcessor);
m_MipGenerator = new MipGenerator(m_Asset);
EncodeBC6H.DefaultInstance = EncodeBC6H.DefaultInstance ?? new EncodeBC6H(asset.renderPipelineResources.encodeBC6HCS);

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: false, name: "CameraColor");
m_CameraColorBufferMipChain = RTHandles.Alloc(Vector2.one, filterMode: FilterMode.Point, colorFormat: RenderTextureFormat.ARGBHalf, sRGB: false, enableRandomWrite: true, enableMSAA: false, useMipMap: true, autoGenerateMips: false, name: "CameraColorBufferMipChain");
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.

{
m_GbufferManager.DestroyBuffers();
m_DbufferManager.DestroyBuffers();
m_BufferPyramid.DestroyBuffers();
m_MipGenerator.Release();
RTHandles.Release(m_CameraColorBufferMipChain);
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_CameraColorBufferMipChain,
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);
RenderDistortion(hdCamera, cmd, m_Asset.renderPipelineResources);
RenderDistortion(hdCamera, cmd);
StopStereoRendering(renderContext, hdCamera);

}
}
void RenderDistortion(HDCamera hdCamera, CommandBuffer cmd, RenderPipelineResources resources)
void RenderDistortion(HDCamera hdCamera, CommandBuffer cmd)
{
if (!hdCamera.frameSettings.enableDistortion)
return;

var colorPyramidRT = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.ColorPyramid);
var pyramidScale = m_BufferPyramid.GetPyramidToScreenScale(hdCamera, colorPyramidRT);
// 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);
var size = new Vector4(hdCamera.actualWidth, hdCamera.actualHeight, 1f / hdCamera.actualWidth, 1f / hdCamera.actualHeight);
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_CameraColorBufferMipChain);
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, m_CameraColorBufferMipChain);
}
float scaleX = hdCamera.actualWidth / (float)m_CameraColorBufferMipChain.rt.width;
float scaleY = hdCamera.actualHeight / (float)m_CameraColorBufferMipChain.rt.height;
cmd.SetGlobalTexture(HDShaderIDs._ColorPyramidTexture, m_CameraColorBufferMipChain);
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_CameraColorBufferMipChain, 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)

5
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 _Mip0 = Shader.PropertyToID("_Mip0");
public static readonly int _AtmosphericScatteringType = Shader.PropertyToID("_AtmosphericScatteringType");
public static readonly int _AmbientProbeCoeffs = Shader.PropertyToID("_AmbientProbeCoeffs");

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


#include "CoreRP/ShaderLibrary/Common.hlsl"
#include "HDRP/Material/Builtin/BuiltinData.hlsl"
#include "HDRP/ShaderVariables.hlsl"
TEXTURE2D(_ColorPyramidTexture);
RW_TEXTURE2D(float4, _CameraColorTexture);
RW_TEXTURE2D(float4, _Destination);
float4 _ColorPyramidScale;
CBUFFER_END
#pragma kernel KMain

return;
// Get source pixel for distortion
float2 distordedUV = float2(dispatchThreadId + int2(distortion * _FetchBias)) * _Size.zw;
float2 distordedUV = float2(dispatchThreadId + int2(distortion * _FetchBias)) * _Size.zw * _ScreenToTargetScale.xy;
_CameraColorTexture[dispatchThreadId] = sampled;
_Destination[dispatchThreadId] = sampled;
}

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


#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch
#pragma kernel KColorGaussian KERNEL_SIZE=8 MAIN_GAUSSIAN=KColorGaussian
#pragma kernel KColorDownsample KERNEL_SIZE=8 MAIN_DOWNSAMPLE=KColorDownsample
#pragma kernel KColorDownsampleCopyMip0 KERNEL_SIZE=8 MAIN_DOWNSAMPLE=KColorDownsampleCopyMip0 COPY_MIP_0
#if COPY_MIP_0
RWTexture2D<float4> _Result;
RWTexture2D<float4> _Mip0;
#else
RWTexture2D<float4> _Source;
#endif
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 MAIN_DOWNSAMPLE(uint2 dispatchThreadId : SV_DispatchThreadID)
{
uint2 offset = dispatchThreadId * 2u;
uint2 size = uint2(_Size.xy) - 1u;
uint2 c00 = clamp(offset + uint2(0u, 0u), 0u, size);
uint2 c10 = clamp(offset + uint2(1u, 0u), 0u, size);
uint2 c11 = clamp(offset + uint2(1u, 1u), 0u, size);
uint2 c01 = clamp(offset + uint2(0u, 1u), 0u, size);
float4 p00 = _Source[c00];
float4 p10 = _Source[c10];
float4 p11 = _Source[c11];
float4 p01 = _Source[c01];
#if COPY_MIP_0
_Mip0[c00] = p00;
_Mip0[c10] = p10;
_Mip0[c11] = p11;
_Mip0[c01] = p01;
#endif
_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

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


using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
using RTHandle = RTHandleSystem.RTHandle;
public class MipGenerator
{
RTHandle m_TempColorTarget;
ComputeShader m_DepthPyramidCS;
ComputeShader m_ColorPyramidCS;
int m_DepthDownsampleKernel;
int m_ColorDownsampleKernel;
int m_ColorDownsampleKernelCopyMip0;
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_ColorDownsampleKernelCopyMip0 = m_ColorPyramidCS.FindKernel("KColorDownsampleCopyMip0");
m_ColorGaussianKernel = m_ColorPyramidCS.FindKernel("KColorGaussian");
}
public void Release()
{
RTHandles.Release(m_TempColorTarget);
m_TempColorTarget = 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, RenderTexture 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 the gaussian pyramid of source into destination
// We can't do it in place as the color pyramid has to be read while writing to the color
// buffer in some cases (e.g. refraction, distortion)
// Returns the number of mips
public int RenderColorGaussianPyramid(CommandBuffer cmd, Vector2Int size, Texture source, RenderTexture destination)
{
// Only create the temporary target on-demand in case the game doesn't actually need it
if (m_TempColorTarget == null)
{
m_TempColorTarget = 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 downsampleKernelMip0 = m_ColorDownsampleKernelCopyMip0;
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 >= 8 || srcMipHeight >= 8)
{
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));
// First dispatch also copies src to dst mip0
if (srcMipLevel == 0)
{
cmd.SetComputeTextureParam(cs, downsampleKernelMip0, HDShaderIDs._Source, source, 0);
cmd.SetComputeTextureParam(cs, downsampleKernelMip0, HDShaderIDs._Mip0, destination, 0);
cmd.SetComputeTextureParam(cs, downsampleKernelMip0, HDShaderIDs._Destination, m_TempColorTarget);
cmd.DispatchCompute(cs, downsampleKernelMip0, (dstMipWidth + 7) / 8, (dstMipHeight + 7) / 8, 1);
}
else
{
cmd.SetComputeTextureParam(cs, downsampleKernel, HDShaderIDs._Source, destination, srcMipLevel);
cmd.SetComputeTextureParam(cs, downsampleKernel, HDShaderIDs._Destination, m_TempColorTarget);
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_TempColorTarget);
cmd.SetComputeTextureParam(cs, gaussianKernel, HDShaderIDs._Destination, destination, 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:

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


fileFormatVersion: 2
guid: ea3e7945ee7dc7a479b9e6846a0c544c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

176
com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramid.cs


using System;
using System.Collections.Generic;
using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
class BufferPyramid
{
List<RTHandleSystem.RTHandle> m_ColorPyramidMips = new List<RTHandleSystem.RTHandle>();
List<RTHandleSystem.RTHandle> m_DepthPyramidMips = new List<RTHandleSystem.RTHandle>();
BufferPyramidProcessor m_Processor;
public BufferPyramid(BufferPyramidProcessor processor)
{
m_Processor = processor;
}
float GetXRscale()
{
// for stereo double-wide, each half of the texture will represent a single eye's pyramid
float scale = 1.0f;
//if (m_Asset.renderPipelineSettings.supportsStereo && (desc.dimension != TextureDimension.Tex2DArray))
// scale = 2.0f; // double-wide
return scale;
}
public void DestroyBuffers()
{
foreach (var rth in m_ColorPyramidMips)
RTHandles.Release(rth);
foreach (var rth in m_DepthPyramidMips)
RTHandles.Release(rth);
}
public int GetPyramidLodCount(Vector2Int size)
{
var minSize = Mathf.Min(size.x, size.y);
return Mathf.Max(0, Mathf.FloorToInt(Mathf.Log(minSize, 2f)));
}
Vector2Int CalculatePyramidMipSize(Vector2Int baseMipSize, int mipIndex)
{
return new Vector2Int(baseMipSize.x >> mipIndex, baseMipSize.y >> mipIndex);
}
Vector2Int CalculatePyramidSize(Vector2Int size)
{
// Instead of using the screen size, we round up to the next power of 2 because currently some platforms don't support NPOT Render Texture with mip maps (PS4 for example)
// Then we render in a Screen Sized viewport.
// Note that even if PS4 supported POT Mips, the buffers would be padded to the next power of 2 anyway (TODO: check with other platforms...)
int pyramidSize = (int)Mathf.NextPowerOfTwo(Mathf.Max(size.x, size.y));
return new Vector2Int((int)(pyramidSize * GetXRscale()), pyramidSize);
}
void UpdatePyramidMips(HDCamera camera, RenderTextureFormat format, List<RTHandleSystem.RTHandle> mipList, int lodCount)
{
int currentLodCount = mipList.Count;
if (lodCount > currentLodCount)
{
for (int i = currentLodCount; i < lodCount; ++i)
{
int mipIndexCopy = i + 1; // Don't remove this copy! It's important for the value to be correctly captured by the lambda.
var newMip = RTHandles.Alloc(size => CalculatePyramidMipSize(CalculatePyramidSize(size), mipIndexCopy), colorFormat: format, sRGB: false, enableRandomWrite: true, useMipMap: false, filterMode: FilterMode.Bilinear, name: string.Format("PyramidMip{0}", i));
mipList.Add(newMip);
}
}
}
public Vector2 GetPyramidToScreenScale(HDCamera camera, RTHandleSystem.RTHandle rth)
{
return new Vector2((float)camera.actualWidth / rth.rt.width, (float)camera.actualHeight / rth.rt.height);
}
public void RenderDepthPyramid(
HDCamera hdCamera,
CommandBuffer cmd,
ScriptableRenderContext renderContext,
RTHandleSystem.RTHandle sourceDepthTexture,
RTHandleSystem.RTHandle targetDepthTexture)
{
int lodCount = Mathf.Min(
GetPyramidLodCount(targetDepthTexture.referenceSize),
GetPyramidLodCount(new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight))
);
if (lodCount == 0)
{
Debug.LogWarning("The target for the pyramid buffer has an invalid size. Skipping DepthPyramid calculation.");
return;
}
UpdatePyramidMips(hdCamera, targetDepthTexture.rt.format, m_DepthPyramidMips, lodCount);
Vector2 scale = GetPyramidToScreenScale(hdCamera, targetDepthTexture);
cmd.SetGlobalVector(HDShaderIDs._DepthPyramidSize, new Vector4(hdCamera.actualWidth, hdCamera.actualHeight, 1f / hdCamera.actualWidth, 1f / hdCamera.actualHeight));
cmd.SetGlobalVector(HDShaderIDs._DepthPyramidScale, new Vector4(scale.x, scale.y, lodCount, 0.0f));
m_Processor.RenderDepthPyramid(
hdCamera.actualWidth, hdCamera.actualHeight,
cmd,
sourceDepthTexture,
targetDepthTexture,
m_DepthPyramidMips,
lodCount,
scale
);
cmd.SetGlobalTexture(HDShaderIDs._DepthPyramidTexture, targetDepthTexture);
}
public void RenderColorPyramid(
HDCamera hdCamera,
CommandBuffer cmd,
ScriptableRenderContext renderContext,
RTHandleSystem.RTHandle sourceColorTexture,
RTHandleSystem.RTHandle targetColorTexture)
{
int lodCount = Mathf.Min(
GetPyramidLodCount(targetColorTexture.referenceSize),
GetPyramidLodCount(new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight))
);
if (lodCount == 0)
{
Debug.LogWarning("The target for the pyramid buffer has an invalid size. Skipping ColorPyramid calculation.");
return;
}
UpdatePyramidMips(hdCamera, targetColorTexture.rt.format, m_ColorPyramidMips, lodCount);
Vector2 scale = GetPyramidToScreenScale(hdCamera, targetColorTexture);
cmd.SetGlobalVector(HDShaderIDs._ColorPyramidSize, new Vector4(hdCamera.actualWidth, hdCamera.actualHeight, 1f / hdCamera.actualWidth, 1f / hdCamera.actualHeight));
cmd.SetGlobalVector(HDShaderIDs._ColorPyramidScale, new Vector4(scale.x, scale.y, lodCount, 0.0f));
m_Processor.RenderColorPyramid(
hdCamera,
cmd,
sourceColorTexture,
targetColorTexture,
m_ColorPyramidMips,
lodCount,
scale
);
cmd.SetGlobalTexture(HDShaderIDs._ColorPyramidTexture, targetColorTexture);
}
public RTHandleSystem.RTHandle AllocColorRT(string id, int frameIndex, RTHandleSystem rtHandleSystem)
{
return rtHandleSystem.Alloc(
size => CalculatePyramidSize(size),
filterMode: FilterMode.Trilinear,
colorFormat: RenderTextureFormat.ARGBHalf,
sRGB: false,
useMipMap: true,
autoGenerateMips: false,
enableRandomWrite: true,
name: string.Format("ColorPyramid-{0}-{1}", id, frameIndex)
);
}
public RTHandleSystem.RTHandle AllocDepthRT(string id, int frameIndex, RTHandleSystem rtHandleSystem)
{
return rtHandleSystem.Alloc(
size => CalculatePyramidSize(size),
filterMode: FilterMode.Trilinear,
colorFormat: RenderTextureFormat.RGFloat,
sRGB: false,
useMipMap: true,
autoGenerateMips: false,
enableRandomWrite: true, // Need randomReadWrite because we downsample the first mip with a compute shader.
name: string.Format("DepthPyramid-{0}-{1}", id, frameIndex)
);
}
}
}

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


fileFormatVersion: 2
guid: 5555ed542465a3a42aa9f58eccc62c68
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

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


using System.Collections.Generic;
using UnityEngine.Assertions;
using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public class BufferPyramidProcessor
{
static readonly int _Size = Shader.PropertyToID("_Size");
static readonly int _Source = Shader.PropertyToID("_Source");
static readonly int _Result = Shader.PropertyToID("_Result");
static readonly int _SrcSize = Shader.PropertyToID("_SrcSize");
const int k_DepthBlockSize = 4;
GPUCopy m_GPUCopy;
TexturePadding m_TexturePadding;
ComputeShader m_ColorPyramidCS;
int m_ColorPyramidKernel;
ComputeShader m_DepthPyramidCS;
int[] m_DepthKernels = null;
int depthKernel8 { get { return m_DepthKernels[0]; } }
int depthKernel1 { get { return m_DepthKernels[1]; } }
List<RenderTexture> m_RenderColorPyramid_CastTmp = new List<RenderTexture>();
public BufferPyramidProcessor(
ComputeShader colorPyramidCS,
ComputeShader depthPyramidCS,
GPUCopy gpuCopy,
TexturePadding texturePadding
)
{
m_ColorPyramidCS = colorPyramidCS;
m_ColorPyramidKernel = m_ColorPyramidCS.FindKernel("KMain");
m_DepthPyramidCS = depthPyramidCS;
m_GPUCopy = gpuCopy;
m_DepthKernels = new int[]
{
m_DepthPyramidCS.FindKernel("KDepthDownSample8"),
m_DepthPyramidCS.FindKernel("KDepthDownSample1")
};
m_TexturePadding = texturePadding;
}
public void RenderDepthPyramid(
int width, int height,
CommandBuffer cmd,
RTHandleSystem.RTHandle sourceTexture,
RTHandleSystem.RTHandle targetTexture,
List<RTHandleSystem.RTHandle> mips,
int lodCount,
Vector2 scale
)
{
m_GPUCopy.SampleCopyChannel_xyzw2x(cmd, sourceTexture, targetTexture, new RectInt(0, 0, width, height));
var src = targetTexture;
for (var i = 0; i < lodCount; i++)
{
var dest = mips[i];
var srcMip = new RectInt(0, 0, width >> i, height >> i);
var dstMip = new RectInt(0, 0, srcMip.width >> 1, srcMip.height >> 1);
var kernel = depthKernel1;
var kernelSize = 1;
var srcWorkMip = srcMip;
var dstWorkMip = dstMip;
if (dstWorkMip.width >= 8 && dstWorkMip.height >= 8)
{
srcWorkMip.width = Mathf.CeilToInt(srcWorkMip.width / 16.0f) * 16;
srcWorkMip.height = Mathf.CeilToInt(srcWorkMip.height / 16.0f) * 16;
dstWorkMip.width = srcWorkMip.width >> 1;
dstWorkMip.height = srcWorkMip.height >> 1;
m_TexturePadding.Pad(cmd, src, srcMip, srcWorkMip);
kernel = depthKernel8;
kernelSize = 8;
}
else
{
m_TexturePadding.Pad(cmd, src, srcMip, new RectInt(0, 0, src.rt.width, src.rt.height));
}
cmd.SetComputeTextureParam(m_DepthPyramidCS, kernel, _Source, src);
cmd.SetComputeTextureParam(m_DepthPyramidCS, kernel, _Result, dest);
// The compute shader work in texture space
// So we must provide the texture's size
cmd.SetComputeVectorParam(m_DepthPyramidCS, _SrcSize, new Vector4(
src.rt.width, src.rt.height,
(1.0f / src.rt.width), (1.0f / src.rt.height))
);
cmd.DispatchCompute(
m_DepthPyramidCS,
kernel,
Mathf.CeilToInt(dstWorkMip.width / (float)kernelSize),
Mathf.CeilToInt(dstWorkMip.height / (float)kernelSize),
1
);
var dstMipWidthToCopy = Mathf.Min(Mathf.Min(targetTexture.rt.width >> (i + 1), dstWorkMip.width), mips[i].rt.width);
var dstMipHeightToCopy = Mathf.Min(Mathf.Min(targetTexture.rt.height >> (i + 1), dstWorkMip.height), mips[i].rt.height);
// If we could bind texture mips as UAV we could avoid this copy...(which moreover copies more than the needed viewport if not fullscreen)
cmd.CopyTexture(mips[i], 0, 0, 0, 0, dstMipWidthToCopy, dstMipHeightToCopy, targetTexture, 0, i + 1, 0, 0);
src = dest;
}
}
public void RenderColorPyramid(
HDCamera hdCamera,
CommandBuffer cmd,
RTHandleSystem.RTHandle sourceTexture,
RTHandleSystem.RTHandle targetTexture,
List<RTHandleSystem.RTHandle> mips,
int lodCount,
Vector2 scale
)
{
// Copy mip 0
// Here we blit a "camera space" texture into a square texture but we want to keep the original viewport.
// Other BlitCameraTexture version will setup the viewport based on the destination RT scale (square here) so we need override it here.
HDUtils.BlitCameraTexture(cmd, hdCamera, sourceTexture, targetTexture, new Rect(0.0f, 0.0f, hdCamera.actualWidth, hdCamera.actualHeight));
m_RenderColorPyramid_CastTmp.Clear();
for (var i = 0; i < mips.Count; ++i)
m_RenderColorPyramid_CastTmp.Add(mips[i]);
RenderColorPyramidMips(
new RectInt(0, 0, hdCamera.actualWidth, hdCamera.actualHeight),
cmd,
targetTexture,
m_RenderColorPyramid_CastTmp,
lodCount,
scale
);
}
public void RenderColorPyramid(
RectInt srcRect,
CommandBuffer cmd,
Texture sourceTexture,
RenderTexture targetTexture,
List<RenderTexture> mips,
int lodCount
)
{
Assert.AreEqual(0, srcRect.x, "Offset are not supported");
Assert.AreEqual(0, srcRect.y, "Offset are not supported");
Assert.IsTrue(srcRect.width > 0);
Assert.IsTrue(srcRect.height > 0);
var scale = new Vector2(
sourceTexture.width / (float)srcRect.width,
sourceTexture.height / (float)srcRect.height
);
cmd.Blit(sourceTexture, targetTexture, scale, Vector2.zero);
RenderColorPyramidMips(
srcRect,
cmd,
targetTexture,
mips,
lodCount,
scale
);
}
void RenderColorPyramidMips(
RectInt srcRect,
CommandBuffer cmd,
RenderTexture targetTexture,
List<RenderTexture> mips,
int lodCount,
Vector2 scale
)
{
Assert.AreEqual(0, srcRect.x, "Offset are not supported");
Assert.AreEqual(0, srcRect.y, "Offset are not supported");
Assert.IsTrue(srcRect.width > 0);
Assert.IsTrue(srcRect.height > 0);
var src = targetTexture;
for (var i = 0; i < lodCount; i++)
{
var dest = mips[i];
var srcMip = new RectInt(0, 0, srcRect.width >> i, srcRect.height >> i);
var srcWorkMip = new RectInt(
0,
0,
Mathf.CeilToInt(srcMip.width / 16.0f) * 16,
Mathf.CeilToInt(srcMip.height / 16.0f) * 16
);
var dstWorkMip = new RectInt(0, 0, srcWorkMip.width >> 1, srcWorkMip.height >> 1);
m_TexturePadding.Pad(cmd, src, srcMip, srcWorkMip);
// TODO: Add proper stereo support to the compute job
cmd.SetComputeTextureParam(m_ColorPyramidCS, m_ColorPyramidKernel, _Source, src);
cmd.SetComputeTextureParam(m_ColorPyramidCS, m_ColorPyramidKernel, _Result, dest);
// _Size is used as a scale inside the whole render target so here we need to keep the full size (and not the scaled size depending on the current camera)
cmd.SetComputeVectorParam(
m_ColorPyramidCS,
_Size,
new Vector4(src.width >> 1, src.height >> 1, 1f / (src.width >> 1), 1f / (src.height >> 1))
);
cmd.DispatchCompute(
m_ColorPyramidCS,
m_ColorPyramidKernel,
dstWorkMip.width / 8,
dstWorkMip.height / 8,
1
);
var dstMipWidthToCopy = Mathf.Min(Mathf.Min(targetTexture.width >> (i + 1), dstWorkMip.width), mips[i].width);
var dstMipHeightToCopy = Mathf.Min(Mathf.Min(targetTexture.height >> (i + 1), dstWorkMip.height), mips[i].height);
// If we could bind texture mips as UAV we could avoid this copy...(which moreover copies more than the needed viewport if not fullscreen)
cmd.CopyTexture(
mips[i],
0, 0, 0, 0,
dstMipWidthToCopy, dstMipHeightToCopy, targetTexture, 0, i + 1, 0, 0
);
src = dest;
}
}
}
}
正在加载...
取消
保存