internal bool EnsureProbeVolumeInAtlasOctahedralDepth(ScriptableRenderContext renderContext, CommandBuffer cmd, ProbeVolume volume) { int key = volume.GetID(); int width = volume.parameters.resolutionX * volume.parameters.resolutionZ * k_ProbeOctahedralDepthWidth; int height = volume.parameters.resolutionY * k_ProbeOctahedralDepthHeight; int size = volume.parameters.resolutionX * volume.parameters.resolutionY * volume.parameters.resolutionZ * k_ProbeOctahedralDepthWidth * k_ProbeOctahedralDepthHeight; Debug.Assert(size > 0, "ProbeVolume: Encountered probe volume with resolution set to zero on all three axes."); // TODO: Store volume resolution inside the atlas's key->bias dictionary. // If resolution has changed since upload, need to free previous allocation from atlas, // and attempt to allocate a new chunk from the atlas for the new resolution settings. // Currently atlas allocator only handles splitting. Need to add merging of neighboring, empty chunks to avoid fragmentation. bool isSlotAllocated = probeVolumeAtlasOctahedralDepth.EnsureTextureSlot(out bool isUploadNeeded, out volume.parameters.octahedralDepthScaleBias, key, width, height); if (isSlotAllocated) { if (isUploadNeeded || volume.dataUpdated) { (var data, var dataValidity, var dataOctahedralDepth) = volume.GetData(); if (data == null || data.Length == 0 || !volume.IsAssetCompatible()) { ReleaseProbeVolumeFromAtlas(volume); return(false); } // Blit: { //Debug.Log("Uploading Probe Volume Data with key " + key + " at scale bias = " + volume.parameters.scaleBias); cmd.SetComputeVectorParam(s_ProbeVolumeAtlasOctahedralDepthBlitCS, HDShaderIDs._ProbeVolumeResolution, new Vector3( volume.parameters.resolutionX, volume.parameters.resolutionY, volume.parameters.resolutionZ )); cmd.SetComputeVectorParam(s_ProbeVolumeAtlasOctahedralDepthBlitCS, HDShaderIDs._ProbeVolumeResolutionInverse, new Vector3( 1.0f / (float)volume.parameters.resolutionX, 1.0f / (float)volume.parameters.resolutionY, 1.0f / (float)volume.parameters.resolutionZ )); cmd.SetComputeVectorParam(s_ProbeVolumeAtlasOctahedralDepthBlitCS, HDShaderIDs._ProbeVolumeAtlasOctahedralDepthScaleBias, volume.parameters.octahedralDepthScaleBias ); Debug.Assert(dataOctahedralDepth.Length == size, "ProbeVolume: The probe volume baked data and its resolution are out of sync! Volume data length is " + dataOctahedralDepth.Length + ", but resolution size is " + size + "."); s_ProbeVolumeAtlasOctahedralDepthBuffer.SetData(dataOctahedralDepth); cmd.SetComputeIntParam(s_ProbeVolumeAtlasOctahedralDepthBlitCS, HDShaderIDs._ProbeVolumeAtlasOctahedralDepthReadBufferCount, size); cmd.SetComputeBufferParam(s_ProbeVolumeAtlasOctahedralDepthBlitCS, s_ProbeVolumeAtlasOctahedralDepthBlitKernel, HDShaderIDs._ProbeVolumeAtlasOctahedralDepthReadBuffer, s_ProbeVolumeAtlasOctahedralDepthBuffer); cmd.SetComputeTextureParam(s_ProbeVolumeAtlasOctahedralDepthBlitCS, s_ProbeVolumeAtlasOctahedralDepthBlitKernel, HDShaderIDs._ProbeVolumeAtlasOctahedralDepthWriteTexture, m_ProbeVolumeAtlasOctahedralDepthRTHandle); // TODO: Determine optimal batch size. const int kBatchSize = 256; int numThreadGroups = Mathf.CeilToInt((float)size / (float)kBatchSize); cmd.DispatchCompute(s_ProbeVolumeAtlasOctahedralDepthBlitCS, s_ProbeVolumeAtlasOctahedralDepthBlitKernel, numThreadGroups, 1, 1); } // Convolve: { Vector4 probeVolumeAtlasOctahedralDepthScaleBiasTexels = new Vector4( Mathf.Floor(volume.parameters.octahedralDepthScaleBias.x * s_ProbeVolumeAtlasOctahedralDepthWidth + 0.5f), Mathf.Floor(volume.parameters.octahedralDepthScaleBias.y * s_ProbeVolumeAtlasOctahedralDepthHeight + 0.5f), Mathf.Floor(volume.parameters.octahedralDepthScaleBias.z * s_ProbeVolumeAtlasOctahedralDepthWidth + 0.5f), Mathf.Floor(volume.parameters.octahedralDepthScaleBias.w * s_ProbeVolumeAtlasOctahedralDepthHeight + 0.5f) ); cmd.SetComputeVectorParam(s_ProbeVolumeAtlasOctahedralDepthConvolveCS, HDShaderIDs._ProbeVolumeAtlasOctahedralDepthScaleBiasTexels, probeVolumeAtlasOctahedralDepthScaleBiasTexels ); cmd.SetComputeTextureParam(s_ProbeVolumeAtlasOctahedralDepthConvolveCS, s_ProbeVolumeAtlasOctahedralDepthConvolveKernel, HDShaderIDs._ProbeVolumeAtlasOctahedralDepthRWTexture, m_ProbeVolumeAtlasOctahedralDepthRTHandle); cmd.SetComputeIntParam(s_ProbeVolumeAtlasOctahedralDepthConvolveCS, HDShaderIDs._FilterSampleCount, 16); // TODO: Expose cmd.SetComputeFloatParam(s_ProbeVolumeAtlasOctahedralDepthConvolveCS, HDShaderIDs._FilterSharpness, 6.0f); // TODO: Expose // Warning: This kernel numthreads must be an integer multiple of OCTAHEDRAL_DEPTH_RESOLUTION // We read + write from the same texture, so any partial work would pollute / cause feedback into neighboring chunks. int widthPixels = (int)(volume.parameters.octahedralDepthScaleBias.x * (float)s_ProbeVolumeAtlasOctahedralDepthWidth); int heightPixels = (int)(volume.parameters.octahedralDepthScaleBias.y * (float)s_ProbeVolumeAtlasOctahedralDepthHeight); int probeCountX = widthPixels / k_ProbeOctahedralDepthWidth; int probeCountY = heightPixels / k_ProbeOctahedralDepthHeight; Debug.Assert((k_ProbeOctahedralDepthWidth == k_ProbeOctahedralDepthHeight) && (k_ProbeOctahedralDepthWidth == 8)); Debug.Assert((probeCountX * k_ProbeOctahedralDepthWidth) == widthPixels); Debug.Assert((probeCountY * k_ProbeOctahedralDepthHeight) == heightPixels); cmd.DispatchCompute(s_ProbeVolumeAtlasOctahedralDepthConvolveCS, s_ProbeVolumeAtlasOctahedralDepthConvolveKernel, probeCountX, probeCountY, 1); } return(true); } return(false); } Debug.Assert(isSlotAllocated, "ProbeVolume: Texture Atlas failed to allocate space for octahedral depth texture { key: " + key + " width: " + width + ", height: " + height); return(false); }
internal bool EnsureProbeVolumeInAtlas(ScriptableRenderContext renderContext, CommandBuffer cmd, ProbeVolume volume) { int key = volume.GetID(); int width = volume.parameters.resolutionX; int height = volume.parameters.resolutionY; int depth = volume.parameters.resolutionZ; int size = volume.parameters.resolutionX * volume.parameters.resolutionY * volume.parameters.resolutionZ; Debug.Assert(size > 0, "ProbeVolume: Encountered probe volume with resolution set to zero on all three axes."); // TODO: Store volume resolution inside the atlas's key->bias dictionary. // If resolution has changed since upload, need to free previous allocation from atlas, // and attempt to allocate a new chunk from the atlas for the new resolution settings. // Currently atlas allocator only handles splitting. Need to add merging of neighboring, empty chunks to avoid fragmentation. bool isSlotAllocated = probeVolumeAtlas.EnsureTextureSlot(out bool isUploadNeeded, out volume.parameters.scale, out volume.parameters.bias, key, width, height, depth); if (isSlotAllocated) { if (isUploadNeeded || volume.dataUpdated) { (var data, var dataValidity, var dataOctahedralDepth) = volume.GetData(); if (data == null || data.Length == 0 || !volume.IsAssetCompatible()) { ReleaseProbeVolumeFromAtlas(volume); return(false); } //Debug.Log("Uploading Probe Volume Data with key " + key + " at scale bias = " + volume.parameters.scaleBias); cmd.SetComputeVectorParam(s_ProbeVolumeAtlasBlitCS, HDShaderIDs._ProbeVolumeResolution, new Vector3( volume.parameters.resolutionX, volume.parameters.resolutionY, volume.parameters.resolutionZ )); cmd.SetComputeVectorParam(s_ProbeVolumeAtlasBlitCS, HDShaderIDs._ProbeVolumeResolutionInverse, new Vector3( 1.0f / (float)volume.parameters.resolutionX, 1.0f / (float)volume.parameters.resolutionY, 1.0f / (float)volume.parameters.resolutionZ )); cmd.SetComputeVectorParam(s_ProbeVolumeAtlasBlitCS, HDShaderIDs._ProbeVolumeAtlasScale, volume.parameters.scale ); cmd.SetComputeVectorParam(s_ProbeVolumeAtlasBlitCS, HDShaderIDs._ProbeVolumeAtlasBias, volume.parameters.bias ); Debug.Assert(data.Length == size, "ProbeVolume: The probe volume baked data and its resolution are out of sync! Volume data length is " + data.Length + ", but resolution size is " + size + "."); Debug.Assert(size < s_MaxProbeVolumeProbeCount, "ProbeVolume: probe volume baked data size exceeds the currently max supported blitable size. Volume data size is " + size + ", but s_MaxProbeVolumeProbeCount is " + s_MaxProbeVolumeProbeCount + ". Please decrease ProbeVolume resolution, or increase ProbeVolumeLighting.s_MaxProbeVolumeProbeCount."); s_ProbeVolumeAtlasBlitDataBuffer.SetData(data); s_ProbeVolumeAtlasBlitDataValidityBuffer.SetData(dataValidity); cmd.SetComputeIntParam(s_ProbeVolumeAtlasBlitCS, HDShaderIDs._ProbeVolumeAtlasReadBufferCount, size); cmd.SetComputeBufferParam(s_ProbeVolumeAtlasBlitCS, s_ProbeVolumeAtlasBlitKernel, HDShaderIDs._ProbeVolumeAtlasReadBuffer, s_ProbeVolumeAtlasBlitDataBuffer); cmd.SetComputeBufferParam(s_ProbeVolumeAtlasBlitCS, s_ProbeVolumeAtlasBlitKernel, HDShaderIDs._ProbeVolumeAtlasReadValidityBuffer, s_ProbeVolumeAtlasBlitDataValidityBuffer); cmd.SetComputeTextureParam(s_ProbeVolumeAtlasBlitCS, s_ProbeVolumeAtlasBlitKernel, HDShaderIDs._ProbeVolumeAtlasWriteTextureSH, m_ProbeVolumeAtlasSHRTHandle); // TODO: Determine optimal batch size. const int kBatchSize = 256; int numThreadGroups = Mathf.CeilToInt((float)size / (float)kBatchSize); cmd.DispatchCompute(s_ProbeVolumeAtlasBlitCS, s_ProbeVolumeAtlasBlitKernel, numThreadGroups, 1, 1); return(true); } return(false); } Debug.Assert(isSlotAllocated, "ProbeVolume: Texture Atlas failed to allocate space for texture { key: " + key + "width: " + width + ", height: " + height + ", depth: " + depth + "}"); return(false); }