Added TS.NET #234
352
Software/TS.NET/.gitignore
vendored
Normal file
352
Software/TS.NET/.gitignore
vendored
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
builds/
|
21
Software/TS.NET/LICENSE
Normal file
21
Software/TS.NET/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 macaba
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
5
Software/TS.NET/README.md
Normal file
5
Software/TS.NET/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# TS.NET
|
||||||
|
|
||||||
|
[Thunderscope](https://github.com/EEVengers/ThunderScope)-compatible PC-host software written in C# using .NET 6 high-performing primitives & SIMD.
|
||||||
|
|
||||||
|
![Flow diagram](docs/flow.png)
|
12
Software/TS.NET/build-scripts/TS.NET.Engine (win-x64).bat
Normal file
12
Software/TS.NET/build-scripts/TS.NET.Engine (win-x64).bat
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
echo Powershell path:
|
||||||
|
where pwsh
|
||||||
|
IF ERRORLEVEL 1 (
|
||||||
|
ECHO Powershell is not installed. Get it here: https://docs.microsoft.com/en-gb/powershell/scripting/install/installing-powershell
|
||||||
|
pause
|
||||||
|
EXIT /B
|
||||||
|
)
|
||||||
|
|
||||||
|
pwsh "win-x64/TS.NET.Engine (win-x64).ps1"
|
||||||
|
pause
|
@ -0,0 +1,12 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
echo Powershell path:
|
||||||
|
where pwsh
|
||||||
|
IF ERRORLEVEL 1 (
|
||||||
|
ECHO Powershell is not installed. Get it here: https://docs.microsoft.com/en-gb/powershell/scripting/install/installing-powershell
|
||||||
|
pause
|
||||||
|
EXIT /B
|
||||||
|
)
|
||||||
|
|
||||||
|
pwsh "win-x64/TS.NET.UI.Avalonia (win-x64).ps1"
|
||||||
|
pause
|
@ -0,0 +1,24 @@
|
|||||||
|
New-Variable -Name "projectFolder" -Value (Join-Path (Resolve-Path ..) 'source/TS.NET.Engine')
|
||||||
|
$xml = [Xml] (Get-Content $projectFolder\TS.NET.Engine.csproj)
|
||||||
|
$version = [Version] $xml.Project.PropertyGroup.Version
|
||||||
|
New-Variable -Name "publishFolder" -Value (Join-Path (Resolve-Path ..) 'builds/win-x64/TS.NET.Engine' $version)
|
||||||
|
|
||||||
|
# Remove destination folder if exists
|
||||||
|
if(Test-Path $publishFolder -PathType Container) {
|
||||||
|
rm -r $publishFolder
|
||||||
|
}
|
||||||
|
|
||||||
|
# Publish application
|
||||||
|
Write-Host "Publishing project..." -ForegroundColor yellow
|
||||||
|
Write-Host -> $publishFolder -ForegroundColor DarkYellow
|
||||||
|
dotnet publish $projectFolder/TS.NET.Engine.csproj -r win-x64 -c Release --self-contained /p:PublishSingleFile=true /p:PublishTrimmed=true /p:IncludeNativeLibrariesForSelfExtract=true --output $publishFolder
|
||||||
|
if ($LastExitCode -ne 0) { break }
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Remove debug files
|
||||||
|
rm $publishFolder/*.pdb
|
||||||
|
|
||||||
|
# Compress-Archive -Force -Path $publishFolder\* -DestinationPath $publishFolder/../TS.NET.Engine_win-x64_v$version.zip
|
||||||
|
|
||||||
|
Write-Host Build Complete -ForegroundColor green
|
||||||
|
Write-Host -> $publishFolder -ForegroundColor DarkYellow
|
@ -0,0 +1,24 @@
|
|||||||
|
New-Variable -Name "projectFolder" -Value (Join-Path (Resolve-Path ..) 'source/TS.NET.UI.Avalonia')
|
||||||
|
$xml = [Xml] (Get-Content $projectFolder\TS.NET.UI.Avalonia.csproj)
|
||||||
|
$version = [Version] $xml.Project.PropertyGroup.Version
|
||||||
|
New-Variable -Name "publishFolder" -Value (Join-Path (Resolve-Path ..) 'builds/win-x64/TS.NET.UI.Avalonia' $version)
|
||||||
|
|
||||||
|
# Remove destination folder if exists
|
||||||
|
if(Test-Path $publishFolder -PathType Container) {
|
||||||
|
rm -r $publishFolder
|
||||||
|
}
|
||||||
|
|
||||||
|
# Publish application
|
||||||
|
Write-Host "Publishing project..." -ForegroundColor yellow
|
||||||
|
Write-Host -> $publishFolder -ForegroundColor DarkYellow
|
||||||
|
dotnet publish $projectFolder/TS.NET.UI.Avalonia.csproj -r win-x64 -c Release --self-contained /p:PublishSingleFile=true /p:PublishTrimmed=true /p:IncludeNativeLibrariesForSelfExtract=true --output $publishFolder
|
||||||
|
if ($LastExitCode -ne 0) { break }
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Remove debug files
|
||||||
|
rm $publishFolder/*.pdb
|
||||||
|
|
||||||
|
# Compress-Archive -Force -Path $publishFolder\* -DestinationPath $publishFolder/../TS.NET.UI.Avalonia_win-x64_v$version.zip
|
||||||
|
|
||||||
|
Write-Host Build Complete -ForegroundColor green
|
||||||
|
Write-Host -> $publishFolder -ForegroundColor DarkYellow
|
BIN
Software/TS.NET/docs/flow.png
Normal file
BIN
Software/TS.NET/docs/flow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
132
Software/TS.NET/source/PlayingWithShaders/OscilloscopeDisplay.cs
Normal file
132
Software/TS.NET/source/PlayingWithShaders/OscilloscopeDisplay.cs
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using ObjectTK;
|
||||||
|
using ObjectTK.GLObjects;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
using OpenTK.Windowing.Desktop;
|
||||||
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
using System;
|
||||||
|
using TS.NET;
|
||||||
|
|
||||||
|
// https://github.com/opentk/LearnOpenTK/blob/master/Chapter1/2-HelloTriangle/Window.cs
|
||||||
|
// https://github.com/jbentham/streaming/blob/main/rpi_opengl_graph.c
|
||||||
|
// https://iosoft.blog/2020/12/15/oscilloscope-display-opengl-raspberry-pi/
|
||||||
|
// https://vitaliburkov.wordpress.com/2016/09/17/simple-and-fast-high-quality-antialiased-lines-with-opengl/
|
||||||
|
|
||||||
|
namespace PlayingWithShaders
|
||||||
|
{
|
||||||
|
public class OscilloscopeDisplay : GameWindow
|
||||||
|
{
|
||||||
|
private ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
|
||||||
|
private ShaderProgram shader;
|
||||||
|
ThunderscopeBridgeReader bridge;
|
||||||
|
IInterprocessSemaphoreWaiter bridgeReadSemaphore;
|
||||||
|
int vbo;
|
||||||
|
int vao;
|
||||||
|
|
||||||
|
public OscilloscopeDisplay(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings) : base(gameWindowSettings, nativeWindowSettings) { }
|
||||||
|
|
||||||
|
protected override void OnLoad()
|
||||||
|
{
|
||||||
|
base.OnLoad();
|
||||||
|
|
||||||
|
uint bufferLength = 4 * 100 * 1000 * 1000; //Maximum record length = 100M samples per channel
|
||||||
|
bridge = new(new ThunderscopeBridgeOptions("ThunderScope.1", bufferLength), loggerFactory);
|
||||||
|
bridgeReadSemaphore = bridge.GetReaderSemaphore();
|
||||||
|
int channelLength = bridge.Configuration.ChannelLength;
|
||||||
|
|
||||||
|
shader = GLFactory.Shader.EmbeddedResVertFrag("Graph", "graph2.vertex.glsl", "graph.fragment.glsl");
|
||||||
|
GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest);
|
||||||
|
GL.Enable(EnableCap.Blend);
|
||||||
|
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||||
|
GL.ClearColor(new Color4(0x21, 0x21, 0x21, 0xff));
|
||||||
|
|
||||||
|
//====== var buffer = GLFactory.Buffer.ArrayBuffer("Channel1", graph); ======
|
||||||
|
vbo = GL.GenBuffer();
|
||||||
|
//var label = $"Buffer: {name}";
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
|
||||||
|
//GL.ObjectLabel(ObjectLabelIdentifier.Buffer, vbo, label.Length, label);
|
||||||
|
int elemSize;
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
elemSize = sizeof(byte);
|
||||||
|
}
|
||||||
|
//GL.BufferData(BufferTarget.ArrayBuffer, elemSize * graph.Length, graph, BufferUsageHint.DynamicRead);
|
||||||
|
GL.BufferData(BufferTarget.ArrayBuffer, elemSize * channelLength, bridge.DataPointer, BufferUsageHint.DynamicRead);
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
|
||||||
|
// ====== vertexArray = GLFactory.VertexArray.FromBuffers("Channel1", buffer); ======
|
||||||
|
vao = GL.GenVertexArray();
|
||||||
|
//var label = $"VertexArray: {name}";
|
||||||
|
GL.BindVertexArray(vao);
|
||||||
|
//GL.ObjectLabel(ObjectLabelIdentifier.VertexArray, vao, name.Length, label);
|
||||||
|
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
|
||||||
|
GL.EnableVertexAttribArray(0);
|
||||||
|
//GL.VertexAttribPointer(0, 1, VertexAttribPointerType.Int, false, elemSize, 0);
|
||||||
|
GL.VertexAttribIPointer(0, 1, VertexAttribIntegerType.UnsignedByte, elemSize, IntPtr.Zero);
|
||||||
|
|
||||||
|
// clean up:
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||||
|
GL.BindVertexArray(0);
|
||||||
|
//=========================
|
||||||
|
}
|
||||||
|
|
||||||
|
protected unsafe override void OnRenderFrame(FrameEventArgs args)
|
||||||
|
{
|
||||||
|
base.OnRenderFrame(args);
|
||||||
|
|
||||||
|
if (bridgeReadSemaphore.Wait(500))
|
||||||
|
{
|
||||||
|
int channelLength = bridge.Configuration.ChannelLength;
|
||||||
|
|
||||||
|
|
||||||
|
GL.UseProgram(shader.Handle);
|
||||||
|
|
||||||
|
//GL.Uniform1(shader.Uniforms["ScaleX"].Location, 1.0f);
|
||||||
|
//GL.Uniform1(shader.Uniforms["OffsetX"].Location, 0.0f);
|
||||||
|
var scale = 1.0f / 128.0f;
|
||||||
|
GL.Uniform1(shader.Uniforms["ScaleY"].Location, scale);
|
||||||
|
GL.Uniform1(shader.Uniforms["OffsetY"].Location, -1f); //The scaling required to map input space to opengl space
|
||||||
|
GL.Uniform4(shader.Uniforms["Color"].Location, Color4.Red);
|
||||||
|
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
|
||||||
|
GL.BufferData(BufferTarget.ArrayBuffer, 1 * channelLength, bridge.DataPointer, BufferUsageHint.DynamicRead);
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||||
|
|
||||||
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||||
|
|
||||||
|
//GL.BindVertexArray(vertexArray.Handle);
|
||||||
|
GL.BindVertexArray(vao);
|
||||||
|
// This is old OpenGL. Consider modern OpenGL at some point https://stackoverflow.com/questions/3484260/opengl-line-width
|
||||||
|
GL.LineWidth(1.0f);
|
||||||
|
GL.DrawArrays(PrimitiveType.LineStrip, 0, channelLength);
|
||||||
|
GL.BindVertexArray(0);
|
||||||
|
|
||||||
|
GL.UseProgram(0);
|
||||||
|
SwapBuffers();
|
||||||
|
bridge.DataRead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnUpdateFrame(FrameEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnUpdateFrame(e);
|
||||||
|
|
||||||
|
if (KeyboardState.IsKeyDown(Keys.Escape))
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResize(ResizeEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnResize(e);
|
||||||
|
|
||||||
|
GL.Viewport(0, 0, Size.X, Size.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Shaders\graph.fragment.glsl" />
|
||||||
|
<None Remove="Shaders\graph.vertex.glsl" />
|
||||||
|
<None Remove="Shaders\graph2.vertex.glsl" />
|
||||||
|
<None Remove="Shaders\Grid.frag" />
|
||||||
|
<None Remove="Shaders\Grid.vert" />
|
||||||
|
<None Remove="Shaders\Shader.shader" />
|
||||||
|
<None Remove="Shaders\SimpleFrag.frag" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Shaders\graph2.vertex.glsl" />
|
||||||
|
<EmbeddedResource Include="Shaders\graph.fragment.glsl" />
|
||||||
|
<EmbeddedResource Include="Shaders\graph.vertex.glsl" />
|
||||||
|
<EmbeddedResource Include="Shaders\Grid.frag" />
|
||||||
|
<EmbeddedResource Include="Shaders\Grid.vert" />
|
||||||
|
<EmbeddedResource Include="Shaders\Shader.shader" />
|
||||||
|
<EmbeddedResource Include="Shaders\SimpleFrag.frag" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
||||||
|
<PackageReference Include="ObjectTK" Version="2.0.0-pre.9" />
|
||||||
|
<PackageReference Include="OpenTK" Version="4.7.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\TS.NET\TS.NET.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
33
Software/TS.NET/source/PlayingWithShaders/Primitives.cs
Normal file
33
Software/TS.NET/source/PlayingWithShaders/Primitives.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using ObjectTK;
|
||||||
|
using ObjectTK.GLObjects;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace PlayingWithShaders {
|
||||||
|
public static class Primitives {
|
||||||
|
|
||||||
|
private static readonly Vector2[] quadVertices = {
|
||||||
|
new Vector2(-1, -1),
|
||||||
|
new Vector2(-1, 1),
|
||||||
|
new Vector2( 1, 1),
|
||||||
|
new Vector2( 1, -1),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly int[] quadIndices = {
|
||||||
|
2, 1, 0,
|
||||||
|
2, 3, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly Lazy<Buffer<Vector2>> _quadPositionBuffer = new Lazy<Buffer<Vector2>>(() => GLFactory.Buffer.ArrayBuffer("Quad Positions", quadVertices));
|
||||||
|
private static readonly Lazy<Buffer<int>> _quadIndexBuffer = new Lazy<Buffer<int>>(() => GLFactory.Buffer.ArrayBuffer("Quad Indices", quadIndices));
|
||||||
|
private static readonly Lazy<VertexArray> _quadVertexArray =
|
||||||
|
new Lazy<VertexArray>(() =>
|
||||||
|
GLFactory.VertexArray.IndexAndVertexBuffers("Quad", _quadIndexBuffer.Value, _quadPositionBuffer.Value)
|
||||||
|
);
|
||||||
|
|
||||||
|
/// A vertex array with a simple quad from (-1.-1) to (1,1).
|
||||||
|
public static VertexArray Quad => _quadVertexArray.Value;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
91
Software/TS.NET/source/PlayingWithShaders/Program.cs
Normal file
91
Software/TS.NET/source/PlayingWithShaders/Program.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// https://www.shadertoy.com/view/slX3W2
|
||||||
|
// https://iquilezles.org/www/articles/distance/distance.htm
|
||||||
|
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
using OpenTK.Windowing.Desktop;
|
||||||
|
using PlayingWithShaders;
|
||||||
|
|
||||||
|
|
||||||
|
Console.WriteLine("Hello, World!");
|
||||||
|
|
||||||
|
NativeWindowSettings nativeWindowSettings = new NativeWindowSettings
|
||||||
|
{
|
||||||
|
Flags = ContextFlags.Debug,
|
||||||
|
Profile = ContextProfile.Core,
|
||||||
|
Title = "PlayingWithShaders",
|
||||||
|
NumberOfSamples = 0,
|
||||||
|
Size = new Vector2i(1024, 768),
|
||||||
|
//APIVersion = new Version(4, 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
using (var window = new OscilloscopeDisplay(GameWindowSettings.Default, nativeWindowSettings))
|
||||||
|
{
|
||||||
|
//GLDebugLog.Message += OnMessage;
|
||||||
|
//window.RenderFrame += OnRenderFrame;
|
||||||
|
//window.UpdateFrame += OnUpdate;
|
||||||
|
//Thread.Sleep(3000);
|
||||||
|
window.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//void OnUpdate(FrameEventArgs obj)
|
||||||
|
//{
|
||||||
|
// var r = new Random();
|
||||||
|
// var seriesIdx = r.Next(_graph.State.Series.Count);
|
||||||
|
// var series = _graph.State.Series[seriesIdx];
|
||||||
|
// var (x, y) = ScatterGraphGenerator.GenNormalDistPt(r);
|
||||||
|
// var pt = DateTime.UtcNow.Ticks;
|
||||||
|
// var str = pt.ToString();
|
||||||
|
// var offset = series.Points.Count;
|
||||||
|
// series.Add(str, x, y);
|
||||||
|
// _graph.State.Update((float)obj.Time);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//void OnMessage(object sender, DebugMessageEventArgs e)
|
||||||
|
//{
|
||||||
|
// Console.Error.WriteLine($"[{e.ID}]{e.Severity}|{e.Type}/{e.Source}: {e.Message}");
|
||||||
|
//}
|
||||||
|
|
||||||
|
//void OnRenderFrame(FrameEventArgs frameEventArgs)
|
||||||
|
//{
|
||||||
|
// var cur = _timer.Elapsed;
|
||||||
|
// var delta = cur - _lastFrame;
|
||||||
|
// _lastFrame = cur;
|
||||||
|
// GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||||
|
// GL.Viewport(0, 0, _window.ClientSize.X, _window.ClientSize.Y);
|
||||||
|
// var aspect = _window.ClientSize.X / (float)_window.ClientSize.Y;
|
||||||
|
// _graph.State.Camera.Current.AspectRatio = aspect;
|
||||||
|
// _graph.State.Camera.Target.AspectRatio = aspect;
|
||||||
|
// _graph.Render();
|
||||||
|
|
||||||
|
// _window.Context.SwapBuffers();
|
||||||
|
//}
|
||||||
|
|
||||||
|
//double onUpdateTime = 1;
|
||||||
|
|
||||||
|
//GLDebugLog.Message += OnMessage;
|
||||||
|
//window.RenderFrame += OnRenderFrame;
|
||||||
|
//window.UpdateFrame += OnUpdate;
|
||||||
|
//window.Run();
|
||||||
|
|
||||||
|
//void OnMessage(object sender, DebugMessageEventArgs e)
|
||||||
|
//{
|
||||||
|
// Console.Error.WriteLine($"[{e.ID}]{e.Severity}|{e.Type}/{e.Source}: {e.Message}");
|
||||||
|
//}
|
||||||
|
|
||||||
|
//void OnRenderFrame(FrameEventArgs frameEventArgs)
|
||||||
|
//{
|
||||||
|
// GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||||
|
// GL.Viewport(0, 0, window.ClientSize.X, window.ClientSize.Y);
|
||||||
|
|
||||||
|
|
||||||
|
// window.Context.SwapBuffers();
|
||||||
|
// window.Title = $"OnRenderFrame: {(1.0 / frameEventArgs.Time):F2} OnUpdate: {(1.0 / onUpdateTime):F2}";
|
||||||
|
//}
|
||||||
|
|
||||||
|
//void OnUpdate(FrameEventArgs frameEventArgs)
|
||||||
|
//{
|
||||||
|
// onUpdateTime = frameEventArgs.Time;
|
||||||
|
//}
|
@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using ObjectTK;
|
||||||
|
using ObjectTK.GLObjects;
|
||||||
|
|
||||||
|
namespace PlayingWithShaders {
|
||||||
|
public static class ShaderExtensions {
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, string> _readCache = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
private static string LoadFromRes(string name) {
|
||||||
|
if (_readCache.TryGetValue(name, out var res)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
// retrieves THIS assembly, not the one that started the process.
|
||||||
|
// in this way, it's always certain to load from here.
|
||||||
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
|
var resources = assembly.GetManifestResourceNames();
|
||||||
|
var resourceName = resources.Single(s => s.EndsWith(name));
|
||||||
|
|
||||||
|
using var stream = assembly.GetManifestResourceStream(resourceName);
|
||||||
|
using var reader = new StreamReader(stream!);
|
||||||
|
var result = reader.ReadToEnd();
|
||||||
|
_readCache[name] = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loads a vertex and fragment shader from an embedded resource in the executing assembly.
|
||||||
|
public static ShaderProgram EmbeddedResVertFrag(this GLShaderFactory fact, string name, string vertName, string fragName) {
|
||||||
|
var vertSrc = LoadFromRes(vertName);
|
||||||
|
var fragSrc = LoadFromRes(fragName);
|
||||||
|
|
||||||
|
return fact.VertexFrag(name, vertSrc, fragSrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
#version 330
|
||||||
|
|
||||||
|
uniform vec4 Color;
|
||||||
|
|
||||||
|
//out vec4 FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragColor = Color;//vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 InPosition;
|
||||||
|
|
||||||
|
uniform int PointCount;
|
||||||
|
uniform float OffsetX;
|
||||||
|
uniform float ScaleX;
|
||||||
|
uniform float OffsetY;
|
||||||
|
uniform float ScaleY;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
float dX = 2/PointCount;
|
||||||
|
|
||||||
|
gl_Position = vec4((InPosition.x * ScaleX) + OffsetX, (InPosition.y * ScaleY) + OffsetY, 0, 1.0);
|
||||||
|
//gl_PointSize = max(1.0, sprite);
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout(location = 0) in uint InPosition;
|
||||||
|
|
||||||
|
uniform int PointCount;
|
||||||
|
//uniform float OffsetX;
|
||||||
|
//uniform float ScaleX;
|
||||||
|
uniform float OffsetY;
|
||||||
|
uniform float ScaleY;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
//float dX = 2/PointCount;
|
||||||
|
|
||||||
|
//gl_Position = vec4(-1 + (InPosition* 0.0078125f), (InPosition + OffsetY) * ScaleY, 0, 1.0);
|
||||||
|
gl_Position = vec4(-1 + (gl_VertexID* 0.0000002f), (InPosition * ScaleY) + OffsetY, 0, 1.0);
|
||||||
|
//gl_PointSize = max(1.0, sprite);
|
||||||
|
}
|
106
Software/TS.NET/source/TS.NET.Benchmarks/CpuDiagnoser.cs
Normal file
106
Software/TS.NET/source/TS.NET.Benchmarks/CpuDiagnoser.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
using BenchmarkDotNet.Analysers;
|
||||||
|
using BenchmarkDotNet.Columns;
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Diagnosers;
|
||||||
|
using BenchmarkDotNet.Engines;
|
||||||
|
using BenchmarkDotNet.Exporters;
|
||||||
|
using BenchmarkDotNet.Loggers;
|
||||||
|
using BenchmarkDotNet.Reports;
|
||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
using BenchmarkDotNet.Validators;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace TS.NET.Benchmark
|
||||||
|
{
|
||||||
|
public class CpuDiagnoserAttribute : Attribute, IConfigSource
|
||||||
|
{
|
||||||
|
public IConfig Config { get; }
|
||||||
|
|
||||||
|
public CpuDiagnoserAttribute()
|
||||||
|
{
|
||||||
|
Config = ManualConfig.CreateEmpty().AddDiagnoser(new CpuDiagnoser());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CpuDiagnoser : IDiagnoser
|
||||||
|
{
|
||||||
|
Process proc;
|
||||||
|
|
||||||
|
public CpuDiagnoser()
|
||||||
|
{
|
||||||
|
this.proc = Process.GetCurrentProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> Ids => new[] { "CPU" };
|
||||||
|
|
||||||
|
public IEnumerable<IExporter> Exporters => Array.Empty<IExporter>();
|
||||||
|
|
||||||
|
public IEnumerable<IAnalyser> Analysers => Array.Empty<IAnalyser>();
|
||||||
|
|
||||||
|
public void DisplayResults(ILogger logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public RunMode GetRunMode(BenchmarkCase benchmarkCase)
|
||||||
|
{
|
||||||
|
return RunMode.NoOverhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
long userStart, userEnd;
|
||||||
|
long privStart, privEnd;
|
||||||
|
|
||||||
|
public void Handle(HostSignal signal, DiagnoserActionParameters parameters)
|
||||||
|
{
|
||||||
|
if (signal == HostSignal.BeforeActualRun)
|
||||||
|
{
|
||||||
|
userStart = proc.UserProcessorTime.Ticks;
|
||||||
|
privStart = proc.PrivilegedProcessorTime.Ticks;
|
||||||
|
}
|
||||||
|
if (signal == HostSignal.AfterActualRun)
|
||||||
|
{
|
||||||
|
userEnd = proc.UserProcessorTime.Ticks;
|
||||||
|
privEnd = proc.PrivilegedProcessorTime.Ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Metric> ProcessResults(DiagnoserResults results)
|
||||||
|
{
|
||||||
|
yield return new Metric(CpuUserMetricDescriptor.Instance, (userEnd - userStart) * 100d / results.TotalOperations);
|
||||||
|
yield return new Metric(CpuPrivilegedMetricDescriptor.Instance, (privEnd - privStart) * 100d / results.TotalOperations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ValidationError> Validate(ValidationParameters validationParameters)
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CpuUserMetricDescriptor : IMetricDescriptor
|
||||||
|
{
|
||||||
|
internal static readonly IMetricDescriptor Instance = new CpuUserMetricDescriptor();
|
||||||
|
|
||||||
|
public string Id => "CPU User Time";
|
||||||
|
public string DisplayName => Id;
|
||||||
|
public string Legend => Id;
|
||||||
|
public string NumberFormat => "0.##";
|
||||||
|
public UnitType UnitType => UnitType.Time;
|
||||||
|
public string Unit => "ns";
|
||||||
|
public bool TheGreaterTheBetter => false;
|
||||||
|
public int PriorityInCategory => 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CpuPrivilegedMetricDescriptor : IMetricDescriptor
|
||||||
|
{
|
||||||
|
internal static readonly IMetricDescriptor Instance = new CpuPrivilegedMetricDescriptor();
|
||||||
|
|
||||||
|
public string Id => "CPU Privileged Time";
|
||||||
|
public string DisplayName => Id;
|
||||||
|
public string Legend => Id;
|
||||||
|
public string NumberFormat => "0.##";
|
||||||
|
public UnitType UnitType => UnitType.Time;
|
||||||
|
public string Unit => "ns";
|
||||||
|
public bool TheGreaterTheBetter => false;
|
||||||
|
public int PriorityInCategory => 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
|
||||||
|
namespace TS.NET.Benchmark
|
||||||
|
{
|
||||||
|
[SimpleJob(RuntimeMoniker.Net60)]
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class PipelineBenchmark
|
||||||
|
{
|
||||||
|
private const int samplingRate = 1000000000;
|
||||||
|
private const int byteBufferSize = 8000000;
|
||||||
|
private readonly Memory<byte> input = new byte[byteBufferSize];
|
||||||
|
private readonly Memory<byte> shuffleOutput = new byte[byteBufferSize];
|
||||||
|
private readonly Memory<ulong> triggerBuffer = new ulong[byteBufferSize / 64];
|
||||||
|
private readonly RisingEdgeTrigger trigger1 = new(200, 190, 1000);
|
||||||
|
private readonly RisingEdgeTrigger trigger2 = new(200, 190, 1000);
|
||||||
|
private readonly RisingEdgeTrigger trigger3 = new(200, 190, 1000);
|
||||||
|
private readonly RisingEdgeTrigger trigger4 = new(200, 190, 1000);
|
||||||
|
private Memory<byte> channel1;
|
||||||
|
private Memory<byte> channel2;
|
||||||
|
private Memory<byte> channel3;
|
||||||
|
private Memory<byte> channel4;
|
||||||
|
Memory<ulong> triggerChannel1;
|
||||||
|
Memory<ulong> triggerChannel2;
|
||||||
|
Memory<ulong> triggerChannel3;
|
||||||
|
Memory<ulong> triggerChannel4;
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Waveforms.FourChannelSine(input.Span, samplingRate, 1000);
|
||||||
|
channel1 = shuffleOutput.Slice(0, 2000000);
|
||||||
|
channel2 = shuffleOutput.Slice(2000000, 2000000);
|
||||||
|
channel3 = shuffleOutput.Slice(4000000, 2000000);
|
||||||
|
channel4 = shuffleOutput.Slice(6000000, 2000000);
|
||||||
|
triggerChannel1 = triggerBuffer.Slice(0, 31250);
|
||||||
|
triggerChannel2 = triggerBuffer.Slice(31250, 31250);
|
||||||
|
triggerChannel3 = triggerBuffer.Slice(31250 * 2, 31250);
|
||||||
|
triggerChannel4 = triggerBuffer.Slice(31250 * 3, 31250);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "4 channels")]
|
||||||
|
public void FourChannelPipeline()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
{
|
||||||
|
Shuffle.FourChannels(input.Span, shuffleOutput.Span);
|
||||||
|
trigger1.ProcessSimd(input: channel1.Span, trigger: triggerChannel1.Span);
|
||||||
|
trigger2.ProcessSimd(input: channel2.Span, trigger: triggerChannel2.Span);
|
||||||
|
trigger3.ProcessSimd(input: channel3.Span, trigger: triggerChannel3.Span);
|
||||||
|
trigger4.ProcessSimd(input: channel4.Span, trigger: triggerChannel4.Span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Software/TS.NET/source/TS.NET.Benchmarks/Program.cs
Normal file
12
Software/TS.NET/source/TS.NET.Benchmarks/Program.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
using TS.NET.Benchmark;
|
||||||
|
|
||||||
|
DefaultConfig.Instance.WithOptions(ConfigOptions.JoinSummary);
|
||||||
|
//_ = BenchmarkRunner.Run(typeof(Program).Assembly);
|
||||||
|
//_ = BenchmarkRunner.Run<ShuffleBenchmark>();
|
||||||
|
//_ = BenchmarkRunner.Run<RisingEdgeTriggerBenchmark>();
|
||||||
|
//_ = BenchmarkRunner.Run<PipelineBenchmark>();
|
||||||
|
_ = BenchmarkRunner.Run<SumU8toI16Benchmark>();
|
||||||
|
_ = BenchmarkRunner.Run<SumU8toI32Benchmark>();
|
||||||
|
Console.ReadKey();
|
@ -0,0 +1,68 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Diagnosers;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
|
||||||
|
namespace TS.NET.Benchmark
|
||||||
|
{
|
||||||
|
[SimpleJob(RuntimeMoniker.Net60)]
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
//[CpuDiagnoser]
|
||||||
|
//[InProcess]
|
||||||
|
//[HardwareCounters(HardwareCounter.TotalIssues)]
|
||||||
|
public class RisingEdgeTriggerBenchmark
|
||||||
|
{
|
||||||
|
private const int samplingRate = 1000000000;
|
||||||
|
private const int byteBufferSize = 8000000;
|
||||||
|
private readonly Memory<byte> buffer1MHz = new byte[byteBufferSize];
|
||||||
|
private readonly Memory<byte> buffer1KHz = new byte[byteBufferSize];
|
||||||
|
private readonly Memory<ulong> triggerBufferU64 = new ulong[byteBufferSize / 64];
|
||||||
|
private readonly RisingEdgeTrigger trigger = new(200, 190, 1000);
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Waveforms.Sine(buffer1MHz.Span, samplingRate, 1000000);
|
||||||
|
Waveforms.Sine(buffer1KHz.Span, samplingRate, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
//[Benchmark(Description = "Rising edge with hysteresis (10 counts) & holdoff (1us) and no SIMD, 1KHz sine (125 x 8MS)")]
|
||||||
|
//public void RisingEdge2()
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < 125; i++)
|
||||||
|
// trigger.RisingEdge(buffer1KHz.Span, triggerBufferU64.Span);
|
||||||
|
//}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Rising edge with hysteresis (10 counts), holdoff (1us) & SIMD, 1KHz sine (125 x 8MS)")]
|
||||||
|
public void RisingEdge1()
|
||||||
|
{
|
||||||
|
trigger.Reset(200, 190, 1000);
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
trigger.ProcessSimd(buffer1KHz.Span, triggerBufferU64.Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0.18 CPU cycles per sample
|
||||||
|
[Benchmark(Description = "Rising edge with hysteresis (10 counts), holdoff (1us) & SIMD, 1MHz sine (125 x 8MS)")]
|
||||||
|
public void RisingEdge2()
|
||||||
|
{
|
||||||
|
trigger.Reset(200, 190, 1000);
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
trigger.ProcessSimd(buffer1MHz.Span, triggerBufferU64.Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
//[Benchmark(Description = "Rising edge with hysteresis (10 counts), holdoff (1ms) & SIMD, 1KHz sine (125 x 8MS)")]
|
||||||
|
//public void RisingEdge3()
|
||||||
|
//{
|
||||||
|
// trigger.Reset(200, 190, 1000000);
|
||||||
|
// for (int i = 0; i < 125; i++)
|
||||||
|
// trigger.ProcessSimd(buffer1KHz.Span, triggerBufferU64.Span);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[Benchmark(Description = "Rising edge with hysteresis (10 counts), holdoff (1ms) & SIMD, 1MHz sine (125 x 8MS)")]
|
||||||
|
//public void RisingEdge4()
|
||||||
|
//{
|
||||||
|
// trigger.Reset(200, 190, 1000000);
|
||||||
|
// for (int i = 0; i < 125; i++)
|
||||||
|
// trigger.ProcessSimd(buffer1MHz.Span, triggerBufferU64.Span);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
36
Software/TS.NET/source/TS.NET.Benchmarks/ShuffleBenchmark.cs
Normal file
36
Software/TS.NET/source/TS.NET.Benchmarks/ShuffleBenchmark.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
|
||||||
|
namespace TS.NET.Benchmark
|
||||||
|
{
|
||||||
|
[SimpleJob(RuntimeMoniker.Net60)]
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
//[CpuDiagnoser]
|
||||||
|
//[InProcess]
|
||||||
|
public class ShuffleBenchmark
|
||||||
|
{
|
||||||
|
private const int byteBufferSize = 8000000;
|
||||||
|
private readonly Memory<byte> input = new byte[byteBufferSize];
|
||||||
|
private readonly Memory<byte> output = new byte[byteBufferSize];
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Waveforms.FourChannelCount(input.Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Four channel shuffle (125 x 8MS)")] // 0.40 CPU cycles per sample
|
||||||
|
public void FourChannels()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
Shuffle.FourChannels(input.Span, output.Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Two channel shuffle (125 x 8MS)")] // 0.32 CPU cycles per sample
|
||||||
|
public void TwoChannels()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
Shuffle.TwoChannels(input.Span, output.Span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
|
||||||
|
namespace TS.NET.Benchmark
|
||||||
|
{
|
||||||
|
[SimpleJob(RuntimeMoniker.Net60)]
|
||||||
|
//[MemoryDiagnoser]
|
||||||
|
public class SumU8toI32Benchmark
|
||||||
|
{
|
||||||
|
private const int byteBufferSize = 8000000;
|
||||||
|
private readonly Memory<byte> input = new byte[byteBufferSize];
|
||||||
|
private readonly Memory<short> bufferI16 = new short[byteBufferSize / 2];
|
||||||
|
private readonly Memory<int> bufferI32 = new int[byteBufferSize / 2];
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Waveforms.Oversampling_1Channel_2Avg(input.Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "I32: Sum by 2 (1GS -> 500MS)", Baseline = true)] // CPU cycles per sample
|
||||||
|
public void I32_2_()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
HorizontalSum.U8ToI32(input.Span, bufferI16.Span, bufferI32.Span, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "I32: Sum by 4 (1GS -> 250MS)")] // CPU cycles per sample
|
||||||
|
public void I32_4_()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
HorizontalSum.U8ToI32(input.Span, bufferI16.Span, bufferI32.Span, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "I32: Sum by 8 (1GS -> 125MS)")] // CPU cycles per sample
|
||||||
|
public void I32_8_()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
HorizontalSum.U8ToI32(input.Span, bufferI16.Span, bufferI32.Span, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//[Benchmark(Description = "I32: Sum by 16 (1GS -> 62.5MS)")] // CPU cycles per sample
|
||||||
|
//public void I32_16_()
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < 125; i++)
|
||||||
|
// Sum.U8ToI32(input.Span, bufferI16.Span, bufferI32.Span, 4);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
|
||||||
|
namespace TS.NET.Benchmark
|
||||||
|
{
|
||||||
|
[SimpleJob(RuntimeMoniker.Net60)]
|
||||||
|
//[MemoryDiagnoser]
|
||||||
|
public class SumU8toI16Benchmark
|
||||||
|
{
|
||||||
|
private const int byteBufferSize = 8000000;
|
||||||
|
private readonly Memory<byte> input = new byte[byteBufferSize];
|
||||||
|
private readonly Memory<short> bufferI16 = new short[byteBufferSize / 2];
|
||||||
|
private readonly Memory<int> bufferI32 = new int[byteBufferSize / 2];
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Waveforms.Oversampling_1Channel_2Avg(input.Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "I16: Sum by 2 (1GS -> 500MS)", Baseline = true)] // x CPU cycles per sample
|
||||||
|
public void I16_2()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
HorizontalSum.U8ToI16(input.Span, bufferI16.Span, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "I16: Sum by 4 (1GS -> 250MS)")] // x CPU cycles per sample
|
||||||
|
public void I16_4()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
HorizontalSum.U8ToI16(input.Span, bufferI16.Span, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "I16: Sum by 8 (1GS -> 125MS)")] // x CPU cycles per sample
|
||||||
|
public void I16_8()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 125; i++)
|
||||||
|
HorizontalSum.U8ToI16(input.Span, bufferI16.Span, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//[Benchmark(Description = "I16: Sum by 16 (1GS -> 62.5MS)")] // x CPU cycles per sample
|
||||||
|
//public void I16_16()
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < 125; i++)
|
||||||
|
// Sum.U8ToI16(input.Span, bufferI16.Span, 4);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[Benchmark(Description = "I16: Sum by 32 (1GS -> 31.25MS)")] // x CPU cycles per sample
|
||||||
|
//public void I16_32()
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < 125; i++)
|
||||||
|
// Sum.U8ToI16(input.Span, bufferI16.Span, 5);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[Benchmark(Description = "I16: Sum by 64 (1GS -> 15.625MS)")] // x CPU cycles per sample
|
||||||
|
//public void I16_64()
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < 125; i++)
|
||||||
|
// Sum.U8ToI16(input.Span, bufferI16.Span, 6);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[Benchmark(Description = "I16: Sum by 128 (1GS -> 7.8125MS)")] // x CPU cycles per sample
|
||||||
|
//public void I16_128()
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < 125; i++)
|
||||||
|
// Sum.U8ToI16(input.Span, bufferI16.Span, 7);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\TS.NET\TS.NET.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
28
Software/TS.NET/source/TS.NET.Engine/Program.cs
Normal file
28
Software/TS.NET/source/TS.NET.Engine/Program.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using TS.NET;
|
||||||
|
using TS.NET.Engine;
|
||||||
|
|
||||||
|
Console.Title = "Engine";
|
||||||
|
using (Process p = Process.GetCurrentProcess())
|
||||||
|
p.PriorityClass = ProcessPriorityClass.High;
|
||||||
|
|
||||||
|
using var loggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole(options => { options.SingleLine = true; options.TimestampFormat = "HH:mm:ss "; }).AddFilter(level => level >= LogLevel.Debug));
|
||||||
|
|
||||||
|
BlockingChannel<ThunderscopeMemory> memoryPool = new();
|
||||||
|
for (int i = 0; i < 120; i++) // 120 = about 1 seconds worth of samples at 1GSPS
|
||||||
|
memoryPool.Writer.Write(new ThunderscopeMemory());
|
||||||
|
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
|
BlockingChannel<ThunderscopeMemory> processingPool = new();
|
||||||
|
ProcessingTask processingTask = new();
|
||||||
|
processingTask.Start(loggerFactory, processingPool.Reader, memoryPool.Writer);
|
||||||
|
InputTask inputTask = new();
|
||||||
|
inputTask.Start(loggerFactory, memoryPool.Reader, processingPool.Writer);
|
||||||
|
|
||||||
|
Console.WriteLine("Running... press any key to stop");
|
||||||
|
Console.ReadKey();
|
||||||
|
|
||||||
|
processingTask.Stop();
|
||||||
|
inputTask.Stop();
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user