You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
9.7 KiB
222 lines
9.7 KiB
using System;
|
|
using UnityEngine.Experimental.Rendering;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
class TextureCacheCubemap : TextureCache
|
|
{
|
|
private RenderTexture m_Cache;
|
|
|
|
const int k_NbFace = 6;
|
|
|
|
// the member variables below are only in use when TextureCache.supportsCubemapArrayTextures is false
|
|
Texture2DArray m_CacheNoCubeArray;
|
|
RenderTexture[] m_StagingRTs;
|
|
int m_NumPanoMipLevels;
|
|
Material m_CubeBlitMaterial;
|
|
int m_CubeMipLevelPropName;
|
|
int m_cubeSrcTexPropName;
|
|
Material m_BlitCubemapFaceMaterial;
|
|
MaterialPropertyBlock m_BlitCubemapFaceProperties;
|
|
|
|
public TextureCacheCubemap(string cacheName = "", int sliceSize = 1)
|
|
: base(cacheName, sliceSize)
|
|
{
|
|
if (HDRenderPipeline.isReady)
|
|
{
|
|
var runtimeShaders = GraphicsSettings.GetRenderPipelineSettings<HDRenderPipelineRuntimeShaders>();
|
|
m_BlitCubemapFaceMaterial = CoreUtils.CreateEngineMaterial(runtimeShaders.blitCubeTextureFacePS);
|
|
}
|
|
|
|
m_BlitCubemapFaceProperties = new MaterialPropertyBlock();
|
|
}
|
|
|
|
override public bool IsCreated()
|
|
{
|
|
return m_Cache.IsCreated();
|
|
}
|
|
|
|
override protected bool TransferToSlice(CommandBuffer cmd, int sliceIndex, Texture[] textureArray)
|
|
{
|
|
if (!TextureCache.supportsCubemapArrayTextures)
|
|
return TransferToPanoCache(cmd, sliceIndex, textureArray);
|
|
else
|
|
{
|
|
// Make sure the array is not null or empty and that the first texture is a render-texture or a texture2D
|
|
if (textureArray == null || textureArray.Length == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// First check here is to check if all the sub-texture have the same size
|
|
for (int texIDx = 1; texIDx < textureArray.Length; ++texIDx)
|
|
{
|
|
// We cannot update if the textures if they don't have the same size or not the right type
|
|
if (textureArray[texIDx].width != textureArray[0].width || textureArray[texIDx].height != textureArray[0].height)
|
|
{
|
|
Debug.LogWarning("All the sub-textures should have the same dimensions to be handled by the texture cache.");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
var mismatch = (m_Cache.width != textureArray[0].width) || (m_Cache.height != textureArray[0].height);
|
|
|
|
if (textureArray[0] is Cubemap)
|
|
{
|
|
mismatch |= (m_Cache.graphicsFormat != (textureArray[0] as Cubemap).graphicsFormat);
|
|
}
|
|
|
|
for (int texIDx = 0; texIDx < textureArray.Length; ++texIDx)
|
|
{
|
|
if (mismatch)
|
|
{
|
|
m_BlitCubemapFaceProperties.SetTexture(HDShaderIDs._InputTex, textureArray[texIDx]);
|
|
m_BlitCubemapFaceProperties.SetFloat(HDShaderIDs._LoD, 0);
|
|
for (int f = 0; f < 6; f++)
|
|
{
|
|
m_BlitCubemapFaceProperties.SetFloat(HDShaderIDs._FaceIndex, (float)f);
|
|
CoreUtils.SetRenderTarget(cmd, m_Cache, ClearFlag.None, Color.black, depthSlice: 6 * (m_SliceSize * sliceIndex + texIDx) + f);
|
|
CoreUtils.DrawFullScreen(cmd, m_BlitCubemapFaceMaterial, m_BlitCubemapFaceProperties);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int f = 0; f < 6; f++)
|
|
cmd.CopyTexture(textureArray[texIDx], f, m_Cache, 6 * (m_SliceSize * sliceIndex + texIDx) + f);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public override Texture GetTexCache()
|
|
{
|
|
return !TextureCache.supportsCubemapArrayTextures ? (Texture)m_CacheNoCubeArray : m_Cache;
|
|
}
|
|
|
|
public bool AllocTextureArray(int numCubeMaps, int width, GraphicsFormat format, bool isMipMapped, Material cubeBlitMaterial)
|
|
{
|
|
var res = AllocTextureArray(numCubeMaps);
|
|
m_NumMipLevels = GetNumMips(width, width); // will calculate same way whether we have cube array or not
|
|
|
|
if (!TextureCache.supportsCubemapArrayTextures)
|
|
{
|
|
m_CubeBlitMaterial = cubeBlitMaterial;
|
|
|
|
int panoWidthTop = 4 * width;
|
|
int panoHeightTop = 2 * width;
|
|
|
|
// create panorama 2D array. Hardcoding the render target for now. No convenient way atm to
|
|
m_CacheNoCubeArray = new Texture2DArray(panoWidthTop, panoHeightTop, numCubeMaps, format, isMipMapped ? TextureCreationFlags.MipChain : TextureCreationFlags.None)
|
|
{
|
|
hideFlags = HideFlags.HideAndDontSave,
|
|
wrapMode = TextureWrapMode.Repeat,
|
|
wrapModeV = TextureWrapMode.Clamp,
|
|
filterMode = FilterMode.Trilinear,
|
|
anisoLevel = 0,
|
|
name = CoreUtils.GetTextureAutoName(panoWidthTop, panoHeightTop, format, TextureDimension.Tex2DArray, depth: numCubeMaps, name: m_CacheName)
|
|
};
|
|
|
|
m_NumPanoMipLevels = isMipMapped ? GetNumMips(panoWidthTop, panoHeightTop) : 1;
|
|
m_StagingRTs = new RenderTexture[m_NumPanoMipLevels];
|
|
for (int m = 0; m < m_NumPanoMipLevels; m++)
|
|
{
|
|
m_StagingRTs[m] = new RenderTexture(Mathf.Max(1, panoWidthTop >> m), Mathf.Max(1, panoHeightTop >> m), 0, format) { hideFlags = HideFlags.HideAndDontSave };
|
|
m_StagingRTs[m].name = CoreUtils.GetRenderTargetAutoName(Mathf.Max(1, panoWidthTop >> m), Mathf.Max(1, panoHeightTop >> m), 1, format, String.Format("PanaCache{0}", m));
|
|
}
|
|
|
|
if (m_CubeBlitMaterial)
|
|
{
|
|
m_CubeMipLevelPropName = Shader.PropertyToID("_cubeMipLvl");
|
|
m_cubeSrcTexPropName = Shader.PropertyToID("_srcCubeTexture");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var desc = new RenderTextureDescriptor(width, width, format, 0)
|
|
{
|
|
dimension = TextureDimension.CubeArray,
|
|
volumeDepth = numCubeMaps * 6, // We need to multiply by the face count of a cubemap here
|
|
autoGenerateMips = false,
|
|
useMipMap = isMipMapped,
|
|
msaaSamples = 1,
|
|
};
|
|
|
|
m_Cache = new RenderTexture(desc)
|
|
{
|
|
hideFlags = HideFlags.HideAndDontSave,
|
|
wrapMode = TextureWrapMode.Clamp,
|
|
filterMode = FilterMode.Trilinear,
|
|
anisoLevel = 0, // It is important to set 0 here, else unity force anisotropy filtering
|
|
name = CoreUtils.GetTextureAutoName(width, width, format, desc.dimension, depth: numCubeMaps, name: m_CacheName, mips: isMipMapped)
|
|
};
|
|
|
|
// We need to clear the content in case it is read on first frame, since on console we have no guarantee that
|
|
// the content won't be NaN
|
|
ClearCache();
|
|
m_Cache.Create();
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
internal void ClearCache()
|
|
{
|
|
var desc = m_Cache.descriptor;
|
|
bool isMipped = desc.useMipMap;
|
|
int mipCount = isMipped ? GetNumMips(desc.width, desc.height) : 1;
|
|
for (int mipIdx = 0; mipIdx < mipCount; ++mipIdx)
|
|
{
|
|
Graphics.SetRenderTarget(m_Cache, mipIdx, CubemapFace.Unknown, -1);
|
|
GL.Clear(false, true, Color.clear);
|
|
}
|
|
}
|
|
|
|
public void Release()
|
|
{
|
|
if (m_CacheNoCubeArray)
|
|
{
|
|
CoreUtils.Destroy(m_CacheNoCubeArray);
|
|
for (int m = 0; m < m_NumPanoMipLevels; m++)
|
|
{
|
|
m_StagingRTs[m].Release();
|
|
}
|
|
m_StagingRTs = null;
|
|
CoreUtils.Destroy(m_CubeBlitMaterial);
|
|
}
|
|
|
|
CoreUtils.Destroy(m_BlitCubemapFaceMaterial);
|
|
|
|
CoreUtils.Destroy(m_Cache);
|
|
}
|
|
|
|
private bool TransferToPanoCache(CommandBuffer cmd, int sliceIndex, Texture[] textureArray)
|
|
{
|
|
for (int texIdx = 0; texIdx < textureArray.Length; ++texIdx)
|
|
{
|
|
m_CubeBlitMaterial.SetTexture(m_cubeSrcTexPropName, textureArray[texIdx]);
|
|
for (int m = 0; m < m_NumPanoMipLevels; m++)
|
|
{
|
|
m_CubeBlitMaterial.SetInt(m_CubeMipLevelPropName, Mathf.Min(m_NumMipLevels - 1, m));
|
|
cmd.Blit(null, m_StagingRTs[m], m_CubeBlitMaterial, 0);
|
|
}
|
|
|
|
for (int m = 0; m < m_NumPanoMipLevels; m++)
|
|
cmd.CopyTexture(m_StagingRTs[m], 0, 0, m_CacheNoCubeArray, m_SliceSize * sliceIndex + texIdx, m);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
internal static long GetApproxCacheSizeInByte(int nbElement, int resolution, int sliceSize)
|
|
{
|
|
return (long)((long)nbElement * resolution * resolution * k_NbFace * k_FP16SizeInByte * k_NbChannel * k_MipmapFactorApprox * sliceSize);
|
|
}
|
|
|
|
internal static int GetMaxCacheSizeForWeightInByte(long weight, int resolution, int sliceSize)
|
|
{
|
|
int theoricalResult = Mathf.FloorToInt(weight / ((long)resolution * resolution * k_NbFace * k_FP16SizeInByte * k_NbChannel * k_MipmapFactorApprox * sliceSize));
|
|
return Mathf.Clamp(theoricalResult, 1, k_MaxSupported);
|
|
}
|
|
}
|
|
}
|