123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Linq;
- using System.Net.Http.Headers;
- using System.Numerics;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- using System.Security.Cryptography;
- using System.Text;
- namespace Veldrid.Common.Plot
- {
- public class LineSeries: BaseVeldridRender,IZoomRender
- {
- public Vector2 WindowScale { get; set; } = Vector2.One;
- public float HScale { get; set; } = 1;
- public float VScale { get; set; } = 1;
- public float HOffset { get; set; }
- public float VOffset { get; set; }
- public bool ZoomEnbled { get; set; }
- private const uint ThreadGroupSizeX = 1000;
- private ProjView projView;
- Pipeline pipeline;
- private PlotInfo plotInfo;
- DeviceBuffer plotInfoBuffer;
- DeviceBuffer projViewBuffer;
- DeviceBuffer dataBuffer;
- ResourceLayout dataLayout;
- ResourceSet dataSet;
- ResourceLayout infoLayout;
- ResourceSet infoSet;
- Shader[] shaders;
- DeviceBuffer resultBuffer;
- DeviceBuffer cpuBuffer;
- ResourceLayout computeLayout;
- ResourceSet computeSet;
- Pipeline computePipline;
- ResourceLayout computeLineInfoLayout;
- ResourceSet computeLineInfoSet;
- Shader computeShader;
- CommandList computeCommandList;
- private object locker = new object();
- public LineSeries(VeldridContent content, uint datalen=1000,uint plotcount=4):base(content)
- {
- dataLenght = datalen;
- PlotInfos = new SeriesInfo[plotcount];
- Margin = new Padding(40, 10, 10, 20);
- }
- internal override void DisposeResources()
- {
- base.DisposeResources();
- pipeline?.Dispose();
- plotInfoBuffer?.Dispose();
- projViewBuffer?.Dispose();
- dataBuffer?.Dispose();
- dataLayout?.Dispose();
- dataSet?.Dispose();
- infoLayout?.Dispose();
- infoSet?.Dispose();
- resultBuffer?.Dispose();
- cpuBuffer?.Dispose();
- computeLayout?.Dispose();
- computeSet?.Dispose();
- computePipline?.Dispose();
- computeCommandList?.Dispose();
- computeLineInfoLayout?.Dispose();
- computeLineInfoSet?.Dispose();
- computeShader?.Dispose();
- }
- private void CreateDataBuffer()
- {
- if (DataLenght == 0 || PlotInfos ==null|| PlotInfos.Length == 0) return;
- lock (locker)
- {
- dataBuffer?.Dispose();
- pipeline?.Dispose();
- dataBuffer = ResourceFactory.CreateBuffer(new BufferDescription()
- {
- SizeInBytes = (uint)(DataLenght * PlotInfos.Length * 4),
- Usage = BufferUsage.StructuredBufferReadWrite,
- StructureByteStride = 4,
- });
- dataSet = ResourceFactory.CreateResourceSet(new ResourceSetDescription(dataLayout, dataBuffer));
- pipeline = CreatePipLine(PrimitiveTopology.LineStrip, new ResourceLayout[] { dataLayout, infoLayout }, new VertexLayoutDescription[0],new[] { shaders[0], shaders[1] });
- datastartindex = 0;
- datatotallen = 0;
- TotalCount = 0;
- MaxAndMin = new Vector2[PlotInfos.Length];
- CreateComputeBuffer();
- }
- }
- internal override void CreateResources()
- {
- base.CreateResources();
-
- plotInfoBuffer = ResourceFactory.CreateBuffer(new BufferDescription()
- {
- SizeInBytes = (uint)Unsafe.SizeOf<PlotInfo>(),
- Usage = BufferUsage.UniformBuffer,
- });
- projViewBuffer = ResourceFactory.CreateBuffer(new BufferDescription()
- {
- SizeInBytes = (uint)Unsafe.SizeOf<ProjView>(),
- Usage = BufferUsage.UniformBuffer ,
- });
- datatotallen = 0;
- datastartindex = 0;
- shaders = CreateShader("LineSeries");
- dataLayout = ResourceFactory.CreateResourceLayout(new ResourceLayoutDescription(new ResourceLayoutElementDescription()
- {
- Name = "DataBuffer",
- Stages = ShaderStages.Vertex,
- Kind = ResourceKind.StructuredBufferReadOnly,
- }));
- infoLayout = ResourceFactory.CreateResourceLayout(new ResourceLayoutDescription(
- new ResourceLayoutElementDescription()
- {
- Name = "InfoBuffer",
- Kind = ResourceKind.UniformBuffer,
- Stages = ShaderStages.Vertex,
- },
- new ResourceLayoutElementDescription()
- {
- Name = "ProjView",
- Kind = ResourceKind.UniformBuffer,
- Stages = ShaderStages.Vertex,
- }));
- infoSet = ResourceFactory.CreateResourceSet(new ResourceSetDescription(infoLayout, plotInfoBuffer, projViewBuffer));
- resultBuffer = ResourceFactory.CreateBuffer(new BufferDescription(20 * 4, BufferUsage.StructuredBufferReadWrite, 4));
- cpuBuffer = ResourceFactory.CreateBuffer(new BufferDescription(resultBuffer.SizeInBytes, BufferUsage.Staging));
- computeLayout = ResourceFactory.CreateResourceLayout(new ResourceLayoutDescription(
- new ResourceLayoutElementDescription("DataBuffer", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
- new ResourceLayoutElementDescription("ResultDataBuffer", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)));
- computeLineInfoLayout = ResourceFactory.CreateResourceLayout(new ResourceLayoutDescription(
- new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute)));
- computeLineInfoSet = ResourceFactory.CreateResourceSet(new ResourceSetDescription(computeLineInfoLayout, plotInfoBuffer));
- ShaderDescription shaderDescription = new ShaderDescription(ShaderStages.Compute, GLSLManger.LoadShader("LineSeries.hlsl"), "main")
- {
- Debug = true,
- };
- computeShader = ResourceFactory.CreateShader(shaderDescription);
- computeCommandList = ResourceFactory.CreateCommandList() ;
- CreateDataBuffer();
- }
- private void CreateComputeBuffer()
- {
- computeSet?.Dispose();
- computePipline?.Dispose();
- computeSet = ResourceFactory.CreateResourceSet(new ResourceSetDescription(computeLayout, dataBuffer, resultBuffer));
- computePipline = ResourceFactory.CreateComputePipeline(new ComputePipelineDescription(computeShader, new[] { computeLayout, computeLineInfoLayout }, ThreadGroupSizeX, 1, 1));
- }
- struct PlotInfo
- {
- public RgbaFloat Color;
- public uint PlotIndex;
- public float Interval;
- public uint DataStartIndex;
- public uint PlotDataLenght;
- }
- struct ProjView
- {
- public Matrix4x4 Proj;
- public Matrix4x4 View;
- }
- public void Clear()
- {
- datastartindex = 0;
- datatotallen = 0;
- TotalCount = 0;
- }
- public ulong TotalCount { get; private set; }
- public Vector2[] MaxAndMin { get; private set; } = new Vector2[0];
- public unsafe void AddData(float[] data)
- {
- if (DataLenght == 0 || PlotInfos == null || PlotInfos.Length == 0) return;
- if (data == null|| data.Length!=PlotInfos.Length) return;
- TotalCount++;
- for(int i=0;i<data.Length;i++)
- {
- GraphicsDevice.UpdateBuffer(dataBuffer,(uint)((datastartindex+i*DataLenght)*Unsafe.SizeOf<float>()),ref data[i],(uint)Unsafe.SizeOf<float>());
- }
- datastartindex++;
- datatotallen++;
- if(datatotallen>DataLenght)datatotallen = DataLenght;
- if (datastartindex >= DataLenght) datastartindex = 0;
- MaxAndMin = new Vector2[PlotInfos.Length];
- //return;
- if (datatotallen > 0)
- {
- computeCommandList.Begin();
- CalcMaxMin(computeCommandList);
- computeCommandList.End();
- GraphicsDevice.SubmitCommands(computeCommandList);
- GraphicsDevice.WaitForIdle();
- }
- }
- private unsafe void CalcMaxMin(CommandList command)
- {
- MaxAndMin = new Vector2[PlotInfos.Length];
- plotInfo.DataStartIndex = datatotallen;
- plotInfo.PlotDataLenght = DataLenght;
- command.SetPipeline(computePipline);
- command.SetComputeResourceSet(0, computeSet);
- command.SetComputeResourceSet(1, computeLineInfoSet);
- for (uint i = 0; i < PlotInfos.Length; i++)
- {
- plotInfo.PlotIndex = i;
- command.UpdateBuffer(plotInfoBuffer, 0, plotInfo);
- command.Dispatch((uint)MathF.Ceiling(((float)datatotallen) / ThreadGroupSizeX), 1, 1);
- }
- command.CopyBuffer(resultBuffer, 0, cpuBuffer, 0, (uint)(MaxAndMin.Length * Unsafe.SizeOf<Vector2>()));
- var mapped = GraphicsDevice.Map(cpuBuffer, MapMode.ReadWrite);
- Unsafe.CopyBlock(ref Unsafe.As<Vector2, byte>(ref MaxAndMin[0]), ref Unsafe.AsRef<byte>(mapped.Data.ToPointer()), (uint)(MaxAndMin.Length * Unsafe.SizeOf<Vector2>()));
- GraphicsDevice.Unmap(cpuBuffer);
- }
- internal unsafe override void DrawData()
- {
- if (DataLenght == 0 || PlotInfos == null || PlotInfos.Length == 0) return;
- lock (locker)
- {
- base.DrawData();
- if (datatotallen == 0) return;
- //CalcMaxMin(CommandList);
- projView.Proj = OrthographicMatrix;
- projView.View = GetLineMatrix(HScale,VScale,0,VOffset);
- CommandList.SetFramebuffer(MainSwapchainBuffer);
- CommandList.UpdateBuffer(projViewBuffer, 0, projView);
- CommandList.UpdateBuffer(plotInfoBuffer, 0, plotInfo);
- CommandList.SetPipeline(pipeline);
- CommandList.SetGraphicsResourceSet(0, dataSet);
- CommandList.SetGraphicsResourceSet(1, infoSet);
- for (uint i = 0; i < PlotInfos.Length; i++)
- {
- if (!PlotInfos[i].Visibily) continue;
- plotInfo.Color = PlotInfos[i].Color;
- plotInfo.PlotDataLenght = DataLenght;
- plotInfo.DataStartIndex = datatotallen == DataLenght ? datastartindex : 0;
- plotInfo.PlotIndex = i;
- CommandList.UpdateBuffer(plotInfoBuffer, 0, plotInfo);
- CommandList.Draw(datatotallen);
- }
- }
- }
- private uint datastartindex = 0;
- private uint datatotallen = 0;
- private uint dataLenght = 1000;
- public float Interval { get => plotInfo.Interval; set => plotInfo.Interval = value; }
- public uint DataLenght
- {
- get => dataLenght;
- set
- {
- if (dataLenght != value)
- {
- dataLenght = value;
- CreateDataBuffer();
- }
- }
- }
- public SeriesInfo[] PlotInfos = new SeriesInfo[0];
- }
- public class SeriesInfo
- {
- public RgbaFloat Color;
- public bool Visibily;
- public string Name = string.Empty;
- }
- }
|