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.
173 lines
6.3 KiB
173 lines
6.3 KiB
using System;
|
|
|
|
namespace UnityEngine.Rendering
|
|
{
|
|
class VrsResources : IDisposable
|
|
{
|
|
internal ProfilingSampler conversionProfilingSampler = new ProfilingSampler("VrsConversion");
|
|
internal ProfilingSampler visualizationProfilingSampler = new ProfilingSampler("VrsVisualization");
|
|
internal GraphicsBuffer conversionLutBuffer;
|
|
internal GraphicsBuffer visualizationLutBuffer;
|
|
|
|
internal ComputeShader textureComputeShader;
|
|
internal int textureReduceKernel = -1;
|
|
internal int textureCopyKernel = -1;
|
|
|
|
internal Vector2Int tileSize;
|
|
|
|
internal GraphicsBuffer validatedShadingRateFragmentSizeBuffer;
|
|
|
|
Shader m_VisualizationShader;
|
|
Material m_VisualizationMaterial;
|
|
internal Material visualizationMaterial
|
|
{
|
|
get
|
|
{
|
|
// explicit check here: handle case where m_Material is set to null when editor reloads
|
|
if (m_VisualizationMaterial == null)
|
|
m_VisualizationMaterial = new Material(m_VisualizationShader);
|
|
|
|
return m_VisualizationMaterial;
|
|
}
|
|
}
|
|
|
|
internal VrsResources(VrsRenderPipelineRuntimeResources resources)
|
|
{
|
|
InitializeResources(resources);
|
|
|
|
#if UNITY_EDITOR
|
|
GraphicsSettings.Unsubscribe<VrsRenderPipelineRuntimeResources>(OnVrsResourcesChanged);
|
|
GraphicsSettings.Subscribe<VrsRenderPipelineRuntimeResources>(OnVrsResourcesChanged);
|
|
#endif
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
void OnVrsResourcesChanged(VrsRenderPipelineRuntimeResources resources, string propertyName)
|
|
{
|
|
DisposeResources();
|
|
InitializeResources(resources);
|
|
}
|
|
#endif
|
|
|
|
~VrsResources()
|
|
{
|
|
Dispose();
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
#if UNITY_EDITOR
|
|
GraphicsSettings.Unsubscribe<VrsRenderPipelineRuntimeResources>(OnVrsResourcesChanged);
|
|
#endif
|
|
DisposeResources();
|
|
}
|
|
|
|
void InitializeResources(VrsRenderPipelineRuntimeResources resources)
|
|
{
|
|
bool success = InitComputeShader(resources);
|
|
if (!success)
|
|
{
|
|
DisposeResources();
|
|
return;
|
|
}
|
|
|
|
m_VisualizationShader = resources.visualizationShader;
|
|
conversionLutBuffer = resources.conversionLookupTable.CreateBuffer();
|
|
visualizationLutBuffer = resources.visualizationLookupTable.CreateBuffer(true);
|
|
AllocFragmentSizeBuffer();
|
|
}
|
|
|
|
void DisposeResources()
|
|
{
|
|
conversionLutBuffer?.Dispose();
|
|
conversionLutBuffer = null;
|
|
|
|
visualizationLutBuffer?.Dispose();
|
|
visualizationLutBuffer = null;
|
|
|
|
validatedShadingRateFragmentSizeBuffer?.Dispose();
|
|
validatedShadingRateFragmentSizeBuffer = null;
|
|
|
|
m_VisualizationShader = null;
|
|
m_VisualizationMaterial = null;
|
|
}
|
|
|
|
void AllocFragmentSizeBuffer()
|
|
{
|
|
// Get available shading rate fragment sizes; unsupported ones
|
|
// will be mapped to the closest supported one.
|
|
var fragmentSize = new uint[Vrs.shadingRateFragmentSizeCount];
|
|
|
|
var lastAvailableFragmentSize = ShadingRateFragmentSize.FragmentSize1x1;
|
|
uint fragmentSizeNativeValue = ShadingRateInfo.QueryNativeValue(lastAvailableFragmentSize);
|
|
|
|
foreach (var availableFragmentSize in ShadingRateInfo.availableFragmentSizes)
|
|
{
|
|
Array.Fill(fragmentSize,
|
|
fragmentSizeNativeValue,
|
|
(int)lastAvailableFragmentSize,
|
|
availableFragmentSize - lastAvailableFragmentSize + 1);
|
|
|
|
lastAvailableFragmentSize = availableFragmentSize;
|
|
fragmentSizeNativeValue = ShadingRateInfo.QueryNativeValue(lastAvailableFragmentSize);
|
|
}
|
|
|
|
Array.Fill(fragmentSize,
|
|
fragmentSizeNativeValue,
|
|
(int)lastAvailableFragmentSize,
|
|
ShadingRateFragmentSize.FragmentSize4x4 - lastAvailableFragmentSize + 1);
|
|
|
|
validatedShadingRateFragmentSizeBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, fragmentSize.Length, sizeof(uint));
|
|
validatedShadingRateFragmentSizeBuffer.SetData(fragmentSize);
|
|
}
|
|
|
|
bool InitComputeShader(VrsRenderPipelineRuntimeResources resources)
|
|
{
|
|
// This Compute Shader resource is used for converting an RGB texture to an R8 SRI
|
|
// Don't initialize it if the device does not support image-based VRS
|
|
if (!ShadingRateInfo.supportsPerImageTile)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!SystemInfo.supportsComputeShaders)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
tileSize = ShadingRateInfo.imageTileSize;
|
|
var tileSizeOk = tileSize.x == tileSize.y && (tileSize.x == 8 || tileSize.x == 16 || tileSize.x == 32);
|
|
if (!tileSizeOk)
|
|
{
|
|
Debug.LogError($"VRS unsupported tile size: {tileSize.x}x{tileSize.y}.");
|
|
return false;
|
|
}
|
|
|
|
// We expect keywords, if the shader was excluded/discarded then no keywords.
|
|
if (resources.textureComputeShader?.keywordSpace.keywordCount <= 0)
|
|
{
|
|
// Invalidate kernel indices in case they were set (shader reload)
|
|
textureReduceKernel = -1;
|
|
textureCopyKernel = -1;
|
|
return false;
|
|
}
|
|
|
|
textureComputeShader = resources.textureComputeShader;
|
|
|
|
// this keyword need only be set once
|
|
textureComputeShader.EnableKeyword($"{VrsShaders.k_TileSizePrefix}{tileSize.x}");
|
|
|
|
// find kernel might fail
|
|
textureReduceKernel = TryFindKernel(textureComputeShader, VrsShaders.k_KernelTextureReduce);
|
|
textureCopyKernel = TryFindKernel(textureComputeShader, VrsShaders.k_KernelTextureReduce);
|
|
|
|
if (textureReduceKernel == -1 || textureCopyKernel == -1)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static int TryFindKernel(ComputeShader computeShader, string name) => computeShader.HasKernel(name) ? computeShader.FindKernel(name) : -1;
|
|
}
|
|
}
|