Files
2026-07-13 13:13:17 +08:00

164 lines
5.1 KiB
C#

#nullable enable
using SharpDX;
using Utilities = T3.Core.Utils.Utilities;
namespace Lib.numbers.floats.process;
[Guid("55cc0f79-96c9-482e-9794-934dc0f87708")]
internal sealed class ValuesToTexture : Instance<ValuesToTexture>
{
[Output(Guid = "f01099a0-a196-4689-9900-edac07908714")]
public readonly Slot<Texture2D> ValuesTexture = new();
public ValuesToTexture()
{
ValuesTexture.UpdateAction += Update;
}
private void Update(EvaluationContext context)
{
_valueListsTmp.Clear();
var useHorizontal = Direction.GetValue(context) == 0;
int listCount;
if (Values.HasInputConnections)
{
listCount = Values.CollectedInputs.Count;
if (listCount == 0)
return;
foreach (var vi in Values.CollectedInputs)
{
var v = vi.GetValue(context);
if (v != null && v.Count > 0)
_valueListsTmp.Add(v);
}
listCount = _valueListsTmp.Count;
if (listCount == 0)
return;
}
else
{
var v = Values.GetValue(context);
if (v == null || v.Count == 0)
return;
listCount = 1;
_valueListsTmp.Add(v);
}
// Use the longest list as sampleCount
var sampleCount = 0;
foreach (var list in _valueListsTmp)
sampleCount = Math.Max(sampleCount, list.Count);
if (sampleCount == 0)
return;
var gain = Gain.GetValue(context);
var offset = Offset.GetValue(context);
var pow = Pow.GetValue(context);
if (Math.Abs(pow) < 0.001f)
return;
var requiredFloats = listCount * sampleCount;
if (_uploadBuffer.Length < requiredFloats)
{
if (_uploadHandle.IsAllocated)
_uploadHandle.Free();
_uploadBuffer = new float[requiredFloats];
_uploadHandle = GCHandle.Alloc(_uploadBuffer, GCHandleType.Pinned);
_uploadPtr = _uploadHandle.AddrOfPinnedObject();
}
// Fill buffer: write row by row (each input list = one row if horizontal)
int o = 0;
if (useHorizontal)
{
foreach (var list in _valueListsTmp)
{
for (int i = 0; i < sampleCount; i++)
{
float v = i < list.Count ? (float)Math.Pow((list[i] + offset) * gain, pow) : 0f;
_uploadBuffer[o++] = v;
}
}
}
else
{
for (int i = 0; i < sampleCount; i++)
{
foreach (var list in _valueListsTmp)
{
float v = i < list.Count ? (float)Math.Pow((list[i] + offset) * gain, pow) : 0f;
_uploadBuffer[o++] = v;
}
}
}
var width = useHorizontal ? sampleCount : listCount;
var height = useHorizontal ? listCount : sampleCount;
if (ValuesTexture.Value == null ||
ValuesTexture.Value.Description.Width != width ||
ValuesTexture.Value.Description.Height != height)
{
if (ValuesTexture.Value != null)
Utilities.Dispose(ref ValuesTexture.Value);
var desc = new Texture2DDescription
{
Width = width,
Height = height,
ArraySize = 1,
BindFlags = BindFlags.ShaderResource,
Usage = ResourceUsage.Default,
MipLevels = 1,
CpuAccessFlags = CpuAccessFlags.None,
Format = Format.R32_Float,
SampleDescription = new SampleDescription(1, 0),
};
ValuesTexture.Value = Texture2D.CreateTexture2D(desc);
}
const int bytesPerTexel = sizeof(float);
var rowPitch = width * bytesPerTexel;
var slicePitch = rowPitch * height;
var dataBox = new DataBox(_uploadPtr, rowPitch, slicePitch);
ResourceManager.Device.ImmediateContext.UpdateSubresource(dataBox, ValuesTexture.Value, 0);
Values.DirtyFlag.Clear();
}
// Reused, pinned upload buffer (avoid per-frame allocations)
private float[] _uploadBuffer = [];
private GCHandle _uploadHandle;
private IntPtr _uploadPtr = IntPtr.Zero;
private readonly List<List<float>> _valueListsTmp = new();
[Input(Guid = "092C8D1F-A70E-4298-B5DF-52C9D62F8E04")]
public readonly MultiInputSlot<List<float>> Values = new();
[Input(Guid = "748FE756-C7EE-4CC1-929E-078F99BEA628")]
public readonly InputSlot<float> Offset = new();
[Input(Guid = "CC812393-F080-4E17-A525-15B09F8ACDD0")]
public readonly InputSlot<float> Gain = new();
[Input(Guid = "51545316-69FC-441F-B59F-44979E32972C")]
public readonly InputSlot<float> Pow = new();
[Input(Guid = "63E90D86-5AD5-4333-8B99-7F8D285C4913", MappedType = typeof(Directions))]
public readonly InputSlot<int> Direction = new();
private enum Directions
{
Horizontal,
Vertical,
}
}