Compare commits
No commits in common. "master" and "v0.7" have entirely different histories.
27
.appveyor.yml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
version: '{build}'
|
||||||
|
platform:
|
||||||
|
- x64
|
||||||
|
image:
|
||||||
|
- Visual Studio 2019
|
||||||
|
- Ubuntu1804
|
||||||
|
install:
|
||||||
|
- cmd: cd c:\tools\vcpkg
|
||||||
|
- cmd: git pull
|
||||||
|
- cmd: bootstrap-vcpkg.bat
|
||||||
|
- cmd: vcpkg install freetype glfw3 capstone[core,arm,arm64,x86] --triplet x64-windows-static
|
||||||
|
- cmd: vcpkg integrate install
|
||||||
|
- cmd: cd %APPVEYOR_BUILD_FOLDER%
|
||||||
|
build_script:
|
||||||
|
- cmd: msbuild .\update\build\win32\update.vcxproj
|
||||||
|
- cmd: msbuild .\profiler\build\win32\Tracy.vcxproj
|
||||||
|
- cmd: msbuild .\capture\build\win32\capture.vcxproj
|
||||||
|
- cmd: msbuild .\library\win32\TracyProfiler.vcxproj /property:Configuration=Release
|
||||||
|
- sh: sudo apt-get update && sudo apt-get -y install libglfw3-dev libgtk2.0-dev libcapstone-dev
|
||||||
|
- sh: make -C update/build/unix debug release
|
||||||
|
- sh: make -C profiler/build/unix debug release
|
||||||
|
- sh: make -C capture/build/unix debug release
|
||||||
|
- sh: make -C library/unix debug release
|
||||||
|
- sh: make -C test
|
||||||
|
- sh: make -C test clean
|
||||||
|
- sh: make -C test TRACYFLAGS=-DTRACY_ON_DEMAND
|
||||||
|
test: off
|
@ -1,18 +0,0 @@
|
|||||||
# Empirical format config, based on observed style guide
|
|
||||||
# Use this only as an help to fit the surrounding code style - don't reformat whole files at once
|
|
||||||
---
|
|
||||||
BasedOnStyle: LLVM
|
|
||||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
|
||||||
AllowShortLoopsOnASingleLine: true
|
|
||||||
AlwaysBreakTemplateDeclarations: Yes
|
|
||||||
BreakBeforeBraces: Allman
|
|
||||||
BreakConstructorInitializers: BeforeComma
|
|
||||||
BreakStringLiterals: false
|
|
||||||
ColumnLimit: 120
|
|
||||||
FixNamespaceComments: false
|
|
||||||
IndentPPDirectives: AfterHash
|
|
||||||
IndentWidth: 4
|
|
||||||
PointerAlignment: Left
|
|
||||||
SpaceBeforeParens: Never
|
|
||||||
SpacesInParentheses: true
|
|
||||||
TabWidth: 4
|
|
61
.clang-tidy
@ -1,61 +0,0 @@
|
|||||||
---
|
|
||||||
Checks:
|
|
||||||
'
|
|
||||||
clang-diagnostic-*,
|
|
||||||
clang-analyzer-*,
|
|
||||||
bugprone-*,
|
|
||||||
google-*,
|
|
||||||
misc-*,
|
|
||||||
modernize-*,
|
|
||||||
performance-*,
|
|
||||||
readability-*,
|
|
||||||
-bugprone-easily-swappable-parameters,
|
|
||||||
-bugprone-implicit-widening-of-multiplication-result,
|
|
||||||
-bugprone-narrowing-conversions,
|
|
||||||
-bugprone-reserved-identifier,
|
|
||||||
-google-readability-braces-around-statements,
|
|
||||||
-google-readability-casting,
|
|
||||||
-google-readability-function-size,
|
|
||||||
-google-readability-todo,
|
|
||||||
-google-readability-namespace-comments,
|
|
||||||
-misc-confusable-identifiers,
|
|
||||||
-misc-no-recursion,
|
|
||||||
-modernize-avoid-c-arrays,
|
|
||||||
-modernize-deprecated-headers,
|
|
||||||
-modernize-use-default-member-init,
|
|
||||||
-modernize-use-trailing-return-type,
|
|
||||||
-performance-no-int-to-ptr,
|
|
||||||
-readability-braces-around-statements,
|
|
||||||
-readability-else-after-return,
|
|
||||||
-readability-function-cognitive-complexity,
|
|
||||||
-readability-identifier-length,
|
|
||||||
-readability-implicit-bool-conversion,
|
|
||||||
-readability-isolate-declaration,
|
|
||||||
-readability-magic-numbers,
|
|
||||||
-readability-qualified-auto,
|
|
||||||
-readability-uppercase-literal-suffix
|
|
||||||
'
|
|
||||||
WarningsAsErrors: ''
|
|
||||||
HeaderFilterRegex: ''
|
|
||||||
FormatStyle: none
|
|
||||||
CheckOptions:
|
|
||||||
llvm-else-after-return.WarnOnConditionVariables: 'false'
|
|
||||||
modernize-loop-convert.MinConfidence: reasonable
|
|
||||||
modernize-replace-auto-ptr.IncludeStyle: llvm
|
|
||||||
modernize-pass-by-value.IncludeStyle: llvm
|
|
||||||
google-readability-namespace-comments.ShortNamespaceLines: '10'
|
|
||||||
google-readability-namespace-comments.SpacesBeforeComments: '2'
|
|
||||||
cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true'
|
|
||||||
google-readability-braces-around-statements.ShortStatementLines: '1'
|
|
||||||
cert-err33-c.CheckedFunctions: '::aligned_alloc;::asctime_s;::at_quick_exit;::atexit;::bsearch;::bsearch_s;::btowc;::c16rtomb;::c32rtomb;::calloc;::clock;::cnd_broadcast;::cnd_init;::cnd_signal;::cnd_timedwait;::cnd_wait;::ctime_s;::fclose;::fflush;::fgetc;::fgetpos;::fgets;::fgetwc;::fopen;::fopen_s;::fprintf;::fprintf_s;::fputc;::fputs;::fputwc;::fputws;::fread;::freopen;::freopen_s;::fscanf;::fscanf_s;::fseek;::fsetpos;::ftell;::fwprintf;::fwprintf_s;::fwrite;::fwscanf;::fwscanf_s;::getc;::getchar;::getenv;::getenv_s;::gets_s;::getwc;::getwchar;::gmtime;::gmtime_s;::localtime;::localtime_s;::malloc;::mbrtoc16;::mbrtoc32;::mbsrtowcs;::mbsrtowcs_s;::mbstowcs;::mbstowcs_s;::memchr;::mktime;::mtx_init;::mtx_lock;::mtx_timedlock;::mtx_trylock;::mtx_unlock;::printf_s;::putc;::putwc;::raise;::realloc;::remove;::rename;::scanf;::scanf_s;::setlocale;::setvbuf;::signal;::snprintf;::snprintf_s;::sprintf;::sprintf_s;::sscanf;::sscanf_s;::strchr;::strerror_s;::strftime;::strpbrk;::strrchr;::strstr;::strtod;::strtof;::strtoimax;::strtok;::strtok_s;::strtol;::strtold;::strtoll;::strtoul;::strtoull;::strtoumax;::strxfrm;::swprintf;::swprintf_s;::swscanf;::swscanf_s;::thrd_create;::thrd_detach;::thrd_join;::thrd_sleep;::time;::timespec_get;::tmpfile;::tmpfile_s;::tmpnam;::tmpnam_s;::tss_create;::tss_get;::tss_set;::ungetc;::ungetwc;::vfprintf;::vfprintf_s;::vfscanf;::vfscanf_s;::vfwprintf;::vfwprintf_s;::vfwscanf;::vfwscanf_s;::vprintf_s;::vscanf;::vscanf_s;::vsnprintf;::vsnprintf_s;::vsprintf;::vsprintf_s;::vsscanf;::vsscanf_s;::vswprintf;::vswprintf_s;::vswscanf;::vswscanf_s;::vwprintf_s;::vwscanf;::vwscanf_s;::wcrtomb;::wcschr;::wcsftime;::wcspbrk;::wcsrchr;::wcsrtombs;::wcsrtombs_s;::wcsstr;::wcstod;::wcstof;::wcstoimax;::wcstok;::wcstok_s;::wcstol;::wcstold;::wcstoll;::wcstombs;::wcstombs_s;::wcstoul;::wcstoull;::wcstoumax;::wcsxfrm;::wctob;::wctrans;::wctype;::wmemchr;::wprintf_s;::wscanf;::wscanf_s;'
|
|
||||||
modernize-loop-convert.MaxCopySize: '16'
|
|
||||||
cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU'
|
|
||||||
cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false'
|
|
||||||
cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false'
|
|
||||||
modernize-use-nullptr.NullMacros: 'NULL'
|
|
||||||
llvm-qualified-auto.AddConstToQualified: 'false'
|
|
||||||
modernize-loop-convert.NamingStyle: CamelCase
|
|
||||||
llvm-else-after-return.WarnOnUnfixable: 'false'
|
|
||||||
google-readability-function-size.StatementThreshold: '800'
|
|
||||||
...
|
|
||||||
|
|
BIN
.github/sponsor.png
vendored
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
83
.github/workflows/build.yml
vendored
@ -1,83 +0,0 @@
|
|||||||
name: build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm-cache
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ windows-latest, macos-15 ]
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
continue-on-error: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- if: startsWith(matrix.os, 'windows')
|
|
||||||
uses: microsoft/setup-msbuild@v2
|
|
||||||
- if: startsWith(matrix.os, 'windows')
|
|
||||||
uses: actions/setup-python@v2
|
|
||||||
with:
|
|
||||||
python-version: '3.x'
|
|
||||||
- if: startsWith(matrix.os, 'windows')
|
|
||||||
run: pip install meson ninja
|
|
||||||
- if: startsWith(matrix.os, 'macos')
|
|
||||||
name: Install macos dependencies
|
|
||||||
run: brew install pkg-config glfw meson
|
|
||||||
- name: Trust git repo
|
|
||||||
run: git config --global --add safe.directory '*'
|
|
||||||
- name: Profiler GUI
|
|
||||||
run: |
|
|
||||||
cmake -B profiler/build -S profiler -DCMAKE_BUILD_TYPE=Release -DGIT_REV=${{ github.sha }}
|
|
||||||
cmake --build profiler/build --parallel --config Release
|
|
||||||
- name: Update utility
|
|
||||||
run: |
|
|
||||||
cmake -B update/build -S update -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build update/build --parallel --config Release
|
|
||||||
- name: Capture utility
|
|
||||||
run: |
|
|
||||||
cmake -B capture/build -S capture -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build capture/build --parallel --config Release
|
|
||||||
- name: Csvexport utility
|
|
||||||
run: |
|
|
||||||
cmake -B csvexport/build -S csvexport -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build csvexport/build --parallel --config Release
|
|
||||||
- name: Import utilities
|
|
||||||
run: |
|
|
||||||
cmake -B import/build -S import -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build import/build --parallel --config Release
|
|
||||||
- if: ${{ !startsWith(matrix.os, 'windows') }}
|
|
||||||
name: Library
|
|
||||||
run: meson setup -Dprefix=$GITHUB_WORKSPACE/bin/lib build && meson compile -C build && meson install -C build
|
|
||||||
- if: ${{ !startsWith(matrix.os, 'windows') }}
|
|
||||||
name: Find Artifacts
|
|
||||||
id: find_artifacts
|
|
||||||
run: |
|
|
||||||
mkdir -p bin
|
|
||||||
cp profiler/build/tracy-profiler bin
|
|
||||||
cp update/build/tracy-update bin
|
|
||||||
cp capture/build/tracy-capture bin
|
|
||||||
cp csvexport/build/tracy-csvexport bin
|
|
||||||
cp import/build/tracy-import-chrome bin
|
|
||||||
cp import/build/tracy-import-fuchsia bin
|
|
||||||
- if: startsWith(matrix.os, 'windows')
|
|
||||||
name: Find Artifacts
|
|
||||||
id: find_artifacts_windows
|
|
||||||
run: |
|
|
||||||
mkdir bin
|
|
||||||
copy profiler\build\Release\tracy-profiler.exe bin
|
|
||||||
copy update\build\Release\tracy-update.exe bin
|
|
||||||
copy capture\build\Release\tracy-capture.exe bin
|
|
||||||
copy csvexport\build\Release\tracy-csvexport.exe bin
|
|
||||||
copy import\build\Release\tracy-import-chrome.exe bin
|
|
||||||
copy import\build\Release\tracy-import-fuchsia.exe bin
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.os }}
|
|
||||||
path: bin
|
|
63
.github/workflows/emscripten.yml
vendored
@ -1,63 +0,0 @@
|
|||||||
name: emscripten
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm-cache
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container: archlinux:base-devel
|
|
||||||
steps:
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pacman -Syu --noconfirm && pacman -S --noconfirm --needed cmake git unzip python ninja zstd
|
|
||||||
- name: Setup emscripten
|
|
||||||
uses: mymindstorm/setup-emsdk@v14
|
|
||||||
with:
|
|
||||||
version: 3.1.67
|
|
||||||
- name: Trust git repo
|
|
||||||
run: git config --global --add safe.directory '*'
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Profiler GUI
|
|
||||||
run: |
|
|
||||||
cmake -G Ninja -B profiler/build -S profiler -DCMAKE_BUILD_TYPE=MinSizeRel -DGIT_REV=${{ github.sha }} -DCMAKE_TOOLCHAIN_FILE=${{env.EMSDK}}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
|
|
||||||
cmake --build profiler/build --parallel
|
|
||||||
- name: Compress artifacts
|
|
||||||
run: |
|
|
||||||
zstd -18 profiler/build/tracy-profiler.js profiler/build/tracy-profiler.wasm
|
|
||||||
gzip -9 profiler/build/tracy-profiler.js profiler/build/tracy-profiler.wasm
|
|
||||||
- name: Find Artifacts
|
|
||||||
id: find_artifacts
|
|
||||||
run: |
|
|
||||||
mkdir -p bin
|
|
||||||
cp profiler/build/index.html bin
|
|
||||||
cp profiler/build/favicon.svg bin
|
|
||||||
cp profiler/build/tracy-profiler.data bin
|
|
||||||
cp profiler/build/tracy-profiler.js.gz bin
|
|
||||||
cp profiler/build/tracy-profiler.js.zst bin
|
|
||||||
cp profiler/build/tracy-profiler.wasm.gz bin
|
|
||||||
cp profiler/build/tracy-profiler.wasm.zst bin
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: emscripten
|
|
||||||
path: bin
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
if: github.ref == 'refs/heads/master'
|
|
||||||
steps:
|
|
||||||
- uses: actions/download-artifact@v4
|
|
||||||
- uses: wlixcc/SFTP-Deploy-Action@v1.2.4
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.USERNAME }}
|
|
||||||
server: ${{ secrets.SERVER }}
|
|
||||||
port: ${{ secrets.PORT }}
|
|
||||||
ssh_private_key: ${{ secrets.PRIVATE_KEY }}
|
|
||||||
local_path: './emscripten/*'
|
|
||||||
remote_path: ${{ secrets.REMOTE_PATH }}
|
|
||||||
sftp_only: true
|
|
30
.github/workflows/gcc.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
name: gcc
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install libraries
|
||||||
|
run: sudo apt-get update && sudo apt-get -y install libglfw3-dev libgtk2.0-dev libcapstone-dev
|
||||||
|
- name: Profiler GUI
|
||||||
|
run: make -C profiler/build/unix debug release
|
||||||
|
- name: Update utility
|
||||||
|
run: make -C update/build/unix debug release
|
||||||
|
- name: Capture utility
|
||||||
|
run: make -C capture/build/unix debug release
|
||||||
|
- name: Library
|
||||||
|
run: make -C library/unix debug release
|
||||||
|
- name: Test application
|
||||||
|
run: |
|
||||||
|
make -C test
|
||||||
|
make -C test clean
|
||||||
|
make -C test TRACYFLAGS=-DTRACY_ON_DEMAND
|
7
.github/workflows/latex.yml
vendored
@ -12,16 +12,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Fix stupidity
|
- name: Fix stupidity
|
||||||
run: |
|
run: |
|
||||||
|
cp AUTHORS AUTHORS.
|
||||||
cp LICENSE LICENSE.
|
cp LICENSE LICENSE.
|
||||||
- name: Compile LaTeX
|
- name: Compile LaTeX
|
||||||
uses: xu-cheng/latex-action@v3
|
uses: xu-cheng/latex-action@v2
|
||||||
with:
|
with:
|
||||||
working_directory: manual
|
working_directory: manual
|
||||||
root_file: tracy.tex
|
root_file: tracy.tex
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: manual
|
name: manual
|
||||||
path: manual/tracy.pdf
|
path: manual/tracy.pdf
|
||||||
|
80
.github/workflows/linux.yml
vendored
@ -1,80 +0,0 @@
|
|||||||
name: linux
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm-cache
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container: archlinux:base-devel
|
|
||||||
steps:
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pacman -Syu --noconfirm && pacman -S --noconfirm --needed freetype2 debuginfod wayland dbus libxkbcommon libglvnd meson cmake git wayland-protocols nodejs
|
|
||||||
- name: Trust git repo
|
|
||||||
run: git config --global --add safe.directory '*'
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Profiler GUI
|
|
||||||
run: |
|
|
||||||
cmake -B profiler/build -S profiler -DCMAKE_BUILD_TYPE=Release -DGIT_REV=${{ github.sha }}
|
|
||||||
cmake --build profiler/build --parallel
|
|
||||||
- name: Update utility
|
|
||||||
run: |
|
|
||||||
cmake -B update/build -S update -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build update/build --parallel
|
|
||||||
- name: Capture utility
|
|
||||||
run: |
|
|
||||||
cmake -B capture/build -S capture -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build capture/build --parallel
|
|
||||||
- name: Csvexport utility
|
|
||||||
run: |
|
|
||||||
cmake -B csvexport/build -S csvexport -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build csvexport/build --parallel
|
|
||||||
- name: Import utilities
|
|
||||||
run: |
|
|
||||||
cmake -B import/build -S import -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build import/build --parallel
|
|
||||||
- name: Library
|
|
||||||
run: meson setup -Dprefix=$GITHUB_WORKSPACE/bin/lib build && meson compile -C build && meson install -C build
|
|
||||||
- name: Test application
|
|
||||||
run: |
|
|
||||||
# test compilation with different flags
|
|
||||||
# we clean the build folder to reset cached variables between runs
|
|
||||||
cmake -B test/build -S test -DCMAKE_BUILD_TYPE=Release
|
|
||||||
cmake --build test/build --parallel
|
|
||||||
rm -rf test/build
|
|
||||||
|
|
||||||
# same with TRACY_ON_DEMAND
|
|
||||||
cmake -B test/build -S test -DCMAKE_BUILD_TYPE=Release -DTRACY_ON_DEMAND=ON .
|
|
||||||
cmake --build test/build --parallel
|
|
||||||
rm -rf test/build
|
|
||||||
|
|
||||||
# same with TRACY_DELAYED_INIT TRACY_MANUAL_LIFETIME
|
|
||||||
cmake -B test/build -S test -DCMAKE_BUILD_TYPE=Release -DTRACY_DELAYED_INIT=ON -DTRACY_MANUAL_LIFETIME=ON .
|
|
||||||
cmake --build test/build --parallel
|
|
||||||
rm -rf test/build
|
|
||||||
|
|
||||||
# same with TRACY_DEMANGLE
|
|
||||||
cmake -B test/build -S test -DCMAKE_BUILD_TYPE=Release -DTRACY_DEMANGLE=ON .
|
|
||||||
cmake --build test/build --parallel
|
|
||||||
rm -rf test/build
|
|
||||||
- name: Find Artifacts
|
|
||||||
id: find_artifacts
|
|
||||||
run: |
|
|
||||||
mkdir -p bin
|
|
||||||
cp profiler/build/tracy-profiler bin
|
|
||||||
cp update/build/tracy-update bin
|
|
||||||
cp capture/build/tracy-capture bin
|
|
||||||
cp csvexport/build/tracy-csvexport bin
|
|
||||||
cp import/build/tracy-import-chrome bin
|
|
||||||
cp import/build/tracy-import-fuchsia bin
|
|
||||||
strip bin/tracy-*
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: arch-linux
|
|
||||||
path: bin
|
|
47
.github/workflows/msvc.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
name: MSVC
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: windows-2019
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: microsoft/setup-msbuild@v1.0.0
|
||||||
|
- name: Integrate vcpkg
|
||||||
|
run: vcpkg integrate install
|
||||||
|
- name: Build vcpkg libraries
|
||||||
|
run: vcpkg install freetype glfw3 capstone[arm,arm64,x86] --triplet x64-windows-static
|
||||||
|
- name: Profiler GUI Debug
|
||||||
|
run: msbuild .\profiler\build\win32\Tracy.vcxproj /property:Configuration=Debug /property:Platform=x64
|
||||||
|
- name: Profiler GUI Release
|
||||||
|
run: msbuild .\profiler\build\win32\Tracy.vcxproj /property:Configuration=Release /property:Platform=x64
|
||||||
|
- name: Update utility Debug
|
||||||
|
run: msbuild .\update\build\win32\update.vcxproj /property:Configuration=Debug /property:Platform=x64
|
||||||
|
- name: Update utility Release
|
||||||
|
run: msbuild .\update\build\win32\update.vcxproj /property:Configuration=Release /property:Platform=x64
|
||||||
|
- name: Capture utility Debug
|
||||||
|
run: msbuild .\capture\build\win32\capture.vcxproj /property:Configuration=Debug /property:Platform=x64
|
||||||
|
- name: Capture utility Release
|
||||||
|
run: msbuild .\capture\build\win32\capture.vcxproj /property:Configuration=Release /property:Platform=x64
|
||||||
|
- name: Library
|
||||||
|
run: msbuild .\library\win32\TracyProfiler.vcxproj /property:Configuration=Release /property:Platform=x64
|
||||||
|
- name: Package binaries
|
||||||
|
run: |
|
||||||
|
mkdir bin
|
||||||
|
mkdir bin\dev
|
||||||
|
copy profiler\build\win32\x64\Release\Tracy.exe bin
|
||||||
|
copy update\build\win32\x64\Release\update.exe bin
|
||||||
|
copy capture\build\win32\x64\Release\capture.exe bin
|
||||||
|
copy library\win32\x64\Release\TracyProfiler.dll bin\dev
|
||||||
|
copy library\win32\x64\Release\TracyProfiler.lib bin\dev
|
||||||
|
7z a Tracy.7z bin
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
path: Tracy.7z
|
25
.gitignore
vendored
@ -1,12 +1,13 @@
|
|||||||
.vs
|
.vs
|
||||||
_build
|
*.opendb
|
||||||
_compiler
|
*.db
|
||||||
tools/*
|
*.vcxproj.user
|
||||||
|
x64
|
||||||
|
Release
|
||||||
|
Debug
|
||||||
*.d
|
*.d
|
||||||
*.o
|
*.o
|
||||||
*.so
|
|
||||||
*.swp
|
*.swp
|
||||||
*.obj
|
|
||||||
imgui.ini
|
imgui.ini
|
||||||
test/tracy_test
|
test/tracy_test
|
||||||
test/tracy_test.exe
|
test/tracy_test.exe
|
||||||
@ -19,18 +20,10 @@ manual/t*.synctex.gz
|
|||||||
manual/t*.toc
|
manual/t*.toc
|
||||||
manual/t*.bbl
|
manual/t*.bbl
|
||||||
manual/t*.blg
|
manual/t*.blg
|
||||||
manual/t*.fdb_latexmk
|
|
||||||
manual/t*.fls
|
|
||||||
profiler/build/win32/packages
|
profiler/build/win32/packages
|
||||||
profiler/build/win32/Tracy.aps
|
profiler/build/win32/Tracy.aps
|
||||||
|
# include the vcpkg install script but not the files it produces
|
||||||
|
vcpkg/*
|
||||||
|
!vcpkg/install_vcpkg_dependencies.bat
|
||||||
.deps/
|
.deps/
|
||||||
.dirstamp
|
.dirstamp
|
||||||
/_*/**
|
|
||||||
/**/__pycache__/**
|
|
||||||
extra/vswhere.exe
|
|
||||||
extra/tracy-build
|
|
||||||
.cache
|
|
||||||
compile_commands.json
|
|
||||||
profiler/build/wasm/Tracy-release.*
|
|
||||||
profiler/build/wasm/Tracy-debug.*
|
|
||||||
profiler/build/wasm/embed.tracy
|
|
||||||
|
2
.mailmap
@ -1,2 +0,0 @@
|
|||||||
<wolf@nereid.pl> <wolf.pld@gmail.com>
|
|
||||||
<wolf@nereid.pl> <bartosz.taudul@game-lion.com>
|
|
7
.vscode/extensions.json
vendored
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"llvm-vs-code-extensions.vscode-clangd",
|
|
||||||
"vadimcn.vscode-lldb",
|
|
||||||
"ms-vscode.cmake-tools"
|
|
||||||
]
|
|
||||||
}
|
|
13
.vscode/launch.json
vendored
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Launch",
|
|
||||||
"type": "lldb",
|
|
||||||
"request": "launch",
|
|
||||||
"program": "${command:cmake.launchTargetPath}",
|
|
||||||
"args": [],
|
|
||||||
"cwd": "${workspaceFolder}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
20
.vscode/settings.json
vendored
@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"cmake.configureOnOpen": true,
|
|
||||||
"cmake.sourceDirectory": [
|
|
||||||
"${workspaceFolder}/profiler",
|
|
||||||
"${workspaceFolder}/capture",
|
|
||||||
"${workspaceFolder}/csvexport",
|
|
||||||
"${workspaceFolder}/import",
|
|
||||||
"${workspaceFolder}/update",
|
|
||||||
"${workspaceFolder}/test",
|
|
||||||
"${workspaceFolder}",
|
|
||||||
],
|
|
||||||
"cmake.buildDirectory": "${sourceDirectory}/build",
|
|
||||||
"cmake.autoSelectActiveFolder": false,
|
|
||||||
"cmake.options.advanced": {
|
|
||||||
"folder": { "statusBarVisibility": "visible" },
|
|
||||||
"variant": { "statusBarVisibility": "compact" }
|
|
||||||
},
|
|
||||||
"cmake.copyCompileCommands": "${workspaceFolder}/compile_commands.json",
|
|
||||||
"lldb.launch.initCommands": ["command script import ${workspaceRoot}/extra/natvis.py"],
|
|
||||||
}
|
|
11
AUTHORS
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Bartosz Taudul <wolf.pld@gmail.com>
|
||||||
|
Kamil Klimek <kamil.klimek@sharkbits.com> (initial find zone implementation)
|
||||||
|
Bartosz Szreder <zgredder@gmail.com> (view/worker split)
|
||||||
|
Arvid Gerstmann <dev@arvid-g.de> (compatibility fixes)
|
||||||
|
Rokas Kupstys <rokups@zoho.com> (compatibility fixes, initial CI work, MingW support)
|
||||||
|
Till Rathmann <till.rathmann@gmx.de> (DLL support)
|
||||||
|
Sherief Farouk <sherief.personal@gmail.com> (compatibility fixes)
|
||||||
|
Dedmen Miller <dedmen@dedmen.de> (find zone bug fixes, improvements)
|
||||||
|
Michał Cichoń <michcic@gmail.com> (OSX call stack decoding backport)
|
||||||
|
Thales Sabino <thales@codeplay.com> (OpenCL support)
|
||||||
|
Andrew Depke <andrewdepke@gmail.com> (Direct3D 12 support)
|
271
CMakeLists.txt
@ -1,271 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
|
||||||
|
|
||||||
# Run version helper script
|
|
||||||
include(cmake/version.cmake)
|
|
||||||
|
|
||||||
project(Tracy LANGUAGES CXX VERSION ${TRACY_VERSION_STRING})
|
|
||||||
|
|
||||||
file(GENERATE OUTPUT .gitignore CONTENT "*")
|
|
||||||
|
|
||||||
if(${BUILD_SHARED_LIBS})
|
|
||||||
set(DEFAULT_STATIC OFF)
|
|
||||||
else()
|
|
||||||
set(DEFAULT_STATIC ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(TRACY_STATIC "Whether to build Tracy as a static library" ${DEFAULT_STATIC})
|
|
||||||
option(TRACY_Fortran "Build Fortran bindings" OFF)
|
|
||||||
option(TRACY_LTO "Enable Link-Time optimization" OFF)
|
|
||||||
|
|
||||||
if(TRACY_Fortran)
|
|
||||||
enable_language(Fortran)
|
|
||||||
set(CMAKE_Fortran_VERSION 2003)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(TRACY_LTO OR CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
|
||||||
include(CheckIPOSupported)
|
|
||||||
check_ipo_supported(RESULT LTO_SUPPORTED)
|
|
||||||
if(NOT LTO_SUPPORTED)
|
|
||||||
message(WARNING "LTO is not supported!")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(LTO_SUPPORTED OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
|
||||||
|
|
||||||
set(TRACY_PUBLIC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/public)
|
|
||||||
|
|
||||||
if(LTO_SUPPORTED)
|
|
||||||
set(TRACY_VISIBILITY "OBJECT")
|
|
||||||
elseif(TRACY_STATIC)
|
|
||||||
set(TRACY_VISIBILITY "STATIC")
|
|
||||||
else()
|
|
||||||
set(TRACY_VISIBILITY "SHARED")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(TracyClient ${TRACY_VISIBILITY} "${TRACY_PUBLIC_DIR}/TracyClient.cpp")
|
|
||||||
target_compile_features(TracyClient PUBLIC cxx_std_11)
|
|
||||||
set_target_properties(TracyClient PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${LTO_SUPPORTED})
|
|
||||||
target_include_directories(TracyClient SYSTEM PUBLIC
|
|
||||||
$<BUILD_INTERFACE:${TRACY_PUBLIC_DIR}>
|
|
||||||
$<INSTALL_INTERFACE:include>)
|
|
||||||
target_link_libraries(
|
|
||||||
TracyClient
|
|
||||||
PUBLIC
|
|
||||||
Threads::Threads
|
|
||||||
${CMAKE_DL_LIBS}
|
|
||||||
)
|
|
||||||
|
|
||||||
if(TRACY_Fortran)
|
|
||||||
add_library(TracyClientF90 ${TRACY_VISIBILITY} "${TRACY_PUBLIC_DIR}/TracyClient.F90")
|
|
||||||
target_include_directories(TracyClientF90 PUBLIC
|
|
||||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
|
|
||||||
$<INSTALL_INTERFACE:include>)
|
|
||||||
target_link_libraries(
|
|
||||||
TracyClientF90
|
|
||||||
PUBLIC
|
|
||||||
TracyClient
|
|
||||||
)
|
|
||||||
set_target_properties(TracyClientF90 PROPERTIES Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
||||||
INTERPROCEDURAL_OPTIMIZATION ${LTO_SUPPORTED})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Public dependency on some libraries required when using Mingw
|
|
||||||
if(WIN32 AND ${CMAKE_CXX_COMPILER_ID} MATCHES "GNU|Clang")
|
|
||||||
target_link_libraries(TracyClient PUBLIC ws2_32 dbghelp)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
|
||||||
find_library(EXECINFO_LIBRARY NAMES execinfo REQUIRED)
|
|
||||||
target_link_libraries(TracyClient PUBLIC ${EXECINFO_LIBRARY})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(TRACY_LIBUNWIND_BACKTRACE)
|
|
||||||
include(FindPkgConfig)
|
|
||||||
pkg_check_modules(unwind REQUIRED libunwind)
|
|
||||||
target_include_directories(TracyClient INTERFACE ${unwind_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(TracyClient INTERFACE ${unwind_LINK_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(TRACY_DEBUGINFOD)
|
|
||||||
include(FindPkgConfig)
|
|
||||||
pkg_check_modules(debuginfod REQUIRED libdebuginfod)
|
|
||||||
target_include_directories(TracyClient INTERFACE ${debuginfod_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(TracyClient INTERFACE ${debuginfod_LINK_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(Tracy::TracyClient ALIAS TracyClient)
|
|
||||||
if(TRACY_Fortran)
|
|
||||||
add_library(Tracy::TracyClient_Fortran ALIAS TracyClientF90)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
macro(set_option option help value)
|
|
||||||
option(${option} ${help} ${value})
|
|
||||||
if(${option})
|
|
||||||
message(STATUS "${option}: ON")
|
|
||||||
target_compile_definitions(TracyClient PUBLIC ${option})
|
|
||||||
else()
|
|
||||||
message(STATUS "${option}: OFF")
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
set_option(TRACY_ENABLE "Enable profiling" ON)
|
|
||||||
set_option(TRACY_ON_DEMAND "On-demand profiling" OFF)
|
|
||||||
set_option(TRACY_CALLSTACK "Enforce callstack collection for tracy regions" OFF)
|
|
||||||
set_option(TRACY_NO_CALLSTACK "Disable all callstack related functionality" OFF)
|
|
||||||
set_option(TRACY_NO_CALLSTACK_INLINES "Disables the inline functions in callstacks" OFF)
|
|
||||||
set_option(TRACY_ONLY_LOCALHOST "Only listen on the localhost interface" OFF)
|
|
||||||
set_option(TRACY_NO_BROADCAST "Disable client discovery by broadcast to local network" OFF)
|
|
||||||
set_option(TRACY_ONLY_IPV4 "Tracy will only accept connections on IPv4 addresses (disable IPv6)" OFF)
|
|
||||||
set_option(TRACY_NO_CODE_TRANSFER "Disable collection of source code" OFF)
|
|
||||||
set_option(TRACY_NO_CONTEXT_SWITCH "Disable capture of context switches" OFF)
|
|
||||||
set_option(TRACY_NO_EXIT "Client executable does not exit until all profile data is sent to server" OFF)
|
|
||||||
set_option(TRACY_NO_SAMPLING "Disable call stack sampling" OFF)
|
|
||||||
set_option(TRACY_NO_VERIFY "Disable zone validation for C API" OFF)
|
|
||||||
set_option(TRACY_NO_VSYNC_CAPTURE "Disable capture of hardware Vsync events" OFF)
|
|
||||||
set_option(TRACY_NO_FRAME_IMAGE "Disable the frame image support and its thread" OFF)
|
|
||||||
set_option(TRACY_NO_SYSTEM_TRACING "Disable systrace sampling" OFF)
|
|
||||||
set_option(TRACY_PATCHABLE_NOPSLEDS "Enable nopsleds for efficient patching by system-level tools (e.g. rr)" OFF)
|
|
||||||
set_option(TRACY_DELAYED_INIT "Enable delayed initialization of the library (init on first call)" OFF)
|
|
||||||
set_option(TRACY_MANUAL_LIFETIME "Enable the manual lifetime management of the profile" OFF)
|
|
||||||
set_option(TRACY_FIBERS "Enable fibers support" OFF)
|
|
||||||
set_option(TRACY_NO_CRASH_HANDLER "Disable crash handling" OFF)
|
|
||||||
set_option(TRACY_TIMER_FALLBACK "Use lower resolution timers" OFF)
|
|
||||||
set_option(TRACY_LIBUNWIND_BACKTRACE "Use libunwind backtracing where supported" OFF)
|
|
||||||
set_option(TRACY_SYMBOL_OFFLINE_RESOLVE "Instead of full runtime symbol resolution, only resolve the image path and offset to enable offline symbol resolution" OFF)
|
|
||||||
set_option(TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT "Enable libbacktrace to support dynamically loaded elfs in symbol resolution resolution after the first symbol resolve operation" OFF)
|
|
||||||
set_option(TRACY_DEBUGINFOD "Enable debuginfod support" OFF)
|
|
||||||
|
|
||||||
# advanced
|
|
||||||
set_option(TRACY_VERBOSE "[advanced] Verbose output from the profiler" OFF)
|
|
||||||
mark_as_advanced(TRACY_VERBOSE)
|
|
||||||
set_option(TRACY_DEMANGLE "[advanced] Don't use default demangling function - You'll need to provide your own" OFF)
|
|
||||||
mark_as_advanced(TRACY_DEMANGLE)
|
|
||||||
|
|
||||||
# handle incompatible combinations
|
|
||||||
if(TRACY_MANUAL_LIFETIME AND NOT TRACY_DELAYED_INIT)
|
|
||||||
message(FATAL_ERROR "TRACY_MANUAL_LIFETIME can not be activated with disabled TRACY_DELAYED_INIT")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT TRACY_STATIC)
|
|
||||||
target_compile_definitions(TracyClient PRIVATE TRACY_EXPORTS)
|
|
||||||
target_compile_definitions(TracyClient PUBLIC TRACY_IMPORTS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
|
|
||||||
set_target_properties(TracyClient PROPERTIES VERSION ${PROJECT_VERSION})
|
|
||||||
if(TRACY_Fortran)
|
|
||||||
set_target_properties(TracyClientF90 PROPERTIES VERSION ${PROJECT_VERSION})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(tracy_includes
|
|
||||||
${TRACY_PUBLIC_DIR}/tracy/TracyC.h
|
|
||||||
${TRACY_PUBLIC_DIR}/tracy/Tracy.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/tracy/TracyD3D11.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/tracy/TracyD3D12.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/tracy/TracyLua.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/tracy/TracyOpenCL.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/tracy/TracyOpenGL.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/tracy/TracyVulkan.hpp)
|
|
||||||
|
|
||||||
set(client_includes
|
|
||||||
${TRACY_PUBLIC_DIR}/client/tracy_concurrentqueue.h
|
|
||||||
${TRACY_PUBLIC_DIR}/client/tracy_rpmalloc.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/tracy_SPSCQueue.h
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyKCore.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyArmCpuTable.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyCallstack.h
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyCallstack.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyCpuid.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyDebug.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyDxt1.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyFastVector.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyLock.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyProfiler.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyRingBuffer.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyScoped.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyStringHelpers.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracySysPower.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracySysTime.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracySysTrace.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/client/TracyThread.hpp)
|
|
||||||
|
|
||||||
set(common_includes
|
|
||||||
${TRACY_PUBLIC_DIR}/common/tracy_lz4.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/tracy_lz4hc.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyAlign.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyAlloc.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyApi.h
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyColor.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyForceInline.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyMutex.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyProtocol.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyQueue.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracySocket.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyStackFrames.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracySystem.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyUwp.hpp
|
|
||||||
${TRACY_PUBLIC_DIR}/common/TracyYield.hpp)
|
|
||||||
|
|
||||||
install(TARGETS TracyClient
|
|
||||||
EXPORT TracyConfig
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
COMPONENT lib)
|
|
||||||
if(TRACY_Fortran)
|
|
||||||
install(TARGETS TracyClientF90
|
|
||||||
EXPORT TracyConfig
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
COMPONENT lib)
|
|
||||||
endif()
|
|
||||||
# Export targets to build tree root
|
|
||||||
export(TARGETS TracyClient
|
|
||||||
NAMESPACE Tracy::
|
|
||||||
FILE ${CMAKE_BINARY_DIR}/TracyTargets.cmake)
|
|
||||||
if(TRACY_Fortran)
|
|
||||||
export(TARGETS TracyClientF90
|
|
||||||
NAMESPACE Tracy::
|
|
||||||
APPEND
|
|
||||||
FILE ${CMAKE_BINARY_DIR}/TracyTargets.cmake)
|
|
||||||
endif()
|
|
||||||
install(FILES ${tracy_includes}
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tracy/tracy)
|
|
||||||
install(FILES ${client_includes}
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tracy/client)
|
|
||||||
install(FILES ${common_includes}
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tracy/common)
|
|
||||||
if(TRACY_Fortran)
|
|
||||||
if(${CMAKE_Fortran_COMPILER_ID} MATCHES "Cray")
|
|
||||||
install(FILES ${PROJECT_BINARY_DIR}/TRACY.mod
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tracy)
|
|
||||||
else()
|
|
||||||
install(FILES ${PROJECT_BINARY_DIR}/tracy.mod
|
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tracy)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
install(EXPORT TracyConfig
|
|
||||||
NAMESPACE Tracy::
|
|
||||||
FILE TracyTargets.cmake
|
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/TracyConfig.cmake"
|
|
||||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/TracyConfig.cmake
|
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
|
||||||
|
|
||||||
option(TRACY_CLIENT_PYTHON "Whether to build Tracy python client library" OFF)
|
|
||||||
|
|
||||||
if(TRACY_CLIENT_PYTHON)
|
|
||||||
if(TRACY_STATIC)
|
|
||||||
message(FATAL_ERROR "Python-bindings require a shared client library")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_subdirectory(python)
|
|
||||||
endif()
|
|
@ -1,6 +0,0 @@
|
|||||||
@PACKAGE_INIT@
|
|
||||||
|
|
||||||
include(CMakeFindDependencyMacro)
|
|
||||||
find_dependency(Threads REQUIRED)
|
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/TracyTargets.cmake")
|
|
2
LICENSE
@ -1,7 +1,7 @@
|
|||||||
Tracy Profiler (https://github.com/wolfpld/tracy) is licensed under the
|
Tracy Profiler (https://github.com/wolfpld/tracy) is licensed under the
|
||||||
3-clause BSD license.
|
3-clause BSD license.
|
||||||
|
|
||||||
Copyright (c) 2017-2025, Bartosz Taudul <wolf@nereid.pl>
|
Copyright (c) 2017-2020, Bartosz Taudul <wolf.pld@gmail.com>
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
748
NEWS
@ -2,740 +2,9 @@ Note: There is no guarantee that version mismatched client and server will
|
|||||||
be able to talk with each other. Network protocol breakages won't be listed
|
be able to talk with each other. Network protocol breakages won't be listed
|
||||||
here.
|
here.
|
||||||
|
|
||||||
vx.xx.x (xxxx-xx-xx)
|
Note: Release numbers are nothing more than numbers. There are some
|
||||||
--------------------
|
"missing" versions due to trace file changes during development. This is not
|
||||||
|
a mistake.
|
||||||
- Enabled workaround for MSVC runtime library SNAFU, which manifested with
|
|
||||||
the profiler executables crashing at startup inside mutex code.
|
|
||||||
- CPU topology data now includes CPU die information.
|
|
||||||
- Clients running under Wine will now report that in the trace info.
|
|
||||||
- Added flame graph.
|
|
||||||
- The Git ref information for the build is now included in the about dialog.
|
|
||||||
- Added support for clipboard copy and paste on Wayland.
|
|
||||||
- The welcome dialog client address entry field will now trim the entered
|
|
||||||
address, so that stray spaces at the start and the end are removed. This
|
|
||||||
should reduce the amount of user precision required when copy pasting the
|
|
||||||
address from somewhere else.
|
|
||||||
- Metal GPU profiling is now available.
|
|
||||||
- Profiling zones can now optionally inherit their parent color.
|
|
||||||
- It is no longer needed to have up-to-date copy of wayland-protocols
|
|
||||||
installed. CMake will download the required version from GitHub.
|
|
||||||
- Added option to show the top inline in symbol statistics list in stead of
|
|
||||||
the symbol name.
|
|
||||||
- Parallel sorting is now performed with PPQSort (which removes potential
|
|
||||||
dependency on TBB).
|
|
||||||
- Added CMake option TRACY_DEBUGINFOD to enable use of libdebuginfod to
|
|
||||||
retrieve symbols on Linux clients.
|
|
||||||
- Added a "custom" label as an option to select for GPU context type.
|
|
||||||
- Symbol code retrieval is now protected against reading no longer available
|
|
||||||
memory.
|
|
||||||
- Clicking on a symbol in the symbol statistics list will now open a popup
|
|
||||||
with two options. This change intends to make the useful but quite hidden
|
|
||||||
disassembly view more discoverable.
|
|
||||||
- "View symbol" shows the symbol code disassembly. It was previously
|
|
||||||
available by right-click on the source file name.
|
|
||||||
- "Sample entry stacks" shows the list window that was previously
|
|
||||||
opened when the symbol entry was clicked.
|
|
||||||
- Plots are now extended to the end of the trace, instead of ending at the
|
|
||||||
last data point.
|
|
||||||
- Added TracyMemoryDiscard macros to mark that all allocations made in a
|
|
||||||
certain memory pool were freed. This enables better support for arena
|
|
||||||
allocators.
|
|
||||||
- It is now possible to fine-tune horizontal and vertical mouse wheel scroll
|
|
||||||
sensitivity.
|
|
||||||
- Added p75 and p90 percentiles in the Find zone window.
|
|
||||||
- Zone info window will now display (approximate) wall-clock time of when
|
|
||||||
the zone appeared, in addition to the previously displayed time from the
|
|
||||||
start of the program.
|
|
||||||
- Zone values passed via ZoneValue macro will be now also displayed in hex.
|
|
||||||
- The csvexport utility can now export plots.
|
|
||||||
- Fortran integration is now available.
|
|
||||||
|
|
||||||
|
|
||||||
v0.11.1 (2024-08-22)
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
- Utilities import-chrome and import-fuchsia now live together in the import
|
|
||||||
directory.
|
|
||||||
- Added TRACY_VERBOSE to available CMake options.
|
|
||||||
- It is now possible to set TRACY_SAMPLING_HZ via a environment variable.
|
|
||||||
- Thread group hints can be now used to group threads together in the
|
|
||||||
profiler UI.
|
|
||||||
- Limit Lua file names to 255 characters, as the source string can contain
|
|
||||||
the whole script, if loaded with loadstring().
|
|
||||||
|
|
||||||
|
|
||||||
v0.11.0 (2024-07-16)
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
- Support for pre-0.9 traces has been dropped.
|
|
||||||
- The old server-side build system has been replaced by CMake. The client
|
|
||||||
integration is not affected. Refer to the manual for details.
|
|
||||||
- Most importantly, a known version of the capstone library is now
|
|
||||||
downloaded from GitHub. You will need to have git installed for this
|
|
||||||
to work (there is a CMake option to use the capstone installed on the
|
|
||||||
system, as was done previously).
|
|
||||||
- Various Meson fixes.
|
|
||||||
- Proper way of loading Vulkan calibrated timestamps extension.
|
|
||||||
- Fixed C API support for GPU tracing when on demand mode is enabled.
|
|
||||||
- Added a way to resynchronize CPU and GPU timestamps.
|
|
||||||
- Using calibrated contexts should always be preferred.
|
|
||||||
- Each synchronization event requires a sync of CPU and GPU, which is
|
|
||||||
something you always want to avoid.
|
|
||||||
- This is not exposed as an easy-to-use API available through the GPU
|
|
||||||
wrappers.
|
|
||||||
- Added TracyIsStarted macro to check if the profiler has been started.
|
|
||||||
Using this functionality only makes sense in the manual lifetime mode,
|
|
||||||
and will always return true in any other mode of operation.
|
|
||||||
- Added basic QNX support.
|
|
||||||
- Zmmword is now recognized as an assemble size directive.
|
|
||||||
- Libunwind can be used for call stack capture on Linux if you build with
|
|
||||||
the TRACY_LIBUNWIND_BACKTRACE define.
|
|
||||||
- Preloading symbols for all modules on Windows, which is always performed
|
|
||||||
on program init, and which can be quite slow, may now be omitted through
|
|
||||||
the TRACY_NO_DBGHELP_INIT_LOAD define. In this mode, symbols will be
|
|
||||||
loaded as needed.
|
|
||||||
- Validation of discontinuous frames has been disabled in on-demand mode.
|
|
||||||
It's quite likely to connect in the middle of a discontinuous frame,
|
|
||||||
which resulted in frame end event for a frame that hasn't been started.
|
|
||||||
- Symbols can be now resolved offline on Windows and Linux.
|
|
||||||
- Enabled with the TRACY_SYMBOL_OFFLINE_RESOLVE define or env variable.
|
|
||||||
- The update utility has two additional options:
|
|
||||||
- -r, which enables resolving symbol and patching stack frames in the
|
|
||||||
trace.
|
|
||||||
- -p, which you can use to modify the paths used for symbol resolution.
|
|
||||||
- Some functionality will be missing if this mode is used. For example,
|
|
||||||
symbol statistics are unavailable.
|
|
||||||
- Resolving symbol names on Linux will now use image cache to reduce the
|
|
||||||
number of dladdr() calls.
|
|
||||||
- Compiling with the TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT define will
|
|
||||||
enable support for run-time updating of known elf ranges in libbacktrace
|
|
||||||
on Linux. Previously, shared objects dlopened() after libbacktrace init
|
|
||||||
would not be visible during symbol resolution.
|
|
||||||
- Zone group count in the Find zone window is now explicitly displayed.
|
|
||||||
- Instrumentation statistics now display in how many threads each source
|
|
||||||
location has appeared in.
|
|
||||||
- Added import tool for fuchsia traces.
|
|
||||||
- https://fuchsia.dev/fuchsia-src/reference/tracing/trace-format
|
|
||||||
- Added checks for overflow of source locations.
|
|
||||||
- As a reminder, Tracy only allows to have 64K unique source locations,
|
|
||||||
split in half between static and dynamic locations.
|
|
||||||
- Runtime checks are active during capture and will stop a trace that
|
|
||||||
goes beyond the limit.
|
|
||||||
- Load-time checks will stop any broken trace file from loading.
|
|
||||||
- Opening the source code view that has no associated address in code
|
|
||||||
(i.e., from the list of instrumented zones, or from the find zone
|
|
||||||
window) will now search the list of symbols for a function name match.
|
|
||||||
- In many cases this will result in displaying the full disassembly view
|
|
||||||
where previously you would only see the source code.
|
|
||||||
- Matching is performed by string comparisons, which in rare cases may
|
|
||||||
result in showing false data.
|
|
||||||
- Press ctrl key while opening source view to keep the old behavior.
|
|
||||||
- If more than one matching symbol is found (e.g., if two classes have
|
|
||||||
methods with the same name, or if a template is instantiated in multiple
|
|
||||||
places in code), it is not possible to tell which of the code locations
|
|
||||||
the source location corresponds to and only the source code will be
|
|
||||||
displayed.
|
|
||||||
- Added TracyNoop macro, which inserts a reference to Tracy's object file
|
|
||||||
into your application. Use it if you want to use Tracy in sampling mode,
|
|
||||||
without any manual instrumentation (so no references of your own exist)
|
|
||||||
and link Tracy as a static library. Linkers will only include library code
|
|
||||||
if code references it, and this doesn't work as intended with Tracy, as it
|
|
||||||
ignores global constructors that have side effects.
|
|
||||||
- ZoneText and ZoneName macros now have a printf-like variant, denoted with
|
|
||||||
a 'F' postfix.
|
|
||||||
- The 'tracy_shared_libs' Meson option was removed. Use interface provided
|
|
||||||
by Meson to set the library type instead.
|
|
||||||
- Dropped the 'tracy_' prefix from Meson options. The `tracy_enable` option
|
|
||||||
remains as it was, as it can be inherited from parent projects.
|
|
||||||
- Fixed display of active / inactive allocations in memory call tree.
|
|
||||||
- Instrumentation statistics can be now sorted by source location.
|
|
||||||
- Added option to hide external code frames in call stack view.
|
|
||||||
- There's now a copy to clipboard button in the statistics view. It copies
|
|
||||||
the visible rows of either the instrumentation or GPU statistics view to
|
|
||||||
a CSV string matching a subset of the csvexport format.
|
|
||||||
- Source file contents can be copied to the clipboard.
|
|
||||||
- Added key binding for immediate reconnect: Ctrl+Shift+Alt+R.
|
|
||||||
- Lock markup is now available through the C API.
|
|
||||||
- Symbol statistics window now allows aggregation of inlined functions in
|
|
||||||
symbols.
|
|
||||||
- Cost measurements of inlined functions in the symbol statistics window
|
|
||||||
can be now relative to the base symbol instead of total program run time.
|
|
||||||
- ScopedZone and AllocSourceLocation now accept color parameter. Impact on
|
|
||||||
existing code should be minimal.
|
|
||||||
- AllocSourceLocation has a new parameter with a default value.
|
|
||||||
- __tracy_alloc_srcloc and __tracy_alloc_srcloc_name break the existing
|
|
||||||
API. This can be easily fixed by setting the last parameter to zero.
|
|
||||||
- To build the profiler GUI with Wayland you now need wayland-scanner and
|
|
||||||
wayland-protocols to be installed. A reasonably recent release of the
|
|
||||||
protocols is required, which, as always, is not available on Ubuntu.
|
|
||||||
Seriously, stop trying to build modern software with that broken distro.
|
|
||||||
- Fractional DPI scaling is now properly supported on Wayland.
|
|
||||||
- Added Python bindings.
|
|
||||||
- The per-line sampling statistics are now also displayed as a percentage
|
|
||||||
of total program run time.
|
|
||||||
- The out-of-focus render frame rate reduction can be now disabled in
|
|
||||||
global settings.
|
|
||||||
- It is now possible to load source files that are newer than the trace.
|
|
||||||
The default setting is still to reject such files.
|
|
||||||
- Memory limit for a capture can be now set, both in the GUI profiler and
|
|
||||||
in the capture utility.
|
|
||||||
- Thread list can be now sorted alphabetically.
|
|
||||||
- It is now possible to adjust plot height.
|
|
||||||
- Trace comparison statistics were expanded and made more clear.
|
|
||||||
- Implemented retrieval of kernel symbol code on Linux.
|
|
||||||
- Added support for multiple compression streams in trace files. This
|
|
||||||
effectively parallelizes both load and save operations.
|
|
||||||
- The default save setup is now set to Zstd level 3 with 4 compression
|
|
||||||
streams. This gives both faster compression time and smaller file size.
|
|
||||||
- New users will be now eased into the profiler with a set of tutorial
|
|
||||||
achievements.
|
|
||||||
- You can now set the timeline options default values in global settings.
|
|
||||||
- Added a check for program memory being available before symbol retrieval
|
|
||||||
on Windows.
|
|
||||||
|
|
||||||
|
|
||||||
v0.10.0 (2023-10-16)
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
- Missed frames region of on-demand captures will be now ignored when
|
|
||||||
calculating trace time span, zone percentages, etc.
|
|
||||||
- Due to technicalities information about locks, frame statistics in trace
|
|
||||||
information window and csvexport utility still include the missed frames
|
|
||||||
time.
|
|
||||||
- When source location dynamic zone coloring mode is enabled, collapsed
|
|
||||||
zones will be now gray-colored. Previously such regions falled back to
|
|
||||||
showing thread colors, which may have been confusing to users.
|
|
||||||
- Vulkan contexts can now use VK_EXT_host_query_reset extension.
|
|
||||||
- System power usage is now reported on x86 Linux.
|
|
||||||
- Program name displayed in broadcast messages can be now changed with the
|
|
||||||
TracySetProgramName() macro.
|
|
||||||
- Zone error markers (red regions and error bars) have been removed for
|
|
||||||
consistency with how all other profiling events are displayed.
|
|
||||||
- It is now possible to export messages in the csvexport utility.
|
|
||||||
- Major overhaul of how timeline items are processed in GUI.
|
|
||||||
- The process of figuring out what needs to be drawn on the timeline has
|
|
||||||
been heavily parallelized.
|
|
||||||
- The impact is especially visible with traces containing large amounts
|
|
||||||
of data. The framerate improvement in such cases can be ~30x.
|
|
||||||
- Consequently, the profiler GUI will now produce multi-core spikes when
|
|
||||||
rendering frames. This may have impact on the profiled application's
|
|
||||||
performance, if both the application and the profiler GUI are running
|
|
||||||
on the same machine. If this is a problem, you may consider the capture
|
|
||||||
utility instead, which is not affected by these changes. Alternatively,
|
|
||||||
you may disable parallelization in the options menu.
|
|
||||||
- Most of the timeline item logic has been written from scratch, which
|
|
||||||
may have taken care of some elusive bugs.
|
|
||||||
- Added global configuration settings dialog. You can find it in the
|
|
||||||
profiler's about menu (the wrench icon in the welcome dialog).
|
|
||||||
- List of found zones in the Find zone menu can be filtered by user text.
|
|
||||||
- Fixed div-by-zero in cvsexport utility when there was only one zone of
|
|
||||||
a kind.
|
|
||||||
- Fixed compatibility problems with FreeBSD.
|
|
||||||
- Added support for dynamically loaded Vulkan symbols.
|
|
||||||
- Trace description or filename is now displayed on the window title bar.
|
|
||||||
- The csvexport utility will now export thread id data.
|
|
||||||
- Improved compatibility with MSVC projects not defining NOMINMAX.
|
|
||||||
- Improved compatibility with Linux setups targeting musl as libc.
|
|
||||||
- Thread safety of Vulkan instrumentation has been reviewed.
|
|
||||||
- D3D11 and D3D12 instrumentation was rewritten.
|
|
||||||
- Added support for efficient profiling when running under rr, the record-
|
|
||||||
replaying debugger. This is enabled with TRACY_PATCHABLE_NOPSLEDS define.
|
|
||||||
- History of viewed symbols is now preserved and you can go back to
|
|
||||||
previously displayed entries.
|
|
||||||
|
|
||||||
|
|
||||||
v0.9.1 (2023-02-26)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Support for pre-0.8 traces has been dropped.
|
|
||||||
- Profiled programs will ignore dlclose() calls.
|
|
||||||
- Added warning when the profiler interface is run with privilege elevation.
|
|
||||||
Advice is given to instead run the client with admin rights.
|
|
||||||
- Switched to official ZEN4 uarch data.
|
|
||||||
- Handle cases when thread name is set, but not through Tracy facilities.
|
|
||||||
- Allow customization of source location data through the following macros:
|
|
||||||
- TracyFunction - defaults to __FUNCTION__
|
|
||||||
- TracyFile - defaults to __FILE__
|
|
||||||
- TracyLine - defaults to __LINE__
|
|
||||||
- Tracy on Linux now targets and requires Wayland by default.
|
|
||||||
- Please don't ask about window decorations on Gnome. Current behavior is
|
|
||||||
the intended behavior. Gnome does not want windows to have decorations,
|
|
||||||
and Tracy respects this choice. If you find this problematic, use a
|
|
||||||
desktop environment that actually listens to its users.
|
|
||||||
- Pass LEGACY=1 parameter to make, if you want to instead rely on the GLFW
|
|
||||||
library, like before.
|
|
||||||
- Other platforms still use GLFW.
|
|
||||||
- Compare traces menu can now display source code differences between two
|
|
||||||
traces.
|
|
||||||
- Assembly listings saved to files have been improved.
|
|
||||||
- Listings are now annotated with source line information.
|
|
||||||
- To improve compatibility with external tools comments are now prefixed
|
|
||||||
with '#' instead of ';'.
|
|
||||||
- Histogram tooltip will now also show left/right counts.
|
|
||||||
- Tracy now actively manages timeline vertical scroll offset in order to keep
|
|
||||||
the thread under the mouse cursor in the same place on screen.
|
|
||||||
- Removed support for AT&T assembly syntax.
|
|
||||||
- Tracy will not display notification if the file selector can't be used.
|
|
||||||
Possible reasons for failure include lack of xdg-desktop-portal.
|
|
||||||
- Using the TRACY_NO_CRASH_HANDLER define will disable handling of
|
|
||||||
application crashes by the profiler.
|
|
||||||
- Tracy will now query jump and call target addresses. This enables discovery
|
|
||||||
of target function names, even if such function has no samples and is not
|
|
||||||
present in any call stack.
|
|
||||||
|
|
||||||
|
|
||||||
v0.9.0 (2022-10-26)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Attention! All the header and source files used for integrating Tracy with
|
|
||||||
applications were moved to the public/ directory. This will break your
|
|
||||||
integration!
|
|
||||||
- To fix this, update the source and include directories lists to point to
|
|
||||||
the new location.
|
|
||||||
- Tracy include files directly referenced by the client were moved to
|
|
||||||
tracy/ subdirectory, to facilitate setups which previously had Tracy
|
|
||||||
checkout parent directory in the include paths list (i.e. when you
|
|
||||||
included "tracy/Tracy.hpp").
|
|
||||||
- Previously, if you have included the Tracy checkout directory in your
|
|
||||||
project include directories list (i.e. you could include "Tracy.hpp"),
|
|
||||||
this could result in third-party library conflicts, e.g. with ImGui.
|
|
||||||
Such scenarios are no longer the case.
|
|
||||||
- Tracy macros now require to be terminated with a semicolon.
|
|
||||||
- The undocumented ___tracy_demangle() function API has been changed. Please
|
|
||||||
refer to the source code for further instructions.
|
|
||||||
- The parameter callback and its registration macro have been extended to
|
|
||||||
include user data pointer. You will need to update your code accordingly.
|
|
||||||
- Plots visualization has been improved.
|
|
||||||
- Each plot now has its own color, which can also be defined by the user.
|
|
||||||
- The area below the plot is now optionally filled with a color.
|
|
||||||
- Plots can now also be configured to be staircase instead of smooth. This
|
|
||||||
new setting is appropriate for many inputs where only discrete values
|
|
||||||
make sense, e.g. the memory allocation plot.
|
|
||||||
- The API for TracyPlotConfig() macro has been changed. Please refer to
|
|
||||||
the manual to see how you can fix this.
|
|
||||||
- Some text labels in the user interface are now more easy to read.
|
|
||||||
- The profiler will now instruct the user in the UI on what can be done, if
|
|
||||||
the send queue is slow to process (typically due to symbol resolution).
|
|
||||||
- If a client with an incompatible protocol is discovered, Tracy will now
|
|
||||||
try to show which versions can be used to handle the connection.
|
|
||||||
- Messages list in zone info window can now show messages exclusive to the
|
|
||||||
zone, filtering out the messages emitted from child zones.
|
|
||||||
- Added capture of vertical synchronization timings on Linux.
|
|
||||||
- The range of frame bar colors in the frames overview on top of the screen
|
|
||||||
can be now controlled with the "Target FPS" entry box in the options menu.
|
|
||||||
- The "Draw frame targets" option does not need to be selected.
|
|
||||||
- Previously the hardcoded FPS target thresholds were: 30, 60, 144 FPS.
|
|
||||||
- Currently the FPS target threshold is: half of target, target, twice the
|
|
||||||
target.
|
|
||||||
- Reworked the way zone names are shortened.
|
|
||||||
- Previously shortening supported only namespace removal, in a way that
|
|
||||||
didn't consider function parameters or template arguments.
|
|
||||||
- Shortening to one-letter namespace chains is no longer available.
|
|
||||||
- The new shortening rules first perform normalization of the function name.
|
|
||||||
- The function const qualifier is removed.
|
|
||||||
- Common return types are removed.
|
|
||||||
- All function parameters and all template arguments are removed.
|
|
||||||
- The next steps consist of repeated removal of namespaces, starting with
|
|
||||||
the most outermost one.
|
|
||||||
- While the old process was all or nothing, the new implementation by
|
|
||||||
default will dynamically adjust to the space available, trying to show
|
|
||||||
the most context possible.
|
|
||||||
- It is also possible to completely disable shortening, or require that it
|
|
||||||
is always performed in full.
|
|
||||||
- Function name normalization is enabled by default, even if there is space
|
|
||||||
to show full function name. This can be changed in options.
|
|
||||||
- Previously shortening was only applied to the zone names displayed on the
|
|
||||||
timeline. Currently this process will also apply to all other places in
|
|
||||||
the UI where function names are displayed. However, in these cases the
|
|
||||||
function names will only be normalized.
|
|
||||||
- Full function names are still available as tooltips, or in fine print if
|
|
||||||
the normalized name is already displayed in a tooltip.
|
|
||||||
- This functionality is disabled if zone name shortening is disabled.
|
|
||||||
- Added context menu for timeline labels. Currently the only option is to hide
|
|
||||||
the selected thread, plot, etc.
|
|
||||||
- You can now provide custom source file contents through a profiler callback.
|
|
||||||
- Exposed Tracy version to client applications (available through the
|
|
||||||
common/TracyVersion.hpp header file).
|
|
||||||
- D3D12 instrumentation is now thread-safe.
|
|
||||||
- Timeline can be now navigated with WASD keys.
|
|
||||||
- Symbol file paths are now normalized on libbacktrace systems. For example,
|
|
||||||
instead of "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/12.2.0/../../../../
|
|
||||||
include/c++/12.2.0/bits/std_mutex.h" Tracy will now report such file as
|
|
||||||
"/usr/include/c++/12.2.0/bits/std_mutex.h".
|
|
||||||
- The import-chrome utility interprets Instant (`i`/`I`) events where the
|
|
||||||
`name` field contains the word `frame` as a frame event. The `name` is the
|
|
||||||
frame set name.
|
|
||||||
- Frame data won't be displayed if there was no frame instrumentation in the
|
|
||||||
profiling session.
|
|
||||||
- Note that some automated functionality (e.g. vertical synchronization
|
|
||||||
capture) may automatically generate frame data, which will force frames to
|
|
||||||
be displayed.
|
|
||||||
- Tracy threads will now be collapsed by default on the timeline.
|
|
||||||
- Clicking on a local thread in the CPU data view will make the thread visible
|
|
||||||
and uncollapsed on the timeline.
|
|
||||||
- Assembly view is now in color.
|
|
||||||
- The profiler UI will no longer unnecessarily redraw the screen if nothing
|
|
||||||
was changed. This should have a profound impact on power usage.
|
|
||||||
- Added microarchitecture data for Zen 4.
|
|
||||||
- Implemented optional propagation of inline cost down the local call stack.
|
|
||||||
- This feature may be useful when trying to get a general outlook of the
|
|
||||||
cost at the top-level function in the symbol.
|
|
||||||
- It is possible to get nonsense data when this is enabled, for example
|
|
||||||
total cost exceeding 100%. This is by design.
|
|
||||||
- Assembly line costs are not affected.
|
|
||||||
- Available clients now also broadcast their PID.
|
|
||||||
- Reversed mouse button assignments for jumping to source / assembly line in
|
|
||||||
symbol view. The left mouse button will now focus the target line.
|
|
||||||
- Assembly lines tooltip will now display local call stack of inline functions
|
|
||||||
(within the symbol).
|
|
||||||
- Right-clicking the source location entry in assembly line will show the
|
|
||||||
local call stack, along with source code preview of each entry and ability
|
|
||||||
to navigate to any selected inline function.
|
|
||||||
- The profiler UI will now indicate that it needs attention if the window is
|
|
||||||
not focused and something interesting happens. For example when a connection
|
|
||||||
is established, or when a saved trace finishes loading, etc. How the
|
|
||||||
attention request is indicated depends on the operating system.
|
|
||||||
- Clicking on the red microarchitecture icon in the symbol view assembly pane
|
|
||||||
will switch the selected microarchitecture to one the profiled application
|
|
||||||
was running on.
|
|
||||||
- Removed option to display instruction latencies in a graphical form. Latency
|
|
||||||
data is still available in instruction tooltip.
|
|
||||||
|
|
||||||
|
|
||||||
v0.8.2 (2022-06-28)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Added support for debuginfod debug information services. Note that
|
|
||||||
since this depends on proper system configuration, vendors providing
|
|
||||||
the debug information, and network retrieval, it is disabled by
|
|
||||||
default. To enable, compile the profiled application with the
|
|
||||||
TRACY_DEBUGINFOD define and link with libdebuginfod.
|
|
||||||
- When Tracy server-side utilities are build with MSVC, the required
|
|
||||||
libraries will be now automatically retrieved and built with vcpkg.
|
|
||||||
- Added microarchitecture data for: Bonnell, Airmont, Goldmont, Goldmont
|
|
||||||
Plus, Tremont.
|
|
||||||
- Recognize additional CPUIDs of Zen 3, Alder Lake, Ice Lake
|
|
||||||
microarchitectures.
|
|
||||||
- Assembly line width will be now extended, if needed. Previously the line
|
|
||||||
width was calculated for the initial layout and changing amount of
|
|
||||||
displayed data (especially listing the read/written registers) didn't
|
|
||||||
affect this, which may have made some lines partially unreadable.
|
|
||||||
- Added ability to filter call stacks in memory tab by inactive allocations.
|
|
||||||
Filtering by inactive allocations helps to pinpoint wasteful allocations
|
|
||||||
in the program.
|
|
||||||
- Plot graph will no longer display min/max values interpolated for
|
|
||||||
animation, but rather true values.
|
|
||||||
- The CPU topology tree structure was replaced by a CPU schematic showing
|
|
||||||
the same thing in a more concise way.
|
|
||||||
|
|
||||||
|
|
||||||
v0.8.1 (2022-04-21)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Support for pre-0.7 traces has been dropped.
|
|
||||||
- Update utility can now scan for source files missing in the trace cache,
|
|
||||||
if the '-c' parameter is given. Found files will be added to the cache.
|
|
||||||
- Added high-priority queue for fast queries to bypass slow symbol queries.
|
|
||||||
- Fixed Android documentation to show how to enable context switch tracing.
|
|
||||||
- Workaround MSVC 2015 stupidity which prevented compilation as C++11.
|
|
||||||
- Added support for showing branch cost data for CPUs that don't report
|
|
||||||
branch retirement events (but do report branch misses).
|
|
||||||
- The right-click context menu available for jump arrows in the symbol view
|
|
||||||
window will now additionally display jump context, i.e. jump sources and
|
|
||||||
jump target source code fragments.
|
|
||||||
- Added freedesktop.org compliant desktop entry and MIME type definition.
|
|
||||||
- The call stack column in list of messages will now be only displayed when
|
|
||||||
at least one message on the list has call stack data.
|
|
||||||
- File dialogs on Unix will be now native to the desktop environment you are
|
|
||||||
using. Note that this relies on xdg-desktop-portal and dbus.
|
|
||||||
|
|
||||||
|
|
||||||
v0.8.0 (2022-03-28)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Support for Cygwin has been dropped. It was not working for a very long
|
|
||||||
time and nobody had complained about it.
|
|
||||||
- Mingw is deprecated due to lack of interest.
|
|
||||||
- Added TRACY_NO_CALLSTACK_INLINES macro to disable inline functions
|
|
||||||
resolution in call stacks on Windows.
|
|
||||||
- Improved function matching algorithm in compare traces view.
|
|
||||||
- Added CMake integration.
|
|
||||||
- Reworked rpmalloc initialization.
|
|
||||||
- Fixed display of messages with newlines on messages list.
|
|
||||||
- Excluded some uninteresting wrapper functions from call stacks (for
|
|
||||||
example SIMD pass-through intrinsics to the compiler built-ins).
|
|
||||||
- Adjusted coloring of instruction hotness in symbol view.
|
|
||||||
- Properly handle rare cases when sampling on Linux is momentary not able to
|
|
||||||
resolve time stamps.
|
|
||||||
- Added Rocket Lake microarchitectural data.
|
|
||||||
- Updated CPU identifier lists.
|
|
||||||
- Implemented GPU timer overflow handling heuristics.
|
|
||||||
- Assembly instructions are now assigned to inline symbols.
|
|
||||||
- You can not only see the assembly source file and line, but also the
|
|
||||||
originating function.
|
|
||||||
- If symbol view is restricted to a single inline function, all assembly
|
|
||||||
instructions not in this context will be dimmed out.
|
|
||||||
- Likewise, the navigation in assembly code will be limited just to the
|
|
||||||
inline context, if a single function is selected.
|
|
||||||
- Kernel call stacks will be now properly captured and displayed in the
|
|
||||||
profiler. Kernel functions are marked with the red color.
|
|
||||||
- The CPU hardware performance counters can be now sampled on Linux.
|
|
||||||
- Three inferred statistics are displayed for lines in both source and
|
|
||||||
assembly code in the symbol view window:
|
|
||||||
- Instructions executed per cycle.
|
|
||||||
- Branch miss rate.
|
|
||||||
- Cache miss rate.
|
|
||||||
- Instruction cost estimation method is no longer tied to software call
|
|
||||||
stack sampling.
|
|
||||||
- The image name filter entry field is now providing a list of available
|
|
||||||
images.
|
|
||||||
- Reentrant function calls may be now excluded from calculations in the
|
|
||||||
statistics view.
|
|
||||||
- Crash handler is now properly removed during profiler destruction.
|
|
||||||
- Repeatedly right-clicking on the same source line in the symbol view
|
|
||||||
window will now cycle through assembly blocks associated with this source
|
|
||||||
line.
|
|
||||||
- Vulkan headers must be now explicitly included before including
|
|
||||||
TracyVulkan.hpp.
|
|
||||||
- The capture utility may now limit capture time to a specified number of
|
|
||||||
seconds.
|
|
||||||
- Fixed message thread assignment in the import-chrome utility.
|
|
||||||
- Sampling data can be now also found in the find zone menu.
|
|
||||||
- Instrumentation failures may now display their context, e.g. the zone text
|
|
||||||
that was to be set.
|
|
||||||
- A warning is now displayed when sampling data is out-of-order.
|
|
||||||
- Average value for plots can be now viewed.
|
|
||||||
- Moved symbol resolution to a separate thread. Profiling will no longer be
|
|
||||||
stuck when there is a large number of symbols to resolve. This not only
|
|
||||||
improves user experience, but also prevents buildup of data (and memory
|
|
||||||
consumption) on the client side.
|
|
||||||
- Android device name will be now reported.
|
|
||||||
- Added support for capturing fibers.
|
|
||||||
- Fibers require additional processing, which has to be enabled by adding
|
|
||||||
the TRACY_FIBERS define on the client side.
|
|
||||||
- Client code requires additional instrumentation using the new macros
|
|
||||||
TracyFiberEnter and TracyFiberLeave (or the corresponding C API
|
|
||||||
variants).
|
|
||||||
- Fibers are represented in traces as separate threads, and are
|
|
||||||
distinguished by green color. Faux context switch regions are used to
|
|
||||||
indicate when a fiber is being run by the worker thread.
|
|
||||||
- Continuous frame marks no longer need to be issued from a single thread.
|
|
||||||
- Context switch call stacks are now captured on Windows and Linux.
|
|
||||||
- Hovering the context switch wait region will now display wait stack,
|
|
||||||
which may provide additional insight into why the switch happened.
|
|
||||||
- Wait stacks inspection can be performed in a new view.
|
|
||||||
- Stacks can be limited to certain threads and to a selected time range.
|
|
||||||
- Stacks are presented either as a sorted list, or as a bottom-up and
|
|
||||||
top-down trees.
|
|
||||||
- Entry call stacks can be now also viewed as a bottom-up and top-down
|
|
||||||
trees.
|
|
||||||
- Updated project build files to MSVC 2022.
|
|
||||||
- Call stack tooltips now also show the executable image name.
|
|
||||||
- Playback frames can be now changed by interacting with the frame image
|
|
||||||
slider using the mouse wheel.
|
|
||||||
- Signal used to handle crashes on Linux can be now redefined.
|
|
||||||
- Various DPI scaling improvements.
|
|
||||||
- User interface can be now scaled in run time.
|
|
||||||
- Symbol code retrieval now also supports kernel on Windows.
|
|
||||||
- Added low-level C API interface for GPU zones.
|
|
||||||
- Symbol child calls can be now listed.
|
|
||||||
- Replaced "restrict time" in memory window with a proper time range limit.
|
|
||||||
- Added Alder Lake microarchitectural data.
|
|
||||||
- Added GPU zone statistics.
|
|
||||||
- Universal Windows Platform support.
|
|
||||||
- All call stack related functionality can be now disabled with the
|
|
||||||
TRACY_NO_CALLSTACK macro.
|
|
||||||
- Added ability to add full-view annotations from the annotations list
|
|
||||||
window.
|
|
||||||
|
|
||||||
|
|
||||||
v0.7.8 (2021-05-19)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Updated Zen 3 and added Tiger Lake microarchitectural data.
|
|
||||||
- Manually disconnecting from the server will no longer display erroneous
|
|
||||||
warning message.
|
|
||||||
- Added ability to display sample time spent in child function calls.
|
|
||||||
- Fixed issue which may have prevented sampling on ARM64.
|
|
||||||
- Added TRACY_NO_FRAME_IMAGE macro to disable frame image compression
|
|
||||||
thread.
|
|
||||||
- Ctrl and shift keys will now modify mouse wheel zoom speed.
|
|
||||||
- Improved user experience in the symbol view window.
|
|
||||||
- Added support for Direct3D 11 instrumentation.
|
|
||||||
- Vulkan contexts can be now calibrated on Linux.
|
|
||||||
- Support loading zstd-compressed chrome traces.
|
|
||||||
- Chrome traces with multiple PID entries (and possibly conflicting TIDs)
|
|
||||||
can be now imported.
|
|
||||||
- Added support for custom source location tag ("loc") in chrome traces.
|
|
||||||
- Sampling frequency can be now controlled using TRACY_SAMPLING_HZ macro.
|
|
||||||
- Trace compression can be now selected when saving a trace.
|
|
||||||
- If a trace cannot be saved, a failure dialog will be displayed.
|
|
||||||
- Run-time memory usage of frame images can be reduced by calculating
|
|
||||||
a compression dictionary. This can be only performed when a trace is saved
|
|
||||||
or through the update utility.
|
|
||||||
|
|
||||||
|
|
||||||
v0.7.7 (2021-04-01)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Linux crash handler will now also catch SIGABRT.
|
|
||||||
- Fixed invalid name assignment to source files discovered client-side.
|
|
||||||
- Added ability to check if a zone is active (which may be used to avoid
|
|
||||||
preparing zone text, etc., as it wouldn't be used anyway).
|
|
||||||
- Improved sorting behavior of internal vectors.
|
|
||||||
- Some data will now be always properly displayed during live capture.
|
|
||||||
This was not particularly visible before, as it mainly concerns edge
|
|
||||||
cases.
|
|
||||||
- Sorting is performed only as needed.
|
|
||||||
- In case of plots the performance during live capture may be decreased,
|
|
||||||
as these were sorted with at least 0.25 second intervals before. Now
|
|
||||||
the sorting is performed every frame.
|
|
||||||
- Some other data, which previously was not sorted, is sorted now.
|
|
||||||
- In headless capture mode sorting will be only performed when the trace
|
|
||||||
is saved to disk.
|
|
||||||
- Fixed some typos in macros.
|
|
||||||
- Fixed handling of non-ANSI file names on Windows. You can now name your
|
|
||||||
traces 'ęśąćż.tracy' and it should work as intended. This is supported on
|
|
||||||
Windows 10 release 1903 and newer.
|
|
||||||
- Fixed sending GPU context name in on-demand mode.
|
|
||||||
- Fixed color channel order in ZoneColor() macro.
|
|
||||||
- Handle failure state when a memory pointer allocation is reported twice,
|
|
||||||
without an intermediate free.
|
|
||||||
- Renamed "call stack parents" to "entry call stacks".
|
|
||||||
- Display number of entry call stacks in assembly line sample count tooltip.
|
|
||||||
- Added tooltips with preview of source code in various places in the UI.
|
|
||||||
|
|
||||||
|
|
||||||
v0.7.6 (2021-02-06)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Various fixes in build scripts.
|
|
||||||
- Fixed a faulty rpmalloc initialization path when the first thing the
|
|
||||||
thread did was sending a message with call stack.
|
|
||||||
- Added fallback timer define for various virtualized environments, which
|
|
||||||
may not be able to access the hardware timer registers. This will result
|
|
||||||
in usage of timer provided by the standard library, with reduced
|
|
||||||
resolution.
|
|
||||||
- Further OpenCL improvements.
|
|
||||||
- Updated libbacktrace.
|
|
||||||
- Adds Mach-O 64-bit FAT support.
|
|
||||||
- Fixes memory corruption when processing Mach-O data.
|
|
||||||
- Fixes missing matching entries during binary search.
|
|
||||||
- Adds support for MiniDebugInfo.
|
|
||||||
- Adds fallback to ELF symbol table if no debug info is available.
|
|
||||||
- Various other fixes.
|
|
||||||
- Store build time of profiled program in captures.
|
|
||||||
- GPU contexts can be now named.
|
|
||||||
- Implemented client -> server source code transfer.
|
|
||||||
|
|
||||||
|
|
||||||
v0.7.5 (2021-01-23)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- More robust handling of system tracing on Android.
|
|
||||||
- Added warning dialog when the connection is lost before all needed data
|
|
||||||
can be retrieved.
|
|
||||||
- Fixed handling of NaN plot entries (by skipping them).
|
|
||||||
- Dynamic zone colors are now supported through the ZoneColor() macro.
|
|
||||||
- Fixed Arm machine code printout to match the one printed by objdump.
|
|
||||||
- Fixed client memory corruption when using colored messages.
|
|
||||||
- Switched to the next-gen ImGui table UI.
|
|
||||||
- Table columns can have their order rearranged, can be hidden, can be
|
|
||||||
sorted both in ascending and descending order (where appropriate).
|
|
||||||
- Table columns state is now preserved between runs.
|
|
||||||
- Various fixes related to restricting listening to localhost.
|
|
||||||
- Improved compatibility of ETW tracing with non-MSVC compilers.
|
|
||||||
- Fixed Vulkan call stack transfer.
|
|
||||||
- Added support for transient GPU zones (OpenGL, Vulkan, Direct3D 12).
|
|
||||||
- OpenCL fixes for assert-less builds and non-active zones.
|
|
||||||
- Added support for thread names and title bar description in traces
|
|
||||||
imported from chrome tracing format.
|
|
||||||
|
|
||||||
|
|
||||||
v0.7.4 (2020-11-15)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Added support for user-provided locks to keep dbghelp calls thread-safe.
|
|
||||||
- Call stacks can be now copied to clipboard.
|
|
||||||
- Allow more control over which automated captures are performed.
|
|
||||||
- Added textual descriptions for some assembly instructions.
|
|
||||||
- Profiler memory usage is now also displayed as a percentage of available
|
|
||||||
physical memory.
|
|
||||||
- Microarchitecture mismatch is now clearly displayed in the source view
|
|
||||||
window.
|
|
||||||
- Added Zen 3 and Cascade Lake microarchitectural data.
|
|
||||||
- Ghost zones are now supporting all zone coloring modes and namespace
|
|
||||||
shortening.
|
|
||||||
- Extend C API to support memory pools.
|
|
||||||
- Frame rate targets can be now visually represented on the timeline view.
|
|
||||||
|
|
||||||
|
|
||||||
v0.7.3 (2020-10-06)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Properly support DPI scaling on Linux (requires GLFW 3.3).
|
|
||||||
- Added early checks for output file validity in the capture utility.
|
|
||||||
- Improvements to presence broadcast handling.
|
|
||||||
- Custom zone colors can be optionally ignored.
|
|
||||||
- Added support for tracking multiple memory pools.
|
|
||||||
- Memory free failure dialog can now show call stack pointing to the failure
|
|
||||||
location.
|
|
||||||
- Added support for Wayland on Linux.
|
|
||||||
- If during the first 5 seconds of the trace there are no frames being
|
|
||||||
reported, the profiler will switch to following last 5 seconds of the
|
|
||||||
trace, instead of displaying three last frames.
|
|
||||||
|
|
||||||
|
|
||||||
v0.7.2 (2020-09-14)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Note: the bitbucket repository is obsolete and will soon stop receiving
|
|
||||||
updates. Migrate to https://github.com/wolfpld/tracy, if you haven't
|
|
||||||
already.
|
|
||||||
- The "waiting for connection" dialog no longer has "cancel" button. To
|
|
||||||
abort connection attempt just use the "close window" button.
|
|
||||||
- Added update notification.
|
|
||||||
- The most recent traced events can be now viewed regardless of timeline
|
|
||||||
zoom level.
|
|
||||||
- Fixed going-to-line in source view (again).
|
|
||||||
- Crash handling on client is now not performed, if there is no active
|
|
||||||
connection.
|
|
||||||
- Added ability to listen only on IPv4 interfaces.
|
|
||||||
|
|
||||||
|
|
||||||
v0.7.1 (2020-08-24)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Dropped support for pre-v0.6 traces.
|
|
||||||
- Fixed regression on non-AVX2 CPUs.
|
|
||||||
- Fixed incorrect calculation of some ghost zones.
|
|
||||||
- Added list of cached source files.
|
|
||||||
- Added import of plot data.
|
|
||||||
- Secure versions of alloc/free macros.
|
|
||||||
- Automated tracing of vertical synchronization on Windows.
|
|
||||||
- Fixed attachment of postponed frame images.
|
|
||||||
- Source location data can be now copied to clipboard from zone info window.
|
|
||||||
- Zones in find zones menu can be now grouped by zone name.
|
|
||||||
- Vulkan and D3D12 GPU contexts can be now calibrated.
|
|
||||||
- Added CSV export utility.
|
|
||||||
- "Go to frame" popup no longer has a dedicated button. To show it, click on
|
|
||||||
the frame counter.
|
|
||||||
- Added macro for checking if profiler is connected.
|
|
||||||
- Implemented optional data removal from traces in the update utility.
|
|
||||||
- Allow manual management of profiler lifetime.
|
|
||||||
- Adjusted priority of ETW threads to time critical.
|
|
||||||
- Annotations can be now freely adjusted on the timeline.
|
|
||||||
- Limiting time range for find zone functionality has been significantly
|
|
||||||
improved.
|
|
||||||
- Added time range limits for statistics and symbol view.
|
|
||||||
- Implemented call stack sampling on Linux (including Android).
|
|
||||||
- Exact time from start of profiling session can be now viewed by hovering
|
|
||||||
the mouse over the time scale.
|
|
||||||
- Code transfer can be now compiled-out.
|
|
||||||
- Added support for zone markup in unloadable modules.
|
|
||||||
- Added image name filter to sampling statistics results window.
|
|
||||||
|
|
||||||
|
|
||||||
v0.7 (2020-06-11)
|
v0.7 (2020-06-11)
|
||||||
-----------------
|
-----------------
|
||||||
@ -798,7 +67,6 @@ update utility to convert your old traces now!
|
|||||||
- OpenCL profiling.
|
- OpenCL profiling.
|
||||||
- Direct3D 12 profiling.
|
- Direct3D 12 profiling.
|
||||||
|
|
||||||
|
|
||||||
v0.6.3 (2020-02-13)
|
v0.6.3 (2020-02-13)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@ -819,7 +87,6 @@ v0.6.3 (2020-02-13)
|
|||||||
- Frame images are now internally compressed using Zstd (instead of LZ4).
|
- Frame images are now internally compressed using Zstd (instead of LZ4).
|
||||||
- Fix display of continuous frame set tooltips.
|
- Fix display of continuous frame set tooltips.
|
||||||
|
|
||||||
|
|
||||||
v0.6.2 (2019-12-30)
|
v0.6.2 (2019-12-30)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@ -834,7 +101,6 @@ v0.6.2 (2019-12-30)
|
|||||||
- Highlight hovered zone from find zone menu zone list on the histogram.
|
- Highlight hovered zone from find zone menu zone list on the histogram.
|
||||||
- Allow copying user data directory location to the clipboard.
|
- Allow copying user data directory location to the clipboard.
|
||||||
|
|
||||||
|
|
||||||
v0.6.1 (2019-11-28)
|
v0.6.1 (2019-11-28)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@ -846,7 +112,6 @@ v0.6.1 (2019-11-28)
|
|||||||
- Client parameters may be now set from the server.
|
- Client parameters may be now set from the server.
|
||||||
- Minor UI fixes.
|
- Minor UI fixes.
|
||||||
|
|
||||||
|
|
||||||
v0.6 (2019-11-17)
|
v0.6 (2019-11-17)
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@ -906,7 +171,6 @@ update utility to convert your old traces now!
|
|||||||
- Implemented configuration of plots.
|
- Implemented configuration of plots.
|
||||||
- Messages can now collect call stacks.
|
- Messages can now collect call stacks.
|
||||||
|
|
||||||
|
|
||||||
v0.5 (2019-08-10)
|
v0.5 (2019-08-10)
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@ -994,7 +258,6 @@ update utility to convert your old traces now!
|
|||||||
- GPU drift value can be now automatically measured.
|
- GPU drift value can be now automatically measured.
|
||||||
- Connection window is now a popup hidden under a dedicated button.
|
- Connection window is now a popup hidden under a dedicated button.
|
||||||
|
|
||||||
|
|
||||||
v0.4.1 (2018-12-30)
|
v0.4.1 (2018-12-30)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@ -1022,7 +285,6 @@ v0.4.1 (2018-12-30)
|
|||||||
- Pressing enter key after entering client address in the welcome dialog
|
- Pressing enter key after entering client address in the welcome dialog
|
||||||
will now automatically begin connection process.
|
will now automatically begin connection process.
|
||||||
|
|
||||||
|
|
||||||
v0.4 (2018-10-09)
|
v0.4 (2018-10-09)
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@ -1154,8 +416,8 @@ v0.4 (2018-10-09)
|
|||||||
- The capture utility will now display time span of the ongoing capture.
|
- The capture utility will now display time span of the ongoing capture.
|
||||||
|
|
||||||
|
|
||||||
v0.3 (2018-07-03)
|
v0.3.3 (2018-07-03)
|
||||||
-----------------
|
-------------------
|
||||||
|
|
||||||
- Breaking change: the format of trace files has changed.
|
- Breaking change: the format of trace files has changed.
|
||||||
- Previous tracy version will crash when trying to open new traces.
|
- Previous tracy version will crash when trying to open new traces.
|
||||||
|
12
README.md
@ -4,20 +4,15 @@
|
|||||||
|
|
||||||
### A real time, nanosecond resolution, remote telemetry, hybrid frame and sampling profiler for games and other applications.
|
### A real time, nanosecond resolution, remote telemetry, hybrid frame and sampling profiler for games and other applications.
|
||||||
|
|
||||||
Tracy supports profiling CPU (Direct support is provided for C, C++, Lua, Python and Fortran integration. At the same time, third-party bindings to many other languages exist on the internet, such as [Rust](https://github.com/nagisa/rust_tracy_client), [Zig](https://github.com/tealsnow/zig-tracy), [C#](https://github.com/clibequilibrium/Tracy-CSharp), [OCaml](https://github.com/imandra-ai/ocaml-tracy), [Odin](https://github.com/oskarnp/odin-tracy), etc.), GPU (All major graphic APIs: OpenGL, Vulkan, Direct3D 11/12, Metal, OpenCL.), memory allocations, locks, context switches, automatically attribute screenshots to captured frames, and much more.
|
Tracy supports profiling CPU (C, C++11, Lua), GPU (OpenGL, Vulkan, OpenCL, Direct3D 12), memory, locks, context switches, per-frame screenshots and more.
|
||||||
|
|
||||||
- [Documentation](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf) for usage and build process instructions
|
For usage **and build process** instructions, consult the user manual [at the following address](https://github.com/wolfpld/tracy/releases).
|
||||||
- [Releases](https://github.com/wolfpld/tracy/releases) containing the documentation (`tracy.pdf`) and compiled Windows x64 binaries (`Tracy-<version>.7z`) as assets
|
|
||||||
- [Changelog](NEWS)
|
|
||||||
- [Interactive demo](https://tracy.nereid.pl/)
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|
[Changelog](NEWS)
|
||||||
|
|
||||||
[An Introduction to Tracy Profiler in C++ - Marcos Slomp - CppCon 2023](https://youtu.be/ghXk3Bk5F2U?t=37)
|
|
||||||
|
|
||||||
[Introduction to Tracy Profiler v0.2](https://www.youtube.com/watch?v=fB5B46lbapc)
|
[Introduction to Tracy Profiler v0.2](https://www.youtube.com/watch?v=fB5B46lbapc)
|
||||||
[New features in Tracy Profiler v0.3](https://www.youtube.com/watch?v=3SXpDpDh2Uo)
|
[New features in Tracy Profiler v0.3](https://www.youtube.com/watch?v=3SXpDpDh2Uo)
|
||||||
@ -25,4 +20,3 @@ Tracy supports profiling CPU (Direct support is provided for C, C++, Lua, Python
|
|||||||
[New features in Tracy Profiler v0.5](https://www.youtube.com/watch?v=P6E7qLMmzTQ)
|
[New features in Tracy Profiler v0.5](https://www.youtube.com/watch?v=P6E7qLMmzTQ)
|
||||||
[New features in Tracy Profiler v0.6](https://www.youtube.com/watch?v=uJkrFgriuOo)
|
[New features in Tracy Profiler v0.6](https://www.youtube.com/watch?v=uJkrFgriuOo)
|
||||||
[New features in Tracy Profiler v0.7](https://www.youtube.com/watch?v=_hU7vw00MZ4)
|
[New features in Tracy Profiler v0.7](https://www.youtube.com/watch?v=_hU7vw00MZ4)
|
||||||
[New features in Tracy Profiler v0.8](https://www.youtube.com/watch?v=30wpRpHTTag)
|
|
||||||
|
7
TODO
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"Would be nice to have" list for 1.0 release:
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
* Pack queue items tightly in the queues.
|
||||||
|
* Use level-of-detail system for plots.
|
||||||
|
* Use per-thread lock data structures.
|
||||||
|
* Use DTrace for BSD/OSX context switch capture.
|
187
Tracy.hpp
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#ifndef __TRACY_HPP__
|
||||||
|
#define __TRACY_HPP__
|
||||||
|
|
||||||
|
#include "common/TracyColor.hpp"
|
||||||
|
#include "common/TracySystem.hpp"
|
||||||
|
|
||||||
|
#ifndef TRACY_ENABLE
|
||||||
|
|
||||||
|
#define ZoneNamed(x,y)
|
||||||
|
#define ZoneNamedN(x,y,z)
|
||||||
|
#define ZoneNamedC(x,y,z)
|
||||||
|
#define ZoneNamedNC(x,y,z,w)
|
||||||
|
|
||||||
|
#define ZoneScoped
|
||||||
|
#define ZoneScopedN(x)
|
||||||
|
#define ZoneScopedC(x)
|
||||||
|
#define ZoneScopedNC(x,y)
|
||||||
|
|
||||||
|
#define ZoneText(x,y)
|
||||||
|
#define ZoneTextV(x,y,z)
|
||||||
|
#define ZoneName(x,y)
|
||||||
|
#define ZoneNameV(x,y,z)
|
||||||
|
#define ZoneValue(x)
|
||||||
|
#define ZoneValueV(x,y)
|
||||||
|
|
||||||
|
#define FrameMark
|
||||||
|
#define FrameMarkNamed(x)
|
||||||
|
#define FrameMarkStart(x)
|
||||||
|
#define FrameMarkEnd(x)
|
||||||
|
|
||||||
|
#define FrameImage(x,y,z,w,a)
|
||||||
|
|
||||||
|
#define TracyLockable( type, varname ) type varname;
|
||||||
|
#define TracyLockableN( type, varname, desc ) type varname;
|
||||||
|
#define TracySharedLockable( type, varname ) type varname;
|
||||||
|
#define TracySharedLockableN( type, varname, desc ) type varname;
|
||||||
|
#define LockableBase( type ) type
|
||||||
|
#define SharedLockableBase( type ) type
|
||||||
|
#define LockMark(x) (void)x;
|
||||||
|
#define LockableName(x,y,z);
|
||||||
|
|
||||||
|
#define TracyPlot(x,y)
|
||||||
|
#define TracyPlotConfig(x,y)
|
||||||
|
|
||||||
|
#define TracyMessage(x,y)
|
||||||
|
#define TracyMessageL(x)
|
||||||
|
#define TracyMessageC(x,y,z)
|
||||||
|
#define TracyMessageLC(x,y)
|
||||||
|
#define TracyAppInfo(x,y)
|
||||||
|
|
||||||
|
#define TracyAlloc(x,y)
|
||||||
|
#define TracyFree(x)
|
||||||
|
|
||||||
|
#define ZoneNamedS(x,y,z)
|
||||||
|
#define ZoneNamedNS(x,y,z,w)
|
||||||
|
#define ZoneNamedCS(x,y,z,w)
|
||||||
|
#define ZoneNamedNCS(x,y,z,w,a)
|
||||||
|
|
||||||
|
#define ZoneScopedS(x)
|
||||||
|
#define ZoneScopedNS(x,y)
|
||||||
|
#define ZoneScopedCS(x,y)
|
||||||
|
#define ZoneScopedNCS(x,y,z)
|
||||||
|
|
||||||
|
#define TracyAllocS(x,y,z)
|
||||||
|
#define TracyFreeS(x,y)
|
||||||
|
|
||||||
|
#define TracyMessageS(x,y,z)
|
||||||
|
#define TracyMessageLS(x,y)
|
||||||
|
#define TracyMessageCS(x,y,z,w)
|
||||||
|
#define TracyMessageLCS(x,y,z)
|
||||||
|
|
||||||
|
#define TracyParameterRegister(x)
|
||||||
|
#define TracyParameterSetup(x,y,z,w)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "client/TracyLock.hpp"
|
||||||
|
#include "client/TracyProfiler.hpp"
|
||||||
|
#include "client/TracyScoped.hpp"
|
||||||
|
|
||||||
|
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
||||||
|
# define ZoneNamed( varname, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
# define ZoneNamedN( varname, name, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
# define ZoneNamedC( varname, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
# define ZoneNamedNC( varname, name, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
#else
|
||||||
|
# define ZoneNamed( varname, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
|
||||||
|
# define ZoneNamedN( varname, name, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
|
||||||
|
# define ZoneNamedC( varname, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
|
||||||
|
# define ZoneNamedNC( varname, name, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ZoneScoped ZoneNamed( ___tracy_scoped_zone, true )
|
||||||
|
#define ZoneScopedN( name ) ZoneNamedN( ___tracy_scoped_zone, name, true )
|
||||||
|
#define ZoneScopedC( color ) ZoneNamedC( ___tracy_scoped_zone, color, true )
|
||||||
|
#define ZoneScopedNC( name, color ) ZoneNamedNC( ___tracy_scoped_zone, name, color, true )
|
||||||
|
|
||||||
|
#define ZoneText( txt, size ) ___tracy_scoped_zone.Text( txt, size );
|
||||||
|
#define ZoneTextV( varname, txt, size ) varname.Text( txt, size );
|
||||||
|
#define ZoneName( txt, size ) ___tracy_scoped_zone.Name( txt, size );
|
||||||
|
#define ZoneNameV( varname, txt, size ) varname.Name( txt, size );
|
||||||
|
#define ZoneValue( value ) ___tracy_scoped_zone.Value( value );
|
||||||
|
#define ZoneValueV( varname, value ) varname.Value( value );
|
||||||
|
|
||||||
|
#define FrameMark tracy::Profiler::SendFrameMark( nullptr );
|
||||||
|
#define FrameMarkNamed( name ) tracy::Profiler::SendFrameMark( name );
|
||||||
|
#define FrameMarkStart( name ) tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgStart );
|
||||||
|
#define FrameMarkEnd( name ) tracy::Profiler::SendFrameMark( name, tracy::QueueType::FrameMarkMsgEnd );
|
||||||
|
|
||||||
|
#define FrameImage( image, width, height, offset, flip ) tracy::Profiler::SendFrameImage( image, width, height, offset, flip );
|
||||||
|
|
||||||
|
#define TracyLockable( type, varname ) tracy::Lockable<type> varname { [] () -> const tracy::SourceLocationData* { static const tracy::SourceLocationData srcloc { nullptr, #type " " #varname, __FILE__, __LINE__, 0 }; return &srcloc; }() };
|
||||||
|
#define TracyLockableN( type, varname, desc ) tracy::Lockable<type> varname { [] () -> const tracy::SourceLocationData* { static const tracy::SourceLocationData srcloc { nullptr, desc, __FILE__, __LINE__, 0 }; return &srcloc; }() };
|
||||||
|
#define TracySharedLockable( type, varname ) tracy::SharedLockable<type> varname { [] () -> const tracy::SourceLocationData* { static const tracy::SourceLocationData srcloc { nullptr, #type " " #varname, __FILE__, __LINE__, 0 }; return &srcloc; }() };
|
||||||
|
#define TracySharedLockableN( type, varname, desc ) tracy::SharedLockable<type> varname { [] () -> const tracy::SourceLocationData* { static const tracy::SourceLocationData srcloc { nullptr, desc, __FILE__, __LINE__, 0 }; return &srcloc; }() };
|
||||||
|
#define LockableBase( type ) tracy::Lockable<type>
|
||||||
|
#define SharedLockableBase( type ) tracy::SharedLockable<type>
|
||||||
|
#define LockMark( varname ) static const tracy::SourceLocationData __tracy_lock_location_##varname { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; varname.Mark( &__tracy_lock_location_##varname );
|
||||||
|
#define LockableName( varname, txt, size ) varname.CustomName( txt, size );
|
||||||
|
|
||||||
|
#define TracyPlot( name, val ) tracy::Profiler::PlotData( name, val );
|
||||||
|
#define TracyPlotConfig( name, type ) tracy::Profiler::ConfigurePlot( name, type );
|
||||||
|
|
||||||
|
#define TracyAppInfo( txt, size ) tracy::Profiler::MessageAppInfo( txt, size );
|
||||||
|
|
||||||
|
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
||||||
|
# define TracyMessage( txt, size ) tracy::Profiler::Message( txt, size, TRACY_CALLSTACK );
|
||||||
|
# define TracyMessageL( txt ) tracy::Profiler::Message( txt, TRACY_CALLSTACK );
|
||||||
|
# define TracyMessageC( txt, size, color ) tracy::Profiler::MessageColor( txt, size, color, TRACY_CALLSTACK );
|
||||||
|
# define TracyMessageLC( txt, color ) tracy::Profiler::MessageColor( txt, color, TRACY_CALLSTACK );
|
||||||
|
|
||||||
|
# define TracyAlloc( ptr, size ) tracy::Profiler::MemAllocCallstack( ptr, size, TRACY_CALLSTACK );
|
||||||
|
# define TracyFree( ptr ) tracy::Profiler::MemFreeCallstack( ptr, TRACY_CALLSTACK );
|
||||||
|
#else
|
||||||
|
# define TracyMessage( txt, size ) tracy::Profiler::Message( txt, size, 0 );
|
||||||
|
# define TracyMessageL( txt ) tracy::Profiler::Message( txt, 0 );
|
||||||
|
# define TracyMessageC( txt, size, color ) tracy::Profiler::MessageColor( txt, size, color, 0 );
|
||||||
|
# define TracyMessageLC( txt, color ) tracy::Profiler::MessageColor( txt, color, 0 );
|
||||||
|
|
||||||
|
# define TracyAlloc( ptr, size ) tracy::Profiler::MemAlloc( ptr, size );
|
||||||
|
# define TracyFree( ptr ) tracy::Profiler::MemFree( ptr );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
# define ZoneNamedS( varname, depth, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), depth, active );
|
||||||
|
# define ZoneNamedNS( varname, name, depth, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), depth, active );
|
||||||
|
# define ZoneNamedCS( varname, color, depth, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), depth, active );
|
||||||
|
# define ZoneNamedNCS( varname, name, color, depth, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), depth, active );
|
||||||
|
|
||||||
|
# define ZoneScopedS( depth ) ZoneNamedS( ___tracy_scoped_zone, depth, true )
|
||||||
|
# define ZoneScopedNS( name, depth ) ZoneNamedNS( ___tracy_scoped_zone, name, depth, true )
|
||||||
|
# define ZoneScopedCS( color, depth ) ZoneNamedCS( ___tracy_scoped_zone, color, depth, true )
|
||||||
|
# define ZoneScopedNCS( name, color, depth ) ZoneNamedNCS( ___tracy_scoped_zone, name, color, depth, true )
|
||||||
|
|
||||||
|
# define TracyAllocS( ptr, size, depth ) tracy::Profiler::MemAllocCallstack( ptr, size, depth );
|
||||||
|
# define TracyFreeS( ptr, depth ) tracy::Profiler::MemFreeCallstack( ptr, depth );
|
||||||
|
|
||||||
|
# define TracyMessageS( txt, size, depth ) tracy::Profiler::Message( txt, size, depth );
|
||||||
|
# define TracyMessageLS( txt, depth ) tracy::Profiler::Message( txt, depth );
|
||||||
|
# define TracyMessageCS( txt, size, color, depth ) tracy::Profiler::MessageColor( txt, size, color, depth );
|
||||||
|
# define TracyMessageLCS( txt, color, depth ) tracy::Profiler::MessageColor( txt, color, depth );
|
||||||
|
#else
|
||||||
|
# define ZoneNamedS( varname, depth, active ) ZoneNamed( varname, active )
|
||||||
|
# define ZoneNamedNS( varname, name, depth, active ) ZoneNamedN( varname, name, active )
|
||||||
|
# define ZoneNamedCS( varname, color, depth, active ) ZoneNamedC( varname, color, active )
|
||||||
|
# define ZoneNamedNCS( varname, name, color, depth, active ) ZoneNamedNC( varname, name, color, active )
|
||||||
|
|
||||||
|
# define ZoneScopedS( depth ) ZoneScoped
|
||||||
|
# define ZoneScopedNS( name, depth ) ZoneScopedN( name )
|
||||||
|
# define ZoneScopedCS( color, depth ) ZoneScopedC( color )
|
||||||
|
# define ZoneScopedNCS( name, color, depth ) ZoneScopedNC( name, color )
|
||||||
|
|
||||||
|
# define TracyAllocS( ptr, size, depth ) TracyAlloc( ptr, size )
|
||||||
|
# define TracyFreeS( ptr, depth ) TracyFree( ptr )
|
||||||
|
|
||||||
|
# define TracyMessageS( txt, size, depth ) TracyMessage( txt, size )
|
||||||
|
# define TracyMessageLS( txt, depth ) TracyMessageL( txt )
|
||||||
|
# define TracyMessageCS( txt, size, color, depth ) TracyMessageC( txt, size, color )
|
||||||
|
# define TracyMessageLCS( txt, color, depth ) TracyMessageLC( txt, color )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TracyParameterRegister( cb ) tracy::Profiler::ParameterRegister( cb );
|
||||||
|
#define TracyParameterSetup( idx, name, isBool, val ) tracy::Profiler::ParameterSetup( idx, name, isBool, val );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
197
TracyC.h
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
#ifndef __TRACYC_HPP__
|
||||||
|
#define __TRACYC_HPP__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "client/TracyCallstack.h"
|
||||||
|
#include "common/TracyApi.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRACY_ENABLE
|
||||||
|
|
||||||
|
typedef const void* TracyCZoneCtx;
|
||||||
|
|
||||||
|
#define TracyCZone(c,x)
|
||||||
|
#define TracyCZoneN(c,x,y)
|
||||||
|
#define TracyCZoneC(c,x,y)
|
||||||
|
#define TracyCZoneNC(c,x,y,z)
|
||||||
|
#define TracyCZoneEnd(c)
|
||||||
|
#define TracyCZoneText(c,x,y)
|
||||||
|
#define TracyCZoneName(c,x,y)
|
||||||
|
#define TracyCZoneValue(c,x)
|
||||||
|
|
||||||
|
#define TracyCAlloc(x,y)
|
||||||
|
#define TracyCFree(x)
|
||||||
|
|
||||||
|
#define TracyCFrameMark
|
||||||
|
#define TracyCFrameMarkNamed(x)
|
||||||
|
#define TracyCFrameMarkStart(x)
|
||||||
|
#define TracyCFrameMarkEnd(x)
|
||||||
|
#define TracyCFrameImage(x,y,z,w,a)
|
||||||
|
|
||||||
|
#define TracyCPlot(x,y)
|
||||||
|
#define TracyCMessage(x,y)
|
||||||
|
#define TracyCMessageL(x)
|
||||||
|
#define TracyCMessageC(x,y,z)
|
||||||
|
#define TracyCMessageLC(x,y)
|
||||||
|
#define TracyCAppInfo(x,y)
|
||||||
|
|
||||||
|
#define TracyCZoneS(x,y,z)
|
||||||
|
#define TracyCZoneNS(x,y,z,w)
|
||||||
|
#define TracyCZoneCS(x,y,z,w)
|
||||||
|
#define TracyCZoneNCS(x,y,z,w,a)
|
||||||
|
|
||||||
|
#define TracyCAllocS(x,y,z)
|
||||||
|
#define TracyCFreeS(x,y)
|
||||||
|
|
||||||
|
#define TracyCMessageS(x,y,z)
|
||||||
|
#define TracyCMessageLS(x,y)
|
||||||
|
#define TracyCMessageCS(x,y,z,w)
|
||||||
|
#define TracyCMessageLCS(x,y,z)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef TracyConcat
|
||||||
|
# define TracyConcat(x,y) TracyConcatIndirect(x,y)
|
||||||
|
#endif
|
||||||
|
#ifndef TracyConcatIndirect
|
||||||
|
# define TracyConcatIndirect(x,y) x##y
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ___tracy_source_location_data
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
const char* function;
|
||||||
|
const char* file;
|
||||||
|
uint32_t line;
|
||||||
|
uint32_t color;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ___tracy_c_zone_context
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
int active;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Some containers don't support storing const types.
|
||||||
|
// This struct, as visible to user, is immutable, so treat it as if const was declared here.
|
||||||
|
typedef /*const*/ struct ___tracy_c_zone_context TracyCZoneCtx;
|
||||||
|
|
||||||
|
TRACY_API uint64_t ___tracy_alloc_srcloc( uint32_t line, const char* source, const char* function );
|
||||||
|
TRACY_API uint64_t ___tracy_alloc_srcloc_name( uint32_t line, const char* source, const char* function, const char* name, size_t nameSz );
|
||||||
|
|
||||||
|
TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin( const struct ___tracy_source_location_data* srcloc, int active );
|
||||||
|
TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_callstack( const struct ___tracy_source_location_data* srcloc, int depth, int active );
|
||||||
|
TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_alloc( uint64_t srcloc, int active );
|
||||||
|
TRACY_API TracyCZoneCtx ___tracy_emit_zone_begin_alloc_callstack( uint64_t srcloc, int depth, int active );
|
||||||
|
TRACY_API void ___tracy_emit_zone_end( TracyCZoneCtx ctx );
|
||||||
|
TRACY_API void ___tracy_emit_zone_text( TracyCZoneCtx ctx, const char* txt, size_t size );
|
||||||
|
TRACY_API void ___tracy_emit_zone_name( TracyCZoneCtx ctx, const char* txt, size_t size );
|
||||||
|
TRACY_API void ___tracy_emit_zone_value( TracyCZoneCtx ctx, uint64_t value );
|
||||||
|
|
||||||
|
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
||||||
|
# define TracyCZone( ctx, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { NULL, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
# define TracyCZoneN( ctx, name, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
# define TracyCZoneC( ctx, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { NULL, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
# define TracyCZoneNC( ctx, name, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
#else
|
||||||
|
# define TracyCZone( ctx, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { NULL, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin( &TracyConcat(__tracy_source_location,__LINE__), active );
|
||||||
|
# define TracyCZoneN( ctx, name, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin( &TracyConcat(__tracy_source_location,__LINE__), active );
|
||||||
|
# define TracyCZoneC( ctx, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { NULL, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin( &TracyConcat(__tracy_source_location,__LINE__), active );
|
||||||
|
# define TracyCZoneNC( ctx, name, color, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin( &TracyConcat(__tracy_source_location,__LINE__), active );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TracyCZoneEnd( ctx ) ___tracy_emit_zone_end( ctx );
|
||||||
|
|
||||||
|
#define TracyCZoneText( ctx, txt, size ) ___tracy_emit_zone_text( ctx, txt, size );
|
||||||
|
#define TracyCZoneName( ctx, txt, size ) ___tracy_emit_zone_name( ctx, txt, size );
|
||||||
|
#define TracyCZoneValue( ctx, value ) ___tracy_emit_zone_value( ctx, value );
|
||||||
|
|
||||||
|
|
||||||
|
TRACY_API void ___tracy_emit_memory_alloc( const void* ptr, size_t size );
|
||||||
|
TRACY_API void ___tracy_emit_memory_alloc_callstack( const void* ptr, size_t size, int depth );
|
||||||
|
TRACY_API void ___tracy_emit_memory_free( const void* ptr );
|
||||||
|
TRACY_API void ___tracy_emit_memory_free_callstack( const void* ptr, int depth );
|
||||||
|
|
||||||
|
TRACY_API void ___tracy_emit_message( const char* txt, size_t size, int callstack );
|
||||||
|
TRACY_API void ___tracy_emit_messageL( const char* txt, int callstack );
|
||||||
|
TRACY_API void ___tracy_emit_messageC( const char* txt, size_t size, uint32_t color, int callstack );
|
||||||
|
TRACY_API void ___tracy_emit_messageLC( const char* txt, uint32_t color, int callstack );
|
||||||
|
|
||||||
|
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
||||||
|
# define TracyCAlloc( ptr, size ) ___tracy_emit_memory_alloc_callstack( ptr, size, TRACY_CALLSTACK )
|
||||||
|
# define TracyCFree( ptr ) ___tracy_emit_memory_free_callstack( ptr, TRACY_CALLSTACK )
|
||||||
|
|
||||||
|
# define TracyCMessage( txt, size ) ___tracy_emit_message( txt, size, TRACY_CALLSTACK );
|
||||||
|
# define TracyCMessageL( txt ) ___tracy_emit_messageL( txt, TRACY_CALLSTACK );
|
||||||
|
# define TracyCMessageC( txt, size, color ) ___tracy_emit_messageC( txt, size, color, TRACY_CALLSTACK );
|
||||||
|
# define TracyCMessageLC( txt, color ) ___tracy_emit_messageLC( txt, color, TRACY_CALLSTACK );
|
||||||
|
#else
|
||||||
|
# define TracyCAlloc( ptr, size ) ___tracy_emit_memory_alloc( ptr, size );
|
||||||
|
# define TracyCFree( ptr ) ___tracy_emit_memory_free( ptr );
|
||||||
|
|
||||||
|
# define TracyCMessage( txt, size ) ___tracy_emit_message( txt, size, 0 );
|
||||||
|
# define TracyCMessageL( txt ) ___tracy_emit_messageL( txt, 0 );
|
||||||
|
# define TracyCMessageC( txt, size, color ) ___tracy_emit_messageC( txt, size, color, 0 );
|
||||||
|
# define TracyCMessageLC( txt, color ) ___tracy_emit_messageLC( txt, color, 0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
TRACY_API void ___tracy_emit_frame_mark( const char* name );
|
||||||
|
TRACY_API void ___tracy_emit_frame_mark_start( const char* name );
|
||||||
|
TRACY_API void ___tracy_emit_frame_mark_end( const char* name );
|
||||||
|
TRACY_API void ___tracy_emit_frame_image( const void* image, uint16_t w, uint16_t h, uint8_t offset, int flip );
|
||||||
|
|
||||||
|
#define TracyCFrameMark ___tracy_emit_frame_mark( 0 );
|
||||||
|
#define TracyCFrameMarkNamed( name ) ___tracy_emit_frame_mark( name );
|
||||||
|
#define TracyCFrameMarkStart( name ) ___tracy_emit_frame_mark_start( name );
|
||||||
|
#define TracyCFrameMarkEnd( name ) ___tracy_emit_frame_mark_end( name );
|
||||||
|
#define TracyCFrameImage( image, width, height, offset, flip ) ___tracy_emit_frame_image( image, width, height, offset, flip );
|
||||||
|
|
||||||
|
|
||||||
|
TRACY_API void ___tracy_emit_plot( const char* name, double val );
|
||||||
|
TRACY_API void ___tracy_emit_message_appinfo( const char* txt, size_t size );
|
||||||
|
|
||||||
|
#define TracyCPlot( name, val ) ___tracy_emit_plot( name, val );
|
||||||
|
#define TracyCAppInfo( txt, color ) ___tracy_emit_message_appinfo( txt, color );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
# define TracyCZoneS( ctx, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { NULL, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,__LINE__), depth, active );
|
||||||
|
# define TracyCZoneNS( ctx, name, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,__LINE__), depth, active );
|
||||||
|
# define TracyCZoneCS( ctx, color, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { NULL, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,__LINE__), depth, active );
|
||||||
|
# define TracyCZoneNCS( ctx, name, color, depth, active ) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack( &TracyConcat(__tracy_source_location,__LINE__), depth, active );
|
||||||
|
|
||||||
|
# define TracyCAllocS( ptr, size, depth ) ___tracy_emit_memory_alloc_callstack( ptr, size, depth )
|
||||||
|
# define TracyCFreeS( ptr, depth ) ___tracy_emit_memory_free_callstack( ptr, depth )
|
||||||
|
|
||||||
|
# define TracyCMessageS( txt, size, depth ) ___tracy_emit_message( txt, size, depth );
|
||||||
|
# define TracyCMessageLS( txt, depth ) ___tracy_emit_messageL( txt, depth );
|
||||||
|
# define TracyCMessageCS( txt, size, color, depth ) ___tracy_emit_messageC( txt, size, color, depth );
|
||||||
|
# define TracyCMessageLCS( txt, color, depth ) ___tracy_emit_messageLC( txt, color, depth );
|
||||||
|
#else
|
||||||
|
# define TracyCZoneS( ctx, depth, active ) TracyCZone( ctx, active )
|
||||||
|
# define TracyCZoneNS( ctx, name, depth, active ) TracyCZoneN( ctx, name, active )
|
||||||
|
# define TracyCZoneCS( ctx, color, depth, active ) TracyCZoneC( ctx, color, active )
|
||||||
|
# define TracyCZoneNCS( ctx, name, color, depth, active ) TracyCZoneNC( ctx, name, color, active )
|
||||||
|
|
||||||
|
# define TracyCAllocS( ptr, size, depth ) TracyCAlloc( ptr, size )
|
||||||
|
# define TracyCFreeS( ptr, depth ) TracyCFree( ptr )
|
||||||
|
|
||||||
|
# define TracyCMessageS( txt, size, depth ) TracyCMessage( txt, size )
|
||||||
|
# define TracyCMessageLS( txt, depth ) TracyCMessageL( txt )
|
||||||
|
# define TracyCMessageCS( txt, size, color, depth ) TracyCMessageC( txt, size, color )
|
||||||
|
# define TracyCMessageLCS( txt, color, depth ) TracyCMessageLC( txt, color )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
47
TracyClient.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// Tracy profiler
|
||||||
|
// ----------------
|
||||||
|
//
|
||||||
|
// For fast integration, compile and
|
||||||
|
// link with this source file (and none
|
||||||
|
// other) in your executable (or in the
|
||||||
|
// main DLL / shared object on multi-DLL
|
||||||
|
// projects).
|
||||||
|
//
|
||||||
|
|
||||||
|
// Define TRACY_ENABLE to enable profiler.
|
||||||
|
|
||||||
|
#include "common/TracySystem.cpp"
|
||||||
|
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
|
||||||
|
#include "common/tracy_lz4.cpp"
|
||||||
|
#include "client/TracyProfiler.cpp"
|
||||||
|
#include "client/TracyCallstack.cpp"
|
||||||
|
#include "client/TracySysTime.cpp"
|
||||||
|
#include "client/TracySysTrace.cpp"
|
||||||
|
#include "common/TracySocket.cpp"
|
||||||
|
#include "client/tracy_rpmalloc.cpp"
|
||||||
|
#include "client/TracyDxt1.cpp"
|
||||||
|
|
||||||
|
#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
|
||||||
|
# include "libbacktrace/alloc.cpp"
|
||||||
|
# include "libbacktrace/dwarf.cpp"
|
||||||
|
# include "libbacktrace/fileline.cpp"
|
||||||
|
# include "libbacktrace/mmapio.cpp"
|
||||||
|
# include "libbacktrace/posix.cpp"
|
||||||
|
# include "libbacktrace/sort.cpp"
|
||||||
|
# include "libbacktrace/state.cpp"
|
||||||
|
# if TRACY_HAS_CALLSTACK == 4
|
||||||
|
# include "libbacktrace/macho.cpp"
|
||||||
|
# else
|
||||||
|
# include "libbacktrace/elf.cpp"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma comment(lib, "ws2_32.lib")
|
||||||
|
# pragma comment(lib, "dbghelp.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
351
TracyD3D12.hpp
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
#ifndef __TRACYD3D12_HPP__
|
||||||
|
#define __TRACYD3D12_HPP__
|
||||||
|
|
||||||
|
#ifndef TRACY_ENABLE
|
||||||
|
|
||||||
|
#define TracyD3D12Context(device, queue) nullptr
|
||||||
|
#define TracyD3D12Destroy(ctx)
|
||||||
|
|
||||||
|
#define TracyD3D12NamedZone(ctx, varname, cmdList, name, active)
|
||||||
|
#define TracyD3D12NamedZoneC(ctx, varname, cmdList, name, color, active)
|
||||||
|
#define TracyD3D12Zone(ctx, cmdList, name)
|
||||||
|
#define TracyD3D12ZoneC(ctx, cmdList, name, color)
|
||||||
|
|
||||||
|
#define TracyD3D12Collect(ctx)
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
class D3D12ZoneScope {};
|
||||||
|
}
|
||||||
|
|
||||||
|
using TracyD3D12Ctx = void*;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "Tracy.hpp"
|
||||||
|
#include "client/TracyProfiler.hpp"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cassert>
|
||||||
|
#include <d3d12.h>
|
||||||
|
#include <dxgi.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
struct D3D12QueryPayload
|
||||||
|
{
|
||||||
|
uint32_t m_queryIdStart = 0;
|
||||||
|
uint32_t m_queryCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Command queue context.
|
||||||
|
class D3D12QueueCtx
|
||||||
|
{
|
||||||
|
friend class D3D12ZoneScope;
|
||||||
|
|
||||||
|
static constexpr uint32_t MaxQueries = 64 * 1024; // Queries are begin and end markers, so we can store half as many total time durations. Must be even!
|
||||||
|
|
||||||
|
bool m_initialized = false;
|
||||||
|
|
||||||
|
ID3D12Device* m_device;
|
||||||
|
ID3D12CommandQueue* m_queue;
|
||||||
|
uint8_t m_context;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D12QueryHeap> m_queryHeap;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D12Resource> m_readbackBuffer;
|
||||||
|
|
||||||
|
// In-progress payload.
|
||||||
|
uint32_t m_queryLimit = MaxQueries;
|
||||||
|
uint32_t m_queryCounter = 0;
|
||||||
|
uint32_t m_previousQueryCounter = 0;
|
||||||
|
|
||||||
|
uint32_t m_activePayload = 0;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D12Fence> m_payloadFence;
|
||||||
|
std::queue<D3D12QueryPayload> m_payloadQueue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
D3D12QueueCtx(ID3D12Device* device, ID3D12CommandQueue* queue)
|
||||||
|
: m_device(device)
|
||||||
|
, m_queue(queue)
|
||||||
|
, m_context(GetGpuCtxCounter().fetch_add(1, std::memory_order_relaxed))
|
||||||
|
{
|
||||||
|
// Verify we support timestamp queries on this queue.
|
||||||
|
|
||||||
|
if (queue->GetDesc().Type == D3D12_COMMAND_LIST_TYPE_COPY)
|
||||||
|
{
|
||||||
|
D3D12_FEATURE_DATA_D3D12_OPTIONS3 featureData{};
|
||||||
|
|
||||||
|
if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3, &featureData, sizeof(featureData))))
|
||||||
|
{
|
||||||
|
assert(false && "Platform does not support profiling of copy queues.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t timestampFrequency;
|
||||||
|
|
||||||
|
if (FAILED(queue->GetTimestampFrequency(×tampFrequency)))
|
||||||
|
{
|
||||||
|
assert(false && "Failed to get timestamp frequency.");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t cpuTimestamp;
|
||||||
|
uint64_t gpuTimestamp;
|
||||||
|
|
||||||
|
if (FAILED(queue->GetClockCalibration(&gpuTimestamp, &cpuTimestamp)))
|
||||||
|
{
|
||||||
|
assert(false && "Failed to get queue clock calibration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
cpuTimestamp = Profiler::GetTime();
|
||||||
|
|
||||||
|
D3D12_QUERY_HEAP_DESC heapDesc{};
|
||||||
|
heapDesc.Type = queue->GetDesc().Type == D3D12_COMMAND_LIST_TYPE_COPY ? D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP : D3D12_QUERY_HEAP_TYPE_TIMESTAMP;
|
||||||
|
heapDesc.Count = m_queryLimit;
|
||||||
|
heapDesc.NodeMask = 0; // #TODO: Support multiple adapters.
|
||||||
|
|
||||||
|
while (FAILED(device->CreateQueryHeap(&heapDesc, IID_PPV_ARGS(&m_queryHeap))))
|
||||||
|
{
|
||||||
|
m_queryLimit /= 2;
|
||||||
|
heapDesc.Count = m_queryLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a readback buffer, which will be used as a destination for the query data.
|
||||||
|
|
||||||
|
D3D12_RESOURCE_DESC readbackBufferDesc{};
|
||||||
|
readbackBufferDesc.Alignment = 0;
|
||||||
|
readbackBufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||||
|
readbackBufferDesc.Width = m_queryLimit * sizeof(uint64_t);
|
||||||
|
readbackBufferDesc.Height = 1;
|
||||||
|
readbackBufferDesc.DepthOrArraySize = 1;
|
||||||
|
readbackBufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
readbackBufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; // Buffers are always row major.
|
||||||
|
readbackBufferDesc.MipLevels = 1;
|
||||||
|
readbackBufferDesc.SampleDesc.Count = 1;
|
||||||
|
readbackBufferDesc.SampleDesc.Quality = 0;
|
||||||
|
readbackBufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
|
D3D12_HEAP_PROPERTIES readbackHeapProps{};
|
||||||
|
readbackHeapProps.Type = D3D12_HEAP_TYPE_READBACK;
|
||||||
|
readbackHeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||||
|
readbackHeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||||
|
readbackHeapProps.CreationNodeMask = 0;
|
||||||
|
readbackHeapProps.VisibleNodeMask = 0; // #TODO: Support multiple adapters.
|
||||||
|
|
||||||
|
if (FAILED(device->CreateCommittedResource(&readbackHeapProps, D3D12_HEAP_FLAG_NONE, &readbackBufferDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_readbackBuffer))))
|
||||||
|
{
|
||||||
|
assert(false && "Failed to create query readback buffer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_payloadFence))))
|
||||||
|
{
|
||||||
|
assert(false && "Failed to create payload fence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* item = Profiler::QueueSerial();
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuNewContext);
|
||||||
|
MemWrite(&item->gpuNewContext.cpuTime, cpuTimestamp);
|
||||||
|
MemWrite(&item->gpuNewContext.gpuTime, gpuTimestamp);
|
||||||
|
memset(&item->gpuNewContext.thread, 0, sizeof(item->gpuNewContext.thread));
|
||||||
|
MemWrite(&item->gpuNewContext.period, 1E+09f / static_cast<float>(timestampFrequency));
|
||||||
|
MemWrite(&item->gpuNewContext.context, m_context);
|
||||||
|
MemWrite(&item->gpuNewContext.accuracyBits, uint8_t{ 0 });
|
||||||
|
MemWrite(&item->gpuNewContext.type, GpuContextType::Direct3D12);
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
GetProfiler().DeferItem(*item);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewFrame()
|
||||||
|
{
|
||||||
|
m_payloadQueue.emplace(D3D12QueryPayload{ m_previousQueryCounter, m_queryCounter });
|
||||||
|
m_previousQueryCounter += m_queryCounter;
|
||||||
|
m_queryCounter = 0;
|
||||||
|
|
||||||
|
if (m_previousQueryCounter >= m_queryLimit)
|
||||||
|
{
|
||||||
|
m_previousQueryCounter -= m_queryLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_queue->Signal(m_payloadFence.Get(), ++m_activePayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collect()
|
||||||
|
{
|
||||||
|
ZoneScopedC(Color::Red4);
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if (!GetProfiler().IsConnected())
|
||||||
|
{
|
||||||
|
m_queryCounter = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Find out what payloads are available.
|
||||||
|
const auto newestReadyPayload = m_payloadFence->GetCompletedValue();
|
||||||
|
const auto payloadCount = m_payloadQueue.size() - (m_activePayload - newestReadyPayload);
|
||||||
|
|
||||||
|
if (!payloadCount)
|
||||||
|
{
|
||||||
|
return; // No payloads are available yet, exit out.
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12_RANGE mapRange{ 0, m_queryLimit * sizeof(uint64_t) };
|
||||||
|
|
||||||
|
// Map the readback buffer so we can fetch the query data from the GPU.
|
||||||
|
void* readbackBufferMapping = nullptr;
|
||||||
|
|
||||||
|
if (FAILED(m_readbackBuffer->Map(0, &mapRange, &readbackBufferMapping)))
|
||||||
|
{
|
||||||
|
assert(false && "Failed to map readback buffer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* timestampData = static_cast<uint64_t*>(readbackBufferMapping);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < payloadCount; ++i)
|
||||||
|
{
|
||||||
|
const auto& payload = m_payloadQueue.front();
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < payload.m_queryCount; ++j)
|
||||||
|
{
|
||||||
|
const auto counter = (payload.m_queryIdStart + j) % m_queryLimit;
|
||||||
|
const auto timestamp = timestampData[counter];
|
||||||
|
const auto queryId = counter;
|
||||||
|
|
||||||
|
auto* item = Profiler::QueueSerial();
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuTime);
|
||||||
|
MemWrite(&item->gpuTime.gpuTime, timestamp);
|
||||||
|
MemWrite(&item->gpuTime.queryId, static_cast<uint16_t>(queryId));
|
||||||
|
MemWrite(&item->gpuTime.context, m_context);
|
||||||
|
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_payloadQueue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_readbackBuffer->Unmap(0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
tracy_force_inline uint32_t NextQueryId()
|
||||||
|
{
|
||||||
|
assert(m_queryCounter < m_queryLimit && "Submitted too many GPU queries! Consider increasing MaxQueries.");
|
||||||
|
|
||||||
|
const uint32_t id = (m_previousQueryCounter + m_queryCounter) % m_queryLimit;
|
||||||
|
m_queryCounter += 2; // Allocate space for a begin and end query.
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline uint8_t GetId() const
|
||||||
|
{
|
||||||
|
return m_context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class D3D12ZoneScope
|
||||||
|
{
|
||||||
|
const bool m_active;
|
||||||
|
D3D12QueueCtx* m_ctx = nullptr;
|
||||||
|
ID3D12GraphicsCommandList* m_cmdList = nullptr;
|
||||||
|
uint32_t m_queryId = 0; // Used for tracking in nested zones.
|
||||||
|
|
||||||
|
public:
|
||||||
|
tracy_force_inline D3D12ZoneScope(D3D12QueueCtx* ctx, ID3D12GraphicsCommandList* cmdList, const SourceLocationData* srcLocation, bool active)
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
: m_active(active && GetProfiler().IsConnected())
|
||||||
|
#else
|
||||||
|
: m_active(active)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (!m_active) return;
|
||||||
|
|
||||||
|
m_ctx = ctx;
|
||||||
|
m_cmdList = cmdList;
|
||||||
|
|
||||||
|
m_queryId = ctx->NextQueryId();
|
||||||
|
cmdList->EndQuery(ctx->m_queryHeap.Get(), D3D12_QUERY_TYPE_TIMESTAMP, m_queryId);
|
||||||
|
|
||||||
|
auto* item = Profiler::QueueSerial();
|
||||||
|
#if defined(TRACY_HAS_CALLSTACK) && defined(TRACY_CALLSTACK)
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuZoneBeginCallstackSerial);
|
||||||
|
#else
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuZoneBeginSerial);
|
||||||
|
#endif
|
||||||
|
MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());
|
||||||
|
MemWrite(&item->gpuZoneBegin.srcloc, reinterpret_cast<uint64_t>(srcLocation));
|
||||||
|
MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());
|
||||||
|
MemWrite(&item->gpuZoneBegin.queryId, static_cast<uint16_t>(m_queryId));
|
||||||
|
MemWrite(&item->gpuZoneBegin.context, ctx->GetId());
|
||||||
|
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
|
||||||
|
#if defined(TRACY_HAS_CALLSTACK) && defined(TRACY_CALLSTACK)
|
||||||
|
GetProfiler().SendCallstack(TRACY_CALLSTACK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline ~D3D12ZoneScope()
|
||||||
|
{
|
||||||
|
if (!m_active) return;
|
||||||
|
|
||||||
|
const auto queryId = m_queryId + 1; // Our end query slot is immediately after the begin slot.
|
||||||
|
m_cmdList->EndQuery(m_ctx->m_queryHeap.Get(), D3D12_QUERY_TYPE_TIMESTAMP, queryId);
|
||||||
|
|
||||||
|
auto* item = Profiler::QueueSerial();
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuZoneEndSerial);
|
||||||
|
MemWrite(&item->gpuZoneEnd.cpuTime, Profiler::GetTime());
|
||||||
|
MemWrite(&item->gpuZoneEnd.thread, GetThreadHandle());
|
||||||
|
MemWrite(&item->gpuZoneEnd.queryId, static_cast<uint16_t>(queryId));
|
||||||
|
MemWrite(&item->gpuZoneEnd.context, m_ctx->GetId());
|
||||||
|
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
|
||||||
|
m_cmdList->ResolveQueryData(m_ctx->m_queryHeap.Get(), D3D12_QUERY_TYPE_TIMESTAMP, m_queryId, 2, m_ctx->m_readbackBuffer.Get(), m_queryId * sizeof(uint64_t));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline D3D12QueueCtx* CreateD3D12Context(ID3D12Device* device, ID3D12CommandQueue* queue)
|
||||||
|
{
|
||||||
|
InitRPMallocThread();
|
||||||
|
|
||||||
|
auto* ctx = static_cast<D3D12QueueCtx*>(tracy_malloc(sizeof(D3D12QueueCtx)));
|
||||||
|
new (ctx) D3D12QueueCtx{ device, queue };
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void DestroyD3D12Context(D3D12QueueCtx* ctx)
|
||||||
|
{
|
||||||
|
ctx->~D3D12QueueCtx();
|
||||||
|
tracy_free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using TracyD3D12Ctx = tracy::D3D12QueueCtx*;
|
||||||
|
|
||||||
|
#define TracyD3D12Context(device, queue) tracy::CreateD3D12Context(device, queue);
|
||||||
|
#define TracyD3D12Destroy(ctx) tracy::DestroyD3D12Context(ctx);
|
||||||
|
|
||||||
|
#define TracyD3D12NewFrame(ctx) ctx->NewFrame();
|
||||||
|
|
||||||
|
#define TracyD3D12NamedZone(ctx, varname, cmdList, name, active) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location, __LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::D3D12ZoneScope varname{ ctx, cmdList, &TracyConcat(__tracy_gpu_source_location, __LINE__), active };
|
||||||
|
#define TracyD3D12NamedZoneC(ctx, varname, cmdList, name, color, active) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location, __LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::D3D12ZoneScope varname{ ctx, cmdList, &TracyConcat(__tracy_gpu_source_location, __LINE__), active };
|
||||||
|
#define TracyD3D12Zone(ctx, cmdList, name) TracyD3D12NamedZone(ctx, ___tracy_gpu_zone, cmdList, name, true)
|
||||||
|
#define TracyD3D12ZoneC(ctx, cmdList, name, color) TracyD3D12NamedZoneC(ctx, ___tracy_gpu_zone, cmdList, name, color, true)
|
||||||
|
|
||||||
|
#define TracyD3D12Collect(ctx) ctx->Collect();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -120,20 +120,17 @@ static inline void LuaRemove( char* script )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void LuaHook( lua_State* L, lua_Debug* ar ) {}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
#include "../common/TracyColor.hpp"
|
#include "common/TracyColor.hpp"
|
||||||
#include "../common/TracyAlign.hpp"
|
#include "common/TracyAlign.hpp"
|
||||||
#include "../common/TracyForceInline.hpp"
|
#include "common/TracyForceInline.hpp"
|
||||||
#include "../common/TracySystem.hpp"
|
#include "common/TracySystem.hpp"
|
||||||
#include "../client/TracyProfiler.hpp"
|
#include "client/TracyProfiler.hpp"
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
@ -153,9 +150,9 @@ static tracy_force_inline void SendLuaCallstack( lua_State* L, uint32_t depth )
|
|||||||
const char* func[64];
|
const char* func[64];
|
||||||
uint32_t fsz[64];
|
uint32_t fsz[64];
|
||||||
uint32_t ssz[64];
|
uint32_t ssz[64];
|
||||||
|
uint32_t spaceNeeded = 4; // cnt
|
||||||
|
|
||||||
uint8_t cnt;
|
uint32_t cnt;
|
||||||
uint16_t spaceNeeded = sizeof( cnt );
|
|
||||||
for( cnt=0; cnt<depth; cnt++ )
|
for( cnt=0; cnt<depth; cnt++ )
|
||||||
{
|
{
|
||||||
if( lua_getstack( L, cnt+1, dbg+cnt ) == 0 ) break;
|
if( lua_getstack( L, cnt+1, dbg+cnt ) == 0 ) break;
|
||||||
@ -165,36 +162,27 @@ static tracy_force_inline void SendLuaCallstack( lua_State* L, uint32_t depth )
|
|||||||
ssz[cnt] = uint32_t( strlen( dbg[cnt].source ) );
|
ssz[cnt] = uint32_t( strlen( dbg[cnt].source ) );
|
||||||
spaceNeeded += fsz[cnt] + ssz[cnt];
|
spaceNeeded += fsz[cnt] + ssz[cnt];
|
||||||
}
|
}
|
||||||
spaceNeeded += cnt * ( 4 + 2 + 2 ); // source line, function string length, source string length
|
spaceNeeded += cnt * ( 4 + 4 + 4 ); // source line, function string length, source string length
|
||||||
|
|
||||||
auto ptr = (char*)tracy_malloc( spaceNeeded + 2 );
|
auto ptr = (char*)tracy_malloc( spaceNeeded + 4 );
|
||||||
auto dst = ptr;
|
auto dst = ptr;
|
||||||
memcpy( dst, &spaceNeeded, 2 ); dst += 2;
|
memcpy( dst, &spaceNeeded, 4 ); dst += 4;
|
||||||
memcpy( dst, &cnt, 1 ); dst++;
|
memcpy( dst, &cnt, 4 ); dst += 4;
|
||||||
for( uint8_t i=0; i<cnt; i++ )
|
for( uint32_t i=0; i<cnt; i++ )
|
||||||
{
|
{
|
||||||
const uint32_t line = dbg[i].currentline;
|
const uint32_t line = dbg[i].currentline;
|
||||||
memcpy( dst, &line, 4 ); dst += 4;
|
memcpy( dst, &line, 4 ); dst += 4;
|
||||||
assert( fsz[i] <= (std::numeric_limits<uint16_t>::max)() );
|
memcpy( dst, fsz+i, 4 ); dst += 4;
|
||||||
memcpy( dst, fsz+i, 2 ); dst += 2;
|
|
||||||
memcpy( dst, func[i], fsz[i] ); dst += fsz[i];
|
memcpy( dst, func[i], fsz[i] ); dst += fsz[i];
|
||||||
assert( ssz[i] <= (std::numeric_limits<uint16_t>::max)() );
|
memcpy( dst, ssz+i, 4 ); dst += 4;
|
||||||
memcpy( dst, ssz+i, 2 ); dst += 2;
|
|
||||||
memcpy( dst, dbg[i].source, ssz[i] ), dst += ssz[i];
|
memcpy( dst, dbg[i].source, ssz[i] ), dst += ssz[i];
|
||||||
}
|
}
|
||||||
assert( dst - ptr == spaceNeeded + 2 );
|
assert( dst - ptr == spaceNeeded + 4 );
|
||||||
|
|
||||||
TracyQueuePrepare( QueueType::CallstackAlloc );
|
TracyLfqPrepare( QueueType::CallstackAlloc );
|
||||||
MemWrite( &item->callstackAllocFat.ptr, (uint64_t)ptr );
|
MemWrite( &item->callstackAlloc.ptr, (uint64_t)ptr );
|
||||||
MemWrite( &item->callstackAllocFat.nativePtr, (uint64_t)Callstack( depth ) );
|
MemWrite( &item->callstackAlloc.nativePtr, (uint64_t)Callstack( depth ) );
|
||||||
TracyQueueCommit( callstackAllocFatThread );
|
TracyLfqCommit;
|
||||||
}
|
|
||||||
|
|
||||||
static inline void LuaShortenSrc( char* dst, const char* src )
|
|
||||||
{
|
|
||||||
size_t l = std::min( (size_t)255, strlen( src ) );
|
|
||||||
memcpy( dst, src, l );
|
|
||||||
dst[l] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int LuaZoneBeginS( lua_State* L )
|
static inline int LuaZoneBeginS( lua_State* L )
|
||||||
@ -206,6 +194,15 @@ static inline int LuaZoneBeginS( lua_State* L )
|
|||||||
if( !GetLuaZoneState().active ) return 0;
|
if( !GetLuaZoneState().active ) return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
|
||||||
|
lua_Debug dbg;
|
||||||
|
lua_getstack( L, 1, &dbg );
|
||||||
|
lua_getinfo( L, "Snl", &dbg );
|
||||||
|
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src );
|
||||||
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
||||||
|
TracyLfqCommit;
|
||||||
|
|
||||||
#ifdef TRACY_CALLSTACK
|
#ifdef TRACY_CALLSTACK
|
||||||
const uint32_t depth = TRACY_CALLSTACK;
|
const uint32_t depth = TRACY_CALLSTACK;
|
||||||
#else
|
#else
|
||||||
@ -213,18 +210,6 @@ static inline int LuaZoneBeginS( lua_State* L )
|
|||||||
#endif
|
#endif
|
||||||
SendLuaCallstack( L, depth );
|
SendLuaCallstack( L, depth );
|
||||||
|
|
||||||
lua_Debug dbg;
|
|
||||||
lua_getstack( L, 1, &dbg );
|
|
||||||
lua_getinfo( L, "Snl", &dbg );
|
|
||||||
char src[256];
|
|
||||||
LuaShortenSrc( src, dbg.source );
|
|
||||||
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src );
|
|
||||||
|
|
||||||
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
|
|
||||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
|
||||||
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
|
||||||
TracyQueueCommit( zoneBeginThread );
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +222,17 @@ static inline int LuaZoneBeginNS( lua_State* L )
|
|||||||
if( !GetLuaZoneState().active ) return 0;
|
if( !GetLuaZoneState().active ) return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
|
||||||
|
lua_Debug dbg;
|
||||||
|
lua_getstack( L, 1, &dbg );
|
||||||
|
lua_getinfo( L, "Snl", &dbg );
|
||||||
|
size_t nsz;
|
||||||
|
const auto name = lua_tolstring( L, 1, &nsz );
|
||||||
|
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src, name, nsz );
|
||||||
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
||||||
|
TracyLfqCommit;
|
||||||
|
|
||||||
#ifdef TRACY_CALLSTACK
|
#ifdef TRACY_CALLSTACK
|
||||||
const uint32_t depth = TRACY_CALLSTACK;
|
const uint32_t depth = TRACY_CALLSTACK;
|
||||||
#else
|
#else
|
||||||
@ -244,20 +240,6 @@ static inline int LuaZoneBeginNS( lua_State* L )
|
|||||||
#endif
|
#endif
|
||||||
SendLuaCallstack( L, depth );
|
SendLuaCallstack( L, depth );
|
||||||
|
|
||||||
lua_Debug dbg;
|
|
||||||
lua_getstack( L, 1, &dbg );
|
|
||||||
lua_getinfo( L, "Snl", &dbg );
|
|
||||||
size_t nsz;
|
|
||||||
char src[256];
|
|
||||||
LuaShortenSrc( src, dbg.source );
|
|
||||||
const auto name = lua_tolstring( L, 1, &nsz );
|
|
||||||
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src, name, nsz );
|
|
||||||
|
|
||||||
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
|
|
||||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
|
||||||
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
|
||||||
TracyQueueCommit( zoneBeginThread );
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -274,17 +256,14 @@ static inline int LuaZoneBegin( lua_State* L )
|
|||||||
if( !GetLuaZoneState().active ) return 0;
|
if( !GetLuaZoneState().active ) return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLoc );
|
||||||
lua_Debug dbg;
|
lua_Debug dbg;
|
||||||
lua_getstack( L, 1, &dbg );
|
lua_getstack( L, 1, &dbg );
|
||||||
lua_getinfo( L, "Snl", &dbg );
|
lua_getinfo( L, "Snl", &dbg );
|
||||||
char src[256];
|
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src );
|
||||||
LuaShortenSrc( src, dbg.source );
|
|
||||||
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src );
|
|
||||||
|
|
||||||
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc );
|
|
||||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
||||||
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
||||||
TracyQueueCommit( zoneBeginThread );
|
TracyLfqCommit;
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -301,19 +280,16 @@ static inline int LuaZoneBeginN( lua_State* L )
|
|||||||
if( !GetLuaZoneState().active ) return 0;
|
if( !GetLuaZoneState().active ) return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLoc );
|
||||||
lua_Debug dbg;
|
lua_Debug dbg;
|
||||||
lua_getstack( L, 1, &dbg );
|
lua_getstack( L, 1, &dbg );
|
||||||
lua_getinfo( L, "Snl", &dbg );
|
lua_getinfo( L, "Snl", &dbg );
|
||||||
size_t nsz;
|
size_t nsz;
|
||||||
char src[256];
|
|
||||||
LuaShortenSrc( src, dbg.source );
|
|
||||||
const auto name = lua_tolstring( L, 1, &nsz );
|
const auto name = lua_tolstring( L, 1, &nsz );
|
||||||
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, src, dbg.name ? dbg.name : dbg.short_src, name, nsz );
|
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src, name, nsz );
|
||||||
|
|
||||||
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc );
|
|
||||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
||||||
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
||||||
TracyQueueCommit( zoneBeginThread );
|
TracyLfqCommit;
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -331,9 +307,9 @@ static inline int LuaZoneEnd( lua_State* L )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TracyQueuePrepare( QueueType::ZoneEnd );
|
TracyLfqPrepare( QueueType::ZoneEnd );
|
||||||
MemWrite( &item->zoneEnd.time, Profiler::GetTime() );
|
MemWrite( &item->zoneEnd.time, Profiler::GetTime() );
|
||||||
TracyQueueCommit( zoneEndThread );
|
TracyLfqCommit;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,15 +326,13 @@ static inline int LuaZoneText( lua_State* L )
|
|||||||
|
|
||||||
auto txt = lua_tostring( L, 1 );
|
auto txt = lua_tostring( L, 1 );
|
||||||
const auto size = strlen( txt );
|
const auto size = strlen( txt );
|
||||||
assert( size < (std::numeric_limits<uint16_t>::max)() );
|
|
||||||
|
|
||||||
auto ptr = (char*)tracy_malloc( size );
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
memcpy( ptr, txt, size );
|
memcpy( ptr, txt, size );
|
||||||
|
ptr[size] = '\0';
|
||||||
TracyQueuePrepare( QueueType::ZoneText );
|
TracyLfqPrepare( QueueType::ZoneText );
|
||||||
MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );
|
MemWrite( &item->zoneText.text, (uint64_t)ptr );
|
||||||
MemWrite( &item->zoneTextFat.size, (uint16_t)size );
|
TracyLfqCommit;
|
||||||
TracyQueueCommit( zoneTextFatThread );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,15 +349,13 @@ static inline int LuaZoneName( lua_State* L )
|
|||||||
|
|
||||||
auto txt = lua_tostring( L, 1 );
|
auto txt = lua_tostring( L, 1 );
|
||||||
const auto size = strlen( txt );
|
const auto size = strlen( txt );
|
||||||
assert( size < (std::numeric_limits<uint16_t>::max)() );
|
|
||||||
|
|
||||||
auto ptr = (char*)tracy_malloc( size );
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
memcpy( ptr, txt, size );
|
memcpy( ptr, txt, size );
|
||||||
|
ptr[size] = '\0';
|
||||||
TracyQueuePrepare( QueueType::ZoneName );
|
TracyLfqPrepare( QueueType::ZoneName );
|
||||||
MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );
|
MemWrite( &item->zoneText.text, (uint64_t)ptr );
|
||||||
MemWrite( &item->zoneTextFat.size, (uint16_t)size );
|
TracyLfqCommit;
|
||||||
TracyQueueCommit( zoneTextFatThread );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,16 +367,14 @@ static inline int LuaMessage( lua_State* L )
|
|||||||
|
|
||||||
auto txt = lua_tostring( L, 1 );
|
auto txt = lua_tostring( L, 1 );
|
||||||
const auto size = strlen( txt );
|
const auto size = strlen( txt );
|
||||||
assert( size < (std::numeric_limits<uint16_t>::max)() );
|
|
||||||
|
|
||||||
auto ptr = (char*)tracy_malloc( size );
|
TracyLfqPrepare( QueueType::Message );
|
||||||
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
memcpy( ptr, txt, size );
|
memcpy( ptr, txt, size );
|
||||||
|
ptr[size] = '\0';
|
||||||
TracyQueuePrepare( QueueType::Message );
|
MemWrite( &item->message.time, Profiler::GetTime() );
|
||||||
MemWrite( &item->messageFat.time, Profiler::GetTime() );
|
MemWrite( &item->message.text, (uint64_t)ptr );
|
||||||
MemWrite( &item->messageFat.text, (uint64_t)ptr );
|
TracyLfqCommit;
|
||||||
MemWrite( &item->messageFat.size, (uint16_t)size );
|
|
||||||
TracyQueueCommit( messageFatThread );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,44 +411,6 @@ static inline void LuaRegister( lua_State* L )
|
|||||||
|
|
||||||
static inline void LuaRemove( char* script ) {}
|
static inline void LuaRemove( char* script ) {}
|
||||||
|
|
||||||
static inline void LuaHook( lua_State* L, lua_Debug* ar )
|
|
||||||
{
|
|
||||||
if ( ar->event == LUA_HOOKCALL )
|
|
||||||
{
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
const auto zoneCnt = GetLuaZoneState().counter++;
|
|
||||||
if ( zoneCnt != 0 && !GetLuaZoneState().active ) return;
|
|
||||||
GetLuaZoneState().active = GetProfiler().IsConnected();
|
|
||||||
if ( !GetLuaZoneState().active ) return;
|
|
||||||
#endif
|
|
||||||
lua_getinfo( L, "Snl", ar );
|
|
||||||
|
|
||||||
char src[256];
|
|
||||||
detail::LuaShortenSrc( src, ar->short_src );
|
|
||||||
|
|
||||||
const auto srcloc = Profiler::AllocSourceLocation( ar->currentline, src, ar->name ? ar->name : ar->short_src );
|
|
||||||
TracyQueuePrepare( QueueType::ZoneBeginAllocSrcLoc );
|
|
||||||
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
|
||||||
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
|
||||||
TracyQueueCommit( zoneBeginThread );
|
|
||||||
}
|
|
||||||
else if (ar->event == LUA_HOOKRET) {
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
assert( GetLuaZoneState().counter != 0 );
|
|
||||||
GetLuaZoneState().counter--;
|
|
||||||
if ( !GetLuaZoneState().active ) return;
|
|
||||||
if ( !GetProfiler().IsConnected() )
|
|
||||||
{
|
|
||||||
GetLuaZoneState().active = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
TracyQueuePrepare( QueueType::ZoneEnd );
|
|
||||||
MemWrite( &item->zoneEnd.time, Profiler::GetTime() );
|
|
||||||
TracyQueueCommit( zoneEndThread );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
333
TracyOpenCL.hpp
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
#ifndef __TRACYOPENCL_HPP__
|
||||||
|
#define __TRACYOPENCL_HPP__
|
||||||
|
|
||||||
|
#if !defined TRACY_ENABLE
|
||||||
|
|
||||||
|
#define TracyCLContext(x, y) nullptr
|
||||||
|
#define TracyCLDestroy(x)
|
||||||
|
#define TracyCLNamedZone(c, x, y, z, w)
|
||||||
|
#define TracyCLNamedZoneC(c, x, y, z, w, a)
|
||||||
|
#define TracyCLZone(c, x, y)
|
||||||
|
#define TracyCLZoneC(c, x, y, z)
|
||||||
|
#define TracyCLCollect(c)
|
||||||
|
|
||||||
|
#define TracyCLNamedZoneS(c, x, y, z, w, a)
|
||||||
|
#define TracyCLNamedZoneCS(c, x, y, z, w, v, a)
|
||||||
|
#define TracyCLZoneS(c, x, y, z)
|
||||||
|
#define TracyCLZoneCS(c, x, y, z, w)
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
class OpenCLCtxScope {};
|
||||||
|
}
|
||||||
|
|
||||||
|
using TracyCLCtx = void*;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <CL/cl.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "Tracy.hpp"
|
||||||
|
#include "client/TracyCallstack.hpp"
|
||||||
|
#include "client/TracyProfiler.hpp"
|
||||||
|
#include "common/TracyAlloc.hpp"
|
||||||
|
|
||||||
|
namespace tracy {
|
||||||
|
|
||||||
|
enum class EventPhase : uint8_t
|
||||||
|
{
|
||||||
|
Begin,
|
||||||
|
End
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventInfo
|
||||||
|
{
|
||||||
|
cl_event event;
|
||||||
|
EventPhase phase;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpenCLCtx
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { QueryCount = 64 * 1024 };
|
||||||
|
|
||||||
|
OpenCLCtx(cl_context context, cl_device_id device)
|
||||||
|
: m_contextId(GetGpuCtxCounter().fetch_add(1, std::memory_order_relaxed))
|
||||||
|
, m_head(0)
|
||||||
|
, m_tail(0)
|
||||||
|
{
|
||||||
|
assert(m_contextId != 255);
|
||||||
|
|
||||||
|
m_hostStartTime = Profiler::GetTime();
|
||||||
|
m_deviceStartTime = GetDeviceTimestamp(context, device);
|
||||||
|
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuNewContext);
|
||||||
|
MemWrite(&item->gpuNewContext.cpuTime, m_hostStartTime);
|
||||||
|
MemWrite(&item->gpuNewContext.gpuTime, m_hostStartTime);
|
||||||
|
memset(&item->gpuNewContext.thread, 0, sizeof(item->gpuNewContext.thread));
|
||||||
|
MemWrite(&item->gpuNewContext.period, 1.0f);
|
||||||
|
MemWrite(&item->gpuNewContext.type, GpuContextType::OpenCL);
|
||||||
|
MemWrite(&item->gpuNewContext.context, (uint8_t) m_contextId);
|
||||||
|
MemWrite(&item->gpuNewContext.accuracyBits, (uint8_t)0);
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
GetProfiler().DeferItem(*item);
|
||||||
|
#endif
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collect()
|
||||||
|
{
|
||||||
|
ZoneScopedC(Color::Red4);
|
||||||
|
|
||||||
|
if (m_tail == m_head) return;
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if (!GetProfiler().IsConnected())
|
||||||
|
{
|
||||||
|
m_head = m_tail = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (m_tail != m_head)
|
||||||
|
{
|
||||||
|
EventInfo eventInfo = m_query[m_tail];
|
||||||
|
cl_event event = eventInfo.event;
|
||||||
|
cl_int eventStatus;
|
||||||
|
cl_int err = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &eventStatus, nullptr);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
if (eventStatus != CL_COMPLETE) return;
|
||||||
|
|
||||||
|
cl_int eventInfoQuery = (eventInfo.phase == EventPhase::Begin)
|
||||||
|
? CL_PROFILING_COMMAND_START
|
||||||
|
: CL_PROFILING_COMMAND_END;
|
||||||
|
|
||||||
|
cl_ulong eventTimeStamp = 0;
|
||||||
|
err = clGetEventProfilingInfo(event, eventInfoQuery, sizeof(cl_ulong), &eventTimeStamp, nullptr);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
assert(eventTimeStamp != 0);
|
||||||
|
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuTime);
|
||||||
|
MemWrite(&item->gpuTime.gpuTime, TimestampOffset(eventTimeStamp));
|
||||||
|
MemWrite(&item->gpuTime.queryId, (uint16_t)m_tail);
|
||||||
|
MemWrite(&item->gpuTime.context, m_contextId);
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
|
||||||
|
if (eventInfo.phase == EventPhase::End)
|
||||||
|
{
|
||||||
|
// Done with the event, so release it
|
||||||
|
assert(clReleaseEvent(event) == CL_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_tail = (m_tail + 1) % QueryCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline uint8_t GetId() const
|
||||||
|
{
|
||||||
|
return m_contextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline unsigned int NextQueryId(EventInfo eventInfo)
|
||||||
|
{
|
||||||
|
const auto id = m_head;
|
||||||
|
m_head = (m_head + 1) % QueryCount;
|
||||||
|
assert(m_head != m_tail);
|
||||||
|
m_query[id] = eventInfo;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline EventInfo& GetQuery(unsigned int id)
|
||||||
|
{
|
||||||
|
assert(id < QueryCount);
|
||||||
|
return m_query[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
tracy_force_inline int64_t GetHostStartTime() const
|
||||||
|
{
|
||||||
|
return m_hostStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline int64_t GetDeviceStartTime() const
|
||||||
|
{
|
||||||
|
return m_deviceStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline int64_t TimestampOffset(int64_t deviceTimestamp) const
|
||||||
|
{
|
||||||
|
return m_hostStartTime + (deviceTimestamp - m_deviceStartTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline int64_t GetDeviceTimestamp(cl_context context, cl_device_id device) const
|
||||||
|
{
|
||||||
|
cl_ulong deviceTimestamp = 0;
|
||||||
|
cl_int err = CL_SUCCESS;
|
||||||
|
cl_command_queue queue = clCreateCommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE, &err);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
uint32_t dummyValue = 42;
|
||||||
|
cl_mem dummyBuffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(uint32_t), nullptr, &err);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
cl_event writeBufferEvent;
|
||||||
|
err = clEnqueueWriteBuffer(queue, dummyBuffer, CL_TRUE, 0, sizeof(uint32_t), &dummyValue, 0, nullptr, &writeBufferEvent);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
err = clWaitForEvents(1, &writeBufferEvent);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
cl_int eventStatus;
|
||||||
|
err = clGetEventInfo(writeBufferEvent, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &eventStatus, nullptr);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
assert(eventStatus == CL_COMPLETE);
|
||||||
|
err = clGetEventProfilingInfo(writeBufferEvent, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &deviceTimestamp, nullptr);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
err = clReleaseEvent(writeBufferEvent);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
err = clReleaseMemObject(dummyBuffer);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
err = clReleaseCommandQueue(queue);
|
||||||
|
assert(err == CL_SUCCESS);
|
||||||
|
|
||||||
|
return (int64_t)deviceTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int m_contextId;
|
||||||
|
|
||||||
|
EventInfo m_query[QueryCount];
|
||||||
|
unsigned int m_head;
|
||||||
|
unsigned int m_tail;
|
||||||
|
|
||||||
|
int64_t m_hostStartTime;
|
||||||
|
int64_t m_deviceStartTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpenCLCtxScope {
|
||||||
|
public:
|
||||||
|
tracy_force_inline OpenCLCtxScope(OpenCLCtx* ctx, const SourceLocationData* srcLoc, bool is_active)
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
: m_active(is_active&& GetProfiler().IsConnected())
|
||||||
|
#else
|
||||||
|
: m_active(is_active)
|
||||||
|
#endif
|
||||||
|
, m_ctx(ctx)
|
||||||
|
, m_event(nullptr)
|
||||||
|
{
|
||||||
|
if (!m_active) return;
|
||||||
|
|
||||||
|
m_beginQueryId = ctx->NextQueryId(EventInfo{ nullptr, EventPhase::Begin });
|
||||||
|
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuZoneBeginSerial);
|
||||||
|
MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());
|
||||||
|
MemWrite(&item->gpuZoneBegin.srcloc, (uint64_t)srcLoc);
|
||||||
|
MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());
|
||||||
|
MemWrite(&item->gpuZoneBegin.queryId, (uint16_t)m_beginQueryId);
|
||||||
|
MemWrite(&item->gpuZoneBegin.context, ctx->GetId());
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline OpenCLCtxScope(OpenCLCtx* ctx, const SourceLocationData* srcLoc, int depth, bool is_active)
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
: m_active(is_active&& GetProfiler().IsConnected())
|
||||||
|
#else
|
||||||
|
: m_active(is_active)
|
||||||
|
#endif
|
||||||
|
, m_ctx(ctx)
|
||||||
|
, m_event(nullptr)
|
||||||
|
{
|
||||||
|
if (!m_active) return;
|
||||||
|
|
||||||
|
m_beginQueryId = ctx->NextQueryId(EventInfo{ nullptr, EventPhase::Begin });
|
||||||
|
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuZoneBeginCallstackSerial);
|
||||||
|
MemWrite(&item->gpuZoneBegin.cpuTime, Profiler::GetTime());
|
||||||
|
MemWrite(&item->gpuZoneBegin.srcloc, (uint64_t)srcLoc);
|
||||||
|
MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle());
|
||||||
|
MemWrite(&item->gpuZoneBegin.queryId, (uint16_t)m_beginQueryId);
|
||||||
|
MemWrite(&item->gpuZoneBegin.context, ctx->GetId());
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
|
||||||
|
GetProfiler().SendCallstack(depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline void SetEvent(cl_event event)
|
||||||
|
{
|
||||||
|
m_event = event;
|
||||||
|
assert(clRetainEvent(m_event) == CL_SUCCESS);
|
||||||
|
m_ctx->GetQuery(m_beginQueryId).event = m_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline ~OpenCLCtxScope()
|
||||||
|
{
|
||||||
|
const auto queryId = m_ctx->NextQueryId(EventInfo{ m_event, EventPhase::End });
|
||||||
|
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite(&item->hdr.type, QueueType::GpuZoneEndSerial);
|
||||||
|
MemWrite(&item->gpuZoneEnd.cpuTime, Profiler::GetTime());
|
||||||
|
MemWrite(&item->gpuZoneEnd.thread, GetThreadHandle());
|
||||||
|
MemWrite(&item->gpuZoneEnd.queryId, (uint16_t)queryId);
|
||||||
|
MemWrite(&item->gpuZoneEnd.context, m_ctx->GetId());
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool m_active;
|
||||||
|
OpenCLCtx* m_ctx;
|
||||||
|
cl_event m_event;
|
||||||
|
unsigned int m_beginQueryId;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline OpenCLCtx* CreateCLContext(cl_context context, cl_device_id device)
|
||||||
|
{
|
||||||
|
InitRPMallocThread();
|
||||||
|
auto ctx = (OpenCLCtx*)tracy_malloc(sizeof(OpenCLCtx));
|
||||||
|
new (ctx) OpenCLCtx(context, device);
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void DestroyCLContext(OpenCLCtx* ctx)
|
||||||
|
{
|
||||||
|
ctx->~OpenCLCtx();
|
||||||
|
tracy_free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tracy
|
||||||
|
|
||||||
|
using TracyCLCtx = tracy::OpenCLCtx*;
|
||||||
|
|
||||||
|
#define TracyCLContext(context, device) tracy::CreateCLContext(context, device);
|
||||||
|
#define TracyCLDestroy(ctx) tracy::DestroyCLContext(ctx);
|
||||||
|
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
||||||
|
# define TracyCLNamedZone(ctx, varname, name, active) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
# define TracyCLNamedZoneC(ctx, varname, name, color, active) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
|
# define TracyCLZone(ctx, name) TracyCLNamedZoneS(ctx, __tracy_gpu_zone, name, TRACY_CALLSTACK, true)
|
||||||
|
# define TracyCLZoneC(ctx, name, color) TracyCLNamedZoneCS(ctx, __tracy_gpu_zone, name, color, TRACY_CALLSTACK, true)
|
||||||
|
#else
|
||||||
|
# define TracyCLNamedZone(ctx, varname, name, active) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__){ name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), active);
|
||||||
|
# define TracyCLNamedZoneC(ctx, varname, name, color, active) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__){ name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), active);
|
||||||
|
# define TracyCLZone(ctx, name) TracyCLNamedZone(ctx, __tracy_gpu_zone, name, true)
|
||||||
|
# define TracyCLZoneC(ctx, name, color) TracyCLNamedZoneC(ctx, __tracy_gpu_zone, name, color, true )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
# define TracyCLNamedZoneS(ctx, varname, name, depth, active) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__){ name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), depth, active);
|
||||||
|
# define TracyCLNamedZoneCS(ctx, varname, name, color, depth, active) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__){ name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::OpenCLCtxScope varname(ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), depth, active);
|
||||||
|
# define TracyCLZoneS(ctx, name, depth) TracyCLNamedZoneS(ctx, __tracy_gpu_zone, name, depth, true)
|
||||||
|
# define TracyCLZoneCS(ctx, name, color, depth) TracyCLNamedZoneCS(ctx, __tracy_gpu_zone, name, color, depth, true)
|
||||||
|
#else
|
||||||
|
#define TracyCLNamedZoneS(ctx, varname, name, depth, active) TracyCLNamedZone(ctx, varname, name, active)
|
||||||
|
#define TracyCLNamedZoneCS(ctx, varname, name, color, depth, active) TracyCLNamedZoneC(ctx, varname, name, color, active)
|
||||||
|
#define TracyCLZoneS(ctx, name, depth) TracyCLZone(ctx, name)
|
||||||
|
#define TracyCLZoneCS(ctx, name, color, depth) TracyCLZoneC(ctx, name, color)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TracyCLNamedZoneSetEvent(varname, event) varname.SetEvent(event)
|
||||||
|
#define TracyCLZoneSetEvent(event) __tracy_gpu_zone.SetEvent(event)
|
||||||
|
|
||||||
|
#define TracyCLCollect(ctx) ctx->Collect()
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,22 +1,23 @@
|
|||||||
#ifndef __TRACYOPENGL_HPP__
|
#ifndef __TRACYOPENGL_HPP__
|
||||||
#define __TRACYOPENGL_HPP__
|
#define __TRACYOPENGL_HPP__
|
||||||
|
|
||||||
|
#if !defined GL_TIMESTAMP && !defined GL_TIMESTAMP_EXT
|
||||||
|
# error "You must include OpenGL 3.2 headers before including TracyOpenGL.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined TRACY_ENABLE || defined __APPLE__
|
#if !defined TRACY_ENABLE || defined __APPLE__
|
||||||
|
|
||||||
#define TracyGpuContext
|
#define TracyGpuContext
|
||||||
#define TracyGpuContextName(x,y)
|
|
||||||
#define TracyGpuNamedZone(x,y,z)
|
#define TracyGpuNamedZone(x,y,z)
|
||||||
#define TracyGpuNamedZoneC(x,y,z,w)
|
#define TracyGpuNamedZoneC(x,y,z,w)
|
||||||
#define TracyGpuZone(x)
|
#define TracyGpuZone(x)
|
||||||
#define TracyGpuZoneC(x,y)
|
#define TracyGpuZoneC(x,y)
|
||||||
#define TracyGpuZoneTransient(x,y,z)
|
|
||||||
#define TracyGpuCollect
|
#define TracyGpuCollect
|
||||||
|
|
||||||
#define TracyGpuNamedZoneS(x,y,z,w)
|
#define TracyGpuNamedZoneS(x,y,z,w)
|
||||||
#define TracyGpuNamedZoneCS(x,y,z,w,a)
|
#define TracyGpuNamedZoneCS(x,y,z,w,a)
|
||||||
#define TracyGpuZoneS(x,y)
|
#define TracyGpuZoneS(x,y)
|
||||||
#define TracyGpuZoneCS(x,y,z)
|
#define TracyGpuZoneCS(x,y,z)
|
||||||
#define TracyGpuZoneTransientS(x,y,z,w)
|
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
@ -25,7 +26,7 @@ class GpuCtxScope
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GpuCtxScope( const SourceLocationData*, bool ) {}
|
GpuCtxScope( const SourceLocationData*, bool ) {}
|
||||||
GpuCtxScope( const SourceLocationData*, int32_t, bool ) {}
|
GpuCtxScope( const SourceLocationData*, int, bool ) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,10 +37,10 @@ public:
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "Tracy.hpp"
|
#include "Tracy.hpp"
|
||||||
#include "../client/TracyProfiler.hpp"
|
#include "client/TracyProfiler.hpp"
|
||||||
#include "../client/TracyCallstack.hpp"
|
#include "client/TracyCallstack.hpp"
|
||||||
#include "../common/TracyAlign.hpp"
|
#include "common/TracyAlign.hpp"
|
||||||
#include "../common/TracyAlloc.hpp"
|
#include "common/TracyAlloc.hpp"
|
||||||
|
|
||||||
#if !defined GL_TIMESTAMP && defined GL_TIMESTAMP_EXT
|
#if !defined GL_TIMESTAMP && defined GL_TIMESTAMP_EXT
|
||||||
# define GL_TIMESTAMP GL_TIMESTAMP_EXT
|
# define GL_TIMESTAMP GL_TIMESTAMP_EXT
|
||||||
@ -49,35 +50,30 @@ public:
|
|||||||
# define glQueryCounter glQueryCounterEXT
|
# define glQueryCounter glQueryCounterEXT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TracyGpuContext tracy::GetGpuCtx().ptr = (tracy::GpuCtx*)tracy::tracy_malloc( sizeof( tracy::GpuCtx ) ); new(tracy::GetGpuCtx().ptr) tracy::GpuCtx;
|
#define TracyGpuContext tracy::InitRPMallocThread(); tracy::GetGpuCtx().ptr = (tracy::GpuCtx*)tracy::tracy_malloc( sizeof( tracy::GpuCtx ) ); new(tracy::GetGpuCtx().ptr) tracy::GpuCtx;
|
||||||
#define TracyGpuContextName( name, size ) tracy::GetGpuCtx().ptr->Name( name, size );
|
|
||||||
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
||||||
# define TracyGpuNamedZone( varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );
|
# define TracyGpuNamedZone( varname, name, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
# define TracyGpuNamedZoneC( varname, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), TRACY_CALLSTACK, active );
|
# define TracyGpuNamedZoneC( varname, name, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), TRACY_CALLSTACK, active );
|
||||||
# define TracyGpuZone( name ) TracyGpuNamedZoneS( ___tracy_gpu_zone, name, TRACY_CALLSTACK, true )
|
# define TracyGpuZone( name ) TracyGpuNamedZoneS( ___tracy_gpu_zone, name, TRACY_CALLSTACK, true )
|
||||||
# define TracyGpuZoneC( name, color ) TracyGpuNamedZoneCS( ___tracy_gpu_zone, name, color, TRACY_CALLSTACK, true )
|
# define TracyGpuZoneC( name, color ) TracyGpuNamedZoneCS( ___tracy_gpu_zone, name, color, TRACY_CALLSTACK, true )
|
||||||
# define TracyGpuZoneTransient( varname, name, active ) tracy::GpuCtxScope varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), TRACY_CALLSTACK, active );
|
|
||||||
#else
|
#else
|
||||||
# define TracyGpuNamedZone( varname, name, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), active );
|
# define TracyGpuNamedZone( varname, name, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), active );
|
||||||
# define TracyGpuNamedZoneC( varname, name, color, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), active );
|
# define TracyGpuNamedZoneC( varname, name, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), active );
|
||||||
# define TracyGpuZone( name ) TracyGpuNamedZone( ___tracy_gpu_zone, name, true )
|
# define TracyGpuZone( name ) TracyGpuNamedZone( ___tracy_gpu_zone, name, true )
|
||||||
# define TracyGpuZoneC( name, color ) TracyGpuNamedZoneC( ___tracy_gpu_zone, name, color, true )
|
# define TracyGpuZoneC( name, color ) TracyGpuNamedZoneC( ___tracy_gpu_zone, name, color, true )
|
||||||
# define TracyGpuZoneTransient( varname, name, active ) tracy::GpuCtxScope varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), active );
|
|
||||||
#endif
|
#endif
|
||||||
#define TracyGpuCollect tracy::GetGpuCtx().ptr->Collect();
|
#define TracyGpuCollect tracy::GetGpuCtx().ptr->Collect();
|
||||||
|
|
||||||
#ifdef TRACY_HAS_CALLSTACK
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
# define TracyGpuNamedZoneS( varname, name, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), depth, active );
|
# define TracyGpuNamedZoneS( varname, name, depth, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), depth, active );
|
||||||
# define TracyGpuNamedZoneCS( varname, name, color, depth, active ) static constexpr tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,TracyLine) { name, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,TracyLine), depth, active );
|
# define TracyGpuNamedZoneCS( varname, name, color, depth, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), depth, active );
|
||||||
# define TracyGpuZoneS( name, depth ) TracyGpuNamedZoneS( ___tracy_gpu_zone, name, depth, true )
|
# define TracyGpuZoneS( name, depth ) TracyGpuNamedZoneS( ___tracy_gpu_zone, name, depth, true )
|
||||||
# define TracyGpuZoneCS( name, color, depth ) TracyGpuNamedZoneCS( ___tracy_gpu_zone, name, color, depth, true )
|
# define TracyGpuZoneCS( name, color, depth ) TracyGpuNamedZoneCS( ___tracy_gpu_zone, name, color, depth, true )
|
||||||
# define TracyGpuZoneTransientS( varname, name, depth, active ) tracy::GpuCtxScope varname( TracyLine, TracyFile, strlen( TracyFile ), TracyFunction, strlen( TracyFunction ), name, strlen( name ), depth, active );
|
|
||||||
#else
|
#else
|
||||||
# define TracyGpuNamedZoneS( varname, name, depth, active ) TracyGpuNamedZone( varname, name, active )
|
# define TracyGpuNamedZoneS( varname, name, depth, active ) TracyGpuNamedZone( varname, name, active )
|
||||||
# define TracyGpuNamedZoneCS( varname, name, color, depth, active ) TracyGpuNamedZoneC( varname, name, color, active )
|
# define TracyGpuNamedZoneCS( varname, name, color, depth, active ) TracyGpuNamedZoneC( varname, name, color, active )
|
||||||
# define TracyGpuZoneS( name, depth ) TracyGpuZone( name )
|
# define TracyGpuZoneS( name, depth ) TracyGpuZone( name )
|
||||||
# define TracyGpuZoneCS( name, color, depth ) TracyGpuZoneC( name, color )
|
# define TracyGpuZoneCS( name, color, depth ) TracyGpuZoneC( name, color )
|
||||||
# define TracyGpuZoneTransientS( varname, name, depth, active ) TracyGpuZoneTransient( varname, name, active )
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
@ -114,7 +110,7 @@ public:
|
|||||||
MemWrite( &item->gpuNewContext.thread, thread );
|
MemWrite( &item->gpuNewContext.thread, thread );
|
||||||
MemWrite( &item->gpuNewContext.period, period );
|
MemWrite( &item->gpuNewContext.period, period );
|
||||||
MemWrite( &item->gpuNewContext.context, m_context );
|
MemWrite( &item->gpuNewContext.context, m_context );
|
||||||
MemWrite( &item->gpuNewContext.flags, uint8_t( 0 ) );
|
MemWrite( &item->gpuNewContext.accuracyBits, (uint8_t)bits );
|
||||||
MemWrite( &item->gpuNewContext.type, GpuContextType::OpenGl );
|
MemWrite( &item->gpuNewContext.type, GpuContextType::OpenGl );
|
||||||
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
@ -124,21 +120,6 @@ public:
|
|||||||
TracyLfqCommit;
|
TracyLfqCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Name( const char* name, uint16_t len )
|
|
||||||
{
|
|
||||||
auto ptr = (char*)tracy_malloc( len );
|
|
||||||
memcpy( ptr, name, len );
|
|
||||||
|
|
||||||
TracyLfqPrepare( QueueType::GpuContextName );
|
|
||||||
MemWrite( &item->gpuContextNameFat.context, m_context );
|
|
||||||
MemWrite( &item->gpuContextNameFat.ptr, (uint64_t)ptr );
|
|
||||||
MemWrite( &item->gpuContextNameFat.size, len );
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
GetProfiler().DeferItem( *item );
|
|
||||||
#endif
|
|
||||||
TracyLfqCommit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Collect()
|
void Collect()
|
||||||
{
|
{
|
||||||
ZoneScopedC( Color::Red4 );
|
ZoneScopedC( Color::Red4 );
|
||||||
@ -215,14 +196,14 @@ public:
|
|||||||
|
|
||||||
TracyLfqPrepare( QueueType::GpuZoneBegin );
|
TracyLfqPrepare( QueueType::GpuZoneBegin );
|
||||||
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
|
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
|
||||||
memset( &item->gpuZoneBegin.thread, 0, sizeof( item->gpuZoneBegin.thread ) );
|
memset( &item->gpuZoneBegin.thread, 0, sizeof( item->gpuZoneBegin.thread ) );
|
||||||
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
|
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
|
||||||
MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );
|
MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );
|
||||||
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
|
|
||||||
TracyLfqCommit;
|
TracyLfqCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
tracy_force_inline GpuCtxScope( const SourceLocationData* srcloc, int32_t depth, bool is_active )
|
tracy_force_inline GpuCtxScope( const SourceLocationData* srcloc, int depth, bool is_active )
|
||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
: m_active( is_active && GetProfiler().IsConnected() )
|
: m_active( is_active && GetProfiler().IsConnected() )
|
||||||
#else
|
#else
|
||||||
@ -234,69 +215,16 @@ public:
|
|||||||
const auto queryId = GetGpuCtx().ptr->NextQueryId();
|
const auto queryId = GetGpuCtx().ptr->NextQueryId();
|
||||||
glQueryCounter( GetGpuCtx().ptr->TranslateOpenGlQueryId( queryId ), GL_TIMESTAMP );
|
glQueryCounter( GetGpuCtx().ptr->TranslateOpenGlQueryId( queryId ), GL_TIMESTAMP );
|
||||||
|
|
||||||
#ifdef TRACY_FIBERS
|
const auto thread = GetThreadHandle();
|
||||||
TracyLfqPrepare( QueueType::GpuZoneBegin );
|
|
||||||
memset( &item->gpuZoneBegin.thread, 0, sizeof( item->gpuZoneBegin.thread ) );
|
|
||||||
#else
|
|
||||||
GetProfiler().SendCallstack( depth );
|
|
||||||
TracyLfqPrepare( QueueType::GpuZoneBeginCallstack );
|
TracyLfqPrepare( QueueType::GpuZoneBeginCallstack );
|
||||||
MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );
|
|
||||||
#endif
|
|
||||||
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
|
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
|
||||||
|
MemWrite( &item->gpuZoneBegin.thread, thread );
|
||||||
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
|
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
|
||||||
MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );
|
MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );
|
||||||
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
|
|
||||||
TracyLfqCommit;
|
TracyLfqCommit;
|
||||||
}
|
|
||||||
|
|
||||||
tracy_force_inline GpuCtxScope( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, bool is_active )
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
: m_active( is_active && GetProfiler().IsConnected() )
|
|
||||||
#else
|
|
||||||
: m_active( is_active )
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if( !m_active ) return;
|
|
||||||
|
|
||||||
const auto queryId = GetGpuCtx().ptr->NextQueryId();
|
|
||||||
glQueryCounter( GetGpuCtx().ptr->TranslateOpenGlQueryId( queryId ), GL_TIMESTAMP );
|
|
||||||
|
|
||||||
TracyLfqPrepare( QueueType::GpuZoneBeginAllocSrcLoc );
|
|
||||||
const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );
|
|
||||||
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
|
|
||||||
memset( &item->gpuZoneBegin.thread, 0, sizeof( item->gpuZoneBegin.thread ) );
|
|
||||||
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
|
|
||||||
MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );
|
|
||||||
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
|
|
||||||
TracyLfqCommit;
|
|
||||||
}
|
|
||||||
|
|
||||||
tracy_force_inline GpuCtxScope( uint32_t line, const char* source, size_t sourceSz, const char* function, size_t functionSz, const char* name, size_t nameSz, int32_t depth, bool is_active )
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
|
||||||
: m_active( is_active && GetProfiler().IsConnected() )
|
|
||||||
#else
|
|
||||||
: m_active( is_active )
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if( !m_active ) return;
|
|
||||||
|
|
||||||
const auto queryId = GetGpuCtx().ptr->NextQueryId();
|
|
||||||
glQueryCounter( GetGpuCtx().ptr->TranslateOpenGlQueryId( queryId ), GL_TIMESTAMP );
|
|
||||||
|
|
||||||
#ifdef TRACY_FIBERS
|
|
||||||
TracyLfqPrepare( QueueType::GpuZoneBeginAllocSrcLoc );
|
|
||||||
memset( &item->gpuZoneBegin.thread, 0, sizeof( item->gpuZoneBegin.thread ) );
|
|
||||||
#else
|
|
||||||
GetProfiler().SendCallstack( depth );
|
GetProfiler().SendCallstack( depth );
|
||||||
TracyLfqPrepare( QueueType::GpuZoneBeginAllocSrcLocCallstack );
|
|
||||||
MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );
|
|
||||||
#endif
|
|
||||||
const auto srcloc = Profiler::AllocSourceLocation( line, source, sourceSz, function, functionSz, name, nameSz );
|
|
||||||
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
|
|
||||||
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
|
|
||||||
MemWrite( &item->gpuZoneBegin.context, GetGpuCtx().ptr->GetId() );
|
|
||||||
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
|
|
||||||
TracyLfqCommit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tracy_force_inline ~GpuCtxScope()
|
tracy_force_inline ~GpuCtxScope()
|
321
TracyVulkan.hpp
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
#ifndef __TRACYVULKAN_HPP__
|
||||||
|
#define __TRACYVULKAN_HPP__
|
||||||
|
|
||||||
|
#if !defined TRACY_ENABLE
|
||||||
|
|
||||||
|
#define TracyVkContext(x,y,z,w) nullptr
|
||||||
|
#define TracyVkDestroy(x)
|
||||||
|
#define TracyVkNamedZone(c,x,y,z,w)
|
||||||
|
#define TracyVkNamedZoneC(c,x,y,z,w,a)
|
||||||
|
#define TracyVkZone(c,x,y)
|
||||||
|
#define TracyVkZoneC(c,x,y,z)
|
||||||
|
#define TracyVkCollect(c,x)
|
||||||
|
|
||||||
|
#define TracyVkNamedZoneS(c,x,y,z,w,a)
|
||||||
|
#define TracyVkNamedZoneCS(c,x,y,z,w,v,a)
|
||||||
|
#define TracyVkZoneS(c,x,y,z)
|
||||||
|
#define TracyVkZoneCS(c,x,y,z,w)
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
class VkCtxScope {};
|
||||||
|
}
|
||||||
|
|
||||||
|
using TracyVkCtx = void*;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#include "Tracy.hpp"
|
||||||
|
#include "client/TracyProfiler.hpp"
|
||||||
|
#include "client/TracyCallstack.hpp"
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
class VkCtx
|
||||||
|
{
|
||||||
|
friend class VkCtxScope;
|
||||||
|
|
||||||
|
enum { QueryCount = 64 * 1024 };
|
||||||
|
|
||||||
|
public:
|
||||||
|
VkCtx( VkPhysicalDevice physdev, VkDevice device, VkQueue queue, VkCommandBuffer cmdbuf )
|
||||||
|
: m_device( device )
|
||||||
|
, m_context( GetGpuCtxCounter().fetch_add( 1, std::memory_order_relaxed ) )
|
||||||
|
, m_head( 0 )
|
||||||
|
, m_tail( 0 )
|
||||||
|
, m_oldCnt( 0 )
|
||||||
|
, m_queryCount( QueryCount )
|
||||||
|
{
|
||||||
|
assert( m_context != 255 );
|
||||||
|
|
||||||
|
VkPhysicalDeviceProperties prop;
|
||||||
|
vkGetPhysicalDeviceProperties( physdev, &prop );
|
||||||
|
const float period = prop.limits.timestampPeriod;
|
||||||
|
|
||||||
|
VkQueryPoolCreateInfo poolInfo = {};
|
||||||
|
poolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
|
||||||
|
poolInfo.queryCount = m_queryCount;
|
||||||
|
poolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
|
||||||
|
while( vkCreateQueryPool( device, &poolInfo, nullptr, &m_query ) != VK_SUCCESS )
|
||||||
|
{
|
||||||
|
m_queryCount /= 2;
|
||||||
|
poolInfo.queryCount = m_queryCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo beginInfo = {};
|
||||||
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
|
|
||||||
|
VkSubmitInfo submitInfo = {};
|
||||||
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &cmdbuf;
|
||||||
|
|
||||||
|
vkBeginCommandBuffer( cmdbuf, &beginInfo );
|
||||||
|
vkCmdResetQueryPool( cmdbuf, m_query, 0, m_queryCount );
|
||||||
|
vkEndCommandBuffer( cmdbuf );
|
||||||
|
vkQueueSubmit( queue, 1, &submitInfo, VK_NULL_HANDLE );
|
||||||
|
vkQueueWaitIdle( queue );
|
||||||
|
|
||||||
|
vkBeginCommandBuffer( cmdbuf, &beginInfo );
|
||||||
|
vkCmdWriteTimestamp( cmdbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, m_query, 0 );
|
||||||
|
vkEndCommandBuffer( cmdbuf );
|
||||||
|
vkQueueSubmit( queue, 1, &submitInfo, VK_NULL_HANDLE );
|
||||||
|
vkQueueWaitIdle( queue );
|
||||||
|
|
||||||
|
int64_t tcpu = Profiler::GetTime();
|
||||||
|
int64_t tgpu;
|
||||||
|
vkGetQueryPoolResults( device, m_query, 0, 1, sizeof( tgpu ), &tgpu, sizeof( tgpu ), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT );
|
||||||
|
|
||||||
|
vkBeginCommandBuffer( cmdbuf, &beginInfo );
|
||||||
|
vkCmdResetQueryPool( cmdbuf, m_query, 0, 1 );
|
||||||
|
vkEndCommandBuffer( cmdbuf );
|
||||||
|
vkQueueSubmit( queue, 1, &submitInfo, VK_NULL_HANDLE );
|
||||||
|
vkQueueWaitIdle( queue );
|
||||||
|
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite( &item->hdr.type, QueueType::GpuNewContext );
|
||||||
|
MemWrite( &item->gpuNewContext.cpuTime, tcpu );
|
||||||
|
MemWrite( &item->gpuNewContext.gpuTime, tgpu );
|
||||||
|
memset( &item->gpuNewContext.thread, 0, sizeof( item->gpuNewContext.thread ) );
|
||||||
|
MemWrite( &item->gpuNewContext.period, period );
|
||||||
|
MemWrite( &item->gpuNewContext.context, m_context );
|
||||||
|
MemWrite( &item->gpuNewContext.accuracyBits, uint8_t( 0 ) );
|
||||||
|
MemWrite( &item->gpuNewContext.type, GpuContextType::Vulkan );
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
GetProfiler().DeferItem( *item );
|
||||||
|
#endif
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
|
||||||
|
m_res = (int64_t*)tracy_malloc( sizeof( int64_t ) * m_queryCount );
|
||||||
|
}
|
||||||
|
|
||||||
|
~VkCtx()
|
||||||
|
{
|
||||||
|
tracy_free( m_res );
|
||||||
|
vkDestroyQueryPool( m_device, m_query, nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Collect( VkCommandBuffer cmdbuf )
|
||||||
|
{
|
||||||
|
ZoneScopedC( Color::Red4 );
|
||||||
|
|
||||||
|
if( m_tail == m_head ) return;
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() )
|
||||||
|
{
|
||||||
|
vkCmdResetQueryPool( cmdbuf, m_query, 0, m_queryCount );
|
||||||
|
m_head = m_tail = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int cnt;
|
||||||
|
if( m_oldCnt != 0 )
|
||||||
|
{
|
||||||
|
cnt = m_oldCnt;
|
||||||
|
m_oldCnt = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cnt = m_head < m_tail ? m_queryCount - m_tail : m_head - m_tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vkGetQueryPoolResults( m_device, m_query, m_tail, cnt, sizeof( int64_t ) * m_queryCount, m_res, sizeof( int64_t ), VK_QUERY_RESULT_64_BIT ) == VK_NOT_READY )
|
||||||
|
{
|
||||||
|
m_oldCnt = cnt;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( unsigned int idx=0; idx<cnt; idx++ )
|
||||||
|
{
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite( &item->hdr.type, QueueType::GpuTime );
|
||||||
|
MemWrite( &item->gpuTime.gpuTime, m_res[idx] );
|
||||||
|
MemWrite( &item->gpuTime.queryId, uint16_t( m_tail + idx ) );
|
||||||
|
MemWrite( &item->gpuTime.context, m_context );
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
vkCmdResetQueryPool( cmdbuf, m_query, m_tail, cnt );
|
||||||
|
|
||||||
|
m_tail += cnt;
|
||||||
|
if( m_tail == m_queryCount ) m_tail = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
tracy_force_inline unsigned int NextQueryId()
|
||||||
|
{
|
||||||
|
const auto id = m_head;
|
||||||
|
m_head = ( m_head + 1 ) % m_queryCount;
|
||||||
|
assert( m_head != m_tail );
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline uint8_t GetId() const
|
||||||
|
{
|
||||||
|
return m_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDevice m_device;
|
||||||
|
VkQueryPool m_query;
|
||||||
|
uint8_t m_context;
|
||||||
|
|
||||||
|
unsigned int m_head;
|
||||||
|
unsigned int m_tail;
|
||||||
|
unsigned int m_oldCnt;
|
||||||
|
unsigned int m_queryCount;
|
||||||
|
|
||||||
|
int64_t* m_res;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VkCtxScope
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
tracy_force_inline VkCtxScope( VkCtx* ctx, const SourceLocationData* srcloc, VkCommandBuffer cmdbuf, bool is_active )
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
: m_active( is_active && GetProfiler().IsConnected() )
|
||||||
|
#else
|
||||||
|
: m_active( is_active )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if( !m_active ) return;
|
||||||
|
m_cmdbuf = cmdbuf;
|
||||||
|
m_ctx = ctx;
|
||||||
|
|
||||||
|
const auto queryId = ctx->NextQueryId();
|
||||||
|
vkCmdWriteTimestamp( cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->m_query, queryId );
|
||||||
|
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite( &item->hdr.type, QueueType::GpuZoneBeginSerial );
|
||||||
|
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
|
||||||
|
MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );
|
||||||
|
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
|
||||||
|
MemWrite( &item->gpuZoneBegin.context, ctx->GetId() );
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline VkCtxScope( VkCtx* ctx, const SourceLocationData* srcloc, VkCommandBuffer cmdbuf, int depth, bool is_active )
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
: m_active( is_active && GetProfiler().IsConnected() )
|
||||||
|
#else
|
||||||
|
: m_active( is_active )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if( !m_active ) return;
|
||||||
|
m_cmdbuf = cmdbuf;
|
||||||
|
m_ctx = ctx;
|
||||||
|
|
||||||
|
const auto queryId = ctx->NextQueryId();
|
||||||
|
vkCmdWriteTimestamp( cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->m_query, queryId );
|
||||||
|
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite( &item->hdr.type, QueueType::GpuZoneBeginCallstackSerial );
|
||||||
|
MemWrite( &item->gpuZoneBegin.cpuTime, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->gpuZoneBegin.srcloc, (uint64_t)srcloc );
|
||||||
|
MemWrite( &item->gpuZoneBegin.thread, GetThreadHandle() );
|
||||||
|
MemWrite( &item->gpuZoneBegin.queryId, uint16_t( queryId ) );
|
||||||
|
MemWrite( &item->gpuZoneBegin.context, ctx->GetId() );
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
|
||||||
|
GetProfiler().SendCallstack( depth );
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline ~VkCtxScope()
|
||||||
|
{
|
||||||
|
if( !m_active ) return;
|
||||||
|
|
||||||
|
const auto queryId = m_ctx->NextQueryId();
|
||||||
|
vkCmdWriteTimestamp( m_cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, m_ctx->m_query, queryId );
|
||||||
|
|
||||||
|
auto item = Profiler::QueueSerial();
|
||||||
|
MemWrite( &item->hdr.type, QueueType::GpuZoneEndSerial );
|
||||||
|
MemWrite( &item->gpuZoneEnd.cpuTime, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->gpuZoneEnd.thread, GetThreadHandle() );
|
||||||
|
MemWrite( &item->gpuZoneEnd.queryId, uint16_t( queryId ) );
|
||||||
|
MemWrite( &item->gpuZoneEnd.context, m_ctx->GetId() );
|
||||||
|
Profiler::QueueSerialFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const bool m_active;
|
||||||
|
|
||||||
|
VkCommandBuffer m_cmdbuf;
|
||||||
|
VkCtx* m_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline VkCtx* CreateVkContext( VkPhysicalDevice physdev, VkDevice device, VkQueue queue, VkCommandBuffer cmdbuf )
|
||||||
|
{
|
||||||
|
InitRPMallocThread();
|
||||||
|
auto ctx = (VkCtx*)tracy_malloc( sizeof( VkCtx ) );
|
||||||
|
new(ctx) VkCtx( physdev, device, queue, cmdbuf );
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void DestroyVkContext( VkCtx* ctx )
|
||||||
|
{
|
||||||
|
ctx->~VkCtx();
|
||||||
|
tracy_free( ctx );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using TracyVkCtx = tracy::VkCtx*;
|
||||||
|
|
||||||
|
#define TracyVkContext( physdev, device, queue, cmdbuf ) tracy::CreateVkContext( physdev, device, queue, cmdbuf );
|
||||||
|
#define TracyVkDestroy( ctx ) tracy::DestroyVkContext( ctx );
|
||||||
|
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
||||||
|
# define TracyVkNamedZone( ctx, varname, cmdbuf, name, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf, TRACY_CALLSTACK, active );
|
||||||
|
# define TracyVkNamedZoneC( ctx, varname, cmdbuf, name, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf, TRACY_CALLSTACK, active );
|
||||||
|
# define TracyVkZone( ctx, cmdbuf, name ) TracyVkNamedZoneS( ctx, ___tracy_gpu_zone, cmdbuf, name, TRACY_CALLSTACK, true )
|
||||||
|
# define TracyVkZoneC( ctx, cmdbuf, name, color ) TracyVkNamedZoneCS( ctx, ___tracy_gpu_zone, cmdbuf, name, color, TRACY_CALLSTACK, true )
|
||||||
|
#else
|
||||||
|
# define TracyVkNamedZone( ctx, varname, cmdbuf, name, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf, active );
|
||||||
|
# define TracyVkNamedZoneC( ctx, varname, cmdbuf, name, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf, active );
|
||||||
|
# define TracyVkZone( ctx, cmdbuf, name ) TracyVkNamedZone( ctx, ___tracy_gpu_zone, cmdbuf, name, true )
|
||||||
|
# define TracyVkZoneC( ctx, cmdbuf, name, color ) TracyVkNamedZoneC( ctx, ___tracy_gpu_zone, cmdbuf, name, color, true )
|
||||||
|
#endif
|
||||||
|
#define TracyVkCollect( ctx, cmdbuf ) ctx->Collect( cmdbuf );
|
||||||
|
|
||||||
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
# define TracyVkNamedZoneS( ctx, varname, cmdbuf, name, depth, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf, depth, active );
|
||||||
|
# define TracyVkNamedZoneCS( ctx, varname, cmdbuf, name, color, depth, active ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::VkCtxScope varname( ctx, &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf, depth, active );
|
||||||
|
# define TracyVkZoneS( ctx, cmdbuf, name, depth ) TracyVkNamedZoneS( ctx, ___tracy_gpu_zone, cmdbuf, name, depth, true )
|
||||||
|
# define TracyVkZoneCS( ctx, cmdbuf, name, color, depth ) TracyVkNamedZoneCS( ctx, ___tracy_gpu_zone, cmdbuf, name, color, depth, true )
|
||||||
|
#else
|
||||||
|
# define TracyVkNamedZoneS( ctx, varname, cmdbuf, name, depth, active ) TracyVkNamedZone( ctx, varname, cmdbuf, name, active )
|
||||||
|
# define TracyVkNamedZoneCS( ctx, varname, cmdbuf, name, color, depth, active ) TracyVkNamedZoneC( ctx, varname, cmdbuf, name, color, active )
|
||||||
|
# define TracyVkZoneS( ctx, cmdbuf, name, depth ) TracyVkZone( ctx, cmdbuf, name )
|
||||||
|
# define TracyVkZoneCS( ctx, cmdbuf, name, color, depth ) TracyVkZoneC( ctx, cmdbuf, name, color )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,28 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
|
||||||
|
|
||||||
option(NO_ISA_EXTENSIONS "Disable ISA extensions (don't pass -march=native or -mcpu=native to the compiler)" OFF)
|
|
||||||
option(NO_STATISTICS "Disable calculation of statistics" ON)
|
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/version.cmake)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
|
||||||
|
|
||||||
project(
|
|
||||||
tracy-capture
|
|
||||||
LANGUAGES C CXX
|
|
||||||
VERSION ${TRACY_VERSION_STRING}
|
|
||||||
)
|
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/config.cmake)
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake)
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake)
|
|
||||||
|
|
||||||
set(PROGRAM_FILES
|
|
||||||
src/capture.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${PROGRAM_FILES} ${COMMON_FILES} ${SERVER_FILES})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE TracyServer TracyGetOpt)
|
|
||||||
set_property(DIRECTORY ${CMAKE_CURRENT_LIST_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME})
|
|
||||||
|
|
||||||
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
12
capture/build/unix/Makefile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
all: debug
|
||||||
|
|
||||||
|
debug:
|
||||||
|
@+make -f debug.mk all
|
||||||
|
|
||||||
|
release:
|
||||||
|
@+make -f release.mk all
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@+make -f build.mk clean
|
||||||
|
|
||||||
|
.PHONY: all clean debug release
|
60
capture/build/unix/build.mk
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
CFLAGS +=
|
||||||
|
CXXFLAGS := $(CFLAGS) -std=gnu++17
|
||||||
|
DEFINES += -DTRACY_NO_STATISTICS
|
||||||
|
INCLUDES := $(shell pkg-config --cflags capstone)
|
||||||
|
LIBS := $(shell pkg-config --libs capstone) -lpthread
|
||||||
|
PROJECT := capture
|
||||||
|
IMAGE := $(PROJECT)-$(BUILD)
|
||||||
|
|
||||||
|
FILTER :=
|
||||||
|
|
||||||
|
BASE := $(shell egrep 'ClCompile.*cpp"' ../win32/$(PROJECT).vcxproj | sed -e 's/.*\"\(.*\)\".*/\1/' | sed -e 's@\\@/@g')
|
||||||
|
BASE2 := $(shell egrep 'ClCompile.*c"' ../win32/$(PROJECT).vcxproj | sed -e 's/.*\"\(.*\)\".*/\1/' | sed -e 's@\\@/@g')
|
||||||
|
|
||||||
|
SRC := $(filter-out $(FILTER),$(BASE))
|
||||||
|
SRC2 := $(filter-out $(FILTER),$(BASE2))
|
||||||
|
|
||||||
|
TBB := $(shell ld -ltbb -o /dev/null 2>/dev/null; echo $$?)
|
||||||
|
ifeq ($(TBB),0)
|
||||||
|
LIBS += -ltbb
|
||||||
|
endif
|
||||||
|
|
||||||
|
OBJDIRBASE := obj/$(BUILD)
|
||||||
|
OBJDIR := $(OBJDIRBASE)/o/o/o
|
||||||
|
|
||||||
|
OBJ := $(addprefix $(OBJDIR)/,$(SRC:%.cpp=%.o))
|
||||||
|
OBJ2 := $(addprefix $(OBJDIR)/,$(SRC2:%.c=%.o))
|
||||||
|
|
||||||
|
all: $(IMAGE)
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp
|
||||||
|
$(CXX) -c $(INCLUDES) $(CXXFLAGS) $(DEFINES) $< -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.d : %.cpp
|
||||||
|
@echo Resolving dependencies of $<
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
@$(CXX) -MM $(INCLUDES) $(CXXFLAGS) $(DEFINES) $< > $@.$$$$; \
|
||||||
|
sed 's,.*\.o[ :]*,$(OBJDIR)/$(<:.cpp=.o) $@ : ,g' < $@.$$$$ > $@; \
|
||||||
|
rm -f $@.$$$$
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.d : %.c
|
||||||
|
@echo Resolving dependencies of $<
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
@$(CC) -MM $(INCLUDES) $(CFLAGS) $(DEFINES) $< > $@.$$$$; \
|
||||||
|
sed 's,.*\.o[ :]*,$(OBJDIR)/$(<:.c=.o) $@ : ,g' < $@.$$$$ > $@; \
|
||||||
|
rm -f $@.$$$$
|
||||||
|
|
||||||
|
$(IMAGE): $(OBJ) $(OBJ2)
|
||||||
|
$(CXX) $(CXXFLAGS) $(DEFINES) $(OBJ) $(OBJ2) $(LIBS) -o $@
|
||||||
|
|
||||||
|
ifneq "$(MAKECMDGOALS)" "clean"
|
||||||
|
-include $(addprefix $(OBJDIR)/,$(SRC:.cpp=.d)) $(addprefix $(OBJDIR)/,$(SRC2:.c=.d))
|
||||||
|
endif
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJDIRBASE) $(IMAGE)*
|
||||||
|
|
||||||
|
.PHONY: clean all
|
11
capture/build/unix/debug.mk
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
ARCH := $(shell uname -m)
|
||||||
|
|
||||||
|
CFLAGS := -g3 -Wall
|
||||||
|
DEFINES := -DDEBUG
|
||||||
|
BUILD := debug
|
||||||
|
|
||||||
|
ifeq ($(ARCH),x86_64)
|
||||||
|
CFLAGS += -msse4.1
|
||||||
|
endif
|
||||||
|
|
||||||
|
include build.mk
|
7
capture/build/unix/release.mk
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
ARCH := $(shell uname -m)
|
||||||
|
|
||||||
|
CFLAGS := -O3 -s -march=native
|
||||||
|
DEFINES := -DNDEBUG
|
||||||
|
BUILD := release
|
||||||
|
|
||||||
|
include build.mk
|
25
capture/build/win32/capture.sln
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.27428.2002
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "capture", "capture.vcxproj", "{447D58BF-94CD-4469-BB90-549C05D03E00}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{447D58BF-94CD-4469-BB90-549C05D03E00}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{447D58BF-94CD-4469-BB90-549C05D03E00}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{447D58BF-94CD-4469-BB90-549C05D03E00}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{447D58BF-94CD-4469-BB90-549C05D03E00}.Release|x64.Build.0 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {3E51386C-43EA-44AC-9F24-AFAFE4D63ADE}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
235
capture/build/win32/capture.vcxproj
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{447D58BF-94CD-4469-BB90-549C05D03E00}</ProjectGuid>
|
||||||
|
<RootNamespace>capture</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
<VcpkgTriplet>x64-windows-static</VcpkgTriplet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup />
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<PreprocessorDefinitions>TRACY_NO_STATISTICS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32_LEAN_AND_MEAN;NOMINMAX;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||||
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\vcpkg\vcpkg\installed\x64-windows-static\include</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>ws2_32.lib;capstone.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\vcpkg\vcpkg\installed\x64-windows-static\debug\lib</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<PreprocessorDefinitions>TRACY_NO_STATISTICS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;WIN32_LEAN_AND_MEAN;NOMINMAX;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||||
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\vcpkg\vcpkg\installed\x64-windows-static\include</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>ws2_32.lib;capstone.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\vcpkg\vcpkg\installed\x64-windows-static\lib</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\common\TracySocket.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\common\TracySystem.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\common\tracy_lz4.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\common\tracy_lz4hc.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\server\TracyMemory.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\server\TracyMmap.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\server\TracyPrint.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\server\TracyTaskDispatch.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\server\TracyTextureCompression.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\server\TracyThreadCompress.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\server\TracyWorker.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\debug.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\entropy_common.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\error_private.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\fse_compress.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\fse_decompress.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\hist.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\huf_compress.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\huf_decompress.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\pool.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\threading.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\xxhash.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstdmt_compress.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_common.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_compress.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_compress_literals.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_compress_sequences.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_compress_superblock.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_ddict.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_decompress.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_decompress_block.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_double_fast.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_fast.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_lazy.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_ldm.c" />
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_opt.c" />
|
||||||
|
<ClCompile Include="..\..\src\capture.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\getopt.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\common\TracyAlign.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\common\TracyAlloc.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\common\TracyColor.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\common\TracyForceInline.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\common\TracyProtocol.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\common\TracyQueue.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\common\TracySocket.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\common\TracySystem.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\common\tracy_lz4.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\common\tracy_lz4hc.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyCharUtil.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyEvent.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyFileRead.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyFileWrite.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyMemory.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyMmap.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyPopcnt.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyPrint.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracySlab.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyTaskDispatch.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyTextureCompression.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyThreadCompress.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyVector.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\server\TracyWorker.hpp" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\bitstream.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\compiler.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\cpu.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\debug.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\error_private.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\fse.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\hist.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\huf.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\mem.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\pool.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\threading.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\xxhash.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstdmt_compress.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_compress_internal.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_compress_literals.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_compress_sequences.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_compress_superblock.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_cwksp.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_ddict.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_decompress_block.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_decompress_internal.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_double_fast.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_errors.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_fast.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_internal.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_lazy.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_ldm.h" />
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_opt.h" />
|
||||||
|
<ClInclude Include="..\..\src\getopt.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
297
capture/build/win32/capture.vcxproj.filters
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="src">
|
||||||
|
<UniqueIdentifier>{729c80ee-4d26-4a5e-8f1f-6c075783eb56}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="server">
|
||||||
|
<UniqueIdentifier>{cf23ef7b-7694-4154-830b-00cf053350ea}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="common">
|
||||||
|
<UniqueIdentifier>{e39d3623-47cd-4752-8da9-3ea324f964c1}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="zstd">
|
||||||
|
<UniqueIdentifier>{043ecb94-f240-4986-94b0-bc5bbd415a82}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\common\tracy_lz4.cpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\common\TracySocket.cpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\common\TracySystem.cpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\server\TracyMemory.cpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\server\TracyWorker.cpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\capture.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\getopt.c">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\common\tracy_lz4hc.cpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\server\TracyPrint.cpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\server\TracyThreadCompress.cpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\server\TracyTaskDispatch.cpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\debug.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\entropy_common.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\error_private.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\fse_compress.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\fse_decompress.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\hist.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\huf_compress.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\huf_decompress.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\pool.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\threading.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\xxhash.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_common.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_compress.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_compress_literals.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_compress_sequences.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_compress_superblock.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_ddict.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_decompress.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_decompress_block.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_double_fast.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_fast.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_lazy.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_ldm.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstd_opt.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\zstd\zstdmt_compress.c">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\server\TracyMmap.cpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\server\TracyTextureCompression.cpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\common\tracy_lz4.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\common\TracyAlloc.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\common\TracyColor.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\common\TracyForceInline.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\common\TracyProtocol.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\common\TracyQueue.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\common\TracySocket.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\common\TracySystem.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyCharUtil.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyEvent.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyFileWrite.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyMemory.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyPopcnt.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracySlab.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyVector.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyWorker.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\getopt.h">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\common\TracyAlign.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\common\tracy_lz4hc.hpp">
|
||||||
|
<Filter>common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyPrint.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyThreadCompress.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyTaskDispatch.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\bitstream.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\compiler.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\cpu.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\debug.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\error_private.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\fse.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\hist.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\huf.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\mem.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\pool.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\threading.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\xxhash.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_compress_internal.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_compress_literals.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_compress_sequences.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_compress_superblock.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_cwksp.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_ddict.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_decompress_block.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_decompress_internal.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_double_fast.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_errors.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_fast.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_internal.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_lazy.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_ldm.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstd_opt.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\zstd\zstdmt_compress.h">
|
||||||
|
<Filter>zstd</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyFileRead.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyMmap.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\server\TracyTextureCompression.hpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -1,98 +1,33 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <io.h>
|
|
||||||
#else
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include "../../public/common/TracyProtocol.hpp"
|
#include "../../common/TracyProtocol.hpp"
|
||||||
#include "../../public/common/TracyStackFrames.hpp"
|
|
||||||
#include "../../server/TracyFileWrite.hpp"
|
#include "../../server/TracyFileWrite.hpp"
|
||||||
#include "../../server/TracyMemory.hpp"
|
#include "../../server/TracyMemory.hpp"
|
||||||
#include "../../server/TracyPrint.hpp"
|
#include "../../server/TracyPrint.hpp"
|
||||||
#include "../../server/TracySysUtil.hpp"
|
|
||||||
#include "../../server/TracyWorker.hpp"
|
#include "../../server/TracyWorker.hpp"
|
||||||
|
#include "getopt.h"
|
||||||
#ifdef _WIN32
|
|
||||||
# include "../../getopt/getopt.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// This atomic is written by a signal handler (SigInt). Traditionally that would
|
bool disconnect = false;
|
||||||
// have had to be `volatile sig_atomic_t`, and annoyingly, `bool` was
|
|
||||||
// technically not allowed there, even though in practice it would work.
|
|
||||||
// The good thing with C++11 atomics is that we can use atomic<bool> instead
|
|
||||||
// here and be on the actually supported path.
|
|
||||||
static std::atomic<bool> s_disconnect { false };
|
|
||||||
|
|
||||||
void SigInt( int )
|
void SigInt( int )
|
||||||
{
|
{
|
||||||
// Relaxed order is closest to a traditional `volatile` write.
|
disconnect = true;
|
||||||
// We don't need stronger ordering since this signal handler doesn't do
|
|
||||||
// anything else that would need to be ordered relatively to this.
|
|
||||||
s_disconnect.store(true, std::memory_order_relaxed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool s_isStdoutATerminal = false;
|
void Usage()
|
||||||
|
|
||||||
void InitIsStdoutATerminal() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
s_isStdoutATerminal = _isatty( fileno( stdout ) );
|
|
||||||
#else
|
|
||||||
s_isStdoutATerminal = isatty( fileno( stdout ) );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsStdoutATerminal() { return s_isStdoutATerminal; }
|
|
||||||
|
|
||||||
#define ANSI_RESET "\033[0m"
|
|
||||||
#define ANSI_BOLD "\033[1m"
|
|
||||||
#define ANSI_BLACK "\033[30m"
|
|
||||||
#define ANSI_RED "\033[31m"
|
|
||||||
#define ANSI_GREEN "\033[32m"
|
|
||||||
#define ANSI_YELLOW "\033[33m"
|
|
||||||
#define ANSI_BLUE "\033[34m"
|
|
||||||
#define ANSI_MAGENTA "\033[35m"
|
|
||||||
#define ANSI_CYAN "\033[36m"
|
|
||||||
#define ANSI_ERASE_LINE "\033[2K"
|
|
||||||
|
|
||||||
// Like printf, but if stdout is a terminal, prepends the output with
|
|
||||||
// the given `ansiEscape` and appends ANSI_RESET.
|
|
||||||
void AnsiPrintf( const char* ansiEscape, const char* format, ... ) {
|
|
||||||
if( IsStdoutATerminal() )
|
|
||||||
{
|
|
||||||
// Prepend ansiEscape and append ANSI_RESET.
|
|
||||||
char buf[256];
|
|
||||||
va_list args;
|
|
||||||
va_start( args, format );
|
|
||||||
vsnprintf( buf, sizeof buf, format, args );
|
|
||||||
va_end( args );
|
|
||||||
printf( "%s%s" ANSI_RESET, ansiEscape, buf );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Just a normal printf.
|
|
||||||
va_list args;
|
|
||||||
va_start( args, format );
|
|
||||||
vfprintf( stdout, format, args );
|
|
||||||
va_end( args );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[noreturn]] void Usage()
|
|
||||||
{
|
{
|
||||||
printf( "Usage: capture -o output.tracy [-a address] [-p port] [-f] [-s seconds] [-m memlimit]\n" );
|
printf( "Usage: capture -o output.tracy [-a address] [-p port]\n" );
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,17 +41,12 @@ int main( int argc, char** argv )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
InitIsStdoutATerminal();
|
const char* address = "localhost";
|
||||||
|
|
||||||
bool overwrite = false;
|
|
||||||
const char* address = "127.0.0.1";
|
|
||||||
const char* output = nullptr;
|
const char* output = nullptr;
|
||||||
int port = 8086;
|
int port = 8086;
|
||||||
int seconds = -1;
|
|
||||||
int64_t memoryLimit = -1;
|
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
while( ( c = getopt( argc, argv, "a:o:p:fs:m:" ) ) != -1 )
|
while( ( c = getopt( argc, argv, "a:o:p:" ) ) != -1 )
|
||||||
{
|
{
|
||||||
switch( c )
|
switch( c )
|
||||||
{
|
{
|
||||||
@ -129,15 +59,6 @@ int main( int argc, char** argv )
|
|||||||
case 'p':
|
case 'p':
|
||||||
port = atoi( optarg );
|
port = atoi( optarg );
|
||||||
break;
|
break;
|
||||||
case 'f':
|
|
||||||
overwrite = true;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
seconds = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
memoryLimit = std::clamp( atoll( optarg ), 1ll, 999ll ) * tracy::GetPhysicalMemorySize() / 100;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
Usage();
|
Usage();
|
||||||
break;
|
break;
|
||||||
@ -146,26 +67,10 @@ int main( int argc, char** argv )
|
|||||||
|
|
||||||
if( !address || !output ) Usage();
|
if( !address || !output ) Usage();
|
||||||
|
|
||||||
struct stat st;
|
|
||||||
if( stat( output, &st ) == 0 && !overwrite )
|
|
||||||
{
|
|
||||||
printf( "Output file %s already exists! Use -f to force overwrite.\n", output );
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* test = fopen( output, "wb" );
|
|
||||||
if( !test )
|
|
||||||
{
|
|
||||||
printf( "Cannot open output file %s for writing!\n", output );
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
fclose( test );
|
|
||||||
unlink( output );
|
|
||||||
|
|
||||||
printf( "Connecting to %s:%i...", address, port );
|
printf( "Connecting to %s:%i...", address, port );
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
tracy::Worker worker( address, port, memoryLimit );
|
tracy::Worker worker( address, port );
|
||||||
while( !worker.HasData() )
|
while( !worker.IsConnected() )
|
||||||
{
|
{
|
||||||
const auto handshake = worker.GetHandshakeStatus();
|
const auto handshake = worker.GetHandshakeStatus();
|
||||||
if( handshake == tracy::HandshakeProtocolMismatch )
|
if( handshake == tracy::HandshakeProtocolMismatch )
|
||||||
@ -183,8 +88,8 @@ int main( int argc, char** argv )
|
|||||||
printf( "\nThe client you are trying to connect to has disconnected during the initial\nconnection handshake. Please check your network configuration.\n" );
|
printf( "\nThe client you are trying to connect to has disconnected during the initial\nconnection handshake. Please check your network configuration.\n" );
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
|
||||||
}
|
}
|
||||||
|
while( !worker.HasData() ) std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
||||||
printf( "\nQueue delay: %s\nTimer resolution: %s\n", tracy::TimeToString( worker.GetDelay() ), tracy::TimeToString( worker.GetResolution() ) );
|
printf( "\nQueue delay: %s\nTimer resolution: %s\n", tracy::TimeToString( worker.GetDelay() ), tracy::TimeToString( worker.GetResolution() ) );
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -196,22 +101,15 @@ int main( int argc, char** argv )
|
|||||||
sigaction( SIGINT, &sigint, &oldsigint );
|
sigaction( SIGINT, &sigint, &oldsigint );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const auto firstTime = worker.GetFirstTime();
|
|
||||||
auto& lock = worker.GetMbpsDataLock();
|
auto& lock = worker.GetMbpsDataLock();
|
||||||
|
|
||||||
const auto t0 = std::chrono::high_resolution_clock::now();
|
const auto t0 = std::chrono::high_resolution_clock::now();
|
||||||
while( worker.IsConnected() )
|
while( worker.IsConnected() )
|
||||||
{
|
{
|
||||||
// Relaxed order is sufficient here because `s_disconnect` is only ever
|
if( disconnect )
|
||||||
// set by this thread or by the SigInt handler, and that handler does
|
|
||||||
// nothing else than storing `s_disconnect`.
|
|
||||||
if( s_disconnect.load( std::memory_order_relaxed ) )
|
|
||||||
{
|
{
|
||||||
worker.Disconnect();
|
worker.Disconnect();
|
||||||
// Relaxed order is sufficient because only this thread ever reads
|
disconnect = false;
|
||||||
// this value.
|
|
||||||
s_disconnect.store(false, std::memory_order_relaxed );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
@ -220,144 +118,48 @@ int main( int argc, char** argv )
|
|||||||
const auto netTotal = worker.GetDataTransferred();
|
const auto netTotal = worker.GetDataTransferred();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
// Output progress info only if destination is a TTY to avoid bloating
|
|
||||||
// log files (so this is not just about usage of ANSI color codes).
|
|
||||||
if( IsStdoutATerminal() )
|
|
||||||
{
|
|
||||||
const char* unit = "Mbps";
|
|
||||||
float unitsPerMbps = 1.f;
|
|
||||||
if( mbps < 0.1f )
|
if( mbps < 0.1f )
|
||||||
{
|
{
|
||||||
unit = "Kbps";
|
printf( "\33[2K\r\033[36;1m%7.2f Kbps", mbps * 1000.f );
|
||||||
unitsPerMbps = 1000.f;
|
|
||||||
}
|
}
|
||||||
AnsiPrintf( ANSI_ERASE_LINE ANSI_CYAN ANSI_BOLD, "\r%7.2f %s", mbps * unitsPerMbps, unit );
|
else
|
||||||
printf( " /");
|
|
||||||
AnsiPrintf( ANSI_CYAN ANSI_BOLD, "%5.1f%%", compRatio * 100.f );
|
|
||||||
printf( " =");
|
|
||||||
AnsiPrintf( ANSI_YELLOW ANSI_BOLD, "%7.2f Mbps", mbps / compRatio );
|
|
||||||
printf( " | ");
|
|
||||||
AnsiPrintf( ANSI_YELLOW, "Tx: ");
|
|
||||||
AnsiPrintf( ANSI_GREEN, "%s", tracy::MemSizeToString( netTotal ) );
|
|
||||||
printf( " | ");
|
|
||||||
AnsiPrintf( ANSI_RED ANSI_BOLD, "%s", tracy::MemSizeToString( tracy::memUsage.load( std::memory_order_relaxed ) ) );
|
|
||||||
if( memoryLimit > 0 )
|
|
||||||
{
|
{
|
||||||
printf( " / " );
|
printf( "\33[2K\r\033[36;1m%7.2f Mbps", mbps );
|
||||||
AnsiPrintf( ANSI_BLUE ANSI_BOLD, "%s", tracy::MemSizeToString( memoryLimit ) );
|
|
||||||
}
|
}
|
||||||
printf( " | ");
|
printf( " \033[0m /\033[36;1m%5.1f%% \033[0m=\033[33;1m%7.2f Mbps \033[0m| \033[33mNet: \033[32m%s \033[0m| \033[33mMem: \033[31;1m%s\033[0m | \033[33mTime: %s\033[0m",
|
||||||
AnsiPrintf( ANSI_RED, "%s", tracy::TimeToString( worker.GetLastTime() - firstTime ) );
|
compRatio * 100.f,
|
||||||
|
mbps / compRatio,
|
||||||
|
tracy::MemSizeToString( netTotal ),
|
||||||
|
tracy::MemSizeToString( tracy::memUsage ),
|
||||||
|
tracy::TimeToString( worker.GetLastTime() ) );
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
||||||
if( seconds != -1 )
|
|
||||||
{
|
|
||||||
const auto dur = std::chrono::high_resolution_clock::now() - t0;
|
|
||||||
if( std::chrono::duration_cast<std::chrono::seconds>(dur).count() >= seconds )
|
|
||||||
{
|
|
||||||
// Relaxed order is sufficient because only this thread ever reads
|
|
||||||
// this value.
|
|
||||||
s_disconnect.store(true, std::memory_order_relaxed );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const auto t1 = std::chrono::high_resolution_clock::now();
|
const auto t1 = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
const auto& failure = worker.GetFailureType();
|
const auto& failure = worker.GetFailureType();
|
||||||
if( failure != tracy::Worker::Failure::None )
|
if( failure != tracy::Worker::Failure::None )
|
||||||
{
|
{
|
||||||
AnsiPrintf( ANSI_RED ANSI_BOLD, "\nInstrumentation failure: %s", tracy::Worker::GetFailureString( failure ) );
|
printf( "\n\033[31;1mInstrumentation failure: %s\033[0m", tracy::Worker::GetFailureString( failure ) );
|
||||||
auto& fd = worker.GetFailureData();
|
|
||||||
if( !fd.message.empty() )
|
|
||||||
{
|
|
||||||
printf( "\nContext: %s", fd.message.c_str() );
|
|
||||||
}
|
|
||||||
if( fd.callstack != 0 )
|
|
||||||
{
|
|
||||||
AnsiPrintf( ANSI_BOLD, "\nFailure callstack:\n" );
|
|
||||||
auto& cs = worker.GetCallstack( fd.callstack );
|
|
||||||
int fidx = 0;
|
|
||||||
for( auto& entry : cs )
|
|
||||||
{
|
|
||||||
auto frameData = worker.GetCallstackFrame( entry );
|
|
||||||
if( !frameData )
|
|
||||||
{
|
|
||||||
printf( "%3i. %p\n", fidx++, (void*)worker.GetCanonicalPointer( entry ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto fsz = frameData->size;
|
|
||||||
for( uint8_t f=0; f<fsz; f++ )
|
|
||||||
{
|
|
||||||
const auto& frame = frameData->data[f];
|
|
||||||
auto txt = worker.GetString( frame.name );
|
|
||||||
|
|
||||||
if( fidx == 0 && f != fsz-1 )
|
|
||||||
{
|
|
||||||
auto test = tracy::s_tracyStackFrames;
|
|
||||||
bool match = false;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if( strcmp( txt, *test ) == 0 )
|
|
||||||
{
|
|
||||||
match = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while( *++test );
|
|
||||||
if( match ) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( f == fsz-1 )
|
|
||||||
{
|
|
||||||
printf( "%3i. ", fidx++ );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AnsiPrintf( ANSI_BLACK ANSI_BOLD, "inl. " );
|
|
||||||
}
|
|
||||||
AnsiPrintf( ANSI_CYAN, "%s ", txt );
|
|
||||||
txt = worker.GetString( frame.file );
|
|
||||||
if( frame.line == 0 )
|
|
||||||
{
|
|
||||||
AnsiPrintf( ANSI_YELLOW, "(%s)", txt );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AnsiPrintf( ANSI_YELLOW, "(%s:%" PRIu32 ")", txt, frame.line );
|
|
||||||
}
|
|
||||||
if( frameData->imageName.Active() )
|
|
||||||
{
|
|
||||||
AnsiPrintf( ANSI_MAGENTA, " %s\n", worker.GetString( frameData->imageName ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf( "\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf( "\nFrames: %" PRIu64 "\nTime span: %s\nZones: %s\nElapsed time: %s\nSaving trace...",
|
printf( "\nFrames: %" PRIu64 "\nTime span: %s\nZones: %s\nElapsed time: %s\nSaving trace...",
|
||||||
worker.GetFrameCount( *worker.GetFramesBase() ), tracy::TimeToString( worker.GetLastTime() - firstTime ), tracy::RealToString( worker.GetZoneCount() ),
|
worker.GetFrameCount( *worker.GetFramesBase() ), tracy::TimeToString( worker.GetLastTime() ), tracy::RealToString( worker.GetZoneCount() ),
|
||||||
tracy::TimeToString( std::chrono::duration_cast<std::chrono::nanoseconds>( t1 - t0 ).count() ) );
|
tracy::TimeToString( std::chrono::duration_cast<std::chrono::nanoseconds>( t1 - t0 ).count() ) );
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
auto f = std::unique_ptr<tracy::FileWrite>( tracy::FileWrite::Open( output, tracy::FileCompression::Zstd, 3, 4 ) );
|
auto f = std::unique_ptr<tracy::FileWrite>( tracy::FileWrite::Open( output ) );
|
||||||
if( f )
|
if( f )
|
||||||
{
|
{
|
||||||
worker.Write( *f, false );
|
worker.Write( *f );
|
||||||
AnsiPrintf( ANSI_GREEN ANSI_BOLD, " done!\n" );
|
printf( " \033[32;1mdone!\033[0m\n" );
|
||||||
f->Finish();
|
f->Finish();
|
||||||
const auto stats = f->GetCompressionStatistics();
|
const auto stats = f->GetCompressionStatistics();
|
||||||
printf( "Trace size %s (%.2f%% ratio)\n", tracy::MemSizeToString( stats.second ), 100.f * stats.second / stats.first );
|
printf( "Trace size %s (%.2f%% ratio)\n", tracy::MemSizeToString( stats.second ), 100.f * stats.second / stats.first );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AnsiPrintf( ANSI_RED ANSI_BOLD, " failed!\n");
|
printf( " \033[31;1failed!\033[0m\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2012-2023, Kim Grasman <kim.grasman@gmail.com>
|
* Copyright (c) 2012-2017, Kim Grasman <kim.grasman@gmail.com>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -159,7 +159,6 @@ int getopt_long(int argc, char* const argv[], const char* optstring,
|
|||||||
const struct option* match = NULL;
|
const struct option* match = NULL;
|
||||||
int num_matches = 0;
|
int num_matches = 0;
|
||||||
size_t argument_name_length = 0;
|
size_t argument_name_length = 0;
|
||||||
size_t option_length = 0;
|
|
||||||
const char* current_argument = NULL;
|
const char* current_argument = NULL;
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
@ -176,16 +175,6 @@ int getopt_long(int argc, char* const argv[], const char* optstring,
|
|||||||
current_argument = argv[optind] + 2;
|
current_argument = argv[optind] + 2;
|
||||||
argument_name_length = strcspn(current_argument, "=");
|
argument_name_length = strcspn(current_argument, "=");
|
||||||
for (; o->name; ++o) {
|
for (; o->name; ++o) {
|
||||||
/* Check for exact match first. */
|
|
||||||
option_length = strlen(o->name);
|
|
||||||
if (option_length == argument_name_length &&
|
|
||||||
strncmp(o->name, current_argument, option_length) == 0) {
|
|
||||||
match = o;
|
|
||||||
num_matches = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If not exact, count the number of abbreviated matches. */
|
|
||||||
if (strncmp(o->name, current_argument, argument_name_length) == 0) {
|
if (strncmp(o->name, current_argument, argument_name_length) == 0) {
|
||||||
match = o;
|
match = o;
|
||||||
++num_matches;
|
++num_matches;
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2012-2023, Kim Grasman <kim.grasman@gmail.com>
|
* Copyright (c) 2012-2017, Kim Grasman <kim.grasman@gmail.com>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
@ -1,8 +1,10 @@
|
|||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(disable:4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined __linux__ && defined __ARM_ARCH
|
|
||||||
|
|
||||||
static const char* DecodeArmImplementer( uint32_t v )
|
static const char* DecodeArmImplementer( uint32_t v )
|
||||||
{
|
{
|
||||||
static char buf[16];
|
static char buf[16];
|
||||||
@ -14,7 +16,6 @@ static const char* DecodeArmImplementer( uint32_t v )
|
|||||||
case 0x44: return "DEC";
|
case 0x44: return "DEC";
|
||||||
case 0x46: return "Fujitsu";
|
case 0x46: return "Fujitsu";
|
||||||
case 0x48: return "HiSilicon";
|
case 0x48: return "HiSilicon";
|
||||||
case 0x49: return "Infineon";
|
|
||||||
case 0x4d: return "Motorola";
|
case 0x4d: return "Motorola";
|
||||||
case 0x4e: return "Nvidia";
|
case 0x4e: return "Nvidia";
|
||||||
case 0x50: return "Applied Micro";
|
case 0x50: return "Applied Micro";
|
||||||
@ -26,7 +27,6 @@ static const char* DecodeArmImplementer( uint32_t v )
|
|||||||
case 0x66: return "Faraday";
|
case 0x66: return "Faraday";
|
||||||
case 0x68: return "HXT";
|
case 0x68: return "HXT";
|
||||||
case 0x69: return "Intel";
|
case 0x69: return "Intel";
|
||||||
case 0xc0: return "Ampere Computing";
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
sprintf( buf, "0x%x", v );
|
sprintf( buf, "0x%x", v );
|
||||||
@ -38,7 +38,7 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
static char buf[16];
|
static char buf[16];
|
||||||
switch( impl )
|
switch( impl )
|
||||||
{
|
{
|
||||||
case 0x41: // ARM
|
case 0x41:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0x810: return "810";
|
case 0x810: return "810";
|
||||||
@ -61,8 +61,8 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
case 0xc09: return " Cortex-A9";
|
case 0xc09: return " Cortex-A9";
|
||||||
case 0xc0c: return " Cortex-A12";
|
case 0xc0c: return " Cortex-A12";
|
||||||
case 0xc0d: return " Rockchip RK3288";
|
case 0xc0d: return " Rockchip RK3288";
|
||||||
case 0xc0e: return " Cortex-A17";
|
|
||||||
case 0xc0f: return " Cortex-A15";
|
case 0xc0f: return " Cortex-A15";
|
||||||
|
case 0xc0e: return " Cortex-A17";
|
||||||
case 0xc14: return " Cortex-R4";
|
case 0xc14: return " Cortex-R4";
|
||||||
case 0xc15: return " Cortex-R5";
|
case 0xc15: return " Cortex-R5";
|
||||||
case 0xc17: return " Cortex-R7";
|
case 0xc17: return " Cortex-R7";
|
||||||
@ -75,7 +75,6 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
case 0xc60: return " Cortex-M0+";
|
case 0xc60: return " Cortex-M0+";
|
||||||
case 0xd00: return " AArch64 simulator";
|
case 0xd00: return " AArch64 simulator";
|
||||||
case 0xd01: return " Cortex-A32";
|
case 0xd01: return " Cortex-A32";
|
||||||
case 0xd02: return " Cortex-A34";
|
|
||||||
case 0xd03: return " Cortex-A53";
|
case 0xd03: return " Cortex-A53";
|
||||||
case 0xd04: return " Cortex-A35";
|
case 0xd04: return " Cortex-A35";
|
||||||
case 0xd05: return " Cortex-A55";
|
case 0xd05: return " Cortex-A55";
|
||||||
@ -92,21 +91,10 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
case 0xd13: return " Cortex-R52";
|
case 0xd13: return " Cortex-R52";
|
||||||
case 0xd20: return " Cortex-M23";
|
case 0xd20: return " Cortex-M23";
|
||||||
case 0xd21: return " Cortex-M33";
|
case 0xd21: return " Cortex-M33";
|
||||||
case 0xd22: return " Cortex-M55";
|
|
||||||
case 0xd40: return " Neoverse V1";
|
|
||||||
case 0xd41: return " Cortex-A78";
|
|
||||||
case 0xd42: return " Cortex-A78AE";
|
|
||||||
case 0xd43: return " Cortex-A65AE";
|
|
||||||
case 0xd44: return " Cortex-X1";
|
|
||||||
case 0xd47: return " Cortex-A710";
|
|
||||||
case 0xd48: return " Cortex-X2";
|
|
||||||
case 0xd49: return " Neoverse N2";
|
|
||||||
case 0xd4a: return " Neoverse E1";
|
case 0xd4a: return " Neoverse E1";
|
||||||
case 0xd4b: return " Cortex-A78C";
|
|
||||||
case 0xd4c: return " Cortex-X1C";
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x42: // Broadcom
|
case 0x42:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0xf: return " Brahma B15";
|
case 0xf: return " Brahma B15";
|
||||||
@ -114,7 +102,7 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
case 0x516: return " ThunderX2";
|
case 0x516: return " ThunderX2";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x43: // Cavium
|
case 0x43:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0xa0: return " ThunderX";
|
case 0xa0: return " ThunderX";
|
||||||
@ -122,37 +110,29 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
case 0xa2: return " ThunderX 81XX";
|
case 0xa2: return " ThunderX 81XX";
|
||||||
case 0xa3: return " ThunderX 83XX";
|
case 0xa3: return " ThunderX 83XX";
|
||||||
case 0xaf: return " ThunderX2 99xx";
|
case 0xaf: return " ThunderX2 99xx";
|
||||||
case 0xb0: return " OcteonTX2";
|
|
||||||
case 0xb1: return " OcteonTX2 T98";
|
|
||||||
case 0xb2: return " OcteonTX2 T96";
|
|
||||||
case 0xb3: return " OcteonTX2 F95";
|
|
||||||
case 0xb4: return " OcteonTX2 F95N";
|
|
||||||
case 0xb5: return " OcteonTX2 F95MM";
|
|
||||||
case 0xb6: return " OcteonTX2 F95O";
|
|
||||||
case 0xb8: return " ThunderX3 T110";
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x44: // DEC
|
case 0x44:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0xa10: return " SA110";
|
case 0xa10: return " SA110";
|
||||||
case 0xa11: return " SA1100";
|
case 0xa11: return " SA1100";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x46: // Fujitsu
|
case 0x46:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0x1: return " A64FX";
|
case 0x1: return " A64FX";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x48: // HiSilicon
|
case 0x48:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0xd01: return " TSV100";
|
case 0xd01: return " TSV100";
|
||||||
case 0xd40: return " Kirin 980";
|
case 0xd40: return " Kirin 980";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x4e: // Nvidia
|
case 0x4e:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0x0: return " Denver";
|
case 0x0: return " Denver";
|
||||||
@ -160,13 +140,13 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
case 0x4: return " Carmel";
|
case 0x4: return " Carmel";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x50: // Applied Micro
|
case 0x50:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0x0: return " X-Gene";
|
case 0x0: return " X-Gene";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x51: // Qualcomm
|
case 0x51:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0xf: return " Scorpion";
|
case 0xf: return " Scorpion";
|
||||||
@ -182,27 +162,18 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
case 0x802: return " Kryo 385 Gold";
|
case 0x802: return " Kryo 385 Gold";
|
||||||
case 0x803: return " Kryo 385 Silver";
|
case 0x803: return " Kryo 385 Silver";
|
||||||
case 0x804: return " Kryo 485 Gold";
|
case 0x804: return " Kryo 485 Gold";
|
||||||
case 0x805: return " Kryo 4xx/5xx Silver";
|
|
||||||
case 0xc00: return " Falkor";
|
case 0xc00: return " Falkor";
|
||||||
case 0xc01: return " Saphira";
|
case 0xc01: return " Saphira";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x53: // Samsung
|
case 0x53:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0x1: return " Exynos M1/M2";
|
case 0x1: return " Exynos M1/M2";
|
||||||
case 0x2: return " Exynos M3";
|
case 0x2: return " Exynos M3";
|
||||||
case 0x3: return " Exynos M4";
|
|
||||||
case 0x4: return " Exynos M5";
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x54: // Texas Instruments
|
case 0x56:
|
||||||
switch( part )
|
|
||||||
{
|
|
||||||
case 0x925: return " TI925";
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
case 0x56: // Marvell
|
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0x131: return " Feroceon 88FR131";
|
case 0x131: return " Feroceon 88FR131";
|
||||||
@ -210,7 +181,7 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
case 0x584: return " PJ4B-MP / PJ4C";
|
case 0x584: return " PJ4B-MP / PJ4C";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x61: // Apple
|
case 0x61:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0x1: return " Cyclone";
|
case 0x1: return " Cyclone";
|
||||||
@ -220,41 +191,27 @@ static const char* DecodeArmPart( uint32_t impl, uint32_t part )
|
|||||||
case 0x5: return " Twister/Elba/Malta";
|
case 0x5: return " Twister/Elba/Malta";
|
||||||
case 0x6: return " Hurricane";
|
case 0x6: return " Hurricane";
|
||||||
case 0x7: return " Hurricane/Myst";
|
case 0x7: return " Hurricane/Myst";
|
||||||
case 0x22: return " M1 Icestorm";
|
|
||||||
case 0x23: return " M1 Firestorm";
|
|
||||||
case 0x24: return " M1 Icestorm Pro";
|
|
||||||
case 0x25: return " M1 Firestorm Pro";
|
|
||||||
case 0x28: return " M1 Icestorm Max";
|
|
||||||
case 0x29: return " M1 Firestorm Max";
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x66: // Faraday
|
case 0x66:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0x526: return " FA526";
|
case 0x526: return " FA526";
|
||||||
case 0x626: return " FA626";
|
case 0x626: return " FA626";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0x68: // HXT
|
case 0x68:
|
||||||
switch( part )
|
switch( part )
|
||||||
{
|
{
|
||||||
case 0x0: return " Phecda";
|
case 0x0: return " Phecda";
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
case 0xc0: // Ampere Computing
|
|
||||||
switch( part )
|
|
||||||
{
|
|
||||||
case 0xac3: return " Ampere1";
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
sprintf( buf, " 0x%x", part );
|
sprintf( buf, " 0x%x", part );
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined __APPLE__ && TARGET_OS_IPHONE == 1
|
|
||||||
|
|
||||||
static const char* DecodeIosDevice( const char* id )
|
static const char* DecodeIosDevice( const char* id )
|
||||||
{
|
{
|
||||||
static const char* DeviceTable[] = {
|
static const char* DeviceTable[] = {
|
||||||
@ -295,24 +252,6 @@ static const char* DecodeIosDevice( const char* id )
|
|||||||
"iPhone12,1", "iPhone 11",
|
"iPhone12,1", "iPhone 11",
|
||||||
"iPhone12,3", "iPhone 11 Pro",
|
"iPhone12,3", "iPhone 11 Pro",
|
||||||
"iPhone12,5", "iPhone 11 Pro Max",
|
"iPhone12,5", "iPhone 11 Pro Max",
|
||||||
"iPhone12,8", "iPhone SE 2nd Gen",
|
|
||||||
"iPhone13,1", "iPhone 12 Mini",
|
|
||||||
"iPhone13,2", "iPhone 12",
|
|
||||||
"iPhone13,3", "iPhone 12 Pro",
|
|
||||||
"iPhone13,4", "iPhone 12 Pro Max",
|
|
||||||
"iPhone14,2", "iPhone 13 Pro",
|
|
||||||
"iPhone14,3", "iPhone 13 Pro Max",
|
|
||||||
"iPhone14,4", "iPhone 13 Mini",
|
|
||||||
"iPhone14,5", "iPhone 13",
|
|
||||||
"iPhone14,6", "iPhone SE 3rd Gen",
|
|
||||||
"iPhone14,7", "iPhone 14",
|
|
||||||
"iPhone14,8", "iPhone 14 Plus",
|
|
||||||
"iPhone15,2", "iPhone 14 Pro",
|
|
||||||
"iPhone15,3", "iPhone 14 Pro Max",
|
|
||||||
"iPhone15,4", "iPhone 15",
|
|
||||||
"iPhone15,5", "iPhone 15 Plus",
|
|
||||||
"iPhone16,1", "iPhone 15 Pro",
|
|
||||||
"iPhone16,2", "iPhone 15 Pro Max",
|
|
||||||
"iPad1,1", "iPad (A1219/A1337)",
|
"iPad1,1", "iPad (A1219/A1337)",
|
||||||
"iPad2,1", "iPad 2 (A1395)",
|
"iPad2,1", "iPad 2 (A1395)",
|
||||||
"iPad2,2", "iPad 2 (A1396)",
|
"iPad2,2", "iPad 2 (A1396)",
|
||||||
@ -363,38 +302,10 @@ static const char* DecodeIosDevice( const char* id )
|
|||||||
"iPad8,6", "iPad Pro 12.9\" 3rd gen (A1876)",
|
"iPad8,6", "iPad Pro 12.9\" 3rd gen (A1876)",
|
||||||
"iPad8,7", "iPad Pro 12.9\" 3rd gen (A1895/A1983/A2014)",
|
"iPad8,7", "iPad Pro 12.9\" 3rd gen (A1895/A1983/A2014)",
|
||||||
"iPad8,8", "iPad Pro 12.9\" 3rd gen (A1895/A1983/A2014)",
|
"iPad8,8", "iPad Pro 12.9\" 3rd gen (A1895/A1983/A2014)",
|
||||||
"iPad8,9", "iPad Pro 11\" 2nd gen (Wifi)",
|
|
||||||
"iPad8,10", "iPad Pro 11\" 2nd gen (Wifi+Cellular)",
|
|
||||||
"iPad8,11", "iPad Pro 12.9\" 4th gen (Wifi)",
|
|
||||||
"iPad8,12", "iPad Pro 12.9\" 4th gen (Wifi+Cellular)",
|
|
||||||
"iPad11,1", "iPad Mini 5th gen (A2133)",
|
"iPad11,1", "iPad Mini 5th gen (A2133)",
|
||||||
"iPad11,2", "iPad Mini 5th gen (A2124/A2125/A2126)",
|
"iPad11,2", "iPad Mini 5th gen (A2124/A2125/A2126)",
|
||||||
"iPad11,3", "iPad Air 3rd gen (A2152)",
|
"iPad11,3", "iPad Air 3rd gen (A2152)",
|
||||||
"iPad11,4", "iPad Air 3rd gen (A2123/A2153/A2154)",
|
"iPad11,4", "iPad Air 3rd gen (A2123/A2153/A2154)",
|
||||||
"iPad11,6", "iPad 8th gen (WiFi)",
|
|
||||||
"iPad11,7", "iPad 8th gen (WiFi+Cellular)",
|
|
||||||
"iPad12,1", "iPad 9th Gen (WiFi)",
|
|
||||||
"iPad12,2", "iPad 9th Gen (WiFi+Cellular)",
|
|
||||||
"iPad13,1", "iPad Air 4th gen (WiFi)",
|
|
||||||
"iPad13,2", "iPad Air 4th gen (WiFi+Cellular)",
|
|
||||||
"iPad13,4", "iPad Pro 11\" 3rd gen",
|
|
||||||
"iPad13,5", "iPad Pro 11\" 3rd gen",
|
|
||||||
"iPad13,6", "iPad Pro 11\" 3rd gen",
|
|
||||||
"iPad13,7", "iPad Pro 11\" 3rd gen",
|
|
||||||
"iPad13,8", "iPad Pro 12.9\" 5th gen",
|
|
||||||
"iPad13,9", "iPad Pro 12.9\" 5th gen",
|
|
||||||
"iPad13,10", "iPad Pro 12.9\" 5th gen",
|
|
||||||
"iPad13,11", "iPad Pro 12.9\" 5th gen",
|
|
||||||
"iPad13,16", "iPad Air 5th Gen (WiFi)",
|
|
||||||
"iPad13,17", "iPad Air 5th Gen (WiFi+Cellular)",
|
|
||||||
"iPad13,18", "iPad 10th Gen",
|
|
||||||
"iPad13,19", "iPad 10th Gen",
|
|
||||||
"iPad14,1", "iPad mini 6th Gen (WiFi)",
|
|
||||||
"iPad14,2", "iPad mini 6th Gen (WiFi+Cellular)",
|
|
||||||
"iPad14,3", "iPad Pro 11\" 4th Gen",
|
|
||||||
"iPad14,4", "iPad Pro 11\" 4th Gen",
|
|
||||||
"iPad14,5", "iPad Pro 12.9\" 6th Gen",
|
|
||||||
"iPad14,6", "iPad Pro 12.9\" 6th Gen",
|
|
||||||
"iPod1,1", "iPod Touch",
|
"iPod1,1", "iPod Touch",
|
||||||
"iPod2,1", "iPod Touch 2nd gen",
|
"iPod2,1", "iPod Touch 2nd gen",
|
||||||
"iPod3,1", "iPod Touch 3rd gen",
|
"iPod3,1", "iPod Touch 3rd gen",
|
||||||
@ -414,6 +325,4 @@ static const char* DecodeIosDevice( const char* id )
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
741
client/TracyCallstack.cpp
Normal file
@ -0,0 +1,741 @@
|
|||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "TracyCallstack.hpp"
|
||||||
|
#include "TracyFastVector.hpp"
|
||||||
|
#include "../common/TracyAlloc.hpp"
|
||||||
|
|
||||||
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
|
||||||
|
#if TRACY_HAS_CALLSTACK == 1
|
||||||
|
# ifndef NOMINMAX
|
||||||
|
# define NOMINMAX
|
||||||
|
# endif
|
||||||
|
# include <windows.h>
|
||||||
|
# include <psapi.h>
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# pragma warning( push )
|
||||||
|
# pragma warning( disable : 4091 )
|
||||||
|
# endif
|
||||||
|
# include <dbghelp.h>
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# pragma warning( pop )
|
||||||
|
# endif
|
||||||
|
#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
|
||||||
|
# include "../libbacktrace/backtrace.hpp"
|
||||||
|
# include <dlfcn.h>
|
||||||
|
# include <cxxabi.h>
|
||||||
|
#elif TRACY_HAS_CALLSTACK == 5
|
||||||
|
# include <dlfcn.h>
|
||||||
|
# include <cxxabi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
static inline char* CopyString( const char* src, size_t sz )
|
||||||
|
{
|
||||||
|
assert( strlen( src ) == sz );
|
||||||
|
auto dst = (char*)tracy_malloc( sz + 1 );
|
||||||
|
memcpy( dst, src, sz );
|
||||||
|
dst[sz] = '\0';
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char* CopyString( const char* src )
|
||||||
|
{
|
||||||
|
const auto sz = strlen( src );
|
||||||
|
auto dst = (char*)tracy_malloc( sz + 1 );
|
||||||
|
memcpy( dst, src, sz );
|
||||||
|
dst[sz] = '\0';
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if TRACY_HAS_CALLSTACK == 1
|
||||||
|
|
||||||
|
enum { MaxCbTrace = 16 };
|
||||||
|
enum { MaxNameSize = 8*1024 };
|
||||||
|
|
||||||
|
int cb_num;
|
||||||
|
CallstackEntry cb_data[MaxCbTrace];
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
typedef unsigned long (__stdcall *t_RtlWalkFrameChain)( void**, unsigned long, unsigned long );
|
||||||
|
t_RtlWalkFrameChain RtlWalkFrameChain = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined __MINGW32__ && API_VERSION_NUMBER < 12
|
||||||
|
extern "C" {
|
||||||
|
// Actual required API_VERSION_NUMBER is unknown because it is undocumented. These functions are not present in at least v11.
|
||||||
|
DWORD IMAGEAPI SymAddrIncludeInlineTrace(HANDLE hProcess, DWORD64 Address);
|
||||||
|
BOOL IMAGEAPI SymQueryInlineTrace(HANDLE hProcess, DWORD64 StartAddress, DWORD StartContext, DWORD64 StartRetAddress,
|
||||||
|
DWORD64 CurAddress, LPDWORD CurContext, LPDWORD CurFrameIndex);
|
||||||
|
BOOL IMAGEAPI SymFromInlineContext(HANDLE hProcess, DWORD64 Address, ULONG InlineContext, PDWORD64 Displacement,
|
||||||
|
PSYMBOL_INFO Symbol);
|
||||||
|
BOOL IMAGEAPI SymGetLineFromInlineContext(HANDLE hProcess, DWORD64 qwAddr, ULONG InlineContext,
|
||||||
|
DWORD64 qwModuleBaseAddress, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line64);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
struct ModuleCache
|
||||||
|
{
|
||||||
|
uint64_t start;
|
||||||
|
uint64_t end;
|
||||||
|
char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static FastVector<ModuleCache>* s_modCache;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void InitCallstack()
|
||||||
|
{
|
||||||
|
RtlWalkFrameChain = (t_RtlWalkFrameChain)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "RtlWalkFrameChain" );
|
||||||
|
|
||||||
|
SymInitialize( GetCurrentProcess(), nullptr, true );
|
||||||
|
SymSetOptions( SYMOPT_LOAD_LINES );
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
HMODULE mod[1024];
|
||||||
|
DWORD needed;
|
||||||
|
HANDLE proc = GetCurrentProcess();
|
||||||
|
|
||||||
|
s_modCache = (FastVector<ModuleCache>*)tracy_malloc( sizeof( FastVector<ModuleCache> ) );
|
||||||
|
new(s_modCache) FastVector<ModuleCache>( 512 );
|
||||||
|
|
||||||
|
if( EnumProcessModules( proc, mod, sizeof( mod ), &needed ) != 0 )
|
||||||
|
{
|
||||||
|
const auto sz = needed / sizeof( HMODULE );
|
||||||
|
for( size_t i=0; i<sz; i++ )
|
||||||
|
{
|
||||||
|
MODULEINFO info;
|
||||||
|
if( GetModuleInformation( proc, mod[i], &info, sizeof( info ) ) != 0 )
|
||||||
|
{
|
||||||
|
const auto base = uint64_t( info.lpBaseOfDll );
|
||||||
|
char name[1024];
|
||||||
|
const auto res = GetModuleFileNameA( mod[i], name, 1021 );
|
||||||
|
if( res > 0 )
|
||||||
|
{
|
||||||
|
auto ptr = name + res;
|
||||||
|
while( ptr > name && *ptr != '\\' && *ptr != '/' ) ptr--;
|
||||||
|
if( ptr > name ) ptr++;
|
||||||
|
const auto namelen = name + res - ptr;
|
||||||
|
auto cache = s_modCache->push_next();
|
||||||
|
cache->start = base;
|
||||||
|
cache->end = base + info.SizeOfImage;
|
||||||
|
cache->name = (char*)tracy_malloc( namelen+3 );
|
||||||
|
cache->name[0] = '[';
|
||||||
|
memcpy( cache->name+1, ptr, namelen );
|
||||||
|
cache->name[namelen+1] = ']';
|
||||||
|
cache->name[namelen+2] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACY_API uintptr_t* CallTrace( int depth )
|
||||||
|
{
|
||||||
|
auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
|
||||||
|
const auto num = RtlWalkFrameChain( (void**)( trace + 1 ), depth, 0 );
|
||||||
|
*trace = num;
|
||||||
|
return trace;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* DecodeCallstackPtrFast( uint64_t ptr )
|
||||||
|
{
|
||||||
|
static char ret[MaxNameSize];
|
||||||
|
const auto proc = GetCurrentProcess();
|
||||||
|
|
||||||
|
char buf[sizeof( SYMBOL_INFO ) + MaxNameSize];
|
||||||
|
auto si = (SYMBOL_INFO*)buf;
|
||||||
|
si->SizeOfStruct = sizeof( SYMBOL_INFO );
|
||||||
|
si->MaxNameLen = MaxNameSize;
|
||||||
|
|
||||||
|
if( SymFromAddr( proc, ptr, nullptr, si ) == 0 )
|
||||||
|
{
|
||||||
|
*ret = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy( ret, si->Name, si->NameLen );
|
||||||
|
ret[si->NameLen] = '\0';
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* GetModuleName( uint64_t addr )
|
||||||
|
{
|
||||||
|
if( ( addr & 0x8000000000000000 ) != 0 ) return "[kernel]";
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
for( auto& v : *s_modCache )
|
||||||
|
{
|
||||||
|
if( addr >= v.start && addr < v.end )
|
||||||
|
{
|
||||||
|
return v.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE mod[1024];
|
||||||
|
DWORD needed;
|
||||||
|
HANDLE proc = GetCurrentProcess();
|
||||||
|
|
||||||
|
if( EnumProcessModules( proc, mod, sizeof( mod ), &needed ) != 0 )
|
||||||
|
{
|
||||||
|
const auto sz = needed / sizeof( HMODULE );
|
||||||
|
for( size_t i=0; i<sz; i++ )
|
||||||
|
{
|
||||||
|
MODULEINFO info;
|
||||||
|
if( GetModuleInformation( proc, mod[i], &info, sizeof( info ) ) != 0 )
|
||||||
|
{
|
||||||
|
const auto base = uint64_t( info.lpBaseOfDll );
|
||||||
|
if( addr >= base && addr < base + info.SizeOfImage )
|
||||||
|
{
|
||||||
|
char name[1024];
|
||||||
|
const auto res = GetModuleFileNameA( mod[i], name, 1021 );
|
||||||
|
if( res > 0 )
|
||||||
|
{
|
||||||
|
auto ptr = name + res;
|
||||||
|
while( ptr > name && *ptr != '\\' && *ptr != '/' ) ptr--;
|
||||||
|
if( ptr > name ) ptr++;
|
||||||
|
const auto namelen = name + res - ptr;
|
||||||
|
auto cache = s_modCache->push_next();
|
||||||
|
cache->start = base;
|
||||||
|
cache->end = base + info.SizeOfImage;
|
||||||
|
cache->name = (char*)tracy_malloc( namelen+3 );
|
||||||
|
cache->name[0] = '[';
|
||||||
|
memcpy( cache->name+1, ptr, namelen );
|
||||||
|
cache->name[namelen+1] = ']';
|
||||||
|
cache->name[namelen+2] = '\0';
|
||||||
|
return cache->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return "[unknown]";
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolData DecodeSymbolAddress( uint64_t ptr )
|
||||||
|
{
|
||||||
|
SymbolData sym;
|
||||||
|
IMAGEHLP_LINE64 line;
|
||||||
|
DWORD displacement = 0;
|
||||||
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
|
if( SymGetLineFromAddr64( GetCurrentProcess(), ptr, &displacement, &line ) == 0 )
|
||||||
|
{
|
||||||
|
sym.file = "[unknown]";
|
||||||
|
sym.line = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sym.file = line.FileName;
|
||||||
|
sym.line = line.LineNumber;
|
||||||
|
}
|
||||||
|
sym.needFree = false;
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolData DecodeCodeAddress( uint64_t ptr )
|
||||||
|
{
|
||||||
|
SymbolData sym;
|
||||||
|
const auto proc = GetCurrentProcess();
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
IMAGEHLP_LINE64 line;
|
||||||
|
DWORD displacement = 0;
|
||||||
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
DWORD inlineNum = SymAddrIncludeInlineTrace( proc, ptr );
|
||||||
|
DWORD ctx = 0;
|
||||||
|
DWORD idx;
|
||||||
|
BOOL doInline = FALSE;
|
||||||
|
if( inlineNum != 0 ) doInline = SymQueryInlineTrace( proc, ptr, 0, ptr, ptr, &ctx, &idx );
|
||||||
|
if( doInline )
|
||||||
|
{
|
||||||
|
if( SymGetLineFromInlineContext( proc, ptr, ctx, 0, &displacement, &line ) != 0 )
|
||||||
|
{
|
||||||
|
sym.file = line.FileName;
|
||||||
|
sym.line = line.LineNumber;
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if( !done )
|
||||||
|
{
|
||||||
|
if( SymGetLineFromAddr64( proc, ptr, &displacement, &line ) == 0 )
|
||||||
|
{
|
||||||
|
sym.file = "[unknown]";
|
||||||
|
sym.line = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sym.file = line.FileName;
|
||||||
|
sym.line = line.LineNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sym.needFree = false;
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
|
||||||
|
{
|
||||||
|
int write;
|
||||||
|
const auto proc = GetCurrentProcess();
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
DWORD inlineNum = SymAddrIncludeInlineTrace( proc, ptr );
|
||||||
|
if( inlineNum > MaxCbTrace - 1 ) inlineNum = MaxCbTrace - 1;
|
||||||
|
DWORD ctx = 0;
|
||||||
|
DWORD idx;
|
||||||
|
BOOL doInline = FALSE;
|
||||||
|
if( inlineNum != 0 ) doInline = SymQueryInlineTrace( proc, ptr, 0, ptr, ptr, &ctx, &idx );
|
||||||
|
if( doInline )
|
||||||
|
{
|
||||||
|
write = inlineNum;
|
||||||
|
cb_num = 1 + inlineNum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
write = 0;
|
||||||
|
cb_num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[sizeof( SYMBOL_INFO ) + MaxNameSize];
|
||||||
|
auto si = (SYMBOL_INFO*)buf;
|
||||||
|
si->SizeOfStruct = sizeof( SYMBOL_INFO );
|
||||||
|
si->MaxNameLen = MaxNameSize;
|
||||||
|
|
||||||
|
const auto moduleName = GetModuleName( ptr );
|
||||||
|
const auto symValid = SymFromAddr( proc, ptr, nullptr, si ) != 0;
|
||||||
|
|
||||||
|
IMAGEHLP_LINE64 line;
|
||||||
|
DWORD displacement = 0;
|
||||||
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
|
|
||||||
|
{
|
||||||
|
const char* filename;
|
||||||
|
if( SymGetLineFromAddr64( proc, ptr, &displacement, &line ) == 0 )
|
||||||
|
{
|
||||||
|
filename = "[unknown]";
|
||||||
|
cb_data[write].line = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filename = line.FileName;
|
||||||
|
cb_data[write].line = line.LineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_data[write].name = symValid ? CopyString( si->Name, si->NameLen ) : CopyString( moduleName );
|
||||||
|
cb_data[write].file = CopyString( filename );
|
||||||
|
if( symValid )
|
||||||
|
{
|
||||||
|
cb_data[write].symLen = si->Size;
|
||||||
|
cb_data[write].symAddr = si->Address;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cb_data[write].symLen = 0;
|
||||||
|
cb_data[write].symAddr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
if( doInline )
|
||||||
|
{
|
||||||
|
for( DWORD i=0; i<inlineNum; i++ )
|
||||||
|
{
|
||||||
|
auto& cb = cb_data[i];
|
||||||
|
const auto symInlineValid = SymFromInlineContext( proc, ptr, ctx, nullptr, si ) != 0;
|
||||||
|
const char* filename;
|
||||||
|
if( SymGetLineFromInlineContext( proc, ptr, ctx, 0, &displacement, &line ) == 0 )
|
||||||
|
{
|
||||||
|
filename = "[unknown]";
|
||||||
|
cb.line = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filename = line.FileName;
|
||||||
|
cb.line = line.LineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb.name = symInlineValid ? CopyString( si->Name, si->NameLen ) : CopyString( moduleName );
|
||||||
|
cb.file = CopyString( filename );
|
||||||
|
if( symInlineValid )
|
||||||
|
{
|
||||||
|
cb.symLen = si->Size;
|
||||||
|
cb.symAddr = si->Address;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cb.symLen = 0;
|
||||||
|
cb.symAddr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return { cb_data, uint8_t( cb_num ), moduleName };
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
|
||||||
|
|
||||||
|
enum { MaxCbTrace = 16 };
|
||||||
|
|
||||||
|
struct backtrace_state* cb_bts;
|
||||||
|
int cb_num;
|
||||||
|
CallstackEntry cb_data[MaxCbTrace];
|
||||||
|
int cb_fixup;
|
||||||
|
|
||||||
|
void InitCallstack()
|
||||||
|
{
|
||||||
|
cb_bts = backtrace_create_state( nullptr, 0, nullptr, nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int FastCallstackDataCb( void* data, uintptr_t pc, uintptr_t lowaddr, const char* fn, int lineno, const char* function )
|
||||||
|
{
|
||||||
|
if( function )
|
||||||
|
{
|
||||||
|
strcpy( (char*)data, function );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char* symname = nullptr;
|
||||||
|
auto vptr = (void*)pc;
|
||||||
|
Dl_info dlinfo;
|
||||||
|
if( dladdr( vptr, &dlinfo ) )
|
||||||
|
{
|
||||||
|
symname = dlinfo.dli_sname;
|
||||||
|
}
|
||||||
|
if( symname )
|
||||||
|
{
|
||||||
|
strcpy( (char*)data, symname );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(char*)data = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FastCallstackErrorCb( void* data, const char* /*msg*/, int /*errnum*/ )
|
||||||
|
{
|
||||||
|
*(char*)data = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* DecodeCallstackPtrFast( uint64_t ptr )
|
||||||
|
{
|
||||||
|
static char ret[1024];
|
||||||
|
backtrace_pcinfo( cb_bts, ptr, FastCallstackDataCb, FastCallstackErrorCb, ret );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SymbolAddressDataCb( void* data, uintptr_t pc, uintptr_t lowaddr, const char* fn, int lineno, const char* function )
|
||||||
|
{
|
||||||
|
auto& sym = *(SymbolData*)data;
|
||||||
|
if( !fn )
|
||||||
|
{
|
||||||
|
const char* symloc = nullptr;
|
||||||
|
Dl_info dlinfo;
|
||||||
|
if( dladdr( (void*)pc, &dlinfo ) ) symloc = dlinfo.dli_fname;
|
||||||
|
if( !symloc ) symloc = "[unknown]";
|
||||||
|
sym.file = symloc;
|
||||||
|
sym.line = 0;
|
||||||
|
sym.needFree = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sym.file = CopyString( fn );
|
||||||
|
sym.line = lineno;
|
||||||
|
sym.needFree = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SymbolAddressErrorCb( void* data, const char* /*msg*/, int /*errnum*/ )
|
||||||
|
{
|
||||||
|
auto& sym = *(SymbolData*)data;
|
||||||
|
sym.file = "[unknown]";
|
||||||
|
sym.line = 0;
|
||||||
|
sym.needFree = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolData DecodeSymbolAddress( uint64_t ptr )
|
||||||
|
{
|
||||||
|
SymbolData sym;
|
||||||
|
backtrace_pcinfo( cb_bts, ptr, SymbolAddressDataCb, SymbolAddressErrorCb, &sym );
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolData DecodeCodeAddress( uint64_t ptr )
|
||||||
|
{
|
||||||
|
return DecodeSymbolAddress( ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CallstackDataCb( void* /*data*/, uintptr_t pc, uintptr_t lowaddr, const char* fn, int lineno, const char* function )
|
||||||
|
{
|
||||||
|
enum { DemangleBufLen = 64*1024 };
|
||||||
|
char demangled[DemangleBufLen];
|
||||||
|
|
||||||
|
cb_data[cb_num].symLen = 0;
|
||||||
|
cb_data[cb_num].symAddr = (uint64_t)lowaddr;
|
||||||
|
|
||||||
|
if( !fn && !function )
|
||||||
|
{
|
||||||
|
const char* symname = nullptr;
|
||||||
|
const char* symloc = nullptr;
|
||||||
|
auto vptr = (void*)pc;
|
||||||
|
ptrdiff_t symoff = 0;
|
||||||
|
|
||||||
|
Dl_info dlinfo;
|
||||||
|
if( dladdr( vptr, &dlinfo ) )
|
||||||
|
{
|
||||||
|
symloc = dlinfo.dli_fname;
|
||||||
|
symname = dlinfo.dli_sname;
|
||||||
|
symoff = (char*)pc - (char*)dlinfo.dli_saddr;
|
||||||
|
|
||||||
|
if( symname && symname[0] == '_' )
|
||||||
|
{
|
||||||
|
size_t len = DemangleBufLen;
|
||||||
|
int status;
|
||||||
|
abi::__cxa_demangle( symname, demangled, &len, &status );
|
||||||
|
if( status == 0 )
|
||||||
|
{
|
||||||
|
symname = demangled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !symname ) symname = "[unknown]";
|
||||||
|
if( !symloc ) symloc = "[unknown]";
|
||||||
|
|
||||||
|
if( symoff == 0 )
|
||||||
|
{
|
||||||
|
cb_data[cb_num].name = CopyString( symname );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
const auto offlen = sprintf( buf, " + %td", symoff );
|
||||||
|
const auto namelen = strlen( symname );
|
||||||
|
auto name = (char*)tracy_malloc( namelen + offlen + 1 );
|
||||||
|
memcpy( name, symname, namelen );
|
||||||
|
memcpy( name + namelen, buf, offlen );
|
||||||
|
name[namelen + offlen] = '\0';
|
||||||
|
cb_data[cb_num].name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
const auto addrlen = sprintf( buf, " [%p]", (void*)pc );
|
||||||
|
const auto loclen = strlen( symloc );
|
||||||
|
auto loc = (char*)tracy_malloc( loclen + addrlen + 1 );
|
||||||
|
memcpy( loc, symloc, loclen );
|
||||||
|
memcpy( loc + loclen, buf, addrlen );
|
||||||
|
loc[loclen + addrlen] = '\0';
|
||||||
|
cb_data[cb_num].file = loc;
|
||||||
|
|
||||||
|
cb_data[cb_num].line = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( !fn ) fn = "[unknown]";
|
||||||
|
if( !function )
|
||||||
|
{
|
||||||
|
function = "[unknown]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( function[0] == '_' )
|
||||||
|
{
|
||||||
|
size_t len = DemangleBufLen;
|
||||||
|
int status;
|
||||||
|
abi::__cxa_demangle( function, demangled, &len, &status );
|
||||||
|
if( status == 0 )
|
||||||
|
{
|
||||||
|
function = demangled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_data[cb_num].name = CopyString( function );
|
||||||
|
cb_data[cb_num].file = CopyString( fn );
|
||||||
|
cb_data[cb_num].line = lineno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ++cb_num >= MaxCbTrace )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CallstackErrorCb( void* /*data*/, const char* /*msg*/, int /*errnum*/ )
|
||||||
|
{
|
||||||
|
for( int i=0; i<cb_num; i++ )
|
||||||
|
{
|
||||||
|
tracy_free( (void*)cb_data[i].name );
|
||||||
|
tracy_free( (void*)cb_data[i].file );
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_data[0].name = CopyString( "[error]" );
|
||||||
|
cb_data[0].file = CopyString( "[error]" );
|
||||||
|
cb_data[0].line = 0;
|
||||||
|
|
||||||
|
cb_num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymInfoCallback( void* /*data*/, uintptr_t pc, const char* symname, uintptr_t symval, uintptr_t symsize )
|
||||||
|
{
|
||||||
|
cb_data[cb_num-1].symLen = (uint32_t)symsize;
|
||||||
|
cb_data[cb_num-1].symAddr = (uint64_t)symval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymInfoError( void* /*data*/, const char* /*msg*/, int /*errnum*/ )
|
||||||
|
{
|
||||||
|
cb_data[cb_num-1].symLen = 0;
|
||||||
|
cb_data[cb_num-1].symAddr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
|
||||||
|
{
|
||||||
|
cb_num = 0;
|
||||||
|
backtrace_pcinfo( cb_bts, ptr, CallstackDataCb, CallstackErrorCb, nullptr );
|
||||||
|
assert( cb_num > 0 );
|
||||||
|
|
||||||
|
backtrace_syminfo( cb_bts, ptr, SymInfoCallback, SymInfoError, nullptr );
|
||||||
|
|
||||||
|
const char* symloc = nullptr;
|
||||||
|
Dl_info dlinfo;
|
||||||
|
if( dladdr( (void*)ptr, &dlinfo ) ) symloc = dlinfo.dli_fname;
|
||||||
|
|
||||||
|
return { cb_data, uint8_t( cb_num ), symloc ? symloc : "[unknown]" };
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif TRACY_HAS_CALLSTACK == 5
|
||||||
|
|
||||||
|
void InitCallstack()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* DecodeCallstackPtrFast( uint64_t ptr )
|
||||||
|
{
|
||||||
|
static char ret[1024];
|
||||||
|
auto vptr = (void*)ptr;
|
||||||
|
const char* symname = nullptr;
|
||||||
|
Dl_info dlinfo;
|
||||||
|
if( dladdr( vptr, &dlinfo ) && dlinfo.dli_sname )
|
||||||
|
{
|
||||||
|
symname = dlinfo.dli_sname;
|
||||||
|
}
|
||||||
|
if( symname )
|
||||||
|
{
|
||||||
|
strcpy( ret, symname );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ret = '\0';
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolData DecodeSymbolAddress( uint64_t ptr )
|
||||||
|
{
|
||||||
|
const char* symloc = nullptr;
|
||||||
|
Dl_info dlinfo;
|
||||||
|
if( dladdr( (void*)ptr, &dlinfo ) ) symloc = dlinfo.dli_fname;
|
||||||
|
if( !symloc ) symloc = "[unknown]";
|
||||||
|
return SymbolData { symloc, 0, false };
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolData DecodeCodeAddress( uint64_t ptr )
|
||||||
|
{
|
||||||
|
return DecodeSymbolAddress( ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
CallstackEntryData DecodeCallstackPtr( uint64_t ptr )
|
||||||
|
{
|
||||||
|
static CallstackEntry cb;
|
||||||
|
cb.line = 0;
|
||||||
|
|
||||||
|
char* demangled = nullptr;
|
||||||
|
const char* symname = nullptr;
|
||||||
|
const char* symloc = nullptr;
|
||||||
|
auto vptr = (void*)ptr;
|
||||||
|
ptrdiff_t symoff = 0;
|
||||||
|
void* symaddr = nullptr;
|
||||||
|
|
||||||
|
Dl_info dlinfo;
|
||||||
|
if( dladdr( vptr, &dlinfo ) )
|
||||||
|
{
|
||||||
|
symloc = dlinfo.dli_fname;
|
||||||
|
symname = dlinfo.dli_sname;
|
||||||
|
symoff = (char*)ptr - (char*)dlinfo.dli_saddr;
|
||||||
|
symaddr = dlinfo.dli_saddr;
|
||||||
|
|
||||||
|
if( symname && symname[0] == '_' )
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
int status;
|
||||||
|
demangled = abi::__cxa_demangle( symname, nullptr, &len, &status );
|
||||||
|
if( status == 0 )
|
||||||
|
{
|
||||||
|
symname = demangled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !symname ) symname = "[unknown]";
|
||||||
|
if( !symloc ) symloc = "[unknown]";
|
||||||
|
|
||||||
|
if( symoff == 0 )
|
||||||
|
{
|
||||||
|
cb.name = CopyString( symname );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
const auto offlen = sprintf( buf, " + %td", symoff );
|
||||||
|
const auto namelen = strlen( symname );
|
||||||
|
auto name = (char*)tracy_malloc( namelen + offlen + 1 );
|
||||||
|
memcpy( name, symname, namelen );
|
||||||
|
memcpy( name + namelen, buf, offlen );
|
||||||
|
name[namelen + offlen] = '\0';
|
||||||
|
cb.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
const auto addrlen = sprintf( buf, " [%p]", (void*)ptr );
|
||||||
|
const auto loclen = strlen( symloc );
|
||||||
|
auto loc = (char*)tracy_malloc( loclen + addrlen + 1 );
|
||||||
|
memcpy( loc, symloc, loclen );
|
||||||
|
memcpy( loc + loclen, buf, addrlen );
|
||||||
|
loc[loclen + addrlen] = '\0';
|
||||||
|
cb.file = loc;
|
||||||
|
|
||||||
|
cb.symLen = 0;
|
||||||
|
cb.symAddr = (uint64_t)symaddr;
|
||||||
|
|
||||||
|
if( demangled ) free( demangled );
|
||||||
|
|
||||||
|
return { &cb, 1, symloc };
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
28
client/TracyCallstack.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef __TRACYCALLSTACK_H__
|
||||||
|
#define __TRACYCALLSTACK_H__
|
||||||
|
|
||||||
|
#if !defined _WIN32 && !defined __CYGWIN__
|
||||||
|
# include <sys/param.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
|
# define TRACY_HAS_CALLSTACK 1
|
||||||
|
#elif defined __ANDROID__
|
||||||
|
# if !defined __arm__ || __ANDROID_API__ >= 21
|
||||||
|
# define TRACY_HAS_CALLSTACK 2
|
||||||
|
# else
|
||||||
|
# define TRACY_HAS_CALLSTACK 5
|
||||||
|
# endif
|
||||||
|
#elif defined __linux
|
||||||
|
# if defined _GNU_SOURCE && defined __GLIBC__
|
||||||
|
# define TRACY_HAS_CALLSTACK 3
|
||||||
|
# else
|
||||||
|
# define TRACY_HAS_CALLSTACK 2
|
||||||
|
# endif
|
||||||
|
#elif defined __APPLE__
|
||||||
|
# define TRACY_HAS_CALLSTACK 4
|
||||||
|
#elif defined BSD
|
||||||
|
# define TRACY_HAS_CALLSTACK 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -2,51 +2,31 @@
|
|||||||
#define __TRACYCALLSTACK_HPP__
|
#define __TRACYCALLSTACK_HPP__
|
||||||
|
|
||||||
#include "../common/TracyApi.h"
|
#include "../common/TracyApi.h"
|
||||||
#include "../common/TracyForceInline.hpp"
|
|
||||||
#include "TracyCallstack.h"
|
#include "TracyCallstack.h"
|
||||||
|
|
||||||
#ifndef TRACY_HAS_CALLSTACK
|
|
||||||
|
|
||||||
namespace tracy
|
|
||||||
{
|
|
||||||
static constexpr bool has_callstack() { return false; }
|
|
||||||
static tracy_force_inline void* Callstack( int32_t /*depth*/ ) { return nullptr; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
|
#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
|
||||||
# include <unwind.h>
|
# include <unwind.h>
|
||||||
#elif TRACY_HAS_CALLSTACK >= 3
|
#elif TRACY_HAS_CALLSTACK >= 3
|
||||||
# ifdef TRACY_LIBUNWIND_BACKTRACE
|
|
||||||
// libunwind is, in general, significantly faster than execinfo based backtraces
|
|
||||||
# define UNW_LOCAL_ONLY
|
|
||||||
# include <libunwind.h>
|
|
||||||
# else
|
|
||||||
# include <execinfo.h>
|
# include <execinfo.h>
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TRACY_DEBUGINFOD
|
|
||||||
# include <elfutils/debuginfod.h>
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "../common/TracyAlloc.hpp"
|
#include "../common/TracyAlloc.hpp"
|
||||||
|
#include "../common/TracyForceInline.hpp"
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
|
|
||||||
static constexpr bool has_callstack() { return true; }
|
struct SymbolData
|
||||||
|
|
||||||
struct CallstackSymbolData
|
|
||||||
{
|
{
|
||||||
const char* file;
|
const char* file;
|
||||||
uint32_t line;
|
uint32_t line;
|
||||||
bool needFree;
|
bool needFree;
|
||||||
uint64_t symAddr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CallstackEntry
|
struct CallstackEntry
|
||||||
@ -65,34 +45,20 @@ struct CallstackEntryData
|
|||||||
const char* imageName;
|
const char* imageName;
|
||||||
};
|
};
|
||||||
|
|
||||||
CallstackSymbolData DecodeSymbolAddress( uint64_t ptr );
|
SymbolData DecodeSymbolAddress( uint64_t ptr );
|
||||||
|
SymbolData DecodeCodeAddress( uint64_t ptr );
|
||||||
const char* DecodeCallstackPtrFast( uint64_t ptr );
|
const char* DecodeCallstackPtrFast( uint64_t ptr );
|
||||||
CallstackEntryData DecodeCallstackPtr( uint64_t ptr );
|
CallstackEntryData DecodeCallstackPtr( uint64_t ptr );
|
||||||
void InitCallstack();
|
void InitCallstack();
|
||||||
void InitCallstackCritical();
|
|
||||||
void EndCallstack();
|
|
||||||
const char* GetKernelModulePath( uint64_t addr );
|
|
||||||
|
|
||||||
#ifdef TRACY_DEBUGINFOD
|
|
||||||
const uint8_t* GetBuildIdForImage( const char* image, size_t& size );
|
|
||||||
debuginfod_client* GetDebuginfodClient();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TRACY_HAS_CALLSTACK == 1
|
#if TRACY_HAS_CALLSTACK == 1
|
||||||
|
|
||||||
extern "C"
|
TRACY_API uintptr_t* CallTrace( int depth );
|
||||||
{
|
|
||||||
typedef unsigned long (__stdcall *___tracy_t_RtlWalkFrameChain)( void**, unsigned long, unsigned long );
|
|
||||||
TRACY_API extern ___tracy_t_RtlWalkFrameChain ___tracy_RtlWalkFrameChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
static tracy_force_inline void* Callstack( int32_t depth )
|
static tracy_force_inline void* Callstack( int depth )
|
||||||
{
|
{
|
||||||
assert( depth >= 1 && depth < 63 );
|
assert( depth >= 1 && depth < 63 );
|
||||||
auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
|
return CallTrace( depth );
|
||||||
const auto num = ___tracy_RtlWalkFrameChain( (void**)( trace + 1 ), depth, 0 );
|
|
||||||
*trace = num;
|
|
||||||
return trace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
|
#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
|
||||||
@ -115,7 +81,7 @@ static _Unwind_Reason_Code tracy_unwind_callback( struct _Unwind_Context* ctx, v
|
|||||||
return _URC_NO_REASON;
|
return _URC_NO_REASON;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tracy_force_inline void* Callstack( int32_t depth )
|
static tracy_force_inline void* Callstack( int depth )
|
||||||
{
|
{
|
||||||
assert( depth >= 1 && depth < 63 );
|
assert( depth >= 1 && depth < 63 );
|
||||||
|
|
||||||
@ -130,18 +96,12 @@ static tracy_force_inline void* Callstack( int32_t depth )
|
|||||||
|
|
||||||
#elif TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
|
#elif TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
|
||||||
|
|
||||||
static tracy_force_inline void* Callstack( int32_t depth )
|
static tracy_force_inline void* Callstack( int depth )
|
||||||
{
|
{
|
||||||
assert( depth >= 1 );
|
assert( depth >= 1 );
|
||||||
|
|
||||||
auto trace = (uintptr_t*)tracy_malloc( ( 1 + (size_t)depth ) * sizeof( uintptr_t ) );
|
auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
|
||||||
|
const auto num = backtrace( (void**)(trace+1), depth );
|
||||||
#ifdef TRACY_LIBUNWIND_BACKTRACE
|
|
||||||
size_t num = unw_backtrace( (void**)(trace+1), depth );
|
|
||||||
#else
|
|
||||||
const auto num = (size_t)backtrace( (void**)(trace+1), depth );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*trace = num;
|
*trace = num;
|
||||||
|
|
||||||
return trace;
|
return trace;
|
@ -90,8 +90,6 @@ static const uint16_t DivTable[255*3+1] = {
|
|||||||
0x0163, 0x0163, 0x0162, 0x0162, 0x0161, 0x0161, 0x0160, 0x0160, 0x015f, 0x015f, 0x015e, 0x015e, 0x015d, 0x015d, 0x015d, 0x015c,
|
0x0163, 0x0163, 0x0162, 0x0162, 0x0161, 0x0161, 0x0160, 0x0160, 0x015f, 0x015f, 0x015e, 0x015e, 0x015d, 0x015d, 0x015d, 0x015c,
|
||||||
0x015c, 0x015b, 0x015b, 0x015a, 0x015a, 0x0159, 0x0159, 0x0158, 0x0158, 0x0158, 0x0157, 0x0157, 0x0156, 0x0156
|
0x015c, 0x015b, 0x015b, 0x015a, 0x015a, 0x0159, 0x0159, 0x0158, 0x0158, 0x0158, 0x0157, 0x0157, 0x0156, 0x0156
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined __ARM_NEON && defined __aarch64__
|
|
||||||
static const uint16_t DivTableNEON[255*3+1] = {
|
static const uint16_t DivTableNEON[255*3+1] = {
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
0x0000, 0x1c71, 0x1af2, 0x1999, 0x1861, 0x1745, 0x1642, 0x1555, 0x147a, 0x13b1, 0x12f6, 0x1249, 0x11a7, 0x1111, 0x1084, 0x1000,
|
0x0000, 0x1c71, 0x1af2, 0x1999, 0x1861, 0x1745, 0x1642, 0x1555, 0x147a, 0x13b1, 0x12f6, 0x1249, 0x11a7, 0x1111, 0x1084, 0x1000,
|
||||||
@ -142,7 +140,6 @@ static const uint16_t DivTableNEON[255*3+1] = {
|
|||||||
0x00b1, 0x00b1, 0x00b1, 0x00b1, 0x00b0, 0x00b0, 0x00b0, 0x00b0, 0x00af, 0x00af, 0x00af, 0x00af, 0x00ae, 0x00ae, 0x00ae, 0x00ae,
|
0x00b1, 0x00b1, 0x00b1, 0x00b1, 0x00b0, 0x00b0, 0x00b0, 0x00b0, 0x00af, 0x00af, 0x00af, 0x00af, 0x00ae, 0x00ae, 0x00ae, 0x00ae,
|
||||||
0x00ae, 0x00ad, 0x00ad, 0x00ad, 0x00ad, 0x00ac, 0x00ac, 0x00ac, 0x00ac, 0x00ac, 0x00ab, 0x00ab, 0x00ab, 0x00ab,
|
0x00ae, 0x00ad, 0x00ad, 0x00ad, 0x00ad, 0x00ac, 0x00ac, 0x00ac, 0x00ac, 0x00ac, 0x00ab, 0x00ab, 0x00ab, 0x00ab,
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static tracy_force_inline uint64_t ProcessRGB( const uint8_t* src )
|
static tracy_force_inline uint64_t ProcessRGB( const uint8_t* src )
|
||||||
@ -175,12 +172,6 @@ static tracy_force_inline uint64_t ProcessRGB( const uint8_t* src )
|
|||||||
return uint64_t( to565( src[0], src[1], src[2] ) ) << 16;
|
return uint64_t( to565( src[0], src[1], src[2] ) ) << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
__m128i amask = _mm_set1_epi32( 0xFFFFFF );
|
|
||||||
px0 = _mm_and_si128( px0, amask );
|
|
||||||
px1 = _mm_and_si128( px1, amask );
|
|
||||||
px2 = _mm_and_si128( px2, amask );
|
|
||||||
px3 = _mm_and_si128( px3, amask );
|
|
||||||
|
|
||||||
__m128i min0 = _mm_min_epu8( px0, px1 );
|
__m128i min0 = _mm_min_epu8( px0, px1 );
|
||||||
__m128i min1 = _mm_min_epu8( px2, px3 );
|
__m128i min1 = _mm_min_epu8( px2, px3 );
|
||||||
__m128i min2 = _mm_min_epu8( min0, min1 );
|
__m128i min2 = _mm_min_epu8( min0, min1 );
|
||||||
@ -501,12 +492,6 @@ static tracy_force_inline void ProcessRGB_AVX( const uint8_t* src, char*& dst )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
__m256i amask = _mm256_set1_epi32( 0xFFFFFF );
|
|
||||||
px0 = _mm256_and_si256( px0, amask );
|
|
||||||
px1 = _mm256_and_si256( px1, amask );
|
|
||||||
px2 = _mm256_and_si256( px2, amask );
|
|
||||||
px3 = _mm256_and_si256( px3, amask );
|
|
||||||
|
|
||||||
__m256i min0 = _mm256_min_epu8( px0, px1 );
|
__m256i min0 = _mm256_min_epu8( px0, px1 );
|
||||||
__m256i min1 = _mm256_min_epu8( px2, px3 );
|
__m256i min1 = _mm256_min_epu8( px2, px3 );
|
||||||
__m256i min2 = _mm256_min_epu8( min0, min1 );
|
__m256i min2 = _mm256_min_epu8( min0, min1 );
|
@ -98,11 +98,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
tracy_no_inline void AllocMore()
|
tracy_no_inline void AllocMore()
|
||||||
{
|
{
|
||||||
const auto cap = size_t( m_end - m_ptr ) * 2;
|
const auto cap = ( m_end - m_ptr ) * 2;
|
||||||
const auto size = size_t( m_write - m_ptr );
|
const auto size = m_write - m_ptr;
|
||||||
T* ptr = (T*)tracy_malloc( sizeof( T ) * cap );
|
T* ptr = (T*)tracy_malloc( sizeof( T ) * cap );
|
||||||
memcpy( ptr, m_ptr, size * sizeof( T ) );
|
memcpy( ptr, m_ptr, size * sizeof( T ) );
|
||||||
tracy_free_fast( m_ptr );
|
tracy_free( m_ptr );
|
||||||
m_ptr = ptr;
|
m_ptr = ptr;
|
||||||
m_write = m_ptr + size;
|
m_write = m_ptr + size;
|
||||||
m_end = m_ptr + cap;
|
m_end = m_ptr + cap;
|
@ -21,10 +21,9 @@ public:
|
|||||||
, m_active( false )
|
, m_active( false )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
assert( m_id != (std::numeric_limits<uint32_t>::max)() );
|
assert( m_id != std::numeric_limits<uint32_t>::max() );
|
||||||
|
|
||||||
auto item = Profiler::QueueSerial();
|
TracyLfqPrepare( QueueType::LockAnnounce );
|
||||||
MemWrite( &item->hdr.type, QueueType::LockAnnounce );
|
|
||||||
MemWrite( &item->lockAnnounce.id, m_id );
|
MemWrite( &item->lockAnnounce.id, m_id );
|
||||||
MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
|
MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
|
||||||
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
|
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
|
||||||
@ -32,7 +31,7 @@ public:
|
|||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
GetProfiler().DeferItem( *item );
|
GetProfiler().DeferItem( *item );
|
||||||
#endif
|
#endif
|
||||||
Profiler::QueueSerialFinish();
|
TracyLfqCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
LockableCtx( const LockableCtx& ) = delete;
|
LockableCtx( const LockableCtx& ) = delete;
|
||||||
@ -40,14 +39,14 @@ public:
|
|||||||
|
|
||||||
tracy_force_inline ~LockableCtx()
|
tracy_force_inline ~LockableCtx()
|
||||||
{
|
{
|
||||||
auto item = Profiler::QueueSerial();
|
TracyLfqPrepare( QueueType::LockTerminate );
|
||||||
MemWrite( &item->hdr.type, QueueType::LockTerminate );
|
|
||||||
MemWrite( &item->lockTerminate.id, m_id );
|
MemWrite( &item->lockTerminate.id, m_id );
|
||||||
MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
|
MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->lockTerminate.type, LockType::Lockable );
|
||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
GetProfiler().DeferItem( *item );
|
GetProfiler().DeferItem( *item );
|
||||||
#endif
|
#endif
|
||||||
Profiler::QueueSerialFinish();
|
TracyLfqCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
tracy_force_inline bool BeforeLock()
|
tracy_force_inline bool BeforeLock()
|
||||||
@ -70,6 +69,7 @@ public:
|
|||||||
MemWrite( &item->lockWait.thread, GetThreadHandle() );
|
MemWrite( &item->lockWait.thread, GetThreadHandle() );
|
||||||
MemWrite( &item->lockWait.id, m_id );
|
MemWrite( &item->lockWait.id, m_id );
|
||||||
MemWrite( &item->lockWait.time, Profiler::GetTime() );
|
MemWrite( &item->lockWait.time, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->lockWait.type, LockType::Lockable );
|
||||||
Profiler::QueueSerialFinish();
|
Profiler::QueueSerialFinish();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -98,6 +98,7 @@ public:
|
|||||||
|
|
||||||
auto item = Profiler::QueueSerial();
|
auto item = Profiler::QueueSerial();
|
||||||
MemWrite( &item->hdr.type, QueueType::LockRelease );
|
MemWrite( &item->hdr.type, QueueType::LockRelease );
|
||||||
|
MemWrite( &item->lockRelease.thread, GetThreadHandle() );
|
||||||
MemWrite( &item->lockRelease.id, m_id );
|
MemWrite( &item->lockRelease.id, m_id );
|
||||||
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
|
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
|
||||||
Profiler::QueueSerialFinish();
|
Profiler::QueueSerialFinish();
|
||||||
@ -154,18 +155,16 @@ public:
|
|||||||
|
|
||||||
tracy_force_inline void CustomName( const char* name, size_t size )
|
tracy_force_inline void CustomName( const char* name, size_t size )
|
||||||
{
|
{
|
||||||
assert( size < (std::numeric_limits<uint16_t>::max)() );
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
auto ptr = (char*)tracy_malloc( size );
|
|
||||||
memcpy( ptr, name, size );
|
memcpy( ptr, name, size );
|
||||||
auto item = Profiler::QueueSerial();
|
ptr[size] = '\0';
|
||||||
MemWrite( &item->hdr.type, QueueType::LockName );
|
TracyLfqPrepare( QueueType::LockName );
|
||||||
MemWrite( &item->lockNameFat.id, m_id );
|
MemWrite( &item->lockName.id, m_id );
|
||||||
MemWrite( &item->lockNameFat.name, (uint64_t)ptr );
|
MemWrite( &item->lockName.name, (uint64_t)ptr );
|
||||||
MemWrite( &item->lockNameFat.size, (uint16_t)size );
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
GetProfiler().DeferItem( *item );
|
GetProfiler().DeferItem( *item );
|
||||||
#endif
|
#endif
|
||||||
Profiler::QueueSerialFinish();
|
TracyLfqCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -235,18 +234,19 @@ public:
|
|||||||
, m_active( false )
|
, m_active( false )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
assert( m_id != (std::numeric_limits<uint32_t>::max)() );
|
assert( m_id != std::numeric_limits<uint32_t>::max() );
|
||||||
|
|
||||||
auto item = Profiler::QueueSerial();
|
TracyLfqPrepare( QueueType::LockAnnounce );
|
||||||
MemWrite( &item->hdr.type, QueueType::LockAnnounce );
|
|
||||||
MemWrite( &item->lockAnnounce.id, m_id );
|
MemWrite( &item->lockAnnounce.id, m_id );
|
||||||
MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
|
MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
|
||||||
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
|
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
|
||||||
MemWrite( &item->lockAnnounce.type, LockType::SharedLockable );
|
MemWrite( &item->lockAnnounce.type, LockType::SharedLockable );
|
||||||
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
GetProfiler().DeferItem( *item );
|
GetProfiler().DeferItem( *item );
|
||||||
#endif
|
#endif
|
||||||
Profiler::QueueSerialFinish();
|
|
||||||
|
TracyLfqCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedLockableCtx( const SharedLockableCtx& ) = delete;
|
SharedLockableCtx( const SharedLockableCtx& ) = delete;
|
||||||
@ -254,14 +254,16 @@ public:
|
|||||||
|
|
||||||
tracy_force_inline ~SharedLockableCtx()
|
tracy_force_inline ~SharedLockableCtx()
|
||||||
{
|
{
|
||||||
auto item = Profiler::QueueSerial();
|
TracyLfqPrepare( QueueType::LockTerminate );
|
||||||
MemWrite( &item->hdr.type, QueueType::LockTerminate );
|
|
||||||
MemWrite( &item->lockTerminate.id, m_id );
|
MemWrite( &item->lockTerminate.id, m_id );
|
||||||
MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
|
MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->lockTerminate.type, LockType::SharedLockable );
|
||||||
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
GetProfiler().DeferItem( *item );
|
GetProfiler().DeferItem( *item );
|
||||||
#endif
|
#endif
|
||||||
Profiler::QueueSerialFinish();
|
|
||||||
|
TracyLfqCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
tracy_force_inline bool BeforeLock()
|
tracy_force_inline bool BeforeLock()
|
||||||
@ -284,6 +286,7 @@ public:
|
|||||||
MemWrite( &item->lockWait.thread, GetThreadHandle() );
|
MemWrite( &item->lockWait.thread, GetThreadHandle() );
|
||||||
MemWrite( &item->lockWait.id, m_id );
|
MemWrite( &item->lockWait.id, m_id );
|
||||||
MemWrite( &item->lockWait.time, Profiler::GetTime() );
|
MemWrite( &item->lockWait.time, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->lockWait.type, LockType::SharedLockable );
|
||||||
Profiler::QueueSerialFinish();
|
Profiler::QueueSerialFinish();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -312,6 +315,7 @@ public:
|
|||||||
|
|
||||||
auto item = Profiler::QueueSerial();
|
auto item = Profiler::QueueSerial();
|
||||||
MemWrite( &item->hdr.type, QueueType::LockRelease );
|
MemWrite( &item->hdr.type, QueueType::LockRelease );
|
||||||
|
MemWrite( &item->lockRelease.thread, GetThreadHandle() );
|
||||||
MemWrite( &item->lockRelease.id, m_id );
|
MemWrite( &item->lockRelease.id, m_id );
|
||||||
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
|
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
|
||||||
Profiler::QueueSerialFinish();
|
Profiler::QueueSerialFinish();
|
||||||
@ -365,6 +369,7 @@ public:
|
|||||||
MemWrite( &item->lockWait.thread, GetThreadHandle() );
|
MemWrite( &item->lockWait.thread, GetThreadHandle() );
|
||||||
MemWrite( &item->lockWait.id, m_id );
|
MemWrite( &item->lockWait.id, m_id );
|
||||||
MemWrite( &item->lockWait.time, Profiler::GetTime() );
|
MemWrite( &item->lockWait.time, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->lockWait.type, LockType::SharedLockable );
|
||||||
Profiler::QueueSerialFinish();
|
Profiler::QueueSerialFinish();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -393,9 +398,9 @@ public:
|
|||||||
|
|
||||||
auto item = Profiler::QueueSerial();
|
auto item = Profiler::QueueSerial();
|
||||||
MemWrite( &item->hdr.type, QueueType::LockSharedRelease );
|
MemWrite( &item->hdr.type, QueueType::LockSharedRelease );
|
||||||
MemWrite( &item->lockReleaseShared.thread, GetThreadHandle() );
|
MemWrite( &item->lockRelease.thread, GetThreadHandle() );
|
||||||
MemWrite( &item->lockReleaseShared.id, m_id );
|
MemWrite( &item->lockRelease.id, m_id );
|
||||||
MemWrite( &item->lockReleaseShared.time, Profiler::GetTime() );
|
MemWrite( &item->lockRelease.time, Profiler::GetTime() );
|
||||||
Profiler::QueueSerialFinish();
|
Profiler::QueueSerialFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,18 +455,16 @@ public:
|
|||||||
|
|
||||||
tracy_force_inline void CustomName( const char* name, size_t size )
|
tracy_force_inline void CustomName( const char* name, size_t size )
|
||||||
{
|
{
|
||||||
assert( size < (std::numeric_limits<uint16_t>::max)() );
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
auto ptr = (char*)tracy_malloc( size );
|
|
||||||
memcpy( ptr, name, size );
|
memcpy( ptr, name, size );
|
||||||
auto item = Profiler::QueueSerial();
|
ptr[size] = '\0';
|
||||||
MemWrite( &item->hdr.type, QueueType::LockName );
|
TracyLfqPrepare( QueueType::LockName );
|
||||||
MemWrite( &item->lockNameFat.id, m_id );
|
MemWrite( &item->lockName.id, m_id );
|
||||||
MemWrite( &item->lockNameFat.name, (uint64_t)ptr );
|
MemWrite( &item->lockName.name, (uint64_t)ptr );
|
||||||
MemWrite( &item->lockNameFat.size, (uint16_t)size );
|
|
||||||
#ifdef TRACY_ON_DEMAND
|
#ifdef TRACY_ON_DEMAND
|
||||||
GetProfiler().DeferItem( *item );
|
GetProfiler().DeferItem( *item );
|
||||||
#endif
|
#endif
|
||||||
Profiler::QueueSerialFinish();
|
TracyLfqCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
3075
client/TracyProfiler.cpp
Normal file
680
client/TracyProfiler.hpp
Normal file
@ -0,0 +1,680 @@
|
|||||||
|
#ifndef __TRACYPROFILER_HPP__
|
||||||
|
#define __TRACYPROFILER_HPP__
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <atomic>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tracy_concurrentqueue.h"
|
||||||
|
#include "TracyCallstack.hpp"
|
||||||
|
#include "TracySysTime.hpp"
|
||||||
|
#include "TracyFastVector.hpp"
|
||||||
|
#include "../common/TracyQueue.hpp"
|
||||||
|
#include "../common/TracyAlign.hpp"
|
||||||
|
#include "../common/TracyAlloc.hpp"
|
||||||
|
#include "../common/TracyMutex.hpp"
|
||||||
|
#include "../common/TracyProtocol.hpp"
|
||||||
|
|
||||||
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
|
# include <intrin.h>
|
||||||
|
#endif
|
||||||
|
#ifdef __APPLE__
|
||||||
|
# include <TargetConditionals.h>
|
||||||
|
# include <mach/mach_time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined _WIN32 || defined __CYGWIN__ || ( ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) && !defined __ANDROID__ ) || __ARM_ARCH >= 6
|
||||||
|
# define TRACY_HW_TIMER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined TRACY_HW_TIMER || ( defined __ARM_ARCH && __ARM_ARCH >= 6 && !defined CLOCK_MONOTONIC_RAW )
|
||||||
|
#include <chrono>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TracyConcat
|
||||||
|
# define TracyConcat(x,y) TracyConcatIndirect(x,y)
|
||||||
|
#endif
|
||||||
|
#ifndef TracyConcatIndirect
|
||||||
|
# define TracyConcatIndirect(x,y) x##y
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
class GpuCtx;
|
||||||
|
class Profiler;
|
||||||
|
class Socket;
|
||||||
|
class UdpBroadcast;
|
||||||
|
|
||||||
|
struct GpuCtxWrapper
|
||||||
|
{
|
||||||
|
GpuCtx* ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
TRACY_API moodycamel::ConcurrentQueue<QueueItem>::ExplicitProducer* GetToken();
|
||||||
|
TRACY_API Profiler& GetProfiler();
|
||||||
|
TRACY_API std::atomic<uint32_t>& GetLockCounter();
|
||||||
|
TRACY_API std::atomic<uint8_t>& GetGpuCtxCounter();
|
||||||
|
TRACY_API GpuCtxWrapper& GetGpuCtx();
|
||||||
|
TRACY_API uint64_t GetThreadHandle();
|
||||||
|
TRACY_API void InitRPMallocThread();
|
||||||
|
|
||||||
|
struct SourceLocationData
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
const char* function;
|
||||||
|
const char* file;
|
||||||
|
uint32_t line;
|
||||||
|
uint32_t color;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
struct LuaZoneState
|
||||||
|
{
|
||||||
|
uint32_t counter;
|
||||||
|
bool active;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define TracyLfqPrepare( _type ) \
|
||||||
|
moodycamel::ConcurrentQueueDefaultTraits::index_t __magic; \
|
||||||
|
auto __token = GetToken(); \
|
||||||
|
auto& __tail = __token->get_tail_index(); \
|
||||||
|
auto item = __token->enqueue_begin( __magic ); \
|
||||||
|
MemWrite( &item->hdr.type, _type );
|
||||||
|
|
||||||
|
#define TracyLfqCommit \
|
||||||
|
__tail.store( __magic + 1, std::memory_order_release );
|
||||||
|
|
||||||
|
#define TracyLfqPrepareC( _type ) \
|
||||||
|
tracy::moodycamel::ConcurrentQueueDefaultTraits::index_t __magic; \
|
||||||
|
auto __token = tracy::GetToken(); \
|
||||||
|
auto& __tail = __token->get_tail_index(); \
|
||||||
|
auto item = __token->enqueue_begin( __magic ); \
|
||||||
|
tracy::MemWrite( &item->hdr.type, _type );
|
||||||
|
|
||||||
|
#define TracyLfqCommitC \
|
||||||
|
__tail.store( __magic + 1, std::memory_order_release );
|
||||||
|
|
||||||
|
|
||||||
|
typedef void(*ParameterCallback)( uint32_t idx, int32_t val );
|
||||||
|
|
||||||
|
class Profiler
|
||||||
|
{
|
||||||
|
struct FrameImageQueueItem
|
||||||
|
{
|
||||||
|
void* image;
|
||||||
|
uint64_t frame;
|
||||||
|
uint16_t w;
|
||||||
|
uint16_t h;
|
||||||
|
uint8_t offset;
|
||||||
|
bool flip;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Profiler();
|
||||||
|
~Profiler();
|
||||||
|
|
||||||
|
static tracy_force_inline int64_t GetTime()
|
||||||
|
{
|
||||||
|
#ifdef TRACY_HW_TIMER
|
||||||
|
# if defined TARGET_OS_IOS && TARGET_OS_IOS == 1
|
||||||
|
return mach_absolute_time();
|
||||||
|
# elif defined __ARM_ARCH && __ARM_ARCH >= 6
|
||||||
|
# ifdef CLOCK_MONOTONIC_RAW
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime( CLOCK_MONOTONIC_RAW, &ts );
|
||||||
|
return int64_t( ts.tv_sec ) * 1000000000ll + int64_t( ts.tv_nsec );
|
||||||
|
# else
|
||||||
|
return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
|
||||||
|
# endif
|
||||||
|
# elif defined _WIN32 || defined __CYGWIN__
|
||||||
|
# ifdef TRACY_TIMER_QPC
|
||||||
|
return GetTimeQpc();
|
||||||
|
# else
|
||||||
|
return int64_t( __rdtsc() );
|
||||||
|
# endif
|
||||||
|
# elif defined __i386 || defined _M_IX86
|
||||||
|
uint32_t eax, edx;
|
||||||
|
asm volatile ( "rdtsc" : "=a" (eax), "=d" (edx) );
|
||||||
|
return ( uint64_t( edx ) << 32 ) + uint64_t( eax );
|
||||||
|
# elif defined __x86_64__ || defined _M_X64
|
||||||
|
uint64_t rax, rdx;
|
||||||
|
asm volatile ( "rdtsc" : "=a" (rax), "=d" (rdx) );
|
||||||
|
return ( rdx << 32 ) + rax;
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline uint32_t GetNextZoneId()
|
||||||
|
{
|
||||||
|
return m_zoneId.fetch_add( 1, std::memory_order_relaxed );
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline QueueItem* QueueSerial()
|
||||||
|
{
|
||||||
|
auto& p = GetProfiler();
|
||||||
|
p.m_serialLock.lock();
|
||||||
|
return p.m_serialQueue.prepare_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void QueueSerialFinish()
|
||||||
|
{
|
||||||
|
auto& p = GetProfiler();
|
||||||
|
p.m_serialQueue.commit_next();
|
||||||
|
p.m_serialLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void SendFrameMark( const char* name )
|
||||||
|
{
|
||||||
|
if( !name ) GetProfiler().m_frameCount.fetch_add( 1, std::memory_order_relaxed );
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( QueueType::FrameMarkMsg );
|
||||||
|
MemWrite( &item->frameMark.time, GetTime() );
|
||||||
|
MemWrite( &item->frameMark.name, uint64_t( name ) );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void SendFrameMark( const char* name, QueueType type )
|
||||||
|
{
|
||||||
|
assert( type == QueueType::FrameMarkMsgStart || type == QueueType::FrameMarkMsgEnd );
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
auto item = QueueSerial();
|
||||||
|
MemWrite( &item->hdr.type, type );
|
||||||
|
MemWrite( &item->frameMark.time, GetTime() );
|
||||||
|
MemWrite( &item->frameMark.name, uint64_t( name ) );
|
||||||
|
QueueSerialFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void SendFrameImage( const void* image, uint16_t w, uint16_t h, uint8_t offset, bool flip )
|
||||||
|
{
|
||||||
|
auto& profiler = GetProfiler();
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !profiler.IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
const auto sz = size_t( w ) * size_t( h ) * 4;
|
||||||
|
auto ptr = (char*)tracy_malloc( sz );
|
||||||
|
memcpy( ptr, image, sz );
|
||||||
|
|
||||||
|
profiler.m_fiLock.lock();
|
||||||
|
auto fi = profiler.m_fiQueue.prepare_next();
|
||||||
|
fi->image = ptr;
|
||||||
|
fi->frame = profiler.m_frameCount.load( std::memory_order_relaxed ) - offset;
|
||||||
|
fi->w = w;
|
||||||
|
fi->h = h;
|
||||||
|
fi->flip = flip;
|
||||||
|
profiler.m_fiQueue.commit_next();
|
||||||
|
profiler.m_fiLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void PlotData( const char* name, int64_t val )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( QueueType::PlotData );
|
||||||
|
MemWrite( &item->plotData.name, (uint64_t)name );
|
||||||
|
MemWrite( &item->plotData.time, GetTime() );
|
||||||
|
MemWrite( &item->plotData.type, PlotDataType::Int );
|
||||||
|
MemWrite( &item->plotData.data.i, val );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void PlotData( const char* name, float val )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( QueueType::PlotData );
|
||||||
|
MemWrite( &item->plotData.name, (uint64_t)name );
|
||||||
|
MemWrite( &item->plotData.time, GetTime() );
|
||||||
|
MemWrite( &item->plotData.type, PlotDataType::Float );
|
||||||
|
MemWrite( &item->plotData.data.f, val );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void PlotData( const char* name, double val )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( QueueType::PlotData );
|
||||||
|
MemWrite( &item->plotData.name, (uint64_t)name );
|
||||||
|
MemWrite( &item->plotData.time, GetTime() );
|
||||||
|
MemWrite( &item->plotData.type, PlotDataType::Double );
|
||||||
|
MemWrite( &item->plotData.data.d, val );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void ConfigurePlot( const char* name, PlotFormatType type )
|
||||||
|
{
|
||||||
|
TracyLfqPrepare( QueueType::PlotConfig );
|
||||||
|
MemWrite( &item->plotConfig.name, (uint64_t)name );
|
||||||
|
MemWrite( &item->plotConfig.type, (uint8_t)type );
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
GetProfiler().DeferItem( *item );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void Message( const char* txt, size_t size, int callstack )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( callstack == 0 ? QueueType::Message : QueueType::MessageCallstack );
|
||||||
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
|
memcpy( ptr, txt, size );
|
||||||
|
ptr[size] = '\0';
|
||||||
|
MemWrite( &item->message.time, GetTime() );
|
||||||
|
MemWrite( &item->message.text, (uint64_t)ptr );
|
||||||
|
TracyLfqCommit;
|
||||||
|
|
||||||
|
if( callstack != 0 ) tracy::GetProfiler().SendCallstack( callstack );
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void Message( const char* txt, int callstack )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( callstack == 0 ? QueueType::MessageLiteral : QueueType::MessageLiteralCallstack );
|
||||||
|
MemWrite( &item->message.time, GetTime() );
|
||||||
|
MemWrite( &item->message.text, (uint64_t)txt );
|
||||||
|
TracyLfqCommit;
|
||||||
|
|
||||||
|
if( callstack != 0 ) tracy::GetProfiler().SendCallstack( callstack );
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void MessageColor( const char* txt, size_t size, uint32_t color, int callstack )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( callstack == 0 ? QueueType::MessageColor : QueueType::MessageColorCallstack );
|
||||||
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
|
memcpy( ptr, txt, size );
|
||||||
|
ptr[size] = '\0';
|
||||||
|
MemWrite( &item->messageColor.time, GetTime() );
|
||||||
|
MemWrite( &item->messageColor.text, (uint64_t)ptr );
|
||||||
|
MemWrite( &item->messageColor.r, uint8_t( ( color ) & 0xFF ) );
|
||||||
|
MemWrite( &item->messageColor.g, uint8_t( ( color >> 8 ) & 0xFF ) );
|
||||||
|
MemWrite( &item->messageColor.b, uint8_t( ( color >> 16 ) & 0xFF ) );
|
||||||
|
TracyLfqCommit;
|
||||||
|
|
||||||
|
if( callstack != 0 ) tracy::GetProfiler().SendCallstack( callstack );
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void MessageColor( const char* txt, uint32_t color, int callstack )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( callstack == 0 ? QueueType::MessageLiteralColor : QueueType::MessageLiteralColorCallstack );
|
||||||
|
MemWrite( &item->messageColor.time, GetTime() );
|
||||||
|
MemWrite( &item->messageColor.text, (uint64_t)txt );
|
||||||
|
MemWrite( &item->messageColor.r, uint8_t( ( color ) & 0xFF ) );
|
||||||
|
MemWrite( &item->messageColor.g, uint8_t( ( color >> 8 ) & 0xFF ) );
|
||||||
|
MemWrite( &item->messageColor.b, uint8_t( ( color >> 16 ) & 0xFF ) );
|
||||||
|
TracyLfqCommit;
|
||||||
|
|
||||||
|
if( callstack != 0 ) tracy::GetProfiler().SendCallstack( callstack );
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void MessageAppInfo( const char* txt, size_t size )
|
||||||
|
{
|
||||||
|
InitRPMallocThread();
|
||||||
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
|
memcpy( ptr, txt, size );
|
||||||
|
ptr[size] = '\0';
|
||||||
|
TracyLfqPrepare( QueueType::MessageAppInfo );
|
||||||
|
MemWrite( &item->message.time, GetTime() );
|
||||||
|
MemWrite( &item->message.text, (uint64_t)ptr );
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
GetProfiler().DeferItem( *item );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void MemAlloc( const void* ptr, size_t size )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
const auto thread = GetThreadHandle();
|
||||||
|
|
||||||
|
GetProfiler().m_serialLock.lock();
|
||||||
|
SendMemAlloc( QueueType::MemAlloc, thread, ptr, size );
|
||||||
|
GetProfiler().m_serialLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void MemFree( const void* ptr )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
const auto thread = GetThreadHandle();
|
||||||
|
|
||||||
|
GetProfiler().m_serialLock.lock();
|
||||||
|
SendMemFree( QueueType::MemFree, thread, ptr );
|
||||||
|
GetProfiler().m_serialLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void MemAllocCallstack( const void* ptr, size_t size, int depth )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
auto& profiler = GetProfiler();
|
||||||
|
# ifdef TRACY_ON_DEMAND
|
||||||
|
if( !profiler.IsConnected() ) return;
|
||||||
|
# endif
|
||||||
|
const auto thread = GetThreadHandle();
|
||||||
|
|
||||||
|
InitRPMallocThread();
|
||||||
|
auto callstack = Callstack( depth );
|
||||||
|
|
||||||
|
profiler.m_serialLock.lock();
|
||||||
|
SendMemAlloc( QueueType::MemAllocCallstack, thread, ptr, size );
|
||||||
|
SendCallstackMemory( callstack );
|
||||||
|
profiler.m_serialLock.unlock();
|
||||||
|
#else
|
||||||
|
MemAlloc( ptr, size );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void MemFreeCallstack( const void* ptr, int depth )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
auto& profiler = GetProfiler();
|
||||||
|
# ifdef TRACY_ON_DEMAND
|
||||||
|
if( !profiler.IsConnected() ) return;
|
||||||
|
# endif
|
||||||
|
const auto thread = GetThreadHandle();
|
||||||
|
|
||||||
|
InitRPMallocThread();
|
||||||
|
auto callstack = Callstack( depth );
|
||||||
|
|
||||||
|
profiler.m_serialLock.lock();
|
||||||
|
SendMemFree( QueueType::MemFreeCallstack, thread, ptr );
|
||||||
|
SendCallstackMemory( callstack );
|
||||||
|
profiler.m_serialLock.unlock();
|
||||||
|
#else
|
||||||
|
MemFree( ptr );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void SendCallstack( int depth )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
auto ptr = Callstack( depth );
|
||||||
|
TracyLfqPrepare( QueueType::Callstack );
|
||||||
|
MemWrite( &item->callstack.ptr, (uint64_t)ptr );
|
||||||
|
TracyLfqCommit;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void ParameterRegister( ParameterCallback cb ) { GetProfiler().m_paramCallback = cb; }
|
||||||
|
static tracy_force_inline void ParameterSetup( uint32_t idx, const char* name, bool isBool, int32_t val )
|
||||||
|
{
|
||||||
|
TracyLfqPrepare( QueueType::ParamSetup );
|
||||||
|
tracy::MemWrite( &item->paramSetup.idx, idx );
|
||||||
|
tracy::MemWrite( &item->paramSetup.name, (uint64_t)name );
|
||||||
|
tracy::MemWrite( &item->paramSetup.isBool, (uint8_t)isBool );
|
||||||
|
tracy::MemWrite( &item->paramSetup.val, val );
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
GetProfiler().DeferItem( *item );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendCallstack( int depth, const char* skipBefore );
|
||||||
|
static void CutCallstack( void* callstack, const char* skipBefore );
|
||||||
|
|
||||||
|
static bool ShouldExit();
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
tracy_force_inline bool IsConnected() const
|
||||||
|
{
|
||||||
|
return m_isConnected.load( std::memory_order_acquire );
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline uint64_t ConnectionId() const
|
||||||
|
{
|
||||||
|
return m_connectionId.load( std::memory_order_acquire );
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline void DeferItem( const QueueItem& item )
|
||||||
|
{
|
||||||
|
m_deferredLock.lock();
|
||||||
|
auto dst = m_deferredQueue.push_next();
|
||||||
|
memcpy( dst, &item, sizeof( item ) );
|
||||||
|
m_deferredLock.unlock();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void RequestShutdown() { m_shutdown.store( true, std::memory_order_relaxed ); m_shutdownManual.store( true, std::memory_order_relaxed ); }
|
||||||
|
bool HasShutdownFinished() const { return m_shutdownFinished.load( std::memory_order_relaxed ); }
|
||||||
|
|
||||||
|
void SendString( uint64_t ptr, const char* str, QueueType type );
|
||||||
|
|
||||||
|
|
||||||
|
// Allocated source location data layout:
|
||||||
|
// 4b payload size
|
||||||
|
// 4b color
|
||||||
|
// 4b source line
|
||||||
|
// fsz function name
|
||||||
|
// 1b null terminator
|
||||||
|
// ssz source file name
|
||||||
|
// 1b null terminator
|
||||||
|
// nsz zone name (optional)
|
||||||
|
|
||||||
|
static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, const char* function )
|
||||||
|
{
|
||||||
|
const auto fsz = strlen( function );
|
||||||
|
const auto ssz = strlen( source );
|
||||||
|
const uint32_t sz = uint32_t( 4 + 4 + 4 + fsz + 1 + ssz + 1 );
|
||||||
|
auto ptr = (char*)tracy_malloc( sz );
|
||||||
|
memcpy( ptr, &sz, 4 );
|
||||||
|
memset( ptr + 4, 0, 4 );
|
||||||
|
memcpy( ptr + 8, &line, 4 );
|
||||||
|
memcpy( ptr + 12, function, fsz+1 );
|
||||||
|
memcpy( ptr + 12 + fsz + 1, source, ssz + 1 );
|
||||||
|
return uint64_t( ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline uint64_t AllocSourceLocation( uint32_t line, const char* source, const char* function, const char* name, size_t nameSz )
|
||||||
|
{
|
||||||
|
const auto fsz = strlen( function );
|
||||||
|
const auto ssz = strlen( source );
|
||||||
|
const uint32_t sz = uint32_t( 4 + 4 + 4 + fsz + 1 + ssz + 1 + nameSz );
|
||||||
|
auto ptr = (char*)tracy_malloc( sz );
|
||||||
|
memcpy( ptr, &sz, 4 );
|
||||||
|
memset( ptr + 4, 0, 4 );
|
||||||
|
memcpy( ptr + 8, &line, 4 );
|
||||||
|
memcpy( ptr + 12, function, fsz+1 );
|
||||||
|
memcpy( ptr + 12 + fsz + 1, source, ssz + 1 );
|
||||||
|
memcpy( ptr + 12 + fsz + 1 + ssz + 1, name, nameSz );
|
||||||
|
return uint64_t( ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class DequeueStatus { DataDequeued, ConnectionLost, QueueEmpty };
|
||||||
|
|
||||||
|
static void LaunchWorker( void* ptr ) { ((Profiler*)ptr)->Worker(); }
|
||||||
|
void Worker();
|
||||||
|
|
||||||
|
static void LaunchCompressWorker( void* ptr ) { ((Profiler*)ptr)->CompressWorker(); }
|
||||||
|
void CompressWorker();
|
||||||
|
|
||||||
|
void ClearQueues( tracy::moodycamel::ConsumerToken& token );
|
||||||
|
void ClearSerial();
|
||||||
|
DequeueStatus Dequeue( tracy::moodycamel::ConsumerToken& token );
|
||||||
|
DequeueStatus DequeueContextSwitches( tracy::moodycamel::ConsumerToken& token, int64_t& timeStop );
|
||||||
|
DequeueStatus DequeueSerial();
|
||||||
|
bool CommitData();
|
||||||
|
|
||||||
|
tracy_force_inline bool AppendData( const void* data, size_t len )
|
||||||
|
{
|
||||||
|
const auto ret = NeedDataSize( len );
|
||||||
|
AppendDataUnsafe( data, len );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline bool NeedDataSize( size_t len )
|
||||||
|
{
|
||||||
|
assert( len <= TargetFrameSize );
|
||||||
|
bool ret = true;
|
||||||
|
if( m_bufferOffset - m_bufferStart + len > TargetFrameSize )
|
||||||
|
{
|
||||||
|
ret = CommitData();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline void AppendDataUnsafe( const void* data, size_t len )
|
||||||
|
{
|
||||||
|
memcpy( m_buffer + m_bufferOffset, data, len );
|
||||||
|
m_bufferOffset += int( len );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SendData( const char* data, size_t len );
|
||||||
|
void SendLongString( uint64_t ptr, const char* str, size_t len, QueueType type );
|
||||||
|
void SendSourceLocation( uint64_t ptr );
|
||||||
|
void SendSourceLocationPayload( uint64_t ptr );
|
||||||
|
void SendCallstackPayload( uint64_t ptr );
|
||||||
|
void SendCallstackPayload64( uint64_t ptr );
|
||||||
|
void SendCallstackAlloc( uint64_t ptr );
|
||||||
|
void SendCallstackFrame( uint64_t ptr );
|
||||||
|
void SendCodeLocation( uint64_t ptr );
|
||||||
|
|
||||||
|
bool HandleServerQuery();
|
||||||
|
void HandleDisconnect();
|
||||||
|
void HandleParameter( uint64_t payload );
|
||||||
|
void HandleSymbolQuery( uint64_t symbol );
|
||||||
|
void HandleSymbolCodeQuery( uint64_t symbol, uint32_t size );
|
||||||
|
|
||||||
|
void CalibrateTimer();
|
||||||
|
void CalibrateDelay();
|
||||||
|
void ReportTopology();
|
||||||
|
|
||||||
|
static tracy_force_inline void SendCallstackMemory( void* ptr )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_HAS_CALLSTACK
|
||||||
|
auto item = GetProfiler().m_serialQueue.prepare_next();
|
||||||
|
MemWrite( &item->hdr.type, QueueType::CallstackMemory );
|
||||||
|
MemWrite( &item->callstackMemory.ptr, (uint64_t)ptr );
|
||||||
|
GetProfiler().m_serialQueue.commit_next();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void SendMemAlloc( QueueType type, const uint64_t thread, const void* ptr, size_t size )
|
||||||
|
{
|
||||||
|
assert( type == QueueType::MemAlloc || type == QueueType::MemAllocCallstack );
|
||||||
|
|
||||||
|
auto item = GetProfiler().m_serialQueue.prepare_next();
|
||||||
|
MemWrite( &item->hdr.type, type );
|
||||||
|
MemWrite( &item->memAlloc.time, GetTime() );
|
||||||
|
MemWrite( &item->memAlloc.thread, thread );
|
||||||
|
MemWrite( &item->memAlloc.ptr, (uint64_t)ptr );
|
||||||
|
if( compile_time_condition<sizeof( size ) == 4>::value )
|
||||||
|
{
|
||||||
|
memcpy( &item->memAlloc.size, &size, 4 );
|
||||||
|
memset( &item->memAlloc.size + 4, 0, 2 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( sizeof( size ) == 8 );
|
||||||
|
memcpy( &item->memAlloc.size, &size, 4 );
|
||||||
|
memcpy( ((char*)&item->memAlloc.size)+4, ((char*)&size)+4, 2 );
|
||||||
|
}
|
||||||
|
GetProfiler().m_serialQueue.commit_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
static tracy_force_inline void SendMemFree( QueueType type, const uint64_t thread, const void* ptr )
|
||||||
|
{
|
||||||
|
assert( type == QueueType::MemFree || type == QueueType::MemFreeCallstack );
|
||||||
|
|
||||||
|
auto item = GetProfiler().m_serialQueue.prepare_next();
|
||||||
|
MemWrite( &item->hdr.type, type );
|
||||||
|
MemWrite( &item->memFree.time, GetTime() );
|
||||||
|
MemWrite( &item->memFree.thread, thread );
|
||||||
|
MemWrite( &item->memFree.ptr, (uint64_t)ptr );
|
||||||
|
GetProfiler().m_serialQueue.commit_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ( defined _WIN32 || defined __CYGWIN__ ) && defined TRACY_TIMER_QPC
|
||||||
|
static int64_t GetTimeQpc();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
double m_timerMul;
|
||||||
|
uint64_t m_resolution;
|
||||||
|
uint64_t m_delay;
|
||||||
|
std::atomic<int64_t> m_timeBegin;
|
||||||
|
uint64_t m_mainThread;
|
||||||
|
uint64_t m_epoch;
|
||||||
|
std::atomic<bool> m_shutdown;
|
||||||
|
std::atomic<bool> m_shutdownManual;
|
||||||
|
std::atomic<bool> m_shutdownFinished;
|
||||||
|
Socket* m_sock;
|
||||||
|
UdpBroadcast* m_broadcast;
|
||||||
|
bool m_noExit;
|
||||||
|
uint32_t m_userPort;
|
||||||
|
std::atomic<uint32_t> m_zoneId;
|
||||||
|
int64_t m_samplingPeriod;
|
||||||
|
|
||||||
|
uint64_t m_threadCtx;
|
||||||
|
int64_t m_refTimeThread;
|
||||||
|
int64_t m_refTimeSerial;
|
||||||
|
int64_t m_refTimeCtx;
|
||||||
|
int64_t m_refTimeGpu;
|
||||||
|
|
||||||
|
void* m_stream; // LZ4_stream_t*
|
||||||
|
char* m_buffer;
|
||||||
|
int m_bufferOffset;
|
||||||
|
int m_bufferStart;
|
||||||
|
|
||||||
|
char* m_lz4Buf;
|
||||||
|
|
||||||
|
FastVector<QueueItem> m_serialQueue, m_serialDequeue;
|
||||||
|
TracyMutex m_serialLock;
|
||||||
|
|
||||||
|
FastVector<FrameImageQueueItem> m_fiQueue, m_fiDequeue;
|
||||||
|
TracyMutex m_fiLock;
|
||||||
|
|
||||||
|
std::atomic<uint64_t> m_frameCount;
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
std::atomic<bool> m_isConnected;
|
||||||
|
std::atomic<uint64_t> m_connectionId;
|
||||||
|
|
||||||
|
TracyMutex m_deferredLock;
|
||||||
|
FastVector<QueueItem> m_deferredQueue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRACY_HAS_SYSTIME
|
||||||
|
void ProcessSysTime();
|
||||||
|
|
||||||
|
SysTime m_sysTime;
|
||||||
|
uint64_t m_sysTimeLast = 0;
|
||||||
|
#else
|
||||||
|
void ProcessSysTime() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ParameterCallback m_paramCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
114
client/TracyScoped.hpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#ifndef __TRACYSCOPED_HPP__
|
||||||
|
#define __TRACYSCOPED_HPP__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../common/TracySystem.hpp"
|
||||||
|
#include "../common/TracyAlign.hpp"
|
||||||
|
#include "../common/TracyAlloc.hpp"
|
||||||
|
#include "TracyProfiler.hpp"
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
class ScopedZone
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
tracy_force_inline ScopedZone( const SourceLocationData* srcloc, bool is_active = true )
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
: m_active( is_active && GetProfiler().IsConnected() )
|
||||||
|
#else
|
||||||
|
: m_active( is_active )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if( !m_active ) return;
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
m_connectionId = GetProfiler().ConnectionId();
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( QueueType::ZoneBegin );
|
||||||
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->zoneBegin.srcloc, (uint64_t)srcloc );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline ScopedZone( const SourceLocationData* srcloc, int depth, bool is_active = true )
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
: m_active( is_active && GetProfiler().IsConnected() )
|
||||||
|
#else
|
||||||
|
: m_active( is_active )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if( !m_active ) return;
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
m_connectionId = GetProfiler().ConnectionId();
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( QueueType::ZoneBeginCallstack );
|
||||||
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
||||||
|
MemWrite( &item->zoneBegin.srcloc, (uint64_t)srcloc );
|
||||||
|
TracyLfqCommit;
|
||||||
|
|
||||||
|
GetProfiler().SendCallstack( depth );
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline ~ScopedZone()
|
||||||
|
{
|
||||||
|
if( !m_active ) return;
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( GetProfiler().ConnectionId() != m_connectionId ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( QueueType::ZoneEnd );
|
||||||
|
MemWrite( &item->zoneEnd.time, Profiler::GetTime() );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline void Text( const char* txt, size_t size )
|
||||||
|
{
|
||||||
|
if( !m_active ) return;
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( GetProfiler().ConnectionId() != m_connectionId ) return;
|
||||||
|
#endif
|
||||||
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
|
memcpy( ptr, txt, size );
|
||||||
|
ptr[size] = '\0';
|
||||||
|
TracyLfqPrepare( QueueType::ZoneText );
|
||||||
|
MemWrite( &item->zoneText.text, (uint64_t)ptr );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline void Name( const char* txt, size_t size )
|
||||||
|
{
|
||||||
|
if( !m_active ) return;
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( GetProfiler().ConnectionId() != m_connectionId ) return;
|
||||||
|
#endif
|
||||||
|
auto ptr = (char*)tracy_malloc( size+1 );
|
||||||
|
memcpy( ptr, txt, size );
|
||||||
|
ptr[size] = '\0';
|
||||||
|
TracyLfqPrepare( QueueType::ZoneName );
|
||||||
|
MemWrite( &item->zoneText.text, (uint64_t)ptr );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_force_inline void Value( uint64_t value )
|
||||||
|
{
|
||||||
|
if( !m_active ) return;
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( GetProfiler().ConnectionId() != m_connectionId ) return;
|
||||||
|
#endif
|
||||||
|
TracyLfqPrepare( QueueType::ZoneValue );
|
||||||
|
MemWrite( &item->zoneValue.value, value );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const bool m_active;
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
uint64_t m_connectionId;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#ifdef TRACY_HAS_SYSTIME
|
#ifdef TRACY_HAS_SYSTIME
|
||||||
|
|
||||||
# if defined _WIN32
|
# if defined _WIN32 || defined __CYGWIN__
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# elif defined __linux__
|
# elif defined __linux__
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
@ -18,7 +18,7 @@
|
|||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
|
|
||||||
# if defined _WIN32
|
# if defined _WIN32 || defined __CYGWIN__
|
||||||
|
|
||||||
static inline uint64_t ConvertTime( const FILETIME& t )
|
static inline uint64_t ConvertTime( const FILETIME& t )
|
||||||
{
|
{
|
||||||
@ -95,7 +95,7 @@ float SysTime::Get()
|
|||||||
const auto diffIdle = idle - oldIdle;
|
const auto diffIdle = idle - oldIdle;
|
||||||
const auto diffUsed = used - oldUsed;
|
const auto diffUsed = used - oldUsed;
|
||||||
|
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
return diffUsed == 0 ? -1 : ( diffUsed - diffIdle ) * 100.f / diffUsed;
|
return diffUsed == 0 ? -1 : ( diffUsed - diffIdle ) * 100.f / diffUsed;
|
||||||
#elif defined __linux__ || defined __APPLE__ || defined BSD
|
#elif defined __linux__ || defined __APPLE__ || defined BSD
|
||||||
const auto total = diffUsed + diffIdle;
|
const auto total = diffUsed + diffIdle;
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef __TRACYSYSTIME_HPP__
|
#ifndef __TRACYSYSTIME_HPP__
|
||||||
#define __TRACYSYSTIME_HPP__
|
#define __TRACYSYSTIME_HPP__
|
||||||
|
|
||||||
#if defined _WIN32 || defined __linux__ || defined __APPLE__
|
#if defined _WIN32 || defined __CYGWIN__ || defined __linux__ || defined __APPLE__
|
||||||
# define TRACY_HAS_SYSTIME
|
# define TRACY_HAS_SYSTIME
|
||||||
#else
|
#else
|
||||||
# include <sys/param.h>
|
# include <sys/param.h>
|
954
client/TracySysTrace.cpp
Normal file
@ -0,0 +1,954 @@
|
|||||||
|
#include "TracySysTrace.hpp"
|
||||||
|
|
||||||
|
#ifdef TRACY_HAS_SYSTEM_TRACING
|
||||||
|
|
||||||
|
# if defined _WIN32 || defined __CYGWIN__
|
||||||
|
|
||||||
|
# ifndef NOMINMAX
|
||||||
|
# define NOMINMAX
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define INITGUID
|
||||||
|
# include <assert.h>
|
||||||
|
# include <string.h>
|
||||||
|
# include <windows.h>
|
||||||
|
# include <dbghelp.h>
|
||||||
|
# include <evntrace.h>
|
||||||
|
# include <evntcons.h>
|
||||||
|
# include <psapi.h>
|
||||||
|
# include <winternl.h>
|
||||||
|
|
||||||
|
# include "../common/TracyAlloc.hpp"
|
||||||
|
# include "../common/TracySystem.hpp"
|
||||||
|
# include "TracyProfiler.hpp"
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
DEFINE_GUID ( /* ce1dbfb4-137e-4da6-87b0-3f59aa102cbc */
|
||||||
|
PerfInfoGuid,
|
||||||
|
0xce1dbfb4,
|
||||||
|
0x137e,
|
||||||
|
0x4da6,
|
||||||
|
0x87, 0xb0, 0x3f, 0x59, 0xaa, 0x10, 0x2c, 0xbc
|
||||||
|
);
|
||||||
|
|
||||||
|
static TRACEHANDLE s_traceHandle;
|
||||||
|
static TRACEHANDLE s_traceHandle2;
|
||||||
|
static EVENT_TRACE_PROPERTIES* s_prop;
|
||||||
|
static DWORD s_pid;
|
||||||
|
|
||||||
|
struct CSwitch
|
||||||
|
{
|
||||||
|
uint32_t newThreadId;
|
||||||
|
uint32_t oldThreadId;
|
||||||
|
int8_t newThreadPriority;
|
||||||
|
int8_t oldThreadPriority;
|
||||||
|
uint8_t previousCState;
|
||||||
|
int8_t spareByte;
|
||||||
|
int8_t oldThreadWaitReason;
|
||||||
|
int8_t oldThreadWaitMode;
|
||||||
|
int8_t oldThreadState;
|
||||||
|
int8_t oldThreadWaitIdealProcessor;
|
||||||
|
uint32_t newThreadWaitTime;
|
||||||
|
uint32_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ReadyThread
|
||||||
|
{
|
||||||
|
uint32_t threadId;
|
||||||
|
int8_t adjustReason;
|
||||||
|
int8_t adjustIncrement;
|
||||||
|
int8_t flag;
|
||||||
|
int8_t reserverd;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThreadTrace
|
||||||
|
{
|
||||||
|
uint32_t processId;
|
||||||
|
uint32_t threadId;
|
||||||
|
uint32_t stackBase;
|
||||||
|
uint32_t stackLimit;
|
||||||
|
uint32_t userStackBase;
|
||||||
|
uint32_t userStackLimit;
|
||||||
|
uint32_t startAddr;
|
||||||
|
uint32_t win32StartAddr;
|
||||||
|
uint32_t tebBase;
|
||||||
|
uint32_t subProcessTag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StackWalkEvent
|
||||||
|
{
|
||||||
|
uint64_t eventTimeStamp;
|
||||||
|
uint32_t stackProcess;
|
||||||
|
uint32_t stackThread;
|
||||||
|
uint64_t stack[192];
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
extern "C" typedef DWORD (WINAPI *t_GetProcessIdOfThread)( HANDLE );
|
||||||
|
extern "C" typedef DWORD (WINAPI *t_GetProcessImageFileNameA)( HANDLE, LPSTR, DWORD );
|
||||||
|
extern "C" ULONG WMIAPI TraceSetInformation(TRACEHANDLE SessionHandle, TRACE_INFO_CLASS InformationClass, PVOID TraceInformation, ULONG InformationLength);
|
||||||
|
t_GetProcessIdOfThread GetProcessIdOfThread = (t_GetProcessIdOfThread)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "GetProcessIdOfThread" );
|
||||||
|
t_GetProcessImageFileNameA GetProcessImageFileNameA = (t_GetProcessImageFileNameA)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "K32GetProcessImageFileNameA" );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" typedef NTSTATUS (WINAPI *t_NtQueryInformationThread)( HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG );
|
||||||
|
extern "C" typedef BOOL (WINAPI *t_EnumProcessModules)( HANDLE, HMODULE*, DWORD, LPDWORD );
|
||||||
|
extern "C" typedef BOOL (WINAPI *t_GetModuleInformation)( HANDLE, HMODULE, LPMODULEINFO, DWORD );
|
||||||
|
extern "C" typedef DWORD (WINAPI *t_GetModuleBaseNameA)( HANDLE, HMODULE, LPSTR, DWORD );
|
||||||
|
extern "C" typedef HRESULT (WINAPI *t_GetThreadDescription)( HANDLE, PWSTR* );
|
||||||
|
|
||||||
|
t_NtQueryInformationThread NtQueryInformationThread = (t_NtQueryInformationThread)GetProcAddress( GetModuleHandleA( "ntdll.dll" ), "NtQueryInformationThread" );
|
||||||
|
t_EnumProcessModules _EnumProcessModules = (t_EnumProcessModules)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "K32EnumProcessModules" );
|
||||||
|
t_GetModuleInformation _GetModuleInformation = (t_GetModuleInformation)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "K32GetModuleInformation" );
|
||||||
|
t_GetModuleBaseNameA _GetModuleBaseNameA = (t_GetModuleBaseNameA)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "K32GetModuleBaseNameA" );
|
||||||
|
|
||||||
|
static t_GetThreadDescription _GetThreadDescription = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void WINAPI EventRecordCallback( PEVENT_RECORD record )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const auto& hdr = record->EventHeader;
|
||||||
|
switch( hdr.ProviderId.Data1 )
|
||||||
|
{
|
||||||
|
case 0x3d6fa8d1: // Thread Guid
|
||||||
|
if( hdr.EventDescriptor.Opcode == 36 )
|
||||||
|
{
|
||||||
|
const auto cswitch = (const CSwitch*)record->UserData;
|
||||||
|
|
||||||
|
TracyLfqPrepare( QueueType::ContextSwitch );
|
||||||
|
MemWrite( &item->contextSwitch.time, hdr.TimeStamp.QuadPart );
|
||||||
|
memcpy( &item->contextSwitch.oldThread, &cswitch->oldThreadId, sizeof( cswitch->oldThreadId ) );
|
||||||
|
memcpy( &item->contextSwitch.newThread, &cswitch->newThreadId, sizeof( cswitch->newThreadId ) );
|
||||||
|
memset( ((char*)&item->contextSwitch.oldThread)+4, 0, 4 );
|
||||||
|
memset( ((char*)&item->contextSwitch.newThread)+4, 0, 4 );
|
||||||
|
MemWrite( &item->contextSwitch.cpu, record->BufferContext.ProcessorNumber );
|
||||||
|
MemWrite( &item->contextSwitch.reason, cswitch->oldThreadWaitReason );
|
||||||
|
MemWrite( &item->contextSwitch.state, cswitch->oldThreadState );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
else if( hdr.EventDescriptor.Opcode == 50 )
|
||||||
|
{
|
||||||
|
const auto rt = (const ReadyThread*)record->UserData;
|
||||||
|
|
||||||
|
TracyLfqPrepare( QueueType::ThreadWakeup );
|
||||||
|
MemWrite( &item->threadWakeup.time, hdr.TimeStamp.QuadPart );
|
||||||
|
memcpy( &item->threadWakeup.thread, &rt->threadId, sizeof( rt->threadId ) );
|
||||||
|
memset( ((char*)&item->threadWakeup.thread)+4, 0, 4 );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
else if( hdr.EventDescriptor.Opcode == 1 || hdr.EventDescriptor.Opcode == 3 )
|
||||||
|
{
|
||||||
|
const auto tt = (const ThreadTrace*)record->UserData;
|
||||||
|
|
||||||
|
uint64_t tid = tt->threadId;
|
||||||
|
if( tid == 0 ) return;
|
||||||
|
uint64_t pid = tt->processId;
|
||||||
|
TracyLfqPrepare( QueueType::TidToPid );
|
||||||
|
MemWrite( &item->tidToPid.tid, tid );
|
||||||
|
MemWrite( &item->tidToPid.pid, pid );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xdef2fe46: // StackWalk Guid
|
||||||
|
if( hdr.EventDescriptor.Opcode == 32 )
|
||||||
|
{
|
||||||
|
const auto sw = (const StackWalkEvent*)record->UserData;
|
||||||
|
if( sw->stackProcess == s_pid && ( sw->stack[0] & 0x8000000000000000 ) == 0 )
|
||||||
|
{
|
||||||
|
const uint64_t sz = ( record->UserDataLength - 16 ) / 8;
|
||||||
|
if( sz > 0 )
|
||||||
|
{
|
||||||
|
auto trace = (uint64_t*)tracy_malloc( ( 1 + sz ) * sizeof( uint64_t ) );
|
||||||
|
memcpy( trace, &sz, sizeof( uint64_t ) );
|
||||||
|
memcpy( trace+1, sw->stack, sizeof( uint64_t ) * sz );
|
||||||
|
TracyLfqPrepare( QueueType::CallstackSample );
|
||||||
|
MemWrite( &item->callstackSample.time, sw->eventTimeStamp );
|
||||||
|
MemWrite( &item->callstackSample.thread, (uint64_t)sw->stackThread );
|
||||||
|
MemWrite( &item->callstackSample.ptr, (uint64_t)trace );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SysTraceStart( int64_t& samplingPeriod )
|
||||||
|
{
|
||||||
|
if( !_GetThreadDescription ) _GetThreadDescription = (t_GetThreadDescription)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "GetThreadDescription" );
|
||||||
|
|
||||||
|
s_pid = GetCurrentProcessId();
|
||||||
|
|
||||||
|
#if defined _WIN64
|
||||||
|
constexpr bool isOs64Bit = true;
|
||||||
|
#else
|
||||||
|
BOOL _iswow64;
|
||||||
|
IsWow64Process( GetCurrentProcess(), &_iswow64 );
|
||||||
|
const bool isOs64Bit = _iswow64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TOKEN_PRIVILEGES priv = {};
|
||||||
|
priv.PrivilegeCount = 1;
|
||||||
|
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
if( LookupPrivilegeValue( nullptr, SE_SYSTEM_PROFILE_NAME, &priv.Privileges[0].Luid ) == 0 ) return false;
|
||||||
|
|
||||||
|
HANDLE pt;
|
||||||
|
if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &pt ) == 0 ) return false;
|
||||||
|
const auto adjust = AdjustTokenPrivileges( pt, FALSE, &priv, 0, nullptr, nullptr );
|
||||||
|
CloseHandle( pt );
|
||||||
|
if( adjust == 0 ) return false;
|
||||||
|
const auto status = GetLastError();
|
||||||
|
if( status != ERROR_SUCCESS ) return false;
|
||||||
|
|
||||||
|
if( isOs64Bit )
|
||||||
|
{
|
||||||
|
TRACE_PROFILE_INTERVAL interval = {};
|
||||||
|
interval.Interval = 1250; // 8 kHz
|
||||||
|
const auto intervalStatus = TraceSetInformation( 0, TraceSampledProfileIntervalInfo, &interval, sizeof( interval ) );
|
||||||
|
if( intervalStatus != ERROR_SUCCESS ) return false;
|
||||||
|
samplingPeriod = 125*1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto psz = sizeof( EVENT_TRACE_PROPERTIES ) + sizeof( KERNEL_LOGGER_NAME );
|
||||||
|
s_prop = (EVENT_TRACE_PROPERTIES*)tracy_malloc( psz );
|
||||||
|
memset( s_prop, 0, sizeof( EVENT_TRACE_PROPERTIES ) );
|
||||||
|
ULONG flags = EVENT_TRACE_FLAG_CSWITCH | EVENT_TRACE_FLAG_DISPATCHER | EVENT_TRACE_FLAG_THREAD;
|
||||||
|
if( isOs64Bit ) flags |= EVENT_TRACE_FLAG_PROFILE;
|
||||||
|
s_prop->EnableFlags = flags;
|
||||||
|
s_prop->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
|
||||||
|
s_prop->Wnode.BufferSize = psz;
|
||||||
|
s_prop->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
||||||
|
#ifdef TRACY_TIMER_QPC
|
||||||
|
s_prop->Wnode.ClientContext = 1;
|
||||||
|
#else
|
||||||
|
s_prop->Wnode.ClientContext = 3;
|
||||||
|
#endif
|
||||||
|
s_prop->Wnode.Guid = SystemTraceControlGuid;
|
||||||
|
s_prop->BufferSize = 1024;
|
||||||
|
s_prop->LoggerNameOffset = sizeof( EVENT_TRACE_PROPERTIES );
|
||||||
|
memcpy( ((char*)s_prop) + sizeof( EVENT_TRACE_PROPERTIES ), KERNEL_LOGGER_NAME, sizeof( KERNEL_LOGGER_NAME ) );
|
||||||
|
|
||||||
|
auto backup = tracy_malloc( psz );
|
||||||
|
memcpy( backup, s_prop, psz );
|
||||||
|
|
||||||
|
const auto controlStatus = ControlTrace( 0, KERNEL_LOGGER_NAME, s_prop, EVENT_TRACE_CONTROL_STOP );
|
||||||
|
if( controlStatus != ERROR_SUCCESS && controlStatus != ERROR_WMI_INSTANCE_NOT_FOUND )
|
||||||
|
{
|
||||||
|
tracy_free( s_prop );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy( s_prop, backup, psz );
|
||||||
|
tracy_free( backup );
|
||||||
|
|
||||||
|
const auto startStatus = StartTrace( &s_traceHandle, KERNEL_LOGGER_NAME, s_prop );
|
||||||
|
if( startStatus != ERROR_SUCCESS )
|
||||||
|
{
|
||||||
|
tracy_free( s_prop );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isOs64Bit )
|
||||||
|
{
|
||||||
|
CLASSIC_EVENT_ID stackId;
|
||||||
|
stackId.EventGuid = PerfInfoGuid;
|
||||||
|
stackId.Type = 46;
|
||||||
|
const auto stackStatus = TraceSetInformation( s_traceHandle, TraceStackTracingInfo, &stackId, sizeof( stackId ) );
|
||||||
|
if( stackStatus != ERROR_SUCCESS )
|
||||||
|
{
|
||||||
|
tracy_free( s_prop );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
WCHAR KernelLoggerName[sizeof( KERNEL_LOGGER_NAME )];
|
||||||
|
#else
|
||||||
|
char KernelLoggerName[sizeof( KERNEL_LOGGER_NAME )];
|
||||||
|
#endif
|
||||||
|
memcpy( KernelLoggerName, KERNEL_LOGGER_NAME, sizeof( KERNEL_LOGGER_NAME ) );
|
||||||
|
EVENT_TRACE_LOGFILE log = {};
|
||||||
|
log.LoggerName = KernelLoggerName;
|
||||||
|
log.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD | PROCESS_TRACE_MODE_RAW_TIMESTAMP;
|
||||||
|
log.EventRecordCallback = EventRecordCallback;
|
||||||
|
|
||||||
|
s_traceHandle2 = OpenTrace( &log );
|
||||||
|
if( s_traceHandle2 == (TRACEHANDLE)INVALID_HANDLE_VALUE )
|
||||||
|
{
|
||||||
|
CloseTrace( s_traceHandle );
|
||||||
|
tracy_free( s_prop );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysTraceStop()
|
||||||
|
{
|
||||||
|
CloseTrace( s_traceHandle2 );
|
||||||
|
CloseTrace( s_traceHandle );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysTraceWorker( void* ptr )
|
||||||
|
{
|
||||||
|
SetThreadName( "Tracy SysTrace" );
|
||||||
|
ProcessTrace( &s_traceHandle2, 1, 0, 0 );
|
||||||
|
ControlTrace( 0, KERNEL_LOGGER_NAME, s_prop, EVENT_TRACE_CONTROL_STOP );
|
||||||
|
tracy_free( s_prop );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysTraceSendExternalName( uint64_t thread )
|
||||||
|
{
|
||||||
|
bool threadSent = false;
|
||||||
|
auto hnd = OpenThread( THREAD_QUERY_INFORMATION, FALSE, DWORD( thread ) );
|
||||||
|
if( hnd == 0 )
|
||||||
|
{
|
||||||
|
hnd = OpenThread( THREAD_QUERY_LIMITED_INFORMATION, FALSE, DWORD( thread ) );
|
||||||
|
}
|
||||||
|
if( hnd != 0 )
|
||||||
|
{
|
||||||
|
PWSTR tmp;
|
||||||
|
_GetThreadDescription( hnd, &tmp );
|
||||||
|
char buf[256];
|
||||||
|
if( tmp )
|
||||||
|
{
|
||||||
|
auto ret = wcstombs( buf, tmp, 256 );
|
||||||
|
if( ret != 0 )
|
||||||
|
{
|
||||||
|
GetProfiler().SendString( thread, buf, QueueType::ExternalThreadName );
|
||||||
|
threadSent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto pid = GetProcessIdOfThread( hnd );
|
||||||
|
if( !threadSent && NtQueryInformationThread && _EnumProcessModules && _GetModuleInformation && _GetModuleBaseNameA )
|
||||||
|
{
|
||||||
|
void* ptr;
|
||||||
|
ULONG retlen;
|
||||||
|
auto status = NtQueryInformationThread( hnd, (THREADINFOCLASS)9 /*ThreadQuerySetWin32StartAddress*/, &ptr, sizeof( &ptr ), &retlen );
|
||||||
|
if( status == 0 )
|
||||||
|
{
|
||||||
|
const auto phnd = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid );
|
||||||
|
if( phnd != INVALID_HANDLE_VALUE )
|
||||||
|
{
|
||||||
|
HMODULE modules[1024];
|
||||||
|
DWORD needed;
|
||||||
|
if( _EnumProcessModules( phnd, modules, 1024 * sizeof( HMODULE ), &needed ) != 0 )
|
||||||
|
{
|
||||||
|
const auto sz = std::min( DWORD( needed / sizeof( HMODULE ) ), DWORD( 1024 ) );
|
||||||
|
for( DWORD i=0; i<sz; i++ )
|
||||||
|
{
|
||||||
|
MODULEINFO info;
|
||||||
|
if( _GetModuleInformation( phnd, modules[i], &info, sizeof( info ) ) != 0 )
|
||||||
|
{
|
||||||
|
if( (uint64_t)ptr >= (uint64_t)info.lpBaseOfDll && (uint64_t)ptr <= (uint64_t)info.lpBaseOfDll + (uint64_t)info.SizeOfImage )
|
||||||
|
{
|
||||||
|
char buf2[1024];
|
||||||
|
if( _GetModuleBaseNameA( phnd, modules[i], buf2, 1024 ) != 0 )
|
||||||
|
{
|
||||||
|
GetProfiler().SendString( thread, buf2, QueueType::ExternalThreadName );
|
||||||
|
threadSent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle( phnd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle( hnd );
|
||||||
|
if( !threadSent )
|
||||||
|
{
|
||||||
|
GetProfiler().SendString( thread, "???", QueueType::ExternalThreadName );
|
||||||
|
threadSent = true;
|
||||||
|
}
|
||||||
|
if( pid != 0 )
|
||||||
|
{
|
||||||
|
{
|
||||||
|
uint64_t _pid = pid;
|
||||||
|
TracyLfqPrepare( QueueType::TidToPid );
|
||||||
|
MemWrite( &item->tidToPid.tid, thread );
|
||||||
|
MemWrite( &item->tidToPid.pid, _pid );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
if( pid == 4 )
|
||||||
|
{
|
||||||
|
GetProfiler().SendString( thread, "System", QueueType::ExternalName );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto phnd = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid );
|
||||||
|
if( phnd != INVALID_HANDLE_VALUE )
|
||||||
|
{
|
||||||
|
char buf2[1024];
|
||||||
|
const auto sz = GetProcessImageFileNameA( phnd, buf2, 1024 );
|
||||||
|
CloseHandle( phnd );
|
||||||
|
if( sz != 0 )
|
||||||
|
{
|
||||||
|
auto ptr = buf2 + sz - 1;
|
||||||
|
while( ptr > buf2 && *ptr != '\\' ) ptr--;
|
||||||
|
if( *ptr == '\\' ) ptr++;
|
||||||
|
GetProfiler().SendString( thread, ptr, QueueType::ExternalName );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !threadSent )
|
||||||
|
{
|
||||||
|
GetProfiler().SendString( thread, "???", QueueType::ExternalThreadName );
|
||||||
|
}
|
||||||
|
GetProfiler().SendString( thread, "???", QueueType::ExternalName );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# elif defined __linux__
|
||||||
|
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <sys/wait.h>
|
||||||
|
# include <fcntl.h>
|
||||||
|
# include <inttypes.h>
|
||||||
|
# include <limits>
|
||||||
|
# include <poll.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <string.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <atomic>
|
||||||
|
|
||||||
|
# include "TracyProfiler.hpp"
|
||||||
|
|
||||||
|
# ifdef __ANDROID__
|
||||||
|
# include "TracySysTracePayload.hpp"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
static const char BasePath[] = "/sys/kernel/debug/tracing/";
|
||||||
|
static const char TracingOn[] = "tracing_on";
|
||||||
|
static const char CurrentTracer[] = "current_tracer";
|
||||||
|
static const char TraceOptions[] = "trace_options";
|
||||||
|
static const char TraceClock[] = "trace_clock";
|
||||||
|
static const char SchedSwitch[] = "events/sched/sched_switch/enable";
|
||||||
|
static const char SchedWakeup[] = "events/sched/sched_wakeup/enable";
|
||||||
|
static const char BufferSizeKb[] = "buffer_size_kb";
|
||||||
|
static const char TracePipe[] = "trace_pipe";
|
||||||
|
|
||||||
|
static std::atomic<bool> traceActive { false };
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
static bool TraceWrite( const char* path, size_t psz, const char* val, size_t vsz )
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
sprintf( tmp, "su -c 'echo \"%s\" > %s%s'", val, BasePath, path );
|
||||||
|
return system( tmp ) == 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static bool TraceWrite( const char* path, size_t psz, const char* val, size_t vsz )
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
memcpy( tmp, BasePath, sizeof( BasePath ) - 1 );
|
||||||
|
memcpy( tmp + sizeof( BasePath ) - 1, path, psz );
|
||||||
|
|
||||||
|
int fd = open( tmp, O_WRONLY );
|
||||||
|
if( fd < 0 ) return false;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
ssize_t cnt = write( fd, val, vsz );
|
||||||
|
if( cnt == (ssize_t)vsz )
|
||||||
|
{
|
||||||
|
close( fd );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if( cnt < 0 )
|
||||||
|
{
|
||||||
|
close( fd );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vsz -= cnt;
|
||||||
|
val += cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
void SysTraceInjectPayload()
|
||||||
|
{
|
||||||
|
int pipefd[2];
|
||||||
|
if( pipe( pipefd ) == 0 )
|
||||||
|
{
|
||||||
|
const auto pid = fork();
|
||||||
|
if( pid == 0 )
|
||||||
|
{
|
||||||
|
// child
|
||||||
|
close( pipefd[1] );
|
||||||
|
if( dup2( pipefd[0], STDIN_FILENO ) >= 0 )
|
||||||
|
{
|
||||||
|
close( pipefd[0] );
|
||||||
|
execlp( "su", "su", "-c", "cat > /data/tracy_systrace", (char*)nullptr );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( pid > 0 )
|
||||||
|
{
|
||||||
|
// parent
|
||||||
|
close( pipefd[0] );
|
||||||
|
|
||||||
|
#ifdef __aarch64__
|
||||||
|
write( pipefd[1], tracy_systrace_aarch64_data, tracy_systrace_aarch64_size );
|
||||||
|
#else
|
||||||
|
write( pipefd[1], tracy_systrace_armv7_data, tracy_systrace_armv7_size );
|
||||||
|
#endif
|
||||||
|
close( pipefd[1] );
|
||||||
|
waitpid( pid, nullptr, 0 );
|
||||||
|
|
||||||
|
system( "su -c 'chmod 700 /data/tracy_systrace'" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool SysTraceStart( int64_t& samplingPeriod )
|
||||||
|
{
|
||||||
|
if( !TraceWrite( TracingOn, sizeof( TracingOn ), "0", 2 ) ) return false;
|
||||||
|
if( !TraceWrite( CurrentTracer, sizeof( CurrentTracer ), "nop", 4 ) ) return false;
|
||||||
|
TraceWrite( TraceOptions, sizeof( TraceOptions ), "norecord-cmd", 13 );
|
||||||
|
TraceWrite( TraceOptions, sizeof( TraceOptions ), "norecord-tgid", 14 );
|
||||||
|
TraceWrite( TraceOptions, sizeof( TraceOptions ), "noirq-info", 11 );
|
||||||
|
TraceWrite( TraceOptions, sizeof( TraceOptions ), "noannotate", 11 );
|
||||||
|
#if defined TRACY_HW_TIMER && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )
|
||||||
|
if( !TraceWrite( TraceClock, sizeof( TraceClock ), "x86-tsc", 8 ) ) return false;
|
||||||
|
#elif __ARM_ARCH >= 6
|
||||||
|
if( !TraceWrite( TraceClock, sizeof( TraceClock ), "mono_raw", 9 ) ) return false;
|
||||||
|
#endif
|
||||||
|
if( !TraceWrite( SchedSwitch, sizeof( SchedSwitch ), "1", 2 ) ) return false;
|
||||||
|
if( !TraceWrite( SchedWakeup, sizeof( SchedWakeup ), "1", 2 ) ) return false;
|
||||||
|
if( !TraceWrite( BufferSizeKb, sizeof( BufferSizeKb ), "512", 4 ) ) return false;
|
||||||
|
|
||||||
|
#if defined __ANDROID__ && ( defined __aarch64__ || defined __ARM_ARCH )
|
||||||
|
SysTraceInjectPayload();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( !TraceWrite( TracingOn, sizeof( TracingOn ), "1", 2 ) ) return false;
|
||||||
|
traceActive.store( true, std::memory_order_relaxed );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysTraceStop()
|
||||||
|
{
|
||||||
|
TraceWrite( TracingOn, sizeof( TracingOn ), "0", 2 );
|
||||||
|
traceActive.store( false, std::memory_order_relaxed );
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t ReadNumber( const char*& ptr )
|
||||||
|
{
|
||||||
|
uint64_t val = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if( *ptr >= '0' && *ptr <= '9' )
|
||||||
|
{
|
||||||
|
val = val * 10 + ( *ptr - '0' );
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t ReadState( char state )
|
||||||
|
{
|
||||||
|
switch( state )
|
||||||
|
{
|
||||||
|
case 'D': return 101;
|
||||||
|
case 'I': return 102;
|
||||||
|
case 'R': return 103;
|
||||||
|
case 'S': return 104;
|
||||||
|
case 'T': return 105;
|
||||||
|
case 't': return 106;
|
||||||
|
case 'W': return 107;
|
||||||
|
case 'X': return 108;
|
||||||
|
case 'Z': return 109;
|
||||||
|
default: return 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ < 18
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Christos Zoulas.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
|
||||||
|
{
|
||||||
|
char *ptr, *eptr;
|
||||||
|
|
||||||
|
if (*buf == NULL || *bufsiz == 0) {
|
||||||
|
*bufsiz = BUFSIZ;
|
||||||
|
if ((*buf = (char*)malloc(*bufsiz)) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ptr = *buf, eptr = *buf + *bufsiz;;) {
|
||||||
|
int c = fgetc(fp);
|
||||||
|
if (c == -1) {
|
||||||
|
if (feof(fp))
|
||||||
|
return ptr == *buf ? -1 : ptr - *buf;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*ptr++ = c;
|
||||||
|
if (c == delimiter) {
|
||||||
|
*ptr = '\0';
|
||||||
|
return ptr - *buf;
|
||||||
|
}
|
||||||
|
if (ptr + 2 >= eptr) {
|
||||||
|
char *nbuf;
|
||||||
|
size_t nbufsiz = *bufsiz * 2;
|
||||||
|
ssize_t d = ptr - *buf;
|
||||||
|
if ((nbuf = (char*)realloc(*buf, nbufsiz)) == NULL)
|
||||||
|
return -1;
|
||||||
|
*buf = nbuf;
|
||||||
|
*bufsiz = nbufsiz;
|
||||||
|
eptr = nbuf + nbufsiz;
|
||||||
|
ptr = nbuf + d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t getline(char **buf, size_t *bufsiz, FILE *fp)
|
||||||
|
{
|
||||||
|
return getdelim(buf, bufsiz, '\n', fp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void HandleTraceLine( const char* line )
|
||||||
|
{
|
||||||
|
line += 23;
|
||||||
|
while( *line != '[' ) line++;
|
||||||
|
line++;
|
||||||
|
const auto cpu = (uint8_t)ReadNumber( line );
|
||||||
|
line++; // ']'
|
||||||
|
while( *line == ' ' ) line++;
|
||||||
|
|
||||||
|
#if defined TRACY_HW_TIMER && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )
|
||||||
|
const auto time = ReadNumber( line );
|
||||||
|
#elif __ARM_ARCH >= 6
|
||||||
|
const auto ts = ReadNumber( line );
|
||||||
|
line++; // '.'
|
||||||
|
const auto tus = ReadNumber( line );
|
||||||
|
const auto time = ts * 1000000000ll + tus * 1000ll;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
line += 2; // ': '
|
||||||
|
if( memcmp( line, "sched_switch", 12 ) == 0 )
|
||||||
|
{
|
||||||
|
line += 14;
|
||||||
|
|
||||||
|
while( memcmp( line, "prev_pid", 8 ) != 0 ) line++;
|
||||||
|
line += 9;
|
||||||
|
|
||||||
|
const auto oldPid = ReadNumber( line );
|
||||||
|
line++;
|
||||||
|
|
||||||
|
while( memcmp( line, "prev_state", 10 ) != 0 ) line++;
|
||||||
|
line += 11;
|
||||||
|
|
||||||
|
const auto oldState = (uint8_t)ReadState( *line );
|
||||||
|
line += 5;
|
||||||
|
|
||||||
|
while( memcmp( line, "next_pid", 8 ) != 0 ) line++;
|
||||||
|
line += 9;
|
||||||
|
|
||||||
|
const auto newPid = ReadNumber( line );
|
||||||
|
|
||||||
|
uint8_t reason = 100;
|
||||||
|
|
||||||
|
TracyLfqPrepare( QueueType::ContextSwitch );
|
||||||
|
MemWrite( &item->contextSwitch.time, time );
|
||||||
|
MemWrite( &item->contextSwitch.oldThread, oldPid );
|
||||||
|
MemWrite( &item->contextSwitch.newThread, newPid );
|
||||||
|
MemWrite( &item->contextSwitch.cpu, cpu );
|
||||||
|
MemWrite( &item->contextSwitch.reason, reason );
|
||||||
|
MemWrite( &item->contextSwitch.state, oldState );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
else if( memcmp( line, "sched_wakeup", 12 ) == 0 )
|
||||||
|
{
|
||||||
|
line += 14;
|
||||||
|
|
||||||
|
while( memcmp( line, "pid", 3 ) != 0 ) line++;
|
||||||
|
line += 4;
|
||||||
|
|
||||||
|
const auto pid = ReadNumber( line );
|
||||||
|
|
||||||
|
TracyLfqPrepare( QueueType::ThreadWakeup );
|
||||||
|
MemWrite( &item->threadWakeup.time, time );
|
||||||
|
MemWrite( &item->threadWakeup.thread, pid );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
static void ProcessTraceLines( int fd )
|
||||||
|
{
|
||||||
|
// Linux pipe buffer is 64KB, additional 1KB is for unfinished lines
|
||||||
|
char* buf = (char*)tracy_malloc( (64+1)*1024 );
|
||||||
|
char* line = buf;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if( !traceActive.load( std::memory_order_relaxed ) ) break;
|
||||||
|
|
||||||
|
const auto rd = read( fd, line, 64*1024 );
|
||||||
|
if( rd <= 0 ) break;
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() )
|
||||||
|
{
|
||||||
|
if( rd < 64*1024 )
|
||||||
|
{
|
||||||
|
assert( line[rd-1] == '\n' );
|
||||||
|
line = buf;
|
||||||
|
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto end = line + rd;
|
||||||
|
line = end - 1;
|
||||||
|
while( line > buf && *line != '\n' ) line--;
|
||||||
|
if( line > buf )
|
||||||
|
{
|
||||||
|
line++;
|
||||||
|
const auto lsz = end - line;
|
||||||
|
memmove( buf, line, lsz );
|
||||||
|
line = buf + lsz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const auto end = line + rd;
|
||||||
|
line = buf;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
auto next = line;
|
||||||
|
while( next < end && *next != '\n' ) next++;
|
||||||
|
next++;
|
||||||
|
if( next >= end )
|
||||||
|
{
|
||||||
|
const auto lsz = end - line;
|
||||||
|
memmove( buf, line, lsz );
|
||||||
|
line = buf + lsz;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleTraceLine( line );
|
||||||
|
line = next;
|
||||||
|
}
|
||||||
|
if( rd < 64*1024 )
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_free( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysTraceWorker( void* ptr )
|
||||||
|
{
|
||||||
|
SetThreadName( "Tracy SysTrace" );
|
||||||
|
int pipefd[2];
|
||||||
|
if( pipe( pipefd ) == 0 )
|
||||||
|
{
|
||||||
|
const auto pid = fork();
|
||||||
|
if( pid == 0 )
|
||||||
|
{
|
||||||
|
// child
|
||||||
|
close( pipefd[0] );
|
||||||
|
dup2( pipefd[1], STDERR_FILENO );
|
||||||
|
if( dup2( pipefd[1], STDOUT_FILENO ) >= 0 )
|
||||||
|
{
|
||||||
|
close( pipefd[1] );
|
||||||
|
#if defined __ANDROID__ && ( defined __aarch64__ || defined __ARM_ARCH )
|
||||||
|
execlp( "su", "su", "-c", "/data/tracy_systrace", (char*)nullptr );
|
||||||
|
#endif
|
||||||
|
execlp( "su", "su", "-c", "cat /sys/kernel/debug/tracing/trace_pipe", (char*)nullptr );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( pid > 0 )
|
||||||
|
{
|
||||||
|
// parent
|
||||||
|
close( pipefd[1] );
|
||||||
|
ProcessTraceLines( pipefd[0] );
|
||||||
|
close( pipefd[0] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void ProcessTraceLines( int fd )
|
||||||
|
{
|
||||||
|
char* buf = (char*)tracy_malloc( 64*1024 );
|
||||||
|
|
||||||
|
struct pollfd pfd;
|
||||||
|
pfd.fd = fd;
|
||||||
|
pfd.events = POLLIN | POLLERR;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
while( poll( &pfd, 1, 0 ) <= 0 )
|
||||||
|
{
|
||||||
|
if( !traceActive.load( std::memory_order_relaxed ) ) break;
|
||||||
|
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto rd = read( fd, buf, 64*1024 );
|
||||||
|
if( rd <= 0 ) break;
|
||||||
|
|
||||||
|
#ifdef TRACY_ON_DEMAND
|
||||||
|
if( !GetProfiler().IsConnected() ) continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto line = buf;
|
||||||
|
const auto end = buf + rd;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
auto next = line;
|
||||||
|
while( next < end && *next != '\n' ) next++;
|
||||||
|
if( next == end ) break;
|
||||||
|
assert( *next == '\n' );
|
||||||
|
next++;
|
||||||
|
|
||||||
|
HandleTraceLine( line );
|
||||||
|
line = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tracy_free( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysTraceWorker( void* ptr )
|
||||||
|
{
|
||||||
|
SetThreadName( "Tracy SysTrace" );
|
||||||
|
char tmp[256];
|
||||||
|
memcpy( tmp, BasePath, sizeof( BasePath ) - 1 );
|
||||||
|
memcpy( tmp + sizeof( BasePath ) - 1, TracePipe, sizeof( TracePipe ) );
|
||||||
|
|
||||||
|
int fd = open( tmp, O_RDONLY );
|
||||||
|
if( fd < 0 ) return;
|
||||||
|
ProcessTraceLines( fd );
|
||||||
|
close( fd );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SysTraceSendExternalName( uint64_t thread )
|
||||||
|
{
|
||||||
|
FILE* f;
|
||||||
|
char fn[256];
|
||||||
|
sprintf( fn, "/proc/%" PRIu64 "/comm", thread );
|
||||||
|
f = fopen( fn, "rb" );
|
||||||
|
if( f )
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
const auto sz = fread( buf, 1, 256, f );
|
||||||
|
if( sz > 0 && buf[sz-1] == '\n' ) buf[sz-1] = '\0';
|
||||||
|
GetProfiler().SendString( thread, buf, QueueType::ExternalThreadName );
|
||||||
|
fclose( f );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetProfiler().SendString( thread, "???", QueueType::ExternalThreadName );
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( fn, "/proc/%" PRIu64 "/status", thread );
|
||||||
|
f = fopen( fn, "rb" );
|
||||||
|
if( f )
|
||||||
|
{
|
||||||
|
int pid = -1;
|
||||||
|
size_t lsz = 1024;
|
||||||
|
auto line = (char*)malloc( lsz );
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
auto rd = getline( &line, &lsz, f );
|
||||||
|
if( rd <= 0 ) break;
|
||||||
|
if( memcmp( "Tgid:\t", line, 6 ) == 0 )
|
||||||
|
{
|
||||||
|
pid = atoi( line + 6 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free( line );
|
||||||
|
fclose( f );
|
||||||
|
if( pid >= 0 )
|
||||||
|
{
|
||||||
|
{
|
||||||
|
uint64_t _pid = pid;
|
||||||
|
TracyLfqPrepare( QueueType::TidToPid );
|
||||||
|
MemWrite( &item->tidToPid.tid, thread );
|
||||||
|
MemWrite( &item->tidToPid.pid, _pid );
|
||||||
|
TracyLfqCommit;
|
||||||
|
}
|
||||||
|
sprintf( fn, "/proc/%i/comm", pid );
|
||||||
|
f = fopen( fn, "rb" );
|
||||||
|
if( f )
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
const auto sz = fread( buf, 1, 256, f );
|
||||||
|
if( sz > 0 && buf[sz-1] == '\n' ) buf[sz-1] = '\0';
|
||||||
|
GetProfiler().SendString( thread, buf, QueueType::ExternalName );
|
||||||
|
fclose( f );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GetProfiler().SendString( thread, "???", QueueType::ExternalName );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,11 +1,8 @@
|
|||||||
#ifndef __TRACYSYSTRACE_HPP__
|
#ifndef __TRACYSYSTRACE_HPP__
|
||||||
#define __TRACYSYSTRACE_HPP__
|
#define __TRACYSYSTRACE_HPP__
|
||||||
|
|
||||||
#if !defined TRACY_NO_SYSTEM_TRACING && ( defined _WIN32 || defined __linux__ )
|
#if !defined TRACY_NO_SYSTEM_TRACING && ( defined _WIN32 || defined __CYGWIN__ || defined __linux__ )
|
||||||
# include "../common/TracyUwp.hpp"
|
|
||||||
# ifndef TRACY_UWP
|
|
||||||
# define TRACY_HAS_SYSTEM_TRACING
|
# define TRACY_HAS_SYSTEM_TRACING
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TRACY_HAS_SYSTEM_TRACING
|
#ifdef TRACY_HAS_SYSTEM_TRACING
|
||||||
@ -19,7 +16,7 @@ bool SysTraceStart( int64_t& samplingPeriod );
|
|||||||
void SysTraceStop();
|
void SysTraceStop();
|
||||||
void SysTraceWorker( void* ptr );
|
void SysTraceWorker( void* ptr );
|
||||||
|
|
||||||
void SysTraceGetExternalName( uint64_t thread, const char*& threadName, const char*& name );
|
void SysTraceSendExternalName( uint64_t thread );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
80
client/TracySysTracePayload.hpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// File: '/home/wolf/desktop/tracy_systrace.armv7' (1210 bytes)`
|
||||||
|
// File: '/home/wolf/desktop/tracy_systrace.aarch64' (1650 bytes)
|
||||||
|
|
||||||
|
// Exported using binary_to_compressed_c.cpp
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
static const unsigned int tracy_systrace_armv7_size = 1210;
|
||||||
|
static const unsigned int tracy_systrace_armv7_data[1212/4] =
|
||||||
|
{
|
||||||
|
0x464c457f, 0x00010101, 0x00000000, 0x00000000, 0x00280003, 0x00000001, 0x00000208, 0x00000034, 0x00000000, 0x05000200, 0x00200034, 0x00280007,
|
||||||
|
0x00000000, 0x00000006, 0x00000034, 0x00000034, 0x00000034, 0x000000e0, 0x000000e0, 0x00000004, 0x00000004, 0x00000003, 0x00000114, 0x00000114,
|
||||||
|
0x00000114, 0x00000013, 0x00000013, 0x00000004, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x000003ed, 0x000003ed, 0x00000005,
|
||||||
|
0x00001000, 0x00000001, 0x000003ed, 0x000013ed, 0x000013ed, 0x000000cd, 0x000000cf, 0x00000006, 0x00001000, 0x00000002, 0x000003f0, 0x000013f0,
|
||||||
|
0x000013f0, 0x000000b8, 0x000000b8, 0x00000006, 0x00000004, 0x6474e551, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000006,
|
||||||
|
0x00000010, 0x70000001, 0x00000394, 0x00000394, 0x00000394, 0x00000008, 0x00000008, 0x00000004, 0x00000004, 0x7379732f, 0x2f6d6574, 0x2f6e6962,
|
||||||
|
0x6b6e696c, 0x00007265, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000012, 0x00000016, 0x00000000,
|
||||||
|
0x00000000, 0x00000012, 0x6f6c6400, 0x006e6570, 0x4342494c, 0x62696c00, 0x732e6c64, 0x6c64006f, 0x006d7973, 0x00000001, 0x00000003, 0x00000001,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000001, 0x00020000, 0x00000002, 0x00010001,
|
||||||
|
0x0000000d, 0x00000010, 0x00000000, 0x00050d63, 0x00020000, 0x00000008, 0x00000000, 0x000014b4, 0x00000116, 0x000014b8, 0x00000216, 0xe52de004,
|
||||||
|
0xe59fe004, 0xe08fe00e, 0xe5bef008, 0x000012bc, 0xe28fc600, 0xe28cca01, 0xe5bcf2bc, 0xe28fc600, 0xe28cca01, 0xe5bcf2b4, 0xe92d4ff0, 0xe28db01c,
|
||||||
|
0xe24dd01c, 0xe24dd801, 0xe59f0154, 0xe3a01001, 0xe08f0000, 0xebfffff1, 0xe59f1148, 0xe1a07000, 0xe08f1001, 0xebfffff0, 0xe59f113c, 0xe1a09000,
|
||||||
|
0xe1a00007, 0xe08f1001, 0xebffffeb, 0xe59f112c, 0xe1a04000, 0xe1a00007, 0xe08f1001, 0xebffffe6, 0xe59f111c, 0xe1a05000, 0xe1a00007, 0xe08f1001,
|
||||||
|
0xebffffe1, 0xe59f110c, 0xe1a06000, 0xe1a00007, 0xe08f1001, 0xebffffdc, 0xe58d0004, 0xe1a00007, 0xe59f10f4, 0xe08f1001, 0xebffffd7, 0xe1a0a000,
|
||||||
|
0xe59f00e8, 0xe3a01000, 0xe3a08000, 0xe08f0000, 0xe12fff39, 0xe1a07000, 0xe3700001, 0xca000001, 0xe3a00000, 0xe12fff34, 0xe3a00009, 0xe58d4000,
|
||||||
|
0xe1cd01b4, 0xe3090680, 0xe3400098, 0xe28d4010, 0xe58d000c, 0xe28d9018, 0xe58d8008, 0xe28d8008, 0xe58d7010, 0xea000003, 0xe1a02000, 0xe3a00001,
|
||||||
|
0xe1a01009, 0xe12fff3a, 0xe1a00004, 0xe3a01001, 0xe3a02000, 0xe12fff35, 0xe3500000, 0xca000008, 0xe1a00008, 0xe3a01000, 0xe12fff36, 0xe1a00004,
|
||||||
|
0xe3a01001, 0xe3a02000, 0xe12fff35, 0xe3500001, 0xbafffff6, 0xe59d3004, 0xe1a00007, 0xe1a01009, 0xe3a02801, 0xe12fff33, 0xe3500001, 0xaaffffe5,
|
||||||
|
0xe59d1000, 0xe3a00000, 0xe12fff31, 0xe24bd01c, 0xe8bd8ff0, 0x00000174, 0x0000016c, 0x0000015d, 0x0000014e, 0x0000013f, 0x00000135, 0x00000126,
|
||||||
|
0x00000114, 0x7ffffe74, 0x00000001, 0x6362696c, 0x006f732e, 0x6e65706f, 0x69786500, 0x6f700074, 0x6e006c6c, 0x736f6e61, 0x7065656c, 0x61657200,
|
||||||
|
0x72770064, 0x00657469, 0x7379732f, 0x72656b2f, 0x2f6c656e, 0x75626564, 0x72742f67, 0x6e696361, 0x72742f67, 0x5f656361, 0x65706970, 0x00000000,
|
||||||
|
0x00000003, 0x000014a8, 0x00000002, 0x00000010, 0x00000017, 0x000001cc, 0x00000014, 0x00000011, 0x00000015, 0x00000000, 0x00000006, 0x00000128,
|
||||||
|
0x0000000b, 0x00000010, 0x00000005, 0x00000158, 0x0000000a, 0x0000001c, 0x6ffffef5, 0x00000174, 0x00000004, 0x0000018c, 0x00000001, 0x0000000d,
|
||||||
|
0x0000001e, 0x00000008, 0x6ffffffb, 0x00000001, 0x6ffffff0, 0x000001a4, 0x6ffffffe, 0x000001ac, 0x6fffffff, 0x00000001, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x000001dc, 0x000001dc,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned int tracy_systrace_aarch64_size = 1650;
|
||||||
|
static const unsigned int tracy_systrace_aarch64_data[1652/4] =
|
||||||
|
{
|
||||||
|
0x464c457f, 0x00010102, 0x00000000, 0x00000000, 0x00b70003, 0x00000001, 0x00000300, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00380040, 0x00400006, 0x00000000, 0x00000006, 0x00000005, 0x00000040, 0x00000000, 0x00000040, 0x00000000, 0x00000040, 0x00000000,
|
||||||
|
0x00000150, 0x00000000, 0x00000150, 0x00000000, 0x00000008, 0x00000000, 0x00000003, 0x00000004, 0x00000190, 0x00000000, 0x00000190, 0x00000000,
|
||||||
|
0x00000190, 0x00000000, 0x00000015, 0x00000000, 0x00000015, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000005, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000004d1, 0x00000000, 0x000004d1, 0x00000000, 0x00010000, 0x00000000, 0x00000001, 0x00000006,
|
||||||
|
0x000004d8, 0x00000000, 0x000104d8, 0x00000000, 0x000104d8, 0x00000000, 0x0000019a, 0x00000000, 0x000001a0, 0x00000000, 0x00010000, 0x00000000,
|
||||||
|
0x00000002, 0x00000006, 0x000004d8, 0x00000000, 0x000104d8, 0x00000000, 0x000104d8, 0x00000000, 0x00000170, 0x00000000, 0x00000170, 0x00000000,
|
||||||
|
0x00000008, 0x00000000, 0x6474e551, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000010, 0x00000000, 0x7379732f, 0x2f6d6574, 0x2f6e6962, 0x6b6e696c, 0x34367265, 0x00000000, 0x00000001, 0x00000004,
|
||||||
|
0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000a0003, 0x00000300, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x0000000a, 0x00000012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000011, 0x00000012, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x62696c00, 0x732e6c64, 0x6c64006f, 0x6e65706f, 0x736c6400, 0x4c006d79, 0x00434249, 0x00000000, 0x00020002, 0x00000000,
|
||||||
|
0x00010001, 0x00000001, 0x00000010, 0x00000000, 0x00050d63, 0x00020000, 0x00000017, 0x00000000, 0x00010668, 0x00000000, 0x00000402, 0x00000002,
|
||||||
|
0x00000000, 0x00000000, 0x00010670, 0x00000000, 0x00000402, 0x00000003, 0x00000000, 0x00000000, 0xa9bf7bf0, 0x90000090, 0xf9433211, 0x91198210,
|
||||||
|
0xd61f0220, 0xd503201f, 0xd503201f, 0xd503201f, 0x90000090, 0xf9433611, 0x9119a210, 0xd61f0220, 0x90000090, 0xf9433a11, 0x9119c210, 0xd61f0220,
|
||||||
|
0xf81b0ffc, 0xa9015ff8, 0xa90257f6, 0xa9034ff4, 0xa9047bfd, 0x910103fd, 0xd14043ff, 0xd10043ff, 0x90000000, 0x91120000, 0x320003e1, 0x97ffffed,
|
||||||
|
0x90000001, 0x91122021, 0xaa0003f7, 0x97ffffed, 0x90000001, 0xaa0003f8, 0x91123421, 0xaa1703e0, 0x97ffffe8, 0x90000001, 0xaa0003f3, 0x91124821,
|
||||||
|
0xaa1703e0, 0x97ffffe3, 0x90000001, 0xaa0003f4, 0x91125c21, 0xaa1703e0, 0x97ffffde, 0x90000001, 0xaa0003f5, 0x91128421, 0xaa1703e0, 0x97ffffd9,
|
||||||
|
0x90000001, 0xaa0003f6, 0x91129821, 0xaa1703e0, 0x97ffffd4, 0xaa0003f7, 0x90000000, 0x9112b000, 0x2a1f03e1, 0xd63f0300, 0x2a0003f8, 0x36f80060,
|
||||||
|
0x2a1f03e0, 0xd63f0260, 0x90000008, 0x3dc11d00, 0x52800128, 0xb81c83b8, 0x781cc3a8, 0x3d8003e0, 0x14000005, 0x93407c02, 0x320003e0, 0x910043e1,
|
||||||
|
0xd63f02e0, 0xd100e3a0, 0x320003e1, 0x2a1f03e2, 0xd63f0280, 0x7100001f, 0x5400014c, 0x910003e0, 0xaa1f03e1, 0xd63f02a0, 0xd100e3a0, 0x320003e1,
|
||||||
|
0x2a1f03e2, 0xd63f0280, 0x7100041f, 0x54ffff0b, 0x910043e1, 0x321003e2, 0x2a1803e0, 0xd63f02c0, 0x7100041f, 0x54fffd0a, 0x2a1f03e0, 0xd63f0260,
|
||||||
|
0x914043ff, 0x910043ff, 0xa9447bfd, 0xa9434ff4, 0xa94257f6, 0xa9415ff8, 0xf84507fc, 0xd65f03c0, 0x00000000, 0x00000000, 0x00989680, 0x00000000,
|
||||||
|
0x6362696c, 0x006f732e, 0x6e65706f, 0x69786500, 0x6f700074, 0x6e006c6c, 0x736f6e61, 0x7065656c, 0x61657200, 0x72770064, 0x00657469, 0x7379732f,
|
||||||
|
0x72656b2f, 0x2f6c656e, 0x75626564, 0x72742f67, 0x6e696361, 0x72742f67, 0x5f656361, 0x65706970, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
|
||||||
|
0x00000001, 0x00000000, 0x00000004, 0x00000000, 0x000001a8, 0x00000000, 0x6ffffef5, 0x00000000, 0x000001c8, 0x00000000, 0x00000005, 0x00000000,
|
||||||
|
0x00000248, 0x00000000, 0x00000006, 0x00000000, 0x000001e8, 0x00000000, 0x0000000a, 0x00000000, 0x0000001c, 0x00000000, 0x0000000b, 0x00000000,
|
||||||
|
0x00000018, 0x00000000, 0x00000015, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00010650, 0x00000000, 0x00000002, 0x00000000,
|
||||||
|
0x00000030, 0x00000000, 0x00000014, 0x00000000, 0x00000007, 0x00000000, 0x00000017, 0x00000000, 0x00000290, 0x00000000, 0x0000001e, 0x00000000,
|
||||||
|
0x00000008, 0x00000000, 0x6ffffffb, 0x00000000, 0x00000001, 0x00000000, 0x6ffffffe, 0x00000000, 0x00000270, 0x00000000, 0x6fffffff, 0x00000000,
|
||||||
|
0x00000001, 0x00000000, 0x6ffffff0, 0x00000000, 0x00000264, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000104d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x000002c0, 0x00000000, 0x000002c0,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -1,36 +1,16 @@
|
|||||||
#ifndef __TRACYTHREAD_HPP__
|
#ifndef __TRACYTHREAD_HPP__
|
||||||
#define __TRACYTHREAD_HPP__
|
#define __TRACYTHREAD_HPP__
|
||||||
|
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
#else
|
#else
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TRACY_MANUAL_LIFETIME
|
|
||||||
# include "tracy_rpmalloc.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef TRACY_MANUAL_LIFETIME
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
extern thread_local bool RpThreadInitDone;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class ThreadExitHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
~ThreadExitHandler()
|
|
||||||
{
|
|
||||||
#ifdef TRACY_MANUAL_LIFETIME
|
|
||||||
rpmalloc_thread_finalize( 1 );
|
|
||||||
RpThreadInitDone = false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined _WIN32
|
|
||||||
|
|
||||||
class Thread
|
class Thread
|
||||||
{
|
{
|
@ -62,6 +62,56 @@
|
|||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Exceptions
|
||||||
|
#ifndef MOODYCAMEL_EXCEPTIONS_ENABLED
|
||||||
|
#if (defined(_MSC_VER) && defined(_CPPUNWIND)) || (defined(__GNUC__) && defined(__EXCEPTIONS)) || (!defined(_MSC_VER) && !defined(__GNUC__))
|
||||||
|
#define MOODYCAMEL_EXCEPTIONS_ENABLED
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED
|
||||||
|
#define MOODYCAMEL_TRY try
|
||||||
|
#define MOODYCAMEL_CATCH(...) catch(__VA_ARGS__)
|
||||||
|
#define MOODYCAMEL_RETHROW throw
|
||||||
|
#define MOODYCAMEL_THROW(expr) throw (expr)
|
||||||
|
#else
|
||||||
|
#define MOODYCAMEL_TRY if (true)
|
||||||
|
#define MOODYCAMEL_CATCH(...) else if (false)
|
||||||
|
#define MOODYCAMEL_RETHROW
|
||||||
|
#define MOODYCAMEL_THROW(expr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MOODYCAMEL_NOEXCEPT
|
||||||
|
#if !defined(MOODYCAMEL_EXCEPTIONS_ENABLED)
|
||||||
|
#define MOODYCAMEL_NOEXCEPT
|
||||||
|
#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) true
|
||||||
|
#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) true
|
||||||
|
#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1800
|
||||||
|
// VS2012's std::is_nothrow_[move_]constructible is broken and returns true when it shouldn't :-(
|
||||||
|
// We have to assume *all* non-trivial constructors may throw on VS2012!
|
||||||
|
#define MOODYCAMEL_NOEXCEPT _NOEXCEPT
|
||||||
|
#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) (std::is_rvalue_reference<valueType>::value && std::is_move_constructible<type>::value ? std::is_trivially_move_constructible<type>::value : std::is_trivially_copy_constructible<type>::value)
|
||||||
|
#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) ((std::is_rvalue_reference<valueType>::value && std::is_move_assignable<type>::value ? std::is_trivially_move_assignable<type>::value || std::is_nothrow_move_assignable<type>::value : std::is_trivially_copy_assignable<type>::value || std::is_nothrow_copy_assignable<type>::value) && MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr))
|
||||||
|
#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1900
|
||||||
|
#define MOODYCAMEL_NOEXCEPT _NOEXCEPT
|
||||||
|
#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) (std::is_rvalue_reference<valueType>::value && std::is_move_constructible<type>::value ? std::is_trivially_move_constructible<type>::value || std::is_nothrow_move_constructible<type>::value : std::is_trivially_copy_constructible<type>::value || std::is_nothrow_copy_constructible<type>::value)
|
||||||
|
#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) ((std::is_rvalue_reference<valueType>::value && std::is_move_assignable<type>::value ? std::is_trivially_move_assignable<type>::value || std::is_nothrow_move_assignable<type>::value : std::is_trivially_copy_assignable<type>::value || std::is_nothrow_copy_assignable<type>::value) && MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr))
|
||||||
|
#else
|
||||||
|
#define MOODYCAMEL_NOEXCEPT noexcept
|
||||||
|
#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) noexcept(expr)
|
||||||
|
#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) noexcept(expr)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// VS2012 doesn't support deleted functions.
|
||||||
|
// In this case, we declare the function normally but don't define it. A link error will be generated if the function is called.
|
||||||
|
#ifndef MOODYCAMEL_DELETE_FUNCTION
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||||
|
#define MOODYCAMEL_DELETE_FUNCTION
|
||||||
|
#else
|
||||||
|
#define MOODYCAMEL_DELETE_FUNCTION = delete
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Compiler-specific likely/unlikely hints
|
// Compiler-specific likely/unlikely hints
|
||||||
namespace moodycamel { namespace details {
|
namespace moodycamel { namespace details {
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
@ -202,7 +252,7 @@ namespace details
|
|||||||
ConcurrentQueueProducerTypelessBase* next;
|
ConcurrentQueueProducerTypelessBase* next;
|
||||||
std::atomic<bool> inactive;
|
std::atomic<bool> inactive;
|
||||||
ProducerToken* token;
|
ProducerToken* token;
|
||||||
uint32_t threadId;
|
uint64_t threadId;
|
||||||
|
|
||||||
ConcurrentQueueProducerTypelessBase()
|
ConcurrentQueueProducerTypelessBase()
|
||||||
: next(nullptr), inactive(false), token(nullptr), threadId(0)
|
: next(nullptr), inactive(false), token(nullptr), threadId(0)
|
||||||
@ -213,10 +263,15 @@ namespace details
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
static inline bool circular_less_than(T a, T b)
|
static inline bool circular_less_than(T a, T b)
|
||||||
{
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4554)
|
||||||
|
#endif
|
||||||
static_assert(std::is_integral<T>::value && !std::numeric_limits<T>::is_signed, "circular_less_than is intended to be used only with unsigned integer types");
|
static_assert(std::is_integral<T>::value && !std::numeric_limits<T>::is_signed, "circular_less_than is intended to be used only with unsigned integer types");
|
||||||
return static_cast<T>(a - b) > static_cast<T>(static_cast<T>(1) << (static_cast<T>(sizeof(T) * CHAR_BIT - 1)));
|
return static_cast<T>(a - b) > static_cast<T>(static_cast<T>(1) << static_cast<T>(sizeof(T) * CHAR_BIT - 1));
|
||||||
// Note: extra parens around rhs of operator<< is MSVC bug: https://developercommunity2.visualstudio.com/t/C4554-triggers-when-both-lhs-and-rhs-is/10034931
|
#ifdef _MSC_VER
|
||||||
// silencing the bug requires #pragma warning(disable: 4554) around the calling code and has no effect when done here.
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
@ -279,7 +334,7 @@ namespace details
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename It>
|
template<typename It>
|
||||||
static inline auto deref_noexcept(It& it) noexcept -> decltype(*it)
|
static inline auto deref_noexcept(It& it) MOODYCAMEL_NOEXCEPT -> decltype(*it)
|
||||||
{
|
{
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
@ -307,7 +362,7 @@ struct ProducerToken
|
|||||||
template<typename T, typename Traits>
|
template<typename T, typename Traits>
|
||||||
explicit ProducerToken(ConcurrentQueue<T, Traits>& queue);
|
explicit ProducerToken(ConcurrentQueue<T, Traits>& queue);
|
||||||
|
|
||||||
ProducerToken(ProducerToken&& other) noexcept
|
ProducerToken(ProducerToken&& other) MOODYCAMEL_NOEXCEPT
|
||||||
: producer(other.producer)
|
: producer(other.producer)
|
||||||
{
|
{
|
||||||
other.producer = nullptr;
|
other.producer = nullptr;
|
||||||
@ -316,13 +371,13 @@ struct ProducerToken
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ProducerToken& operator=(ProducerToken&& other) noexcept
|
inline ProducerToken& operator=(ProducerToken&& other) MOODYCAMEL_NOEXCEPT
|
||||||
{
|
{
|
||||||
swap(other);
|
swap(other);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(ProducerToken& other) noexcept
|
void swap(ProducerToken& other) MOODYCAMEL_NOEXCEPT
|
||||||
{
|
{
|
||||||
std::swap(producer, other.producer);
|
std::swap(producer, other.producer);
|
||||||
if (producer != nullptr) {
|
if (producer != nullptr) {
|
||||||
@ -352,8 +407,8 @@ struct ProducerToken
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable copying and assignment
|
// Disable copying and assignment
|
||||||
ProducerToken(ProducerToken const&) = delete;
|
ProducerToken(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
ProducerToken& operator=(ProducerToken const&) = delete;
|
ProducerToken& operator=(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename T, typename Traits> friend class ConcurrentQueue;
|
template<typename T, typename Traits> friend class ConcurrentQueue;
|
||||||
@ -368,18 +423,18 @@ struct ConsumerToken
|
|||||||
template<typename T, typename Traits>
|
template<typename T, typename Traits>
|
||||||
explicit ConsumerToken(ConcurrentQueue<T, Traits>& q);
|
explicit ConsumerToken(ConcurrentQueue<T, Traits>& q);
|
||||||
|
|
||||||
ConsumerToken(ConsumerToken&& other) noexcept
|
ConsumerToken(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT
|
||||||
: initialOffset(other.initialOffset), lastKnownGlobalOffset(other.lastKnownGlobalOffset), itemsConsumedFromCurrent(other.itemsConsumedFromCurrent), currentProducer(other.currentProducer), desiredProducer(other.desiredProducer)
|
: initialOffset(other.initialOffset), lastKnownGlobalOffset(other.lastKnownGlobalOffset), itemsConsumedFromCurrent(other.itemsConsumedFromCurrent), currentProducer(other.currentProducer), desiredProducer(other.desiredProducer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ConsumerToken& operator=(ConsumerToken&& other) noexcept
|
inline ConsumerToken& operator=(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT
|
||||||
{
|
{
|
||||||
swap(other);
|
swap(other);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(ConsumerToken& other) noexcept
|
void swap(ConsumerToken& other) MOODYCAMEL_NOEXCEPT
|
||||||
{
|
{
|
||||||
std::swap(initialOffset, other.initialOffset);
|
std::swap(initialOffset, other.initialOffset);
|
||||||
std::swap(lastKnownGlobalOffset, other.lastKnownGlobalOffset);
|
std::swap(lastKnownGlobalOffset, other.lastKnownGlobalOffset);
|
||||||
@ -389,8 +444,8 @@ struct ConsumerToken
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable copying and assignment
|
// Disable copying and assignment
|
||||||
ConsumerToken(ConsumerToken const&) = delete;
|
ConsumerToken(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
ConsumerToken& operator=(ConsumerToken const&) = delete;
|
ConsumerToken& operator=(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename T, typename Traits> friend class ConcurrentQueue;
|
template<typename T, typename Traits> friend class ConcurrentQueue;
|
||||||
@ -503,10 +558,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable copying and copy assignment
|
// Disable copying and copy assignment
|
||||||
ConcurrentQueue(ConcurrentQueue const&) = delete;
|
ConcurrentQueue(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
ConcurrentQueue(ConcurrentQueue&& other) = delete;
|
ConcurrentQueue(ConcurrentQueue&& other) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
ConcurrentQueue& operator=(ConcurrentQueue const&) = delete;
|
ConcurrentQueue& operator=(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
ConcurrentQueue& operator=(ConcurrentQueue&& other) = delete;
|
ConcurrentQueue& operator=(ConcurrentQueue&& other) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
tracy_force_inline T* enqueue_begin(producer_token_t const& token, index_t& currentTailIndex)
|
tracy_force_inline T* enqueue_begin(producer_token_t const& token, index_t& currentTailIndex)
|
||||||
@ -660,8 +715,8 @@ private:
|
|||||||
FreeList(FreeList&& other) : freeListHead(other.freeListHead.load(std::memory_order_relaxed)) { other.freeListHead.store(nullptr, std::memory_order_relaxed); }
|
FreeList(FreeList&& other) : freeListHead(other.freeListHead.load(std::memory_order_relaxed)) { other.freeListHead.store(nullptr, std::memory_order_relaxed); }
|
||||||
void swap(FreeList& other) { details::swap_relaxed(freeListHead, other.freeListHead); }
|
void swap(FreeList& other) { details::swap_relaxed(freeListHead, other.freeListHead); }
|
||||||
|
|
||||||
FreeList(FreeList const&) = delete;
|
FreeList(FreeList const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
FreeList& operator=(FreeList const&) = delete;
|
FreeList& operator=(FreeList const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||||
|
|
||||||
inline void add(N* node)
|
inline void add(N* node)
|
||||||
{
|
{
|
||||||
@ -850,8 +905,8 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T* operator[](index_t idx) noexcept { return static_cast<T*>(static_cast<void*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }
|
inline T* operator[](index_t idx) MOODYCAMEL_NOEXCEPT { return static_cast<T*>(static_cast<void*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }
|
||||||
inline T const* operator[](index_t idx) const noexcept { return static_cast<T const*>(static_cast<void const*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }
|
inline T const* operator[](index_t idx) const MOODYCAMEL_NOEXCEPT { return static_cast<T const*>(static_cast<void const*>(elements)) + static_cast<size_t>(idx & static_cast<index_t>(BLOCK_SIZE - 1)); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// IMPORTANT: This must be the first member in Block, so that if T depends on the alignment of
|
// IMPORTANT: This must be the first member in Block, so that if T depends on the alignment of
|
||||||
@ -1417,17 +1472,17 @@ ConsumerToken::ConsumerToken(ConcurrentQueue<T, Traits>& queue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Traits>
|
template<typename T, typename Traits>
|
||||||
inline void swap(ConcurrentQueue<T, Traits>& a, ConcurrentQueue<T, Traits>& b) noexcept
|
inline void swap(ConcurrentQueue<T, Traits>& a, ConcurrentQueue<T, Traits>& b) MOODYCAMEL_NOEXCEPT
|
||||||
{
|
{
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void swap(ProducerToken& a, ProducerToken& b) noexcept
|
inline void swap(ProducerToken& a, ProducerToken& b) MOODYCAMEL_NOEXCEPT
|
||||||
{
|
{
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void swap(ConsumerToken& a, ConsumerToken& b) noexcept
|
inline void swap(ConsumerToken& a, ConsumerToken& b) MOODYCAMEL_NOEXCEPT
|
||||||
{
|
{
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
2495
client/tracy_rpmalloc.cpp
Normal file
@ -20,12 +20,11 @@ namespace tracy
|
|||||||
#if defined(__clang__) || defined(__GNUC__)
|
#if defined(__clang__) || defined(__GNUC__)
|
||||||
# define RPMALLOC_EXPORT __attribute__((visibility("default")))
|
# define RPMALLOC_EXPORT __attribute__((visibility("default")))
|
||||||
# define RPMALLOC_ALLOCATOR
|
# define RPMALLOC_ALLOCATOR
|
||||||
# if (defined(__clang_major__) && (__clang_major__ < 4)) || (defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD)
|
# define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__))
|
||||||
# define RPMALLOC_ATTRIB_MALLOC
|
# if defined(__clang_major__) && (__clang_major__ < 4)
|
||||||
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||||
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||||
# else
|
# else
|
||||||
# define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__))
|
|
||||||
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size)))
|
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size)))
|
||||||
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) __attribute__((alloc_size(count, size)))
|
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) __attribute__((alloc_size(count, size)))
|
||||||
# endif
|
# endif
|
||||||
@ -46,24 +45,13 @@ namespace tracy
|
|||||||
# define RPMALLOC_CDECL
|
# define RPMALLOC_CDECL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce
|
//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes
|
||||||
// a very small overhead due to some size calculations not being compile time constants
|
|
||||||
#ifndef RPMALLOC_CONFIGURABLE
|
#ifndef RPMALLOC_CONFIGURABLE
|
||||||
#define RPMALLOC_CONFIGURABLE 0
|
#define RPMALLOC_CONFIGURABLE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_* functions).
|
|
||||||
// Will introduce a very small overhead to track fully allocated spans in heaps
|
|
||||||
#ifndef RPMALLOC_FIRST_CLASS_HEAPS
|
|
||||||
#define RPMALLOC_FIRST_CLASS_HEAPS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//! Flag to rpaligned_realloc to not preserve content in reallocation
|
//! Flag to rpaligned_realloc to not preserve content in reallocation
|
||||||
#define RPMALLOC_NO_PRESERVE 1
|
#define RPMALLOC_NO_PRESERVE 1
|
||||||
//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be done in-place,
|
|
||||||
// in which case the original pointer is still valid (just like a call to realloc which failes to allocate
|
|
||||||
// a new block).
|
|
||||||
#define RPMALLOC_GROW_OR_FAIL 2
|
|
||||||
|
|
||||||
typedef struct rpmalloc_global_statistics_t {
|
typedef struct rpmalloc_global_statistics_t {
|
||||||
//! Current amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)
|
//! Current amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)
|
||||||
@ -111,7 +99,7 @@ typedef struct rpmalloc_thread_statistics_t {
|
|||||||
size_t from_reserved;
|
size_t from_reserved;
|
||||||
//! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)
|
//! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)
|
||||||
size_t map_calls;
|
size_t map_calls;
|
||||||
} span_use[64];
|
} span_use[32];
|
||||||
//! Per size class statistics (only if ENABLE_STATISTICS=1)
|
//! Per size class statistics (only if ENABLE_STATISTICS=1)
|
||||||
struct {
|
struct {
|
||||||
//! Current number of allocations
|
//! Current number of allocations
|
||||||
@ -143,8 +131,7 @@ typedef struct rpmalloc_config_t {
|
|||||||
// larger than 65535 (storable in an uint16_t), if it is you must use natural
|
// larger than 65535 (storable in an uint16_t), if it is you must use natural
|
||||||
// alignment to shift it into 16 bits. If you set a memory_map function, you
|
// alignment to shift it into 16 bits. If you set a memory_map function, you
|
||||||
// must also set a memory_unmap function or else the default implementation will
|
// must also set a memory_unmap function or else the default implementation will
|
||||||
// be used for both. This function must be thread safe, it can be called by
|
// be used for both.
|
||||||
// multiple threads simultaneously.
|
|
||||||
void* (*memory_map)(size_t size, size_t* offset);
|
void* (*memory_map)(size_t size, size_t* offset);
|
||||||
//! Unmap the memory pages starting at address and spanning the given number of bytes.
|
//! Unmap the memory pages starting at address and spanning the given number of bytes.
|
||||||
// If release is set to non-zero, the unmap is for an entire span range as returned by
|
// If release is set to non-zero, the unmap is for an entire span range as returned by
|
||||||
@ -152,18 +139,8 @@ typedef struct rpmalloc_config_t {
|
|||||||
// release argument holds the size of the entire span range. If release is set to 0,
|
// release argument holds the size of the entire span range. If release is set to 0,
|
||||||
// the unmap is a partial decommit of a subset of the mapped memory range.
|
// the unmap is a partial decommit of a subset of the mapped memory range.
|
||||||
// If you set a memory_unmap function, you must also set a memory_map function or
|
// If you set a memory_unmap function, you must also set a memory_map function or
|
||||||
// else the default implementation will be used for both. This function must be thread
|
// else the default implementation will be used for both.
|
||||||
// safe, it can be called by multiple threads simultaneously.
|
|
||||||
void (*memory_unmap)(void* address, size_t size, size_t offset, size_t release);
|
void (*memory_unmap)(void* address, size_t size, size_t offset, size_t release);
|
||||||
//! Called when an assert fails, if asserts are enabled. Will use the standard assert()
|
|
||||||
// if this is not set.
|
|
||||||
void (*error_callback)(const char* message);
|
|
||||||
//! Called when a call to map memory pages fails (out of memory). If this callback is
|
|
||||||
// not set or returns zero the library will return a null pointer in the allocation
|
|
||||||
// call. If this callback returns non-zero the map call will be retried. The argument
|
|
||||||
// passed is the number of bytes that was requested in the map call. Only used if
|
|
||||||
// the default system memory map function is used (memory_map callback is not set).
|
|
||||||
int (*map_fail_callback)(size_t size);
|
|
||||||
//! Size of memory pages. The page size MUST be a power of two. All memory mapping
|
//! Size of memory pages. The page size MUST be a power of two. All memory mapping
|
||||||
// requests to memory_map will be made with size set to a multiple of the page size.
|
// requests to memory_map will be made with size set to a multiple of the page size.
|
||||||
// Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system page size is used.
|
// Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system page size is used.
|
||||||
@ -186,14 +163,10 @@ typedef struct rpmalloc_config_t {
|
|||||||
// For Windows, see https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support
|
// For Windows, see https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support
|
||||||
// For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
|
// For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
|
||||||
int enable_huge_pages;
|
int enable_huge_pages;
|
||||||
//! Respectively allocated pages and huge allocated pages names for systems
|
|
||||||
// supporting it to be able to distinguish among anonymous regions.
|
|
||||||
const char *page_name;
|
|
||||||
const char *huge_page_name;
|
|
||||||
} rpmalloc_config_t;
|
} rpmalloc_config_t;
|
||||||
|
|
||||||
//! Initialize allocator with default configuration
|
//! Initialize allocator with default configuration
|
||||||
TRACY_API int
|
RPMALLOC_EXPORT int
|
||||||
rpmalloc_initialize(void);
|
rpmalloc_initialize(void);
|
||||||
|
|
||||||
//! Initialize allocator with given configuration
|
//! Initialize allocator with given configuration
|
||||||
@ -205,16 +178,16 @@ RPMALLOC_EXPORT const rpmalloc_config_t*
|
|||||||
rpmalloc_config(void);
|
rpmalloc_config(void);
|
||||||
|
|
||||||
//! Finalize allocator
|
//! Finalize allocator
|
||||||
TRACY_API void
|
RPMALLOC_EXPORT void
|
||||||
rpmalloc_finalize(void);
|
rpmalloc_finalize(void);
|
||||||
|
|
||||||
//! Initialize allocator for calling thread
|
//! Initialize allocator for calling thread
|
||||||
TRACY_API void
|
RPMALLOC_EXPORT void
|
||||||
rpmalloc_thread_initialize(void);
|
rpmalloc_thread_initialize(void);
|
||||||
|
|
||||||
//! Finalize allocator for calling thread
|
//! Finalize allocator for calling thread
|
||||||
TRACY_API void
|
RPMALLOC_EXPORT void
|
||||||
rpmalloc_thread_finalize(int release_caches);
|
rpmalloc_thread_finalize(void);
|
||||||
|
|
||||||
//! Perform deferred deallocations pending for the calling thread heap
|
//! Perform deferred deallocations pending for the calling thread heap
|
||||||
RPMALLOC_EXPORT void
|
RPMALLOC_EXPORT void
|
||||||
@ -249,7 +222,7 @@ RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
|||||||
rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2);
|
rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2);
|
||||||
|
|
||||||
//! Reallocate the given block to at least the given size
|
//! Reallocate the given block to at least the given size
|
||||||
TRACY_API RPMALLOC_ALLOCATOR void*
|
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
||||||
rprealloc(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
rprealloc(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||||
|
|
||||||
//! Reallocate the given block to at least the given size and alignment,
|
//! Reallocate the given block to at least the given size and alignment,
|
||||||
@ -267,13 +240,6 @@ rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, unsi
|
|||||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
||||||
rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||||
|
|
||||||
//! Allocate a memory block of at least the given size and alignment, and zero initialize it.
|
|
||||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
|
||||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
|
||||||
// internals is that this must also be strictly less than the span size (default 64KiB)
|
|
||||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
|
||||||
rpaligned_calloc(size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
|
||||||
|
|
||||||
//! Allocate a memory block of at least the given size and alignment.
|
//! Allocate a memory block of at least the given size and alignment.
|
||||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||||
@ -286,78 +252,10 @@ rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB
|
|||||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||||
// internals is that this must also be strictly less than the span size (default 64KiB)
|
// internals is that this must also be strictly less than the span size (default 64KiB)
|
||||||
RPMALLOC_EXPORT int
|
RPMALLOC_EXPORT int
|
||||||
rpposix_memalign(void** memptr, size_t alignment, size_t size);
|
rpposix_memalign(void **memptr, size_t alignment, size_t size);
|
||||||
|
|
||||||
//! Query the usable size of the given memory block (from given pointer to the end of block)
|
//! Query the usable size of the given memory block (from given pointer to the end of block)
|
||||||
RPMALLOC_EXPORT size_t
|
RPMALLOC_EXPORT size_t
|
||||||
rpmalloc_usable_size(void* ptr);
|
rpmalloc_usable_size(void* ptr);
|
||||||
|
|
||||||
#if RPMALLOC_FIRST_CLASS_HEAPS
|
|
||||||
|
|
||||||
//! Heap type
|
|
||||||
typedef struct heap_t rpmalloc_heap_t;
|
|
||||||
|
|
||||||
//! Acquire a new heap. Will reuse existing released heaps or allocate memory for a new heap
|
|
||||||
// if none available. Heap API is implemented with the strict assumption that only one single
|
|
||||||
// thread will call heap functions for a given heap at any given time, no functions are thread safe.
|
|
||||||
RPMALLOC_EXPORT rpmalloc_heap_t*
|
|
||||||
rpmalloc_heap_acquire(void);
|
|
||||||
|
|
||||||
//! Release a heap (does NOT free the memory allocated by the heap, use rpmalloc_heap_free_all before destroying the heap).
|
|
||||||
// Releasing a heap will enable it to be reused by other threads. Safe to pass a null pointer.
|
|
||||||
RPMALLOC_EXPORT void
|
|
||||||
rpmalloc_heap_release(rpmalloc_heap_t* heap);
|
|
||||||
|
|
||||||
//! Allocate a memory block of at least the given size using the given heap.
|
|
||||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
|
||||||
rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
|
||||||
|
|
||||||
//! Allocate a memory block of at least the given size using the given heap. The returned
|
|
||||||
// block will have the requested alignment. Alignment must be a power of two and a multiple of sizeof(void*),
|
|
||||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
|
||||||
// internals is that this must also be strictly less than the span size (default 64KiB).
|
|
||||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
|
||||||
rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
|
||||||
|
|
||||||
//! Allocate a memory block of at least the given size using the given heap and zero initialize it.
|
|
||||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
|
||||||
rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
|
||||||
|
|
||||||
//! Allocate a memory block of at least the given size using the given heap and zero initialize it. The returned
|
|
||||||
// block will have the requested alignment. Alignment must either be zero, or a power of two and a multiple of sizeof(void*),
|
|
||||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
|
||||||
// internals is that this must also be strictly less than the span size (default 64KiB).
|
|
||||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
|
||||||
rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
|
||||||
|
|
||||||
//! Reallocate the given block to at least the given size. The memory block MUST be allocated
|
|
||||||
// by the same heap given to this function.
|
|
||||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
|
||||||
rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
|
||||||
|
|
||||||
//! Reallocate the given block to at least the given size. The memory block MUST be allocated
|
|
||||||
// by the same heap given to this function. The returned block will have the requested alignment.
|
|
||||||
// Alignment must be either zero, or a power of two and a multiple of sizeof(void*), and should ideally be
|
|
||||||
// less than memory page size. A caveat of rpmalloc internals is that this must also be strictly less than
|
|
||||||
// the span size (default 64KiB).
|
|
||||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
|
|
||||||
rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4);
|
|
||||||
|
|
||||||
//! Free the given memory block from the given heap. The memory block MUST be allocated
|
|
||||||
// by the same heap given to this function.
|
|
||||||
RPMALLOC_EXPORT void
|
|
||||||
rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr);
|
|
||||||
|
|
||||||
//! Free all memory allocated by the heap
|
|
||||||
RPMALLOC_EXPORT void
|
|
||||||
rpmalloc_heap_free_all(rpmalloc_heap_t* heap);
|
|
||||||
|
|
||||||
//! Set the given heap as the current heap for the calling thread. A heap MUST only be current heap
|
|
||||||
// for a single thread, a heap can never be shared between multiple threads. The previous
|
|
||||||
// current heap for the calling thread is released to be reused by other threads.
|
|
||||||
RPMALLOC_EXPORT void
|
|
||||||
rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
1269
cmake/CPM.cmake
@ -1,300 +0,0 @@
|
|||||||
#.rst:
|
|
||||||
# ECMFindModuleHelpers
|
|
||||||
# --------------------
|
|
||||||
#
|
|
||||||
# Helper macros for find modules: ecm_find_package_version_check(),
|
|
||||||
# ecm_find_package_parse_components() and
|
|
||||||
# ecm_find_package_handle_library_components().
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# ecm_find_package_version_check(<name>)
|
|
||||||
#
|
|
||||||
# Prints warnings if the CMake version or the project's required CMake version
|
|
||||||
# is older than that required by extra-cmake-modules.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# ecm_find_package_parse_components(<name>
|
|
||||||
# RESULT_VAR <variable>
|
|
||||||
# KNOWN_COMPONENTS <component1> [<component2> [...]]
|
|
||||||
# [SKIP_DEPENDENCY_HANDLING])
|
|
||||||
#
|
|
||||||
# This macro will populate <variable> with a list of components found in
|
|
||||||
# <name>_FIND_COMPONENTS, after checking that all those components are in the
|
|
||||||
# list of KNOWN_COMPONENTS; if there are any unknown components, it will print
|
|
||||||
# an error or warning (depending on the value of <name>_FIND_REQUIRED) and call
|
|
||||||
# return().
|
|
||||||
#
|
|
||||||
# The order of components in <variable> is guaranteed to match the order they
|
|
||||||
# are listed in the KNOWN_COMPONENTS argument.
|
|
||||||
#
|
|
||||||
# If SKIP_DEPENDENCY_HANDLING is not set, for each component the variable
|
|
||||||
# <name>_<component>_component_deps will be checked for dependent components.
|
|
||||||
# If <component> is listed in <name>_FIND_COMPONENTS, then all its (transitive)
|
|
||||||
# dependencies will also be added to <variable>.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# ecm_find_package_handle_library_components(<name>
|
|
||||||
# COMPONENTS <component> [<component> [...]]
|
|
||||||
# [SKIP_DEPENDENCY_HANDLING])
|
|
||||||
# [SKIP_PKG_CONFIG])
|
|
||||||
#
|
|
||||||
# Creates an imported library target for each component. The operation of this
|
|
||||||
# macro depends on the presence of a number of CMake variables.
|
|
||||||
#
|
|
||||||
# The <name>_<component>_lib variable should contain the name of this library,
|
|
||||||
# and <name>_<component>_header variable should contain the name of a header
|
|
||||||
# file associated with it (whatever relative path is normally passed to
|
|
||||||
# '#include'). <name>_<component>_header_subdir variable can be used to specify
|
|
||||||
# which subdirectory of the include path the headers will be found in.
|
|
||||||
# ecm_find_package_components() will then search for the library
|
|
||||||
# and include directory (creating appropriate cache variables) and create an
|
|
||||||
# imported library target named <name>::<component>.
|
|
||||||
#
|
|
||||||
# Additional variables can be used to provide additional information:
|
|
||||||
#
|
|
||||||
# If SKIP_PKG_CONFIG, the <name>_<component>_pkg_config variable is set, and
|
|
||||||
# pkg-config is found, the pkg-config module given by
|
|
||||||
# <name>_<component>_pkg_config will be searched for and used to help locate the
|
|
||||||
# library and header file. It will also be used to set
|
|
||||||
# <name>_<component>_VERSION.
|
|
||||||
#
|
|
||||||
# Note that if version information is found via pkg-config,
|
|
||||||
# <name>_<component>_FIND_VERSION can be set to require a particular version
|
|
||||||
# for each component.
|
|
||||||
#
|
|
||||||
# If SKIP_DEPENDENCY_HANDLING is not set, the INTERFACE_LINK_LIBRARIES property
|
|
||||||
# of the imported target for <component> will be set to contain the imported
|
|
||||||
# targets for the components listed in <name>_<component>_component_deps.
|
|
||||||
# <component>_FOUND will also be set to false if any of the components in
|
|
||||||
# <name>_<component>_component_deps are not found. This requires the components
|
|
||||||
# in <name>_<component>_component_deps to be listed before <component> in the
|
|
||||||
# COMPONENTS argument.
|
|
||||||
#
|
|
||||||
# The following variables will be set:
|
|
||||||
#
|
|
||||||
# ``<name>_TARGETS``
|
|
||||||
# the imported targets
|
|
||||||
# ``<name>_LIBRARIES``
|
|
||||||
# the found libraries
|
|
||||||
# ``<name>_INCLUDE_DIRS``
|
|
||||||
# the combined required include directories for the components
|
|
||||||
# ``<name>_DEFINITIONS``
|
|
||||||
# the "other" CFLAGS provided by pkg-config, if any
|
|
||||||
# ``<name>_VERSION``
|
|
||||||
# the value of ``<name>_<component>_VERSION`` for the first component that
|
|
||||||
# has this variable set (note that components are searched for in the order
|
|
||||||
# they are passed to the macro), although if it is already set, it will not
|
|
||||||
# be altered
|
|
||||||
#
|
|
||||||
# Note that these variables are never cleared, so if
|
|
||||||
# ecm_find_package_handle_library_components() is called multiple times with
|
|
||||||
# different components (typically because of multiple find_package() calls) then
|
|
||||||
# ``<name>_TARGETS``, for example, will contain all the targets found in any
|
|
||||||
# call (although no duplicates).
|
|
||||||
#
|
|
||||||
# Since pre-1.0.0.
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2014 Alex Merry <alex.merry@kde.org>
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. The name of the author may not be used to endorse or promote products
|
|
||||||
# derived from this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
macro(ecm_find_package_version_check module_name)
|
|
||||||
if(CMAKE_VERSION VERSION_LESS 2.8.12)
|
|
||||||
message(FATAL_ERROR "CMake 2.8.12 is required by Find${module_name}.cmake")
|
|
||||||
endif()
|
|
||||||
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
|
|
||||||
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use Find${module_name}.cmake")
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
macro(ecm_find_package_parse_components module_name)
|
|
||||||
set(ecm_fppc_options SKIP_DEPENDENCY_HANDLING)
|
|
||||||
set(ecm_fppc_oneValueArgs RESULT_VAR)
|
|
||||||
set(ecm_fppc_multiValueArgs KNOWN_COMPONENTS DEFAULT_COMPONENTS)
|
|
||||||
cmake_parse_arguments(ECM_FPPC "${ecm_fppc_options}" "${ecm_fppc_oneValueArgs}" "${ecm_fppc_multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(ECM_FPPC_UNPARSED_ARGUMENTS)
|
|
||||||
message(FATAL_ERROR "Unexpected arguments to ecm_find_package_parse_components: ${ECM_FPPC_UNPARSED_ARGUMENTS}")
|
|
||||||
endif()
|
|
||||||
if(NOT ECM_FPPC_RESULT_VAR)
|
|
||||||
message(FATAL_ERROR "Missing RESULT_VAR argument to ecm_find_package_parse_components")
|
|
||||||
endif()
|
|
||||||
if(NOT ECM_FPPC_KNOWN_COMPONENTS)
|
|
||||||
message(FATAL_ERROR "Missing KNOWN_COMPONENTS argument to ecm_find_package_parse_components")
|
|
||||||
endif()
|
|
||||||
if(NOT ECM_FPPC_DEFAULT_COMPONENTS)
|
|
||||||
set(ECM_FPPC_DEFAULT_COMPONENTS ${ECM_FPPC_KNOWN_COMPONENTS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${module_name}_FIND_COMPONENTS)
|
|
||||||
set(ecm_fppc_requestedComps ${${module_name}_FIND_COMPONENTS})
|
|
||||||
|
|
||||||
if(NOT ECM_FPPC_SKIP_DEPENDENCY_HANDLING)
|
|
||||||
# Make sure deps are included
|
|
||||||
foreach(ecm_fppc_comp ${ecm_fppc_requestedComps})
|
|
||||||
foreach(ecm_fppc_dep_comp ${${module_name}_${ecm_fppc_comp}_component_deps})
|
|
||||||
list(FIND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}" ecm_fppc_index)
|
|
||||||
if("${ecm_fppc_index}" STREQUAL "-1")
|
|
||||||
if(NOT ${module_name}_FIND_QUIETLY)
|
|
||||||
message(STATUS "${module_name}: ${ecm_fppc_comp} requires ${${module_name}_${ecm_fppc_comp}_component_deps}")
|
|
||||||
endif()
|
|
||||||
list(APPEND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
else()
|
|
||||||
message(STATUS "Skipping dependency handling for ${module_name}")
|
|
||||||
endif()
|
|
||||||
list(REMOVE_DUPLICATES ecm_fppc_requestedComps)
|
|
||||||
|
|
||||||
# This makes sure components are listed in the same order as
|
|
||||||
# KNOWN_COMPONENTS (potentially important for inter-dependencies)
|
|
||||||
set(${ECM_FPPC_RESULT_VAR})
|
|
||||||
foreach(ecm_fppc_comp ${ECM_FPPC_KNOWN_COMPONENTS})
|
|
||||||
list(FIND ecm_fppc_requestedComps "${ecm_fppc_comp}" ecm_fppc_index)
|
|
||||||
if(NOT "${ecm_fppc_index}" STREQUAL "-1")
|
|
||||||
list(APPEND ${ECM_FPPC_RESULT_VAR} "${ecm_fppc_comp}")
|
|
||||||
list(REMOVE_AT ecm_fppc_requestedComps ${ecm_fppc_index})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
# if there are any left, they are unknown components
|
|
||||||
if(ecm_fppc_requestedComps)
|
|
||||||
set(ecm_fppc_msgType STATUS)
|
|
||||||
if(${module_name}_FIND_REQUIRED)
|
|
||||||
set(ecm_fppc_msgType FATAL_ERROR)
|
|
||||||
endif()
|
|
||||||
if(NOT ${module_name}_FIND_QUIETLY)
|
|
||||||
message(${ecm_fppc_msgType} "${module_name}: requested unknown components ${ecm_fppc_requestedComps}")
|
|
||||||
endif()
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(${ECM_FPPC_RESULT_VAR} ${ECM_FPPC_DEFAULT_COMPONENTS})
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
macro(ecm_find_package_handle_library_components module_name)
|
|
||||||
set(ecm_fpwc_options SKIP_PKG_CONFIG SKIP_DEPENDENCY_HANDLING)
|
|
||||||
set(ecm_fpwc_oneValueArgs)
|
|
||||||
set(ecm_fpwc_multiValueArgs COMPONENTS)
|
|
||||||
cmake_parse_arguments(ECM_FPWC "${ecm_fpwc_options}" "${ecm_fpwc_oneValueArgs}" "${ecm_fpwc_multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(ECM_FPWC_UNPARSED_ARGUMENTS)
|
|
||||||
message(FATAL_ERROR "Unexpected arguments to ecm_find_package_handle_components: ${ECM_FPWC_UNPARSED_ARGUMENTS}")
|
|
||||||
endif()
|
|
||||||
if(NOT ECM_FPWC_COMPONENTS)
|
|
||||||
message(FATAL_ERROR "Missing COMPONENTS argument to ecm_find_package_handle_components")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package(PkgConfig QUIET)
|
|
||||||
foreach(ecm_fpwc_comp ${ECM_FPWC_COMPONENTS})
|
|
||||||
set(ecm_fpwc_dep_vars)
|
|
||||||
set(ecm_fpwc_dep_targets)
|
|
||||||
if(NOT SKIP_DEPENDENCY_HANDLING)
|
|
||||||
foreach(ecm_fpwc_dep ${${module_name}_${ecm_fpwc_comp}_component_deps})
|
|
||||||
list(APPEND ecm_fpwc_dep_vars "${module_name}_${ecm_fpwc_dep}_FOUND")
|
|
||||||
list(APPEND ecm_fpwc_dep_targets "${module_name}::${ecm_fpwc_dep}")
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT ECM_FPWC_SKIP_PKG_CONFIG AND ${module_name}_${ecm_fpwc_comp}_pkg_config)
|
|
||||||
pkg_check_modules(PKG_${module_name}_${ecm_fpwc_comp} QUIET
|
|
||||||
${${module_name}_${ecm_fpwc_comp}_pkg_config})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_path(${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
|
|
||||||
NAMES ${${module_name}_${ecm_fpwc_comp}_header}
|
|
||||||
HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_INCLUDE_DIRS}
|
|
||||||
PATH_SUFFIXES ${${module_name}_${ecm_fpwc_comp}_header_subdir}
|
|
||||||
)
|
|
||||||
find_library(${module_name}_${ecm_fpwc_comp}_LIBRARY
|
|
||||||
NAMES ${${module_name}_${ecm_fpwc_comp}_lib}
|
|
||||||
HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_LIBRARY_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
set(${module_name}_${ecm_fpwc_comp}_VERSION "${PKG_${module_name}_${ecm_fpwc_comp}_VERSION}")
|
|
||||||
if(NOT ${module_name}_VERSION)
|
|
||||||
set(${module_name}_VERSION ${${module_name}_${ecm_fpwc_comp}_VERSION})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_name_mismatched_arg)
|
|
||||||
if(NOT CMAKE_VERSION VERSION_LESS 3.17)
|
|
||||||
set(_name_mismatched_arg NAME_MISMATCHED)
|
|
||||||
endif()
|
|
||||||
find_package_handle_standard_args(${module_name}_${ecm_fpwc_comp}
|
|
||||||
FOUND_VAR
|
|
||||||
${module_name}_${ecm_fpwc_comp}_FOUND
|
|
||||||
REQUIRED_VARS
|
|
||||||
${module_name}_${ecm_fpwc_comp}_LIBRARY
|
|
||||||
${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
|
|
||||||
${ecm_fpwc_dep_vars}
|
|
||||||
VERSION_VAR
|
|
||||||
${module_name}_${ecm_fpwc_comp}_VERSION
|
|
||||||
${_name_mismatched_arg}
|
|
||||||
)
|
|
||||||
|
|
||||||
mark_as_advanced(
|
|
||||||
${module_name}_${ecm_fpwc_comp}_LIBRARY
|
|
||||||
${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
|
|
||||||
)
|
|
||||||
|
|
||||||
if(${module_name}_${ecm_fpwc_comp}_FOUND)
|
|
||||||
list(APPEND ${module_name}_LIBRARIES
|
|
||||||
"${${module_name}_${ecm_fpwc_comp}_LIBRARY}")
|
|
||||||
list(APPEND ${module_name}_INCLUDE_DIRS
|
|
||||||
"${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}")
|
|
||||||
set(${module_name}_DEFINITIONS
|
|
||||||
${${module_name}_DEFINITIONS}
|
|
||||||
${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS})
|
|
||||||
if(NOT TARGET ${module_name}::${ecm_fpwc_comp})
|
|
||||||
add_library(${module_name}::${ecm_fpwc_comp} UNKNOWN IMPORTED)
|
|
||||||
set_target_properties(${module_name}::${ecm_fpwc_comp} PROPERTIES
|
|
||||||
IMPORTED_LOCATION "${${module_name}_${ecm_fpwc_comp}_LIBRARY}"
|
|
||||||
INTERFACE_COMPILE_OPTIONS "${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}"
|
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}"
|
|
||||||
INTERFACE_LINK_LIBRARIES "${ecm_fpwc_dep_targets}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
list(APPEND ${module_name}_TARGETS
|
|
||||||
"${module_name}::${ecm_fpwc_comp}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
if(${module_name}_LIBRARIES)
|
|
||||||
list(REMOVE_DUPLICATES ${module_name}_LIBRARIES)
|
|
||||||
endif()
|
|
||||||
if(${module_name}_INCLUDE_DIRS)
|
|
||||||
list(REMOVE_DUPLICATES ${module_name}_INCLUDE_DIRS)
|
|
||||||
endif()
|
|
||||||
if(${module_name}_DEFINITIONS)
|
|
||||||
list(REMOVE_DUPLICATES ${module_name}_DEFINITIONS)
|
|
||||||
endif()
|
|
||||||
if(${module_name}_TARGETS)
|
|
||||||
list(REMOVE_DUPLICATES ${module_name}_TARGETS)
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
@ -1,170 +0,0 @@
|
|||||||
#.rst:
|
|
||||||
# FindWaylandScanner
|
|
||||||
# ------------------
|
|
||||||
#
|
|
||||||
# Try to find wayland-scanner.
|
|
||||||
#
|
|
||||||
# If the wayland-scanner executable is not in your PATH, you can provide
|
|
||||||
# an alternative name or full path location with the ``WaylandScanner_EXECUTABLE``
|
|
||||||
# variable.
|
|
||||||
#
|
|
||||||
# This will define the following variables:
|
|
||||||
#
|
|
||||||
# ``WaylandScanner_FOUND``
|
|
||||||
# True if wayland-scanner is available.
|
|
||||||
#
|
|
||||||
# ``WaylandScanner_EXECUTABLE``
|
|
||||||
# The wayland-scanner executable.
|
|
||||||
#
|
|
||||||
# If ``WaylandScanner_FOUND`` is TRUE, it will also define the following imported
|
|
||||||
# target:
|
|
||||||
#
|
|
||||||
# ``Wayland::Scanner``
|
|
||||||
# The wayland-scanner executable.
|
|
||||||
#
|
|
||||||
# This module provides the following functions to generate C protocol
|
|
||||||
# implementations:
|
|
||||||
#
|
|
||||||
# - ``ecm_add_wayland_client_protocol``
|
|
||||||
# - ``ecm_add_wayland_server_protocol``
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# ecm_add_wayland_client_protocol(<source_files_var>
|
|
||||||
# PROTOCOL <xmlfile>
|
|
||||||
# BASENAME <basename>)
|
|
||||||
#
|
|
||||||
# Generate Wayland client protocol files from ``<xmlfile>`` XML
|
|
||||||
# definition for the ``<basename>`` interface and append those files
|
|
||||||
# to ``<source_files_var>``.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# ecm_add_wayland_server_protocol(<source_files_var>
|
|
||||||
# PROTOCOL <xmlfile>
|
|
||||||
# BASENAME <basename>)
|
|
||||||
#
|
|
||||||
# Generate Wayland server protocol files from ``<xmlfile>`` XML
|
|
||||||
# definition for the ``<basename>`` interface and append those files
|
|
||||||
# to ``<source_files_var>``.
|
|
||||||
#
|
|
||||||
# Since 1.4.0.
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2012-2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
# 3. The name of the author may not be used to endorse or promote products
|
|
||||||
# derived from this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#=============================================================================
|
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpers.cmake)
|
|
||||||
|
|
||||||
ecm_find_package_version_check(WaylandScanner)
|
|
||||||
|
|
||||||
# Find wayland-scanner
|
|
||||||
find_program(WaylandScanner_EXECUTABLE NAMES wayland-scanner)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(WaylandScanner
|
|
||||||
FOUND_VAR
|
|
||||||
WaylandScanner_FOUND
|
|
||||||
REQUIRED_VARS
|
|
||||||
WaylandScanner_EXECUTABLE
|
|
||||||
)
|
|
||||||
|
|
||||||
mark_as_advanced(WaylandScanner_EXECUTABLE)
|
|
||||||
|
|
||||||
if(NOT TARGET Wayland::Scanner AND WaylandScanner_FOUND)
|
|
||||||
add_executable(Wayland::Scanner IMPORTED)
|
|
||||||
set_target_properties(Wayland::Scanner PROPERTIES
|
|
||||||
IMPORTED_LOCATION "${WaylandScanner_EXECUTABLE}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(FeatureSummary)
|
|
||||||
set_package_properties(WaylandScanner PROPERTIES
|
|
||||||
URL "https://wayland.freedesktop.org/"
|
|
||||||
DESCRIPTION "Executable that converts XML protocol files to C code"
|
|
||||||
)
|
|
||||||
|
|
||||||
function(ecm_add_wayland_client_protocol out_var)
|
|
||||||
# Parse arguments
|
|
||||||
set(oneValueArgs PROTOCOL BASENAME)
|
|
||||||
cmake_parse_arguments(ARGS "" "${oneValueArgs}" "" ${ARGN})
|
|
||||||
|
|
||||||
if(ARGS_UNPARSED_ARGUMENTS)
|
|
||||||
message(FATAL_ERROR "Unknown keywords given to ecm_add_wayland_client_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)
|
|
||||||
set(_client_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-client-protocol.h")
|
|
||||||
set(_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-protocol.c")
|
|
||||||
|
|
||||||
set_source_files_properties(${_client_header} GENERATED)
|
|
||||||
set_source_files_properties(${_code} GENERATED)
|
|
||||||
set_property(SOURCE ${_client_header} PROPERTY SKIP_AUTOMOC ON)
|
|
||||||
|
|
||||||
add_custom_command(OUTPUT "${_client_header}"
|
|
||||||
COMMAND ${WaylandScanner_EXECUTABLE} client-header ${_infile} ${_client_header}
|
|
||||||
DEPENDS ${WaylandScanner_EXECUTABLE} ${_infile}
|
|
||||||
VERBATIM
|
|
||||||
)
|
|
||||||
|
|
||||||
add_custom_command(OUTPUT "${_code}"
|
|
||||||
COMMAND ${WaylandScanner_EXECUTABLE} private-code ${_infile} ${_code}
|
|
||||||
DEPENDS ${WaylandScanner_EXECUTABLE} ${_infile} ${_client_header}
|
|
||||||
VERBATIM
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND ${out_var} "${_client_header}" "${_code}")
|
|
||||||
set(${out_var} ${${out_var}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
|
|
||||||
function(ecm_add_wayland_server_protocol out_var)
|
|
||||||
# Parse arguments
|
|
||||||
set(oneValueArgs PROTOCOL BASENAME)
|
|
||||||
cmake_parse_arguments(ARGS "" "${oneValueArgs}" "" ${ARGN})
|
|
||||||
|
|
||||||
if(ARGS_UNPARSED_ARGUMENTS)
|
|
||||||
message(FATAL_ERROR "Unknown keywords given to ecm_add_wayland_server_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
ecm_add_wayland_client_protocol(${out_var}
|
|
||||||
PROTOCOL ${ARGS_PROTOCOL}
|
|
||||||
BASENAME ${ARGS_BASENAME})
|
|
||||||
|
|
||||||
get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)
|
|
||||||
set(_server_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-server-protocol.h")
|
|
||||||
set_property(SOURCE ${_server_header} PROPERTY SKIP_AUTOMOC ON)
|
|
||||||
set_source_files_properties(${_server_header} GENERATED)
|
|
||||||
|
|
||||||
add_custom_command(OUTPUT "${_server_header}"
|
|
||||||
COMMAND ${WaylandScanner_EXECUTABLE} server-header ${_infile} ${_server_header}
|
|
||||||
DEPENDS ${WaylandScanner_EXECUTABLE} ${_infile}
|
|
||||||
VERBATIM
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND ${out_var} "${_server_header}")
|
|
||||||
set(${out_var} ${${out_var}} PARENT_SCOPE)
|
|
||||||
endfunction()
|
|
@ -1,62 +0,0 @@
|
|||||||
if (NOT NO_ISA_EXTENSIONS)
|
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64")
|
|
||||||
CHECK_CXX_COMPILER_FLAG("-mcpu=native" COMPILER_SUPPORTS_MCPU_NATIVE)
|
|
||||||
if(COMPILER_SUPPORTS_MARCH_NATIVE)
|
|
||||||
add_compile_options(-mcpu=native)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
|
|
||||||
if(COMPILER_SUPPORTS_MARCH_NATIVE)
|
|
||||||
add_compile_options(-march=native)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(WIN32)
|
|
||||||
add_compile_options(/arch:AVX2)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT LEGACY)
|
|
||||||
set(USE_WAYLAND ON)
|
|
||||||
else()
|
|
||||||
set(USE_WAYLAND OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
|
||||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fexperimental-library>)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)
|
|
||||||
add_compile_options(/MP)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(EMSCRIPTEN)
|
|
||||||
add_compile_options(-pthread -DIMGUI_IMPL_OPENGL_ES2)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT EMSCRIPTEN)
|
|
||||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
find_program(MOLD_LINKER mold)
|
|
||||||
if(MOLD_LINKER)
|
|
||||||
set(CMAKE_LINKER_TYPE "MOLD")
|
|
||||||
endif()
|
|
||||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
||||||
add_compile_options(-fno-eliminate-unused-debug-types)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_program(CCACHE ccache)
|
|
||||||
if(CCACHE)
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
file(GENERATE OUTPUT .gitignore CONTENT "*")
|
|
||||||
|
|
||||||
set(CMAKE_COLOR_DIAGNOSTICS ON)
|
|
@ -1,12 +0,0 @@
|
|||||||
diff --git a/extra_symbols.txt b/extra_symbols.txt
|
|
||||||
index b95bb58..6b8f616 100644
|
|
||||||
--- a/extra_symbols.txt
|
|
||||||
+++ b/extra_symbols.txt
|
|
||||||
@@ -1,3 +1,7 @@
|
|
||||||
+glCompressedTexImage2D
|
|
||||||
+GL_LINEAR_MIPMAP_LINEAR
|
|
||||||
+GL_TEXTURE_WRAP_S
|
|
||||||
+GL_TEXTURE_WRAP_T
|
|
||||||
glReadPixels
|
|
||||||
glClearColor
|
|
||||||
glClear
|
|
@ -1,14 +0,0 @@
|
|||||||
diff '--color=auto' -ruN 72d8f61727dc878102157113d1998f86b852d20e/imconfig.h new/imconfig.h
|
|
||||||
--- 72d8f61727dc878102157113d1998f86b852d20e/imconfig.h 2024-09-27 14:28:05.568760349 +0200
|
|
||||||
+++ new/imconfig.h 2024-09-27 14:29:47.310243707 +0200
|
|
||||||
@@ -113,6 +113,10 @@
|
|
||||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
|
||||||
//#define ImDrawIdx unsigned int
|
|
||||||
|
|
||||||
+#ifdef __EMSCRIPTEN__
|
|
||||||
+#define ImDrawIdx unsigned int
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
|
||||||
//struct ImDrawList;
|
|
||||||
//struct ImDrawCmd;
|
|
@ -1,56 +0,0 @@
|
|||||||
diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h
|
|
||||||
index d6ffa5a2d..e48372c64 100644
|
|
||||||
--- a/backends/imgui_impl_opengl3_loader.h
|
|
||||||
+++ b/backends/imgui_impl_opengl3_loader.h
|
|
||||||
@@ -179,6 +179,7 @@ typedef khronos_uint8_t GLubyte;
|
|
||||||
#define GL_VERSION 0x1F02
|
|
||||||
#define GL_EXTENSIONS 0x1F03
|
|
||||||
#define GL_LINEAR 0x2601
|
|
||||||
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
|
|
||||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
|
||||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
|
||||||
#define GL_TEXTURE_WRAP_S 0x2802
|
|
||||||
@@ -241,8 +242,10 @@ GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
|
|
||||||
#define GL_TEXTURE0 0x84C0
|
|
||||||
#define GL_ACTIVE_TEXTURE 0x84E0
|
|
||||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
|
||||||
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
|
|
||||||
#ifdef GL_GLEXT_PROTOTYPES
|
|
||||||
GLAPI void APIENTRY glActiveTexture (GLenum texture);
|
|
||||||
+GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
|
|
||||||
#endif
|
|
||||||
#endif /* GL_VERSION_1_3 */
|
|
||||||
#ifndef GL_VERSION_1_4
|
|
||||||
@@ -478,7 +481,7 @@ GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
|
|
||||||
|
|
||||||
/* gl3w internal state */
|
|
||||||
union ImGL3WProcs {
|
|
||||||
- GL3WglProc ptr[59];
|
|
||||||
+ GL3WglProc ptr[60];
|
|
||||||
struct {
|
|
||||||
PFNGLACTIVETEXTUREPROC ActiveTexture;
|
|
||||||
PFNGLATTACHSHADERPROC AttachShader;
|
|
||||||
@@ -494,6 +497,7 @@ union ImGL3WProcs {
|
|
||||||
PFNGLCLEARPROC Clear;
|
|
||||||
PFNGLCLEARCOLORPROC ClearColor;
|
|
||||||
PFNGLCOMPILESHADERPROC CompileShader;
|
|
||||||
+ PFNGLCOMPRESSEDTEXIMAGE2DPROC CompressedTexImage2D;
|
|
||||||
PFNGLCREATEPROGRAMPROC CreateProgram;
|
|
||||||
PFNGLCREATESHADERPROC CreateShader;
|
|
||||||
PFNGLDELETEBUFFERSPROC DeleteBuffers;
|
|
||||||
@@ -559,6 +563,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
|
||||||
#define glClear imgl3wProcs.gl.Clear
|
|
||||||
#define glClearColor imgl3wProcs.gl.ClearColor
|
|
||||||
#define glCompileShader imgl3wProcs.gl.CompileShader
|
|
||||||
+#define glCompressedTexImage2D imgl3wProcs.gl.CompressedTexImage2D
|
|
||||||
#define glCreateProgram imgl3wProcs.gl.CreateProgram
|
|
||||||
#define glCreateShader imgl3wProcs.gl.CreateShader
|
|
||||||
#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
|
|
||||||
@@ -854,6 +859,7 @@ static const char *proc_names[] = {
|
|
||||||
"glClear",
|
|
||||||
"glClearColor",
|
|
||||||
"glCompileShader",
|
|
||||||
+ "glCompressedTexImage2D",
|
|
||||||
"glCreateProgram",
|
|
||||||
"glCreateShader",
|
|
||||||
"glDeleteBuffers",
|
|
@ -1,35 +0,0 @@
|
|||||||
set(TRACY_COMMON_DIR ${CMAKE_CURRENT_LIST_DIR}/../public/common)
|
|
||||||
|
|
||||||
set(TRACY_COMMON_SOURCES
|
|
||||||
tracy_lz4.cpp
|
|
||||||
tracy_lz4hc.cpp
|
|
||||||
TracySocket.cpp
|
|
||||||
TracyStackFrames.cpp
|
|
||||||
TracySystem.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
list(TRANSFORM TRACY_COMMON_SOURCES PREPEND "${TRACY_COMMON_DIR}/")
|
|
||||||
|
|
||||||
|
|
||||||
set(TRACY_SERVER_DIR ${CMAKE_CURRENT_LIST_DIR}/../server)
|
|
||||||
|
|
||||||
set(TRACY_SERVER_SOURCES
|
|
||||||
TracyMemory.cpp
|
|
||||||
TracyMmap.cpp
|
|
||||||
TracyPrint.cpp
|
|
||||||
TracySysUtil.cpp
|
|
||||||
TracyTaskDispatch.cpp
|
|
||||||
TracyTextureCompression.cpp
|
|
||||||
TracyThreadCompress.cpp
|
|
||||||
TracyWorker.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
list(TRANSFORM TRACY_SERVER_SOURCES PREPEND "${TRACY_SERVER_DIR}/")
|
|
||||||
|
|
||||||
|
|
||||||
add_library(TracyServer STATIC EXCLUDE_FROM_ALL ${TRACY_COMMON_SOURCES} ${TRACY_SERVER_SOURCES})
|
|
||||||
target_include_directories(TracyServer PUBLIC ${TRACY_COMMON_DIR} ${TRACY_SERVER_DIR})
|
|
||||||
target_link_libraries(TracyServer PUBLIC TracyCapstone libzstd PPQSort::PPQSort)
|
|
||||||
if(NO_STATISTICS)
|
|
||||||
target_compile_definitions(TracyServer PUBLIC TRACY_NO_STATISTICS)
|
|
||||||
endif()
|
|
@ -1,222 +0,0 @@
|
|||||||
# Vendor Specific CMake
|
|
||||||
# The Tracy project keeps most vendor source locally
|
|
||||||
|
|
||||||
set (ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../")
|
|
||||||
|
|
||||||
# Dependencies are taken from the system first and if not found, they are pulled with CPM and built from source
|
|
||||||
|
|
||||||
include(FindPkgConfig)
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/CPM.cmake)
|
|
||||||
|
|
||||||
option(DOWNLOAD_CAPSTONE "Force download capstone" ON)
|
|
||||||
option(DOWNLOAD_GLFW "Force download glfw" OFF)
|
|
||||||
option(DOWNLOAD_FREETYPE "Force download freetype" OFF)
|
|
||||||
|
|
||||||
# capstone
|
|
||||||
|
|
||||||
pkg_check_modules(CAPSTONE capstone)
|
|
||||||
if(CAPSTONE_FOUND AND NOT DOWNLOAD_CAPSTONE)
|
|
||||||
message(STATUS "Capstone found: ${CAPSTONE}")
|
|
||||||
add_library(TracyCapstone INTERFACE)
|
|
||||||
target_include_directories(TracyCapstone INTERFACE ${CAPSTONE_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(TracyCapstone INTERFACE ${CAPSTONE_LINK_LIBRARIES})
|
|
||||||
else()
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME capstone
|
|
||||||
GITHUB_REPOSITORY capstone-engine/capstone
|
|
||||||
GIT_TAG 6.0.0-Alpha1
|
|
||||||
OPTIONS
|
|
||||||
"CAPSTONE_X86_ATT_DISABLE ON"
|
|
||||||
"CAPSTONE_ALPHA_SUPPORT OFF"
|
|
||||||
"CAPSTONE_HPPA_SUPPORT OFF"
|
|
||||||
"CAPSTONE_LOONGARCH_SUPPORT OFF"
|
|
||||||
"CAPSTONE_M680X_SUPPORT OFF"
|
|
||||||
"CAPSTONE_M68K_SUPPORT OFF"
|
|
||||||
"CAPSTONE_MIPS_SUPPORT OFF"
|
|
||||||
"CAPSTONE_MOS65XX_SUPPORT OFF"
|
|
||||||
"CAPSTONE_PPC_SUPPORT OFF"
|
|
||||||
"CAPSTONE_SPARC_SUPPORT OFF"
|
|
||||||
"CAPSTONE_SYSTEMZ_SUPPORT OFF"
|
|
||||||
"CAPSTONE_XCORE_SUPPORT OFF"
|
|
||||||
"CAPSTONE_TRICORE_SUPPORT OFF"
|
|
||||||
"CAPSTONE_TMS320C64X_SUPPORT OFF"
|
|
||||||
"CAPSTONE_M680X_SUPPORT OFF"
|
|
||||||
"CAPSTONE_EVM_SUPPORT OFF"
|
|
||||||
"CAPSTONE_WASM_SUPPORT OFF"
|
|
||||||
"CAPSTONE_BPF_SUPPORT OFF"
|
|
||||||
"CAPSTONE_RISCV_SUPPORT OFF"
|
|
||||||
"CAPSTONE_SH_SUPPORT OFF"
|
|
||||||
"CAPSTONE_XTENSA_SUPPORT OFF"
|
|
||||||
"CAPSTONE_BUILD_MACOS_THIN ON"
|
|
||||||
EXCLUDE_FROM_ALL TRUE
|
|
||||||
)
|
|
||||||
add_library(TracyCapstone INTERFACE)
|
|
||||||
target_include_directories(TracyCapstone INTERFACE ${capstone_SOURCE_DIR}/include/capstone)
|
|
||||||
target_link_libraries(TracyCapstone INTERFACE capstone)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# GLFW
|
|
||||||
|
|
||||||
if(NOT USE_WAYLAND AND NOT EMSCRIPTEN)
|
|
||||||
pkg_check_modules(GLFW glfw3)
|
|
||||||
if (GLFW_FOUND AND NOT DOWNLOAD_GLFW)
|
|
||||||
add_library(TracyGlfw3 INTERFACE)
|
|
||||||
target_include_directories(TracyGlfw3 INTERFACE ${GLFW_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(TracyGlfw3 INTERFACE ${GLFW_LINK_LIBRARIES})
|
|
||||||
else()
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME glfw
|
|
||||||
GITHUB_REPOSITORY glfw/glfw
|
|
||||||
GIT_TAG 3.4
|
|
||||||
OPTIONS
|
|
||||||
"GLFW_BUILD_EXAMPLES OFF"
|
|
||||||
"GLFW_BUILD_TESTS OFF"
|
|
||||||
"GLFW_BUILD_DOCS OFF"
|
|
||||||
"GLFW_INSTALL OFF"
|
|
||||||
EXCLUDE_FROM_ALL TRUE
|
|
||||||
)
|
|
||||||
add_library(TracyGlfw3 INTERFACE)
|
|
||||||
target_link_libraries(TracyGlfw3 INTERFACE glfw)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# freetype
|
|
||||||
|
|
||||||
pkg_check_modules(FREETYPE freetype2)
|
|
||||||
if (FREETYPE_FOUND AND NOT DOWNLOAD_FREETYPE)
|
|
||||||
add_library(TracyFreetype INTERFACE)
|
|
||||||
target_include_directories(TracyFreetype INTERFACE ${FREETYPE_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(TracyFreetype INTERFACE ${FREETYPE_LINK_LIBRARIES})
|
|
||||||
else()
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME freetype
|
|
||||||
GITHUB_REPOSITORY freetype/freetype
|
|
||||||
GIT_TAG VER-2-13-3
|
|
||||||
OPTIONS
|
|
||||||
"FT_DISABLE_HARFBUZZ ON"
|
|
||||||
"FT_WITH_HARFBUZZ OFF"
|
|
||||||
EXCLUDE_FROM_ALL TRUE
|
|
||||||
)
|
|
||||||
add_library(TracyFreetype INTERFACE)
|
|
||||||
target_link_libraries(TracyFreetype INTERFACE freetype)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Zstd
|
|
||||||
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME zstd
|
|
||||||
GITHUB_REPOSITORY facebook/zstd
|
|
||||||
GIT_TAG v1.5.7
|
|
||||||
OPTIONS
|
|
||||||
"ZSTD_BUILD_SHARED OFF"
|
|
||||||
EXCLUDE_FROM_ALL TRUE
|
|
||||||
SOURCE_SUBDIR build/cmake
|
|
||||||
)
|
|
||||||
|
|
||||||
# Diff Template Library
|
|
||||||
|
|
||||||
set(DTL_DIR "${ROOT_DIR}/dtl")
|
|
||||||
file(GLOB_RECURSE DTL_HEADERS CONFIGURE_DEPENDS RELATIVE ${DTL_DIR} "*.hpp")
|
|
||||||
add_library(TracyDtl INTERFACE)
|
|
||||||
target_sources(TracyDtl INTERFACE ${DTL_HEADERS})
|
|
||||||
target_include_directories(TracyDtl INTERFACE ${DTL_DIR})
|
|
||||||
|
|
||||||
|
|
||||||
# Get Opt
|
|
||||||
|
|
||||||
set(GETOPT_DIR "${ROOT_DIR}/getopt")
|
|
||||||
set(GETOPT_SOURCES ${GETOPT_DIR}/getopt.c)
|
|
||||||
set(GETOPT_HEADERS ${GETOPT_DIR}/getopt.h)
|
|
||||||
add_library(TracyGetOpt STATIC EXCLUDE_FROM_ALL ${GETOPT_SOURCES} ${GETOPT_HEADERS})
|
|
||||||
target_include_directories(TracyGetOpt PUBLIC ${GETOPT_DIR})
|
|
||||||
|
|
||||||
|
|
||||||
# ImGui
|
|
||||||
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME ImGui
|
|
||||||
GITHUB_REPOSITORY ocornut/imgui
|
|
||||||
GIT_TAG v1.91.8-docking
|
|
||||||
DOWNLOAD_ONLY TRUE
|
|
||||||
PATCHES
|
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/imgui-emscripten.patch"
|
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/imgui-loader.patch"
|
|
||||||
)
|
|
||||||
|
|
||||||
set(IMGUI_SOURCES
|
|
||||||
imgui_widgets.cpp
|
|
||||||
imgui_draw.cpp
|
|
||||||
imgui_demo.cpp
|
|
||||||
imgui.cpp
|
|
||||||
imgui_tables.cpp
|
|
||||||
misc/freetype/imgui_freetype.cpp
|
|
||||||
backends/imgui_impl_opengl3.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
list(TRANSFORM IMGUI_SOURCES PREPEND "${ImGui_SOURCE_DIR}/")
|
|
||||||
|
|
||||||
add_library(TracyImGui STATIC EXCLUDE_FROM_ALL ${IMGUI_SOURCES})
|
|
||||||
target_include_directories(TracyImGui PUBLIC ${ImGui_SOURCE_DIR})
|
|
||||||
target_link_libraries(TracyImGui PUBLIC TracyFreetype)
|
|
||||||
target_compile_definitions(TracyImGui PRIVATE "IMGUI_ENABLE_FREETYPE")
|
|
||||||
|
|
||||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
||||||
target_compile_definitions(TracyImGui PRIVATE "IMGUI_DISABLE_DEBUG_TOOLS")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# NFD
|
|
||||||
|
|
||||||
if (NOT NO_FILESELECTOR AND NOT EMSCRIPTEN)
|
|
||||||
set(NFD_DIR "${ROOT_DIR}/nfd")
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
set(NFD_SOURCES "${NFD_DIR}/nfd_win.cpp")
|
|
||||||
elseif (APPLE)
|
|
||||||
set(NFD_SOURCES "${NFD_DIR}/nfd_cocoa.m")
|
|
||||||
else()
|
|
||||||
if (GTK_FILESELECTOR)
|
|
||||||
set(NFD_SOURCES "${NFD_DIR}/nfd_gtk.cpp")
|
|
||||||
else()
|
|
||||||
set(NFD_SOURCES "${NFD_DIR}/nfd_portal.cpp")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
file(GLOB_RECURSE NFD_HEADERS CONFIGURE_DEPENDS RELATIVE ${NFD_DIR} "*.h")
|
|
||||||
add_library(TracyNfd STATIC EXCLUDE_FROM_ALL ${NFD_SOURCES} ${NFD_HEADERS})
|
|
||||||
target_include_directories(TracyNfd PUBLIC ${NFD_DIR})
|
|
||||||
|
|
||||||
if (APPLE)
|
|
||||||
find_library(APPKIT_LIBRARY AppKit)
|
|
||||||
find_library(UNIFORMTYPEIDENTIFIERS_LIBRARY UniformTypeIdentifiers)
|
|
||||||
target_link_libraries(TracyNfd PUBLIC ${APPKIT_LIBRARY} ${UNIFORMTYPEIDENTIFIERS_LIBRARY})
|
|
||||||
elseif (UNIX)
|
|
||||||
if (GTK_FILESELECTOR)
|
|
||||||
pkg_check_modules(GTK3 gtk+-3.0)
|
|
||||||
if (NOT GTK3_FOUND)
|
|
||||||
message(FATAL_ERROR "GTK3 not found. Please install it or set GTK_FILESELECTOR to OFF.")
|
|
||||||
endif()
|
|
||||||
add_library(TracyGtk3 INTERFACE)
|
|
||||||
target_include_directories(TracyGtk3 INTERFACE ${GTK3_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(TracyGtk3 INTERFACE ${GTK3_LINK_LIBRARIES})
|
|
||||||
target_link_libraries(TracyNfd PUBLIC TracyGtk3)
|
|
||||||
else()
|
|
||||||
pkg_check_modules(DBUS dbus-1)
|
|
||||||
if (NOT DBUS_FOUND)
|
|
||||||
message(FATAL_ERROR "D-Bus not found. Please install it or set GTK_FILESELECTOR to ON.")
|
|
||||||
endif()
|
|
||||||
add_library(TracyDbus INTERFACE)
|
|
||||||
target_include_directories(TracyDbus INTERFACE ${DBUS_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(TracyDbus INTERFACE ${DBUS_LINK_LIBRARIES})
|
|
||||||
target_link_libraries(TracyNfd PUBLIC TracyDbus)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# PPQSort
|
|
||||||
|
|
||||||
CPMAddPackage(
|
|
||||||
NAME PPQSort
|
|
||||||
GITHUB_REPOSITORY GabTux/PPQSort
|
|
||||||
VERSION 1.0.5
|
|
||||||
EXCLUDE_FROM_ALL TRUE
|
|
||||||
)
|
|
@ -1,24 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
|
||||||
|
|
||||||
message("Parsing public/common/TracyVersion.hpp file")
|
|
||||||
|
|
||||||
file(READ "${CMAKE_CURRENT_LIST_DIR}/../public/common/TracyVersion.hpp" version)
|
|
||||||
|
|
||||||
# Note: This looks for a specific pattern in TracyVersion.hpp, if it changes
|
|
||||||
# this needs updating.
|
|
||||||
string(REGEX MATCH "Major = ([0-9]+)" _ ${version})
|
|
||||||
|
|
||||||
# This works do to the above () subexpression selection. See
|
|
||||||
# https://cmake.org/cmake/help/latest/command/string.html#regex-match for more
|
|
||||||
# details
|
|
||||||
set(TRACY_VERSION_MAJOR ${CMAKE_MATCH_1})
|
|
||||||
|
|
||||||
string(REGEX MATCH "Minor = ([0-9]+)" _ ${version})
|
|
||||||
set(TRACY_VERSION_MINOR ${CMAKE_MATCH_1})
|
|
||||||
|
|
||||||
string(REGEX MATCH "Patch = ([0-9]+)" _ ${version})
|
|
||||||
set(TRACY_VERSION_PATCH ${CMAKE_MATCH_1})
|
|
||||||
|
|
||||||
set(TRACY_VERSION_STRING "${TRACY_VERSION_MAJOR}.${TRACY_VERSION_MINOR}.${TRACY_VERSION_PATCH}")
|
|
||||||
|
|
||||||
message("VERSION ${TRACY_VERSION_STRING}")
|
|
33
common/TracyAlloc.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef __TRACYALLOC_HPP__
|
||||||
|
#define __TRACYALLOC_HPP__
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
# include "../client/tracy_rpmalloc.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
static inline void* tracy_malloc( size_t size )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
return rpmalloc( size );
|
||||||
|
#else
|
||||||
|
return malloc( size );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void tracy_free( void* ptr )
|
||||||
|
{
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
rpfree( ptr );
|
||||||
|
#else
|
||||||
|
free( ptr );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef __TRACYAPI_H__
|
#ifndef __TRACYAPI_H__
|
||||||
#define __TRACYAPI_H__
|
#define __TRACYAPI_H__
|
||||||
|
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
# if defined TRACY_EXPORTS
|
# if defined TRACY_EXPORTS
|
||||||
# define TRACY_API __declspec(dllexport)
|
# define TRACY_API __declspec(dllexport)
|
||||||
# elif defined TRACY_IMPORTS
|
# elif defined TRACY_IMPORTS
|
@ -9,14 +9,14 @@ namespace tracy
|
|||||||
|
|
||||||
constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; }
|
constexpr unsigned Lz4CompressBound( unsigned isize ) { return isize + ( isize / 255 ) + 16; }
|
||||||
|
|
||||||
enum : uint32_t { ProtocolVersion = 72 };
|
enum : uint32_t { ProtocolVersion = 35 };
|
||||||
enum : uint16_t { BroadcastVersion = 3 };
|
enum : uint32_t { BroadcastVersion = 1 };
|
||||||
|
|
||||||
using lz4sz_t = uint32_t;
|
using lz4sz_t = uint32_t;
|
||||||
|
|
||||||
enum { TargetFrameSize = 256 * 1024 };
|
enum { TargetFrameSize = 256 * 1024 };
|
||||||
enum { LZ4Size = Lz4CompressBound( TargetFrameSize ) };
|
enum { LZ4Size = Lz4CompressBound( TargetFrameSize ) };
|
||||||
static_assert( LZ4Size <= (std::numeric_limits<lz4sz_t>::max)(), "LZ4Size greater than lz4sz_t" );
|
static_assert( LZ4Size <= std::numeric_limits<lz4sz_t>::max(), "LZ4Size greater than lz4sz_t" );
|
||||||
static_assert( TargetFrameSize * 2 >= 64 * 1024, "Not enough space for LZ4 stream buffer" );
|
static_assert( TargetFrameSize * 2 >= 64 * 1024, "Not enough space for LZ4 stream buffer" );
|
||||||
|
|
||||||
enum { HandshakeShibbolethSize = 8 };
|
enum { HandshakeShibbolethSize = 8 };
|
||||||
@ -34,7 +34,7 @@ enum HandshakeStatus : uint8_t
|
|||||||
enum { WelcomeMessageProgramNameSize = 64 };
|
enum { WelcomeMessageProgramNameSize = 64 };
|
||||||
enum { WelcomeMessageHostInfoSize = 1024 };
|
enum { WelcomeMessageHostInfoSize = 1024 };
|
||||||
|
|
||||||
#pragma pack( push, 1 )
|
#pragma pack( 1 )
|
||||||
|
|
||||||
// Must increase left query space after handling!
|
// Must increase left query space after handling!
|
||||||
enum ServerQuery : uint8_t
|
enum ServerQuery : uint8_t
|
||||||
@ -44,18 +44,14 @@ enum ServerQuery : uint8_t
|
|||||||
ServerQueryThreadString,
|
ServerQueryThreadString,
|
||||||
ServerQuerySourceLocation,
|
ServerQuerySourceLocation,
|
||||||
ServerQueryPlotName,
|
ServerQueryPlotName,
|
||||||
ServerQueryFrameName,
|
|
||||||
ServerQueryParameter,
|
|
||||||
ServerQueryFiberName,
|
|
||||||
ServerQueryExternalName,
|
|
||||||
// Items above are high priority. Split order must be preserved. See IsQueryPrio().
|
|
||||||
ServerQueryDisconnect,
|
|
||||||
ServerQueryCallstackFrame,
|
ServerQueryCallstackFrame,
|
||||||
|
ServerQueryFrameName,
|
||||||
|
ServerQueryDisconnect,
|
||||||
|
ServerQueryExternalName,
|
||||||
|
ServerQueryParameter,
|
||||||
ServerQuerySymbol,
|
ServerQuerySymbol,
|
||||||
ServerQuerySymbolCode,
|
ServerQuerySymbolCode,
|
||||||
ServerQuerySourceCode,
|
ServerQueryCodeLocation
|
||||||
ServerQueryDataTransfer,
|
|
||||||
ServerQueryDataTransferPart
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerQueryPacket
|
struct ServerQueryPacket
|
||||||
@ -78,18 +74,6 @@ enum CpuArchitecture : uint8_t
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct WelcomeFlag
|
|
||||||
{
|
|
||||||
enum _t : uint8_t
|
|
||||||
{
|
|
||||||
OnDemand = 1 << 0,
|
|
||||||
IsApple = 1 << 1,
|
|
||||||
CodeTransfer = 1 << 2,
|
|
||||||
CombineSamples = 1 << 3,
|
|
||||||
IdentifySamples = 1 << 4,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WelcomeMessage
|
struct WelcomeMessage
|
||||||
{
|
{
|
||||||
double timerMul;
|
double timerMul;
|
||||||
@ -98,10 +82,10 @@ struct WelcomeMessage
|
|||||||
uint64_t delay;
|
uint64_t delay;
|
||||||
uint64_t resolution;
|
uint64_t resolution;
|
||||||
uint64_t epoch;
|
uint64_t epoch;
|
||||||
uint64_t exectime;
|
|
||||||
uint64_t pid;
|
uint64_t pid;
|
||||||
int64_t samplingPeriod;
|
int64_t samplingPeriod;
|
||||||
uint8_t flags;
|
uint8_t onDemand;
|
||||||
|
uint8_t isApple;
|
||||||
uint8_t cpuArch;
|
uint8_t cpuArch;
|
||||||
char cpuManufacturer[12];
|
char cpuManufacturer[12];
|
||||||
uint32_t cpuId;
|
uint32_t cpuId;
|
||||||
@ -122,47 +106,17 @@ enum { OnDemandPayloadMessageSize = sizeof( OnDemandPayloadMessage ) };
|
|||||||
|
|
||||||
|
|
||||||
struct BroadcastMessage
|
struct BroadcastMessage
|
||||||
{
|
|
||||||
uint16_t broadcastVersion;
|
|
||||||
uint16_t listenPort;
|
|
||||||
uint32_t protocolVersion;
|
|
||||||
uint64_t pid;
|
|
||||||
int32_t activeTime; // in seconds
|
|
||||||
char programName[WelcomeMessageProgramNameSize];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BroadcastMessage_v2
|
|
||||||
{
|
|
||||||
uint16_t broadcastVersion;
|
|
||||||
uint16_t listenPort;
|
|
||||||
uint32_t protocolVersion;
|
|
||||||
int32_t activeTime;
|
|
||||||
char programName[WelcomeMessageProgramNameSize];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BroadcastMessage_v1
|
|
||||||
{
|
{
|
||||||
uint32_t broadcastVersion;
|
uint32_t broadcastVersion;
|
||||||
uint32_t protocolVersion;
|
uint32_t protocolVersion;
|
||||||
uint32_t listenPort;
|
uint32_t listenPort;
|
||||||
uint32_t activeTime;
|
uint32_t activeTime; // in seconds
|
||||||
char programName[WelcomeMessageProgramNameSize];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BroadcastMessage_v0
|
|
||||||
{
|
|
||||||
uint32_t broadcastVersion;
|
|
||||||
uint32_t protocolVersion;
|
|
||||||
uint32_t activeTime;
|
|
||||||
char programName[WelcomeMessageProgramNameSize];
|
char programName[WelcomeMessageProgramNameSize];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { BroadcastMessageSize = sizeof( BroadcastMessage ) };
|
enum { BroadcastMessageSize = sizeof( BroadcastMessage ) };
|
||||||
enum { BroadcastMessageSize_v2 = sizeof( BroadcastMessage_v2 ) };
|
|
||||||
enum { BroadcastMessageSize_v1 = sizeof( BroadcastMessage_v1 ) };
|
|
||||||
enum { BroadcastMessageSize_v0 = sizeof( BroadcastMessage_v0 ) };
|
|
||||||
|
|
||||||
#pragma pack( pop )
|
#pragma pack()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
604
common/TracyQueue.hpp
Normal file
@ -0,0 +1,604 @@
|
|||||||
|
#ifndef __TRACYQUEUE_HPP__
|
||||||
|
#define __TRACYQUEUE_HPP__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class QueueType : uint8_t
|
||||||
|
{
|
||||||
|
ZoneText,
|
||||||
|
ZoneName,
|
||||||
|
Message,
|
||||||
|
MessageColor,
|
||||||
|
MessageCallstack,
|
||||||
|
MessageColorCallstack,
|
||||||
|
MessageAppInfo,
|
||||||
|
ZoneBeginAllocSrcLoc,
|
||||||
|
ZoneBeginAllocSrcLocLean,
|
||||||
|
ZoneBeginAllocSrcLocCallstack,
|
||||||
|
ZoneBeginAllocSrcLocCallstackLean,
|
||||||
|
CallstackMemory,
|
||||||
|
CallstackMemoryLean,
|
||||||
|
Callstack,
|
||||||
|
CallstackLean,
|
||||||
|
CallstackAlloc,
|
||||||
|
CallstackAllocLean,
|
||||||
|
CallstackSample,
|
||||||
|
CallstackSampleLean,
|
||||||
|
FrameImage,
|
||||||
|
FrameImageLean,
|
||||||
|
ZoneBegin,
|
||||||
|
ZoneBeginCallstack,
|
||||||
|
ZoneEnd,
|
||||||
|
LockWait,
|
||||||
|
LockObtain,
|
||||||
|
LockRelease,
|
||||||
|
LockSharedWait,
|
||||||
|
LockSharedObtain,
|
||||||
|
LockSharedRelease,
|
||||||
|
LockName,
|
||||||
|
MemAlloc,
|
||||||
|
MemFree,
|
||||||
|
MemAllocCallstack,
|
||||||
|
MemFreeCallstack,
|
||||||
|
GpuZoneBegin,
|
||||||
|
GpuZoneBeginCallstack,
|
||||||
|
GpuZoneEnd,
|
||||||
|
GpuZoneBeginSerial,
|
||||||
|
GpuZoneBeginCallstackSerial,
|
||||||
|
GpuZoneEndSerial,
|
||||||
|
PlotData,
|
||||||
|
ContextSwitch,
|
||||||
|
ThreadWakeup,
|
||||||
|
GpuTime,
|
||||||
|
Terminate,
|
||||||
|
KeepAlive,
|
||||||
|
ThreadContext,
|
||||||
|
Crash,
|
||||||
|
CrashReport,
|
||||||
|
ZoneValidation,
|
||||||
|
ZoneValue,
|
||||||
|
FrameMarkMsg,
|
||||||
|
FrameMarkMsgStart,
|
||||||
|
FrameMarkMsgEnd,
|
||||||
|
SourceLocation,
|
||||||
|
LockAnnounce,
|
||||||
|
LockTerminate,
|
||||||
|
LockMark,
|
||||||
|
MessageLiteral,
|
||||||
|
MessageLiteralColor,
|
||||||
|
MessageLiteralCallstack,
|
||||||
|
MessageLiteralColorCallstack,
|
||||||
|
GpuNewContext,
|
||||||
|
CallstackFrameSize,
|
||||||
|
CallstackFrame,
|
||||||
|
SymbolInformation,
|
||||||
|
CodeInformation,
|
||||||
|
SysTimeReport,
|
||||||
|
TidToPid,
|
||||||
|
PlotConfig,
|
||||||
|
ParamSetup,
|
||||||
|
ParamPingback,
|
||||||
|
CpuTopology,
|
||||||
|
StringData,
|
||||||
|
ThreadName,
|
||||||
|
CustomStringData,
|
||||||
|
PlotName,
|
||||||
|
SourceLocationPayload,
|
||||||
|
CallstackPayload,
|
||||||
|
CallstackAllocPayload,
|
||||||
|
FrameName,
|
||||||
|
FrameImageData,
|
||||||
|
ExternalName,
|
||||||
|
ExternalThreadName,
|
||||||
|
SymbolCode,
|
||||||
|
NUM_TYPES
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack( 1 )
|
||||||
|
|
||||||
|
struct QueueThreadContext
|
||||||
|
{
|
||||||
|
uint64_t thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueZoneBeginLean
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueZoneBegin : public QueueZoneBeginLean
|
||||||
|
{
|
||||||
|
uint64_t srcloc; // ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueZoneEnd
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueZoneValidation
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueZoneValue
|
||||||
|
{
|
||||||
|
uint64_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueStringTransfer
|
||||||
|
{
|
||||||
|
uint64_t ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueFrameMark
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
uint64_t name; // ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueFrameImageLean
|
||||||
|
{
|
||||||
|
uint64_t frame;
|
||||||
|
uint16_t w;
|
||||||
|
uint16_t h;
|
||||||
|
uint8_t flip;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueFrameImage : public QueueFrameImageLean
|
||||||
|
{
|
||||||
|
uint64_t image; // ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueSourceLocation
|
||||||
|
{
|
||||||
|
uint64_t name;
|
||||||
|
uint64_t function; // ptr
|
||||||
|
uint64_t file; // ptr
|
||||||
|
uint32_t line;
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueZoneText
|
||||||
|
{
|
||||||
|
uint64_t text; // ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LockType : uint8_t
|
||||||
|
{
|
||||||
|
Lockable,
|
||||||
|
SharedLockable
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueLockAnnounce
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
int64_t time;
|
||||||
|
uint64_t lckloc; // ptr
|
||||||
|
LockType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueLockTerminate
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
int64_t time;
|
||||||
|
LockType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueLockWait
|
||||||
|
{
|
||||||
|
uint64_t thread;
|
||||||
|
uint32_t id;
|
||||||
|
int64_t time;
|
||||||
|
LockType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueLockObtain
|
||||||
|
{
|
||||||
|
uint64_t thread;
|
||||||
|
uint32_t id;
|
||||||
|
int64_t time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueLockRelease
|
||||||
|
{
|
||||||
|
uint64_t thread;
|
||||||
|
uint32_t id;
|
||||||
|
int64_t time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueLockMark
|
||||||
|
{
|
||||||
|
uint64_t thread;
|
||||||
|
uint32_t id;
|
||||||
|
uint64_t srcloc; // ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueLockName
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
uint64_t name; // ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PlotDataType : uint8_t
|
||||||
|
{
|
||||||
|
Float,
|
||||||
|
Double,
|
||||||
|
Int
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueuePlotData
|
||||||
|
{
|
||||||
|
uint64_t name; // ptr
|
||||||
|
int64_t time;
|
||||||
|
PlotDataType type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
double d;
|
||||||
|
float f;
|
||||||
|
int64_t i;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueMessage
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
uint64_t text; // ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueMessageColor : public QueueMessage
|
||||||
|
{
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Don't change order, only add new entries at the end, this is also used on trace dumps!
|
||||||
|
enum class GpuContextType : uint8_t
|
||||||
|
{
|
||||||
|
Invalid,
|
||||||
|
OpenGl,
|
||||||
|
Vulkan,
|
||||||
|
OpenCL,
|
||||||
|
Direct3D12
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueGpuNewContext
|
||||||
|
{
|
||||||
|
int64_t cpuTime;
|
||||||
|
int64_t gpuTime;
|
||||||
|
uint64_t thread;
|
||||||
|
float period;
|
||||||
|
uint8_t context;
|
||||||
|
uint8_t accuracyBits;
|
||||||
|
GpuContextType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueGpuZoneBegin
|
||||||
|
{
|
||||||
|
int64_t cpuTime;
|
||||||
|
uint64_t srcloc;
|
||||||
|
uint64_t thread;
|
||||||
|
uint16_t queryId;
|
||||||
|
uint8_t context;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueGpuZoneEnd
|
||||||
|
{
|
||||||
|
int64_t cpuTime;
|
||||||
|
uint64_t thread;
|
||||||
|
uint16_t queryId;
|
||||||
|
uint8_t context;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueGpuTime
|
||||||
|
{
|
||||||
|
int64_t gpuTime;
|
||||||
|
uint16_t queryId;
|
||||||
|
uint8_t context;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueMemAlloc
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
uint64_t thread;
|
||||||
|
uint64_t ptr;
|
||||||
|
char size[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueMemFree
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
uint64_t thread;
|
||||||
|
uint64_t ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCallstackMemory
|
||||||
|
{
|
||||||
|
uint64_t ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCallstack
|
||||||
|
{
|
||||||
|
uint64_t ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCallstackAlloc
|
||||||
|
{
|
||||||
|
uint64_t ptr;
|
||||||
|
uint64_t nativePtr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCallstackSampleLean
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
uint64_t thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCallstackSample : public QueueCallstackSampleLean
|
||||||
|
{
|
||||||
|
uint64_t ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCallstackFrameSize
|
||||||
|
{
|
||||||
|
uint64_t ptr;
|
||||||
|
uint8_t size;
|
||||||
|
uint64_t imageName;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCallstackFrame
|
||||||
|
{
|
||||||
|
uint64_t name;
|
||||||
|
uint64_t file;
|
||||||
|
uint32_t line;
|
||||||
|
uint64_t symAddr;
|
||||||
|
char symLen[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueSymbolInformation
|
||||||
|
{
|
||||||
|
uint64_t file;
|
||||||
|
uint32_t line;
|
||||||
|
uint64_t symAddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCodeInformation
|
||||||
|
{
|
||||||
|
uint64_t ptr;
|
||||||
|
uint64_t file;
|
||||||
|
uint32_t line;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCrashReport
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
uint64_t text; // ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueSysTime
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
float sysTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueContextSwitch
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
uint64_t oldThread;
|
||||||
|
uint64_t newThread;
|
||||||
|
uint8_t cpu;
|
||||||
|
uint8_t reason;
|
||||||
|
uint8_t state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueThreadWakeup
|
||||||
|
{
|
||||||
|
int64_t time;
|
||||||
|
uint64_t thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueTidToPid
|
||||||
|
{
|
||||||
|
uint64_t tid;
|
||||||
|
uint64_t pid;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PlotFormatType : uint8_t
|
||||||
|
{
|
||||||
|
Number,
|
||||||
|
Memory,
|
||||||
|
Percentage
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueuePlotConfig
|
||||||
|
{
|
||||||
|
uint64_t name; // ptr
|
||||||
|
uint8_t type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueParamSetup
|
||||||
|
{
|
||||||
|
uint32_t idx;
|
||||||
|
uint64_t name; // ptr
|
||||||
|
uint8_t isBool;
|
||||||
|
int32_t val;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueCpuTopology
|
||||||
|
{
|
||||||
|
uint32_t package;
|
||||||
|
uint32_t core;
|
||||||
|
uint32_t thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueHeader
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
QueueType type;
|
||||||
|
uint8_t idx;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueItem
|
||||||
|
{
|
||||||
|
QueueHeader hdr;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
QueueThreadContext threadCtx;
|
||||||
|
QueueZoneBegin zoneBegin;
|
||||||
|
QueueZoneBeginLean zoneBeginLean;
|
||||||
|
QueueZoneEnd zoneEnd;
|
||||||
|
QueueZoneValidation zoneValidation;
|
||||||
|
QueueZoneValue zoneValue;
|
||||||
|
QueueStringTransfer stringTransfer;
|
||||||
|
QueueFrameMark frameMark;
|
||||||
|
QueueFrameImage frameImage;
|
||||||
|
QueueFrameImage frameImageLean;
|
||||||
|
QueueSourceLocation srcloc;
|
||||||
|
QueueZoneText zoneText;
|
||||||
|
QueueLockAnnounce lockAnnounce;
|
||||||
|
QueueLockTerminate lockTerminate;
|
||||||
|
QueueLockWait lockWait;
|
||||||
|
QueueLockObtain lockObtain;
|
||||||
|
QueueLockRelease lockRelease;
|
||||||
|
QueueLockMark lockMark;
|
||||||
|
QueueLockName lockName;
|
||||||
|
QueuePlotData plotData;
|
||||||
|
QueueMessage message;
|
||||||
|
QueueMessageColor messageColor;
|
||||||
|
QueueGpuNewContext gpuNewContext;
|
||||||
|
QueueGpuZoneBegin gpuZoneBegin;
|
||||||
|
QueueGpuZoneEnd gpuZoneEnd;
|
||||||
|
QueueGpuTime gpuTime;
|
||||||
|
QueueMemAlloc memAlloc;
|
||||||
|
QueueMemFree memFree;
|
||||||
|
QueueCallstackMemory callstackMemory;
|
||||||
|
QueueCallstack callstack;
|
||||||
|
QueueCallstackAlloc callstackAlloc;
|
||||||
|
QueueCallstackSample callstackSample;
|
||||||
|
QueueCallstackSampleLean callstackSampleLean;
|
||||||
|
QueueCallstackFrameSize callstackFrameSize;
|
||||||
|
QueueCallstackFrame callstackFrame;
|
||||||
|
QueueSymbolInformation symbolInformation;
|
||||||
|
QueueCodeInformation codeInformation;
|
||||||
|
QueueCrashReport crashReport;
|
||||||
|
QueueSysTime sysTime;
|
||||||
|
QueueContextSwitch contextSwitch;
|
||||||
|
QueueThreadWakeup threadWakeup;
|
||||||
|
QueueTidToPid tidToPid;
|
||||||
|
QueuePlotConfig plotConfig;
|
||||||
|
QueueParamSetup paramSetup;
|
||||||
|
QueueCpuTopology cpuTopology;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
|
||||||
|
enum { QueueItemSize = sizeof( QueueItem ) };
|
||||||
|
|
||||||
|
static constexpr size_t QueueDataSize[] = {
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneText ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneText ), // zone name
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMessage ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMessageColor ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMessage ), // callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMessageColor ), // callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMessage ), // app info
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), // allocated source location, not for network transfer
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneBeginLean ), // lean allocated source location
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), // allocated source location, callstack, not for network transfer
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneBeginLean ), // lean allocated source location, callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCallstackMemory ), // not for network transfer
|
||||||
|
sizeof( QueueHeader ), // lean callstack memory
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCallstack ), // not for network transfer
|
||||||
|
sizeof( QueueHeader ), // lean callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCallstackAlloc ), // not for network transfer
|
||||||
|
sizeof( QueueHeader ), // lean callstack alloc
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCallstackSample ), // not for network transfer
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCallstackSampleLean ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueFrameImage ), // not for network transfer
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueFrameImageLean ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneBegin ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneBegin ), // callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneEnd ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockWait ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockObtain ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockRelease ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockWait ), // shared
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockObtain ), // shared
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockRelease ), // shared
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockName ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMemAlloc ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMemFree ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMemAlloc ), // callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMemFree ), // callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ), // callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueGpuZoneEnd ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ), // serial
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueGpuZoneBegin ), // serial, callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueGpuZoneEnd ), // serial
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueuePlotData ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueContextSwitch ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueThreadWakeup ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueGpuTime ),
|
||||||
|
// above items must be first
|
||||||
|
sizeof( QueueHeader ), // terminate
|
||||||
|
sizeof( QueueHeader ), // keep alive
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueThreadContext ),
|
||||||
|
sizeof( QueueHeader ), // crash
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCrashReport ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneValidation ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueZoneValue ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // continuous frames
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // start
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // end
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueSourceLocation ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockAnnounce ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockTerminate ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueLockMark ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMessage ), // literal
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMessageColor ), // literal
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMessage ), // literal, callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueMessageColor ), // literal, callstack
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueGpuNewContext ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCallstackFrameSize ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCallstackFrame ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueSymbolInformation ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCodeInformation ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueSysTime ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueTidToPid ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueuePlotConfig ),
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueParamSetup ),
|
||||||
|
sizeof( QueueHeader ), // param pingback
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueCpuTopology ),
|
||||||
|
// keep all QueueStringTransfer below
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // string data
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // thread name
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // custom string data
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // plot name
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // allocated source location payload
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // callstack payload
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // callstack alloc payload
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame name
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // frame image data
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external name
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // external thread name
|
||||||
|
sizeof( QueueHeader ) + sizeof( QueueStringTransfer ), // symbol code
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert( QueueItemSize == 32, "Queue item size not 32 bytes" );
|
||||||
|
static_assert( sizeof( QueueDataSize ) / sizeof( size_t ) == (uint8_t)QueueType::NUM_TYPES, "QueueDataSize mismatch" );
|
||||||
|
static_assert( sizeof( void* ) <= sizeof( uint64_t ), "Pointer size > 8 bytes" );
|
||||||
|
static_assert( sizeof( void* ) == sizeof( uintptr_t ), "Pointer size != uintptr_t" );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,4 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -8,7 +7,6 @@
|
|||||||
|
|
||||||
#include "TracyAlloc.hpp"
|
#include "TracyAlloc.hpp"
|
||||||
#include "TracySocket.hpp"
|
#include "TracySocket.hpp"
|
||||||
#include "TracySystem.hpp"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# ifndef NOMINMAX
|
# ifndef NOMINMAX
|
||||||
@ -21,9 +19,6 @@
|
|||||||
# pragma warning(disable:4267)
|
# pragma warning(disable:4267)
|
||||||
# endif
|
# endif
|
||||||
# define poll WSAPoll
|
# define poll WSAPoll
|
||||||
# ifdef _MSC_VER
|
|
||||||
# pragma comment(lib, "ws2_32.lib")
|
|
||||||
# endif
|
|
||||||
#else
|
#else
|
||||||
# include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
@ -111,16 +106,15 @@ Socket::~Socket()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Socket::Connect( const char* addr, uint16_t port )
|
bool Socket::Connect( const char* addr, int port )
|
||||||
{
|
{
|
||||||
assert( !IsValid() );
|
assert( !IsValid() );
|
||||||
|
|
||||||
if( m_ptr )
|
if( m_ptr )
|
||||||
{
|
{
|
||||||
const auto c = connect( m_connSock, m_ptr->ai_addr, m_ptr->ai_addrlen );
|
const auto c = connect( m_connSock, m_ptr->ai_addr, m_ptr->ai_addrlen );
|
||||||
if( c == -1 )
|
assert( c == -1 );
|
||||||
{
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
#if defined _WIN32
|
|
||||||
const auto err = WSAGetLastError();
|
const auto err = WSAGetLastError();
|
||||||
if( err == WSAEALREADY || err == WSAEINPROGRESS ) return false;
|
if( err == WSAEALREADY || err == WSAEINPROGRESS ) return false;
|
||||||
if( err != WSAEISCONN )
|
if( err != WSAEISCONN )
|
||||||
@ -131,9 +125,8 @@ bool Socket::Connect( const char* addr, uint16_t port )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
const auto err = errno;
|
if( errno == EALREADY || errno == EINPROGRESS ) return false;
|
||||||
if( err == EALREADY || err == EINPROGRESS ) return false;
|
if( errno != EISCONN )
|
||||||
if( err != EISCONN )
|
|
||||||
{
|
{
|
||||||
freeaddrinfo( m_res );
|
freeaddrinfo( m_res );
|
||||||
close( m_connSock );
|
close( m_connSock );
|
||||||
@ -141,9 +134,8 @@ bool Socket::Connect( const char* addr, uint16_t port )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
u_long nonblocking = 0;
|
u_long nonblocking = 0;
|
||||||
ioctlsocket( m_connSock, FIONBIO, &nonblocking );
|
ioctlsocket( m_connSock, FIONBIO, &nonblocking );
|
||||||
#else
|
#else
|
||||||
@ -164,7 +156,7 @@ bool Socket::Connect( const char* addr, uint16_t port )
|
|||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
char portbuf[32];
|
char portbuf[32];
|
||||||
sprintf( portbuf, "%" PRIu16, port );
|
sprintf( portbuf, "%i", port );
|
||||||
|
|
||||||
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
|
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
|
||||||
int sock = 0;
|
int sock = 0;
|
||||||
@ -175,7 +167,7 @@ bool Socket::Connect( const char* addr, uint16_t port )
|
|||||||
int val = 1;
|
int val = 1;
|
||||||
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
||||||
#endif
|
#endif
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
u_long nonblocking = 1;
|
u_long nonblocking = 1;
|
||||||
ioctlsocket( sock, FIONBIO, &nonblocking );
|
ioctlsocket( sock, FIONBIO, &nonblocking );
|
||||||
#else
|
#else
|
||||||
@ -188,7 +180,7 @@ bool Socket::Connect( const char* addr, uint16_t port )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
const auto err = WSAGetLastError();
|
const auto err = WSAGetLastError();
|
||||||
if( err != WSAEWOULDBLOCK )
|
if( err != WSAEWOULDBLOCK )
|
||||||
{
|
{
|
||||||
@ -211,7 +203,7 @@ bool Socket::Connect( const char* addr, uint16_t port )
|
|||||||
freeaddrinfo( res );
|
freeaddrinfo( res );
|
||||||
if( !ptr ) return false;
|
if( !ptr ) return false;
|
||||||
|
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
u_long nonblocking = 0;
|
u_long nonblocking = 0;
|
||||||
ioctlsocket( sock, FIONBIO, &nonblocking );
|
ioctlsocket( sock, FIONBIO, &nonblocking );
|
||||||
#else
|
#else
|
||||||
@ -223,48 +215,6 @@ bool Socket::Connect( const char* addr, uint16_t port )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Socket::ConnectBlocking( const char* addr, uint16_t port )
|
|
||||||
{
|
|
||||||
assert( !IsValid() );
|
|
||||||
assert( !m_ptr );
|
|
||||||
|
|
||||||
struct addrinfo hints;
|
|
||||||
struct addrinfo *res, *ptr;
|
|
||||||
|
|
||||||
memset( &hints, 0, sizeof( hints ) );
|
|
||||||
hints.ai_family = AF_UNSPEC;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
|
|
||||||
char portbuf[32];
|
|
||||||
sprintf( portbuf, "%" PRIu16, port );
|
|
||||||
|
|
||||||
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
|
|
||||||
int sock = 0;
|
|
||||||
for( ptr = res; ptr; ptr = ptr->ai_next )
|
|
||||||
{
|
|
||||||
if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;
|
|
||||||
#if defined __APPLE__
|
|
||||||
int val = 1;
|
|
||||||
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
|
||||||
#endif
|
|
||||||
if( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) == -1 )
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
closesocket( sock );
|
|
||||||
#else
|
|
||||||
close( sock );
|
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
freeaddrinfo( res );
|
|
||||||
if( !ptr ) return false;
|
|
||||||
|
|
||||||
m_sock.store( sock, std::memory_order_relaxed );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socket::Close()
|
void Socket::Close()
|
||||||
{
|
{
|
||||||
const auto sock = m_sock.load( std::memory_order_relaxed );
|
const auto sock = m_sock.load( std::memory_order_relaxed );
|
||||||
@ -297,7 +247,7 @@ int Socket::GetSendBufSize()
|
|||||||
{
|
{
|
||||||
const auto sock = m_sock.load( std::memory_order_relaxed );
|
const auto sock = m_sock.load( std::memory_order_relaxed );
|
||||||
int bufSize;
|
int bufSize;
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
int sz = sizeof( bufSize );
|
int sz = sizeof( bufSize );
|
||||||
getsockopt( sock, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, &sz );
|
getsockopt( sock, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, &sz );
|
||||||
#else
|
#else
|
||||||
@ -356,24 +306,6 @@ int Socket::Recv( void* _buf, int len, int timeout )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Socket::ReadUpTo( void* _buf, int len )
|
|
||||||
{
|
|
||||||
const auto sock = m_sock.load( std::memory_order_relaxed );
|
|
||||||
auto buf = (char*)_buf;
|
|
||||||
|
|
||||||
int rd = 0;
|
|
||||||
while( len > 0 )
|
|
||||||
{
|
|
||||||
const auto res = recv( sock, buf, len, 0 );
|
|
||||||
if( res == 0 ) break;
|
|
||||||
if( res == -1 ) return -1;
|
|
||||||
len -= res;
|
|
||||||
rd += res;
|
|
||||||
buf += res;
|
|
||||||
}
|
|
||||||
return rd;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Socket::Read( void* buf, int len, int timeout )
|
bool Socket::Read( void* buf, int len, int timeout )
|
||||||
{
|
{
|
||||||
auto cbuf = (char*)buf;
|
auto cbuf = (char*)buf;
|
||||||
@ -451,48 +383,36 @@ ListenSocket::~ListenSocket()
|
|||||||
if( m_sock != -1 ) Close();
|
if( m_sock != -1 ) Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int addrinfo_and_socket_for_family( uint16_t port, int ai_family, struct addrinfo** res )
|
bool ListenSocket::Listen( int port, int backlog )
|
||||||
{
|
|
||||||
struct addrinfo hints;
|
|
||||||
memset( &hints, 0, sizeof( hints ) );
|
|
||||||
hints.ai_family = ai_family;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
#ifndef TRACY_ONLY_LOCALHOST
|
|
||||||
const char* onlyLocalhost = GetEnvVar( "TRACY_ONLY_LOCALHOST" );
|
|
||||||
if( !onlyLocalhost || onlyLocalhost[0] != '1' )
|
|
||||||
{
|
|
||||||
hints.ai_flags = AI_PASSIVE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
char portbuf[32];
|
|
||||||
sprintf( portbuf, "%" PRIu16, port );
|
|
||||||
if( getaddrinfo( nullptr, portbuf, &hints, res ) != 0 ) return -1;
|
|
||||||
int sock = socket( (*res)->ai_family, (*res)->ai_socktype, (*res)->ai_protocol );
|
|
||||||
if (sock == -1) freeaddrinfo( *res );
|
|
||||||
return sock;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ListenSocket::Listen( uint16_t port, int backlog )
|
|
||||||
{
|
{
|
||||||
assert( m_sock == -1 );
|
assert( m_sock == -1 );
|
||||||
|
|
||||||
struct addrinfo* res = nullptr;
|
struct addrinfo* res;
|
||||||
|
struct addrinfo hints;
|
||||||
|
|
||||||
#if !defined TRACY_ONLY_IPV4 && !defined TRACY_ONLY_LOCALHOST
|
memset( &hints, 0, sizeof( hints ) );
|
||||||
const char* onlyIPv4 = GetEnvVar( "TRACY_ONLY_IPV4" );
|
hints.ai_family = AF_INET6;
|
||||||
if( !onlyIPv4 || onlyIPv4[0] != '1' )
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
{
|
#ifndef TRACY_ONLY_LOCALHOST
|
||||||
m_sock = addrinfo_and_socket_for_family( port, AF_INET6, &res );
|
hints.ai_flags = AI_PASSIVE;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char portbuf[32];
|
||||||
|
sprintf( portbuf, "%i", port );
|
||||||
|
|
||||||
|
if( getaddrinfo( nullptr, portbuf, &hints, &res ) != 0 ) return false;
|
||||||
|
|
||||||
|
m_sock = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
|
||||||
if (m_sock == -1)
|
if (m_sock == -1)
|
||||||
{
|
{
|
||||||
// IPV6 protocol may not be available/is disabled. Try to create a socket
|
// IPV6 protocol may not be available/is disabled. Try to create a socket
|
||||||
// with the IPV4 protocol
|
// with the IPV4 protocol
|
||||||
m_sock = addrinfo_and_socket_for_family( port, AF_INET, &res );
|
hints.ai_family = AF_INET;
|
||||||
|
if( getaddrinfo( nullptr, portbuf, &hints, &res ) != 0 ) return false;
|
||||||
|
m_sock = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
|
||||||
if( m_sock == -1 ) return false;
|
if( m_sock == -1 ) return false;
|
||||||
}
|
}
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
unsigned long val = 0;
|
unsigned long val = 0;
|
||||||
setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );
|
setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );
|
||||||
#elif defined BSD
|
#elif defined BSD
|
||||||
@ -563,7 +483,7 @@ UdpBroadcast::~UdpBroadcast()
|
|||||||
if( m_sock != -1 ) Close();
|
if( m_sock != -1 ) Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UdpBroadcast::Open( const char* addr, uint16_t port )
|
bool UdpBroadcast::Open( const char* addr, int port )
|
||||||
{
|
{
|
||||||
assert( m_sock == -1 );
|
assert( m_sock == -1 );
|
||||||
|
|
||||||
@ -575,7 +495,7 @@ bool UdpBroadcast::Open( const char* addr, uint16_t port )
|
|||||||
hints.ai_socktype = SOCK_DGRAM;
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
|
||||||
char portbuf[32];
|
char portbuf[32];
|
||||||
sprintf( portbuf, "%" PRIu16, port );
|
sprintf( portbuf, "%i", port );
|
||||||
|
|
||||||
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
|
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
|
||||||
int sock = 0;
|
int sock = 0;
|
||||||
@ -586,7 +506,7 @@ bool UdpBroadcast::Open( const char* addr, uint16_t port )
|
|||||||
int val = 1;
|
int val = 1;
|
||||||
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
||||||
#endif
|
#endif
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
unsigned long broadcast = 1;
|
unsigned long broadcast = 1;
|
||||||
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
|
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
|
||||||
#else
|
#else
|
||||||
@ -607,7 +527,6 @@ bool UdpBroadcast::Open( const char* addr, uint16_t port )
|
|||||||
if( !ptr ) return false;
|
if( !ptr ) return false;
|
||||||
|
|
||||||
m_sock = sock;
|
m_sock = sock;
|
||||||
inet_pton( AF_INET, addr, &m_addr );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -622,13 +541,13 @@ void UdpBroadcast::Close()
|
|||||||
m_sock = -1;
|
m_sock = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int UdpBroadcast::Send( uint16_t port, const void* data, int len )
|
int UdpBroadcast::Send( int port, const void* data, int len )
|
||||||
{
|
{
|
||||||
assert( m_sock != -1 );
|
assert( m_sock != -1 );
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons( port );
|
addr.sin_port = htons( port );
|
||||||
addr.sin_addr.s_addr = m_addr;
|
addr.sin_addr.s_addr = INADDR_BROADCAST;
|
||||||
return sendto( m_sock, (const char*)data, len, MSG_NOSIGNAL, (sockaddr*)&addr, sizeof( addr ) );
|
return sendto( m_sock, (const char*)data, len, MSG_NOSIGNAL, (sockaddr*)&addr, sizeof( addr ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,10 +563,8 @@ IpAddress::~IpAddress()
|
|||||||
|
|
||||||
void IpAddress::Set( const struct sockaddr& addr )
|
void IpAddress::Set( const struct sockaddr& addr )
|
||||||
{
|
{
|
||||||
#if defined _WIN32 && ( !defined NTDDI_WIN10 || NTDDI_VERSION < NTDDI_WIN10 )
|
#if __MINGW32__
|
||||||
struct sockaddr_in tmp;
|
auto ai = (struct sockaddr_in*)&addr;
|
||||||
memcpy( &tmp, &addr, sizeof( tmp ) );
|
|
||||||
auto ai = &tmp;
|
|
||||||
#else
|
#else
|
||||||
auto ai = (const struct sockaddr_in*)&addr;
|
auto ai = (const struct sockaddr_in*)&addr;
|
||||||
#endif
|
#endif
|
||||||
@ -668,7 +585,7 @@ UdpListen::~UdpListen()
|
|||||||
if( m_sock != -1 ) Close();
|
if( m_sock != -1 ) Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UdpListen::Listen( uint16_t port )
|
bool UdpListen::Listen( int port )
|
||||||
{
|
{
|
||||||
assert( m_sock == -1 );
|
assert( m_sock == -1 );
|
||||||
|
|
||||||
@ -679,14 +596,14 @@ bool UdpListen::Listen( uint16_t port )
|
|||||||
int val = 1;
|
int val = 1;
|
||||||
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
||||||
#endif
|
#endif
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
unsigned long reuse = 1;
|
unsigned long reuse = 1;
|
||||||
setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof( reuse ) );
|
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof( reuse ) );
|
||||||
#else
|
#else
|
||||||
int reuse = 1;
|
int reuse = 1;
|
||||||
setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
|
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
|
||||||
#endif
|
#endif
|
||||||
#if defined _WIN32
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
unsigned long broadcast = 1;
|
unsigned long broadcast = 1;
|
||||||
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
|
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
|
||||||
#else
|
#else
|
||||||
@ -732,14 +649,14 @@ void UdpListen::Close()
|
|||||||
m_sock = -1;
|
m_sock = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* UdpListen::Read( size_t& len, IpAddress& addr, int timeout )
|
const char* UdpListen::Read( size_t& len, IpAddress& addr )
|
||||||
{
|
{
|
||||||
static char buf[2048];
|
static char buf[2048];
|
||||||
|
|
||||||
struct pollfd fd;
|
struct pollfd fd;
|
||||||
fd.fd = (socket_t)m_sock;
|
fd.fd = (socket_t)m_sock;
|
||||||
fd.events = POLLIN;
|
fd.events = POLLIN;
|
||||||
if( poll( &fd, 1, timeout ) <= 0 ) return nullptr;
|
if( poll( &fd, 1, 10 ) <= 0 ) return nullptr;
|
||||||
|
|
||||||
sockaddr sa;
|
sockaddr sa;
|
||||||
socklen_t salen = sizeof( struct sockaddr );
|
socklen_t salen = sizeof( struct sockaddr );
|
@ -2,9 +2,10 @@
|
|||||||
#define __TRACYSOCKET_HPP__
|
#define __TRACYSOCKET_HPP__
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "TracyForceInline.hpp"
|
||||||
|
|
||||||
struct addrinfo;
|
struct addrinfo;
|
||||||
struct sockaddr;
|
struct sockaddr;
|
||||||
|
|
||||||
@ -22,14 +23,12 @@ public:
|
|||||||
Socket( int sock );
|
Socket( int sock );
|
||||||
~Socket();
|
~Socket();
|
||||||
|
|
||||||
bool Connect( const char* addr, uint16_t port );
|
bool Connect( const char* addr, int port );
|
||||||
bool ConnectBlocking( const char* addr, uint16_t port );
|
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
int Send( const void* buf, int len );
|
int Send( const void* buf, int len );
|
||||||
int GetSendBufSize();
|
int GetSendBufSize();
|
||||||
|
|
||||||
int ReadUpTo( void* buf, int len );
|
|
||||||
bool Read( void* buf, int len, int timeout );
|
bool Read( void* buf, int len, int timeout );
|
||||||
|
|
||||||
template<typename ShouldExit>
|
template<typename ShouldExit>
|
||||||
@ -75,7 +74,7 @@ public:
|
|||||||
ListenSocket();
|
ListenSocket();
|
||||||
~ListenSocket();
|
~ListenSocket();
|
||||||
|
|
||||||
bool Listen( uint16_t port, int backlog );
|
bool Listen( int port, int backlog );
|
||||||
Socket* Accept();
|
Socket* Accept();
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
@ -94,10 +93,10 @@ public:
|
|||||||
UdpBroadcast();
|
UdpBroadcast();
|
||||||
~UdpBroadcast();
|
~UdpBroadcast();
|
||||||
|
|
||||||
bool Open( const char* addr, uint16_t port );
|
bool Open( const char* addr, int port );
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
int Send( uint16_t port, const void* data, int len );
|
int Send( int port, const void* data, int len );
|
||||||
|
|
||||||
UdpBroadcast( const UdpBroadcast& ) = delete;
|
UdpBroadcast( const UdpBroadcast& ) = delete;
|
||||||
UdpBroadcast( UdpBroadcast&& ) = delete;
|
UdpBroadcast( UdpBroadcast&& ) = delete;
|
||||||
@ -106,7 +105,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int m_sock;
|
int m_sock;
|
||||||
uint32_t m_addr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IpAddress
|
class IpAddress
|
||||||
@ -136,10 +134,10 @@ public:
|
|||||||
UdpListen();
|
UdpListen();
|
||||||
~UdpListen();
|
~UdpListen();
|
||||||
|
|
||||||
bool Listen( uint16_t port );
|
bool Listen( int port );
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
const char* Read( size_t& len, IpAddress& addr, int timeout );
|
const char* Read( size_t& len, IpAddress& addr );
|
||||||
|
|
||||||
UdpListen( const UdpListen& ) = delete;
|
UdpListen( const UdpListen& ) = delete;
|
||||||
UdpListen( UdpListen&& ) = delete;
|
UdpListen( UdpListen&& ) = delete;
|
239
common/TracySystem.cpp
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
#if defined _MSC_VER || defined __CYGWIN__ || defined _WIN32
|
||||||
|
# ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
# endif
|
||||||
|
# ifndef NOMINMAX
|
||||||
|
# define NOMINMAX
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(disable:4996)
|
||||||
|
#endif
|
||||||
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
|
# include <windows.h>
|
||||||
|
#else
|
||||||
|
# include <pthread.h>
|
||||||
|
# include <string.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
# ifdef __ANDROID__
|
||||||
|
# include <sys/types.h>
|
||||||
|
# else
|
||||||
|
# include <sys/syscall.h>
|
||||||
|
# endif
|
||||||
|
# include <fcntl.h>
|
||||||
|
#elif defined __FreeBSD__
|
||||||
|
# include <sys/thr.h>
|
||||||
|
#elif defined __NetBSD__ || defined __DragonFly__
|
||||||
|
# include <sys/lwp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
# define __STDC_FORMAT_MACROS
|
||||||
|
#endif
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "TracySystem.hpp"
|
||||||
|
|
||||||
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
|
extern "C" typedef HRESULT (WINAPI *t_SetThreadDescription)( HANDLE, PCWSTR );
|
||||||
|
extern "C" typedef HRESULT (WINAPI *t_GetThreadDescription)( HANDLE, PWSTR* );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
# include <atomic>
|
||||||
|
# include "TracyAlloc.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
TRACY_API uint64_t GetThreadHandleImpl()
|
||||||
|
{
|
||||||
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
|
static_assert( sizeof( decltype( GetCurrentThreadId() ) ) <= sizeof( uint64_t ), "Thread handle too big to fit in protocol" );
|
||||||
|
return uint64_t( GetCurrentThreadId() );
|
||||||
|
#elif defined __APPLE__
|
||||||
|
uint64_t id;
|
||||||
|
pthread_threadid_np( pthread_self(), &id );
|
||||||
|
return id;
|
||||||
|
#elif defined __ANDROID__
|
||||||
|
return (uint64_t)gettid();
|
||||||
|
#elif defined __linux__
|
||||||
|
return (uint64_t)syscall( SYS_gettid );
|
||||||
|
#elif defined __FreeBSD__
|
||||||
|
long id;
|
||||||
|
thr_self( &id );
|
||||||
|
return id;
|
||||||
|
#elif defined __NetBSD__
|
||||||
|
return _lwp_self();
|
||||||
|
#elif defined __DragonFly__
|
||||||
|
return lwp_gettid();
|
||||||
|
#elif defined __OpenBSD__
|
||||||
|
return getthrid();
|
||||||
|
#else
|
||||||
|
static_assert( sizeof( decltype( pthread_self() ) ) <= sizeof( uint64_t ), "Thread handle too big to fit in protocol" );
|
||||||
|
return uint64_t( pthread_self() );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
struct ThreadNameData
|
||||||
|
{
|
||||||
|
uint64_t id;
|
||||||
|
const char* name;
|
||||||
|
ThreadNameData* next;
|
||||||
|
};
|
||||||
|
std::atomic<ThreadNameData*>& GetThreadNameData();
|
||||||
|
TRACY_API void InitRPMallocThread();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TRACY_API void SetThreadName( const char* name )
|
||||||
|
{
|
||||||
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
|
static auto _SetThreadDescription = (t_SetThreadDescription)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "SetThreadDescription" );
|
||||||
|
if( _SetThreadDescription )
|
||||||
|
{
|
||||||
|
wchar_t buf[256];
|
||||||
|
mbstowcs( buf, name, 256 );
|
||||||
|
_SetThreadDescription( GetCurrentThread(), buf );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
# if defined _MSC_VER
|
||||||
|
const DWORD MS_VC_EXCEPTION=0x406D1388;
|
||||||
|
# pragma pack( push, 8 )
|
||||||
|
struct THREADNAME_INFO
|
||||||
|
{
|
||||||
|
DWORD dwType;
|
||||||
|
LPCSTR szName;
|
||||||
|
DWORD dwThreadID;
|
||||||
|
DWORD dwFlags;
|
||||||
|
};
|
||||||
|
# pragma pack(pop)
|
||||||
|
|
||||||
|
DWORD ThreadId = GetCurrentThreadId();
|
||||||
|
THREADNAME_INFO info;
|
||||||
|
info.dwType = 0x1000;
|
||||||
|
info.szName = name;
|
||||||
|
info.dwThreadID = ThreadId;
|
||||||
|
info.dwFlags = 0;
|
||||||
|
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
|
||||||
|
}
|
||||||
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#elif defined _GNU_SOURCE && !defined __EMSCRIPTEN__ && !defined __CYGWIN__
|
||||||
|
{
|
||||||
|
const auto sz = strlen( name );
|
||||||
|
if( sz <= 15 )
|
||||||
|
{
|
||||||
|
pthread_setname_np( pthread_self(), name );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
memcpy( buf, name, 15 );
|
||||||
|
buf[15] = '\0';
|
||||||
|
pthread_setname_np( pthread_self(), buf );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
{
|
||||||
|
InitRPMallocThread();
|
||||||
|
const auto sz = strlen( name );
|
||||||
|
char* buf = (char*)tracy_malloc( sz+1 );
|
||||||
|
memcpy( buf, name, sz );
|
||||||
|
buf[sz] = '\0';
|
||||||
|
auto data = (ThreadNameData*)tracy_malloc( sizeof( ThreadNameData ) );
|
||||||
|
data->id = detail::GetThreadHandleImpl();
|
||||||
|
data->name = buf;
|
||||||
|
data->next = GetThreadNameData().load( std::memory_order_relaxed );
|
||||||
|
while( !GetThreadNameData().compare_exchange_weak( data->next, data, std::memory_order_release, std::memory_order_relaxed ) ) {}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACY_API const char* GetThreadName( uint64_t id )
|
||||||
|
{
|
||||||
|
static char buf[256];
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
auto ptr = GetThreadNameData().load( std::memory_order_relaxed );
|
||||||
|
while( ptr )
|
||||||
|
{
|
||||||
|
if( ptr->id == id )
|
||||||
|
{
|
||||||
|
return ptr->name;
|
||||||
|
}
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# if defined _WIN32 || defined __CYGWIN__
|
||||||
|
static auto _GetThreadDescription = (t_GetThreadDescription)GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "GetThreadDescription" );
|
||||||
|
if( _GetThreadDescription )
|
||||||
|
{
|
||||||
|
auto hnd = OpenThread( THREAD_QUERY_LIMITED_INFORMATION, FALSE, (DWORD)id );
|
||||||
|
if( hnd != 0 )
|
||||||
|
{
|
||||||
|
PWSTR tmp;
|
||||||
|
_GetThreadDescription( hnd, &tmp );
|
||||||
|
auto ret = wcstombs( buf, tmp, 256 );
|
||||||
|
CloseHandle( hnd );
|
||||||
|
if( ret != 0 )
|
||||||
|
{
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# elif defined __linux__
|
||||||
|
int cs, fd;
|
||||||
|
char path[32];
|
||||||
|
# ifdef __ANDROID__
|
||||||
|
int tid = gettid();
|
||||||
|
# else
|
||||||
|
int tid = (int) syscall( SYS_gettid );
|
||||||
|
# endif
|
||||||
|
snprintf( path, sizeof( path ), "/proc/self/task/%d/comm", tid );
|
||||||
|
sprintf( buf, "%" PRIu64, id );
|
||||||
|
# ifndef __ANDROID__
|
||||||
|
pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &cs );
|
||||||
|
# endif
|
||||||
|
if ( ( fd = open( path, O_RDONLY ) ) > 0) {
|
||||||
|
int len = read( fd, buf, 255 );
|
||||||
|
if( len > 0 )
|
||||||
|
{
|
||||||
|
buf[len] = 0;
|
||||||
|
if( len > 1 && buf[len-1] == '\n' )
|
||||||
|
{
|
||||||
|
buf[len-1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close( fd );
|
||||||
|
}
|
||||||
|
# ifndef __ANDROID__
|
||||||
|
pthread_setcancelstate( cs, 0 );
|
||||||
|
# endif
|
||||||
|
return buf;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
sprintf( buf, "%" PRIu64, id );
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
common/TracySystem.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef __TRACYSYSTEM_HPP__
|
||||||
|
#define __TRACYSYSTEM_HPP__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "TracyApi.h"
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
TRACY_API uint64_t GetThreadHandleImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TRACY_ENABLE
|
||||||
|
TRACY_API uint64_t GetThreadHandle();
|
||||||
|
#else
|
||||||
|
static inline uint64_t GetThreadHandle()
|
||||||
|
{
|
||||||
|
return detail::GetThreadHandleImpl();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TRACY_API void SetThreadName( const char* name );
|
||||||
|
TRACY_API const char* GetThreadName( uint64_t id );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* LZ4 - Fast LZ compression algorithm
|
* LZ4 - Fast LZ compression algorithm
|
||||||
* Header File
|
* Header File
|
||||||
* Copyright (C) 2011-2020, Yann Collet.
|
* Copyright (C) 2011-present, Yann Collet.
|
||||||
|
|
||||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
|
||||||
@ -33,6 +33,7 @@
|
|||||||
- LZ4 source repository : https://github.com/lz4/lz4
|
- LZ4 source repository : https://github.com/lz4/lz4
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef TRACY_LZ4_H_2983827168210
|
#ifndef TRACY_LZ4_H_2983827168210
|
||||||
#define TRACY_LZ4_H_2983827168210
|
#define TRACY_LZ4_H_2983827168210
|
||||||
|
|
||||||
@ -40,11 +41,13 @@
|
|||||||
#include <stddef.h> /* size_t */
|
#include <stddef.h> /* size_t */
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Introduction
|
Introduction
|
||||||
|
|
||||||
LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,
|
LZ4 is lossless compression algorithm, providing compression speed at 500 MB/s per core,
|
||||||
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
|
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
|
||||||
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
|
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
|
||||||
|
|
||||||
@ -56,19 +59,16 @@
|
|||||||
- unbounded multiple steps (described as Streaming compression)
|
- unbounded multiple steps (described as Streaming compression)
|
||||||
|
|
||||||
lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).
|
lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).
|
||||||
Decompressing such a compressed block requires additional metadata.
|
Decompressing a block requires additional metadata, such as its compressed size.
|
||||||
Exact metadata depends on exact decompression function.
|
|
||||||
For the typical case of LZ4_decompress_safe(),
|
|
||||||
metadata includes block's compressed size, and maximum bound of decompressed size.
|
|
||||||
Each application is free to encode and pass such metadata in whichever way it wants.
|
Each application is free to encode and pass such metadata in whichever way it wants.
|
||||||
|
|
||||||
lz4.h only handle blocks, it can not generate Frames.
|
lz4.h only handle blocks, it can not generate Frames.
|
||||||
|
|
||||||
Blocks are different from Frames (doc/lz4_Frame_format.md).
|
Blocks are different from Frames (doc/lz4_Frame_format.md).
|
||||||
Frames bundle both blocks and metadata in a specified manner.
|
Frames bundle both blocks and metadata in a specified manner.
|
||||||
Embedding metadata is required for compressed data to be self-contained and portable.
|
This are required for compressed data to be self-contained and portable.
|
||||||
Frame format is delivered through a companion API, declared in lz4frame.h.
|
Frame format is delivered through a companion API, declared in lz4frame.h.
|
||||||
The `lz4` CLI can only manage frames.
|
Note that the `lz4` CLI can only manage frames.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*^***************************************************************
|
/*^***************************************************************
|
||||||
@ -95,114 +95,64 @@
|
|||||||
# define LZ4LIB_API LZ4LIB_VISIBILITY
|
# define LZ4LIB_API LZ4LIB_VISIBILITY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! LZ4_FREESTANDING :
|
|
||||||
* When this macro is set to 1, it enables "freestanding mode" that is
|
|
||||||
* suitable for typical freestanding environment which doesn't support
|
|
||||||
* standard C library.
|
|
||||||
*
|
|
||||||
* - LZ4_FREESTANDING is a compile-time switch.
|
|
||||||
* - It requires the following macros to be defined:
|
|
||||||
* LZ4_memcpy, LZ4_memmove, LZ4_memset.
|
|
||||||
* - It only enables LZ4/HC functions which don't use heap.
|
|
||||||
* All LZ4F_* functions are not supported.
|
|
||||||
* - See tests/freestanding.c to check its basic setup.
|
|
||||||
*/
|
|
||||||
#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1)
|
|
||||||
# define LZ4_HEAPMODE 0
|
|
||||||
# define LZ4HC_HEAPMODE 0
|
|
||||||
# define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1
|
|
||||||
# if !defined(LZ4_memcpy)
|
|
||||||
# error "LZ4_FREESTANDING requires macro 'LZ4_memcpy'."
|
|
||||||
# endif
|
|
||||||
# if !defined(LZ4_memset)
|
|
||||||
# error "LZ4_FREESTANDING requires macro 'LZ4_memset'."
|
|
||||||
# endif
|
|
||||||
# if !defined(LZ4_memmove)
|
|
||||||
# error "LZ4_FREESTANDING requires macro 'LZ4_memmove'."
|
|
||||||
# endif
|
|
||||||
#elif ! defined(LZ4_FREESTANDING)
|
|
||||||
# define LZ4_FREESTANDING 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*------ Version ------*/
|
/*------ Version ------*/
|
||||||
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
|
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
|
||||||
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
|
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
|
||||||
#define LZ4_VERSION_RELEASE 4 /* for tweaks, bug-fixes, or development */
|
#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
|
||||||
|
|
||||||
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
||||||
|
|
||||||
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
|
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
|
||||||
#define LZ4_QUOTE(str) #str
|
#define LZ4_QUOTE(str) #str
|
||||||
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
|
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
|
||||||
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) /* requires v1.7.3+ */
|
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION)
|
||||||
|
|
||||||
namespace tracy
|
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */
|
||||||
{
|
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version */
|
||||||
|
|
||||||
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version; requires v1.3.0+ */
|
|
||||||
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version; requires v1.7.5+ */
|
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Tuning parameter
|
* Tuning parameter
|
||||||
**************************************/
|
**************************************/
|
||||||
#define LZ4_MEMORY_USAGE_MIN 10
|
|
||||||
#define LZ4_MEMORY_USAGE_DEFAULT 14
|
|
||||||
#define LZ4_MEMORY_USAGE_MAX 20
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* LZ4_MEMORY_USAGE :
|
* LZ4_MEMORY_USAGE :
|
||||||
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; )
|
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
|
||||||
* Increasing memory usage improves compression ratio, at the cost of speed.
|
* Increasing memory usage improves compression ratio.
|
||||||
* Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality.
|
* Reduced memory usage may improve speed, thanks to better cache locality.
|
||||||
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
||||||
*/
|
*/
|
||||||
#ifndef LZ4_MEMORY_USAGE
|
#ifndef LZ4_MEMORY_USAGE
|
||||||
# define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT
|
# define LZ4_MEMORY_USAGE 14
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN)
|
|
||||||
# error "LZ4_MEMORY_USAGE is too small !"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX)
|
|
||||||
# error "LZ4_MEMORY_USAGE is too large !"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Simple Functions
|
* Simple Functions
|
||||||
**************************************/
|
**************************************/
|
||||||
/*! LZ4_compress_default() :
|
/*! LZ4_compress_default() :
|
||||||
* Compresses 'srcSize' bytes from buffer 'src'
|
Compresses 'srcSize' bytes from buffer 'src'
|
||||||
* into already allocated 'dst' buffer of size 'dstCapacity'.
|
into already allocated 'dst' buffer of size 'dstCapacity'.
|
||||||
* Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
|
Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
|
||||||
* It also runs faster, so it's a recommended setting.
|
It also runs faster, so it's a recommended setting.
|
||||||
* If the function cannot compress 'src' into a more limited 'dst' budget,
|
If the function cannot compress 'src' into a more limited 'dst' budget,
|
||||||
* compression stops *immediately*, and the function result is zero.
|
compression stops *immediately*, and the function result is zero.
|
||||||
* In which case, 'dst' content is undefined (invalid).
|
In which case, 'dst' content is undefined (invalid).
|
||||||
* srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
|
srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
|
||||||
* dstCapacity : size of buffer 'dst' (which must be already allocated)
|
dstCapacity : size of buffer 'dst' (which must be already allocated)
|
||||||
* @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
|
@return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
|
||||||
* or 0 if compression fails
|
or 0 if compression fails
|
||||||
* Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
|
Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
|
||||||
*/
|
*/
|
||||||
LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
|
LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
|
||||||
|
|
||||||
/*! LZ4_decompress_safe() :
|
/*! LZ4_decompress_safe() :
|
||||||
* compressedSize : is the exact complete size of the compressed block.
|
compressedSize : is the exact complete size of the compressed block.
|
||||||
* dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size.
|
dstCapacity : is the size of destination buffer, which must be already allocated.
|
||||||
* @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
|
@return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
|
||||||
* If destination buffer is not large enough, decoding will stop and output an error code (negative value).
|
If destination buffer is not large enough, decoding will stop and output an error code (negative value).
|
||||||
* If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||||
* Note 1 : This function is protected against malicious data packets :
|
Note : This function is protected against malicious data packets (never writes outside 'dst' buffer, nor read outside 'source' buffer).
|
||||||
* it will never writes outside 'dst' buffer, nor read outside 'source' buffer,
|
*/
|
||||||
* even if the compressed block is maliciously modified to order the decoder to do these actions.
|
|
||||||
* In such case, the decoder stops immediately, and considers the compressed block malformed.
|
|
||||||
* Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them.
|
|
||||||
* The implementation is free to send / store / derive this information in whichever way is most beneficial.
|
|
||||||
* If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead.
|
|
||||||
*/
|
|
||||||
LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
|
LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
|
||||||
|
|
||||||
|
|
||||||
@ -228,8 +178,7 @@ LZ4LIB_API int LZ4_compressBound(int inputSize);
|
|||||||
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
||||||
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
||||||
An acceleration value of "1" is the same as regular LZ4_compress_default()
|
An acceleration value of "1" is the same as regular LZ4_compress_default()
|
||||||
Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).
|
Values <= 0 will be replaced by ACCELERATION_DEFAULT (currently == 1, see lz4.c).
|
||||||
Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c).
|
|
||||||
*/
|
*/
|
||||||
LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||||
|
|
||||||
@ -255,18 +204,7 @@ LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* d
|
|||||||
* New value is necessarily <= input value.
|
* New value is necessarily <= input value.
|
||||||
* @return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
|
* @return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
|
||||||
* or 0 if compression fails.
|
* or 0 if compression fails.
|
||||||
*
|
*/
|
||||||
* Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+):
|
|
||||||
* the produced compressed content could, in specific circumstances,
|
|
||||||
* require to be decompressed into a destination buffer larger
|
|
||||||
* by at least 1 byte than the content to decompress.
|
|
||||||
* If an application uses `LZ4_compress_destSize()`,
|
|
||||||
* it's highly recommended to update liblz4 to v1.9.2 or better.
|
|
||||||
* If this can't be done or ensured,
|
|
||||||
* the receiving decompression function should provide
|
|
||||||
* a dstCapacity which is > decompressedSize, by at least 1 byte.
|
|
||||||
* See https://github.com/lz4/lz4/issues/859 for details
|
|
||||||
*/
|
|
||||||
LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
|
LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
|
||||||
|
|
||||||
|
|
||||||
@ -274,35 +212,25 @@ LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePt
|
|||||||
* Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
|
* Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
|
||||||
* into destination buffer 'dst' of size 'dstCapacity'.
|
* into destination buffer 'dst' of size 'dstCapacity'.
|
||||||
* Up to 'targetOutputSize' bytes will be decoded.
|
* Up to 'targetOutputSize' bytes will be decoded.
|
||||||
* The function stops decoding on reaching this objective.
|
* The function stops decoding on reaching this objective,
|
||||||
* This can be useful to boost performance
|
* which can boost performance when only the beginning of a block is required.
|
||||||
* whenever only the beginning of a block is required.
|
|
||||||
*
|
*
|
||||||
* @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize)
|
* @return : the number of bytes decoded in `dst` (necessarily <= dstCapacity)
|
||||||
* If source stream is detected malformed, function returns a negative result.
|
* If source stream is detected malformed, function returns a negative result.
|
||||||
*
|
*
|
||||||
* Note 1 : @return can be < targetOutputSize, if compressed block contains less data.
|
* Note : @return can be < targetOutputSize, if compressed block contains less data.
|
||||||
*
|
*
|
||||||
* Note 2 : targetOutputSize must be <= dstCapacity
|
* Note 2 : this function features 2 parameters, targetOutputSize and dstCapacity,
|
||||||
*
|
* and expects targetOutputSize <= dstCapacity.
|
||||||
* Note 3 : this function effectively stops decoding on reaching targetOutputSize,
|
* It effectively stops decoding on reaching targetOutputSize,
|
||||||
* so dstCapacity is kind of redundant.
|
* so dstCapacity is kind of redundant.
|
||||||
* This is because in older versions of this function,
|
* This is because in a previous version of this function,
|
||||||
* decoding operation would still write complete sequences.
|
* decoding operation would not "break" a sequence in the middle.
|
||||||
* Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize,
|
* As a consequence, there was no guarantee that decoding would stop at exactly targetOutputSize,
|
||||||
* it could write more bytes, though only up to dstCapacity.
|
* it could write more bytes, though only up to dstCapacity.
|
||||||
* Some "margin" used to be required for this operation to work properly.
|
* Some "margin" used to be required for this operation to work properly.
|
||||||
* Thankfully, this is no longer necessary.
|
* This is no longer necessary.
|
||||||
* The function nonetheless keeps the same signature, in an effort to preserve API compatibility.
|
* The function nonetheless keeps its signature, in an effort to not break API.
|
||||||
*
|
|
||||||
* Note 4 : If srcSize is the exact size of the block,
|
|
||||||
* then targetOutputSize can be any value,
|
|
||||||
* including larger than the block's decompressed size.
|
|
||||||
* The function will, at most, generate block's decompressed size.
|
|
||||||
*
|
|
||||||
* Note 5 : If srcSize is _larger_ than block's compressed size,
|
|
||||||
* then targetOutputSize **MUST** be <= block's decompressed size.
|
|
||||||
* Otherwise, *silent corruption will occur*.
|
|
||||||
*/
|
*/
|
||||||
LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
|
LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
|
||||||
|
|
||||||
@ -312,25 +240,8 @@ LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcS
|
|||||||
***********************************************/
|
***********************************************/
|
||||||
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
|
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
|
||||||
|
|
||||||
/**
|
|
||||||
Note about RC_INVOKED
|
|
||||||
|
|
||||||
- RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio).
|
|
||||||
https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros
|
|
||||||
|
|
||||||
- Since rc.exe is a legacy compiler, it truncates long symbol (> 30 chars)
|
|
||||||
and reports warning "RC4011: identifier truncated".
|
|
||||||
|
|
||||||
- To eliminate the warning, we surround long preprocessor symbol with
|
|
||||||
"#if !defined(RC_INVOKED) ... #endif" block that means
|
|
||||||
"skip this block when rc.exe is trying to read it".
|
|
||||||
*/
|
|
||||||
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
|
|
||||||
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
|
||||||
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
|
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
|
||||||
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
|
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
|
||||||
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*! LZ4_resetStream_fast() : v1.9.0+
|
/*! LZ4_resetStream_fast() : v1.9.0+
|
||||||
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
|
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
|
||||||
@ -414,12 +325,8 @@ typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
|
|||||||
* creation / destruction of streaming decompression tracking context.
|
* creation / destruction of streaming decompression tracking context.
|
||||||
* A tracking context can be re-used multiple times.
|
* A tracking context can be re-used multiple times.
|
||||||
*/
|
*/
|
||||||
#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */
|
|
||||||
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
|
||||||
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
|
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
|
||||||
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
|
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
|
||||||
#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*! LZ4_setStreamDecode() :
|
/*! LZ4_setStreamDecode() :
|
||||||
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
|
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
|
||||||
@ -469,10 +376,7 @@ LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
|
|||||||
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
|
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
|
||||||
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
|
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
|
||||||
*/
|
*/
|
||||||
LZ4LIB_API int
|
LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity);
|
||||||
LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode,
|
|
||||||
const char* src, char* dst,
|
|
||||||
int srcSize, int dstCapacity);
|
|
||||||
|
|
||||||
|
|
||||||
/*! LZ4_decompress_*_usingDict() :
|
/*! LZ4_decompress_*_usingDict() :
|
||||||
@ -483,20 +387,7 @@ LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode,
|
|||||||
* Performance tip : Decompression speed can be substantially increased
|
* Performance tip : Decompression speed can be substantially increased
|
||||||
* when dst == dictStart + dictSize.
|
* when dst == dictStart + dictSize.
|
||||||
*/
|
*/
|
||||||
LZ4LIB_API int
|
LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
|
||||||
LZ4_decompress_safe_usingDict(const char* src, char* dst,
|
|
||||||
int srcSize, int dstCapacity,
|
|
||||||
const char* dictStart, int dictSize);
|
|
||||||
|
|
||||||
LZ4LIB_API int
|
|
||||||
LZ4_decompress_safe_partial_usingDict(const char* src, char* dst,
|
|
||||||
int compressedSize,
|
|
||||||
int targetOutputSize, int maxOutputSize,
|
|
||||||
const char* dictStart, int dictSize);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LZ4_H_2983827168210 */
|
|
||||||
|
|
||||||
|
|
||||||
/*^*************************************
|
/*^*************************************
|
||||||
@ -523,19 +414,14 @@ LZ4_decompress_safe_partial_usingDict(const char* src, char* dst,
|
|||||||
* define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
|
* define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#ifdef LZ4_STATIC_LINKING_ONLY
|
|
||||||
|
|
||||||
#ifndef TRACY_LZ4_STATIC_3504398509
|
|
||||||
#define TRACY_LZ4_STATIC_3504398509
|
|
||||||
|
|
||||||
#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS
|
#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS
|
||||||
#define LZ4LIB_STATIC_API LZ4LIB_API
|
#define LZ4LIB_STATIC_API LZ4LIB_API
|
||||||
#else
|
#else
|
||||||
#define LZ4LIB_STATIC_API
|
#define LZ4LIB_STATIC_API
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace tracy
|
#ifdef LZ4_STATIC_LINKING_ONLY
|
||||||
{
|
|
||||||
|
|
||||||
/*! LZ4_compress_fast_extState_fastReset() :
|
/*! LZ4_compress_fast_extState_fastReset() :
|
||||||
* A variant of LZ4_compress_fast_extState().
|
* A variant of LZ4_compress_fast_extState().
|
||||||
@ -575,131 +461,80 @@ LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const c
|
|||||||
* stream (and source buffer) must remain in-place / accessible / unchanged
|
* stream (and source buffer) must remain in-place / accessible / unchanged
|
||||||
* through the completion of the first compression call on the stream.
|
* through the completion of the first compression call on the stream.
|
||||||
*/
|
*/
|
||||||
LZ4LIB_STATIC_API void
|
LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream);
|
||||||
LZ4_attach_dictionary(LZ4_stream_t* workingStream,
|
|
||||||
const LZ4_stream_t* dictionaryStream);
|
|
||||||
|
|
||||||
|
|
||||||
/*! In-place compression and decompression
|
|
||||||
*
|
|
||||||
* It's possible to have input and output sharing the same buffer,
|
|
||||||
* for highly constrained memory environments.
|
|
||||||
* In both cases, it requires input to lay at the end of the buffer,
|
|
||||||
* and decompression to start at beginning of the buffer.
|
|
||||||
* Buffer size must feature some margin, hence be larger than final size.
|
|
||||||
*
|
|
||||||
* |<------------------------buffer--------------------------------->|
|
|
||||||
* |<-----------compressed data--------->|
|
|
||||||
* |<-----------decompressed size------------------>|
|
|
||||||
* |<----margin---->|
|
|
||||||
*
|
|
||||||
* This technique is more useful for decompression,
|
|
||||||
* since decompressed size is typically larger,
|
|
||||||
* and margin is short.
|
|
||||||
*
|
|
||||||
* In-place decompression will work inside any buffer
|
|
||||||
* which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize).
|
|
||||||
* This presumes that decompressedSize > compressedSize.
|
|
||||||
* Otherwise, it means compression actually expanded data,
|
|
||||||
* and it would be more efficient to store such data with a flag indicating it's not compressed.
|
|
||||||
* This can happen when data is not compressible (already compressed, or encrypted).
|
|
||||||
*
|
|
||||||
* For in-place compression, margin is larger, as it must be able to cope with both
|
|
||||||
* history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX,
|
|
||||||
* and data expansion, which can happen when input is not compressible.
|
|
||||||
* As a consequence, buffer size requirements are much higher,
|
|
||||||
* and memory savings offered by in-place compression are more limited.
|
|
||||||
*
|
|
||||||
* There are ways to limit this cost for compression :
|
|
||||||
* - Reduce history size, by modifying LZ4_DISTANCE_MAX.
|
|
||||||
* Note that it is a compile-time constant, so all compressions will apply this limit.
|
|
||||||
* Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX,
|
|
||||||
* so it's a reasonable trick when inputs are known to be small.
|
|
||||||
* - Require the compressor to deliver a "maximum compressed size".
|
|
||||||
* This is the `dstCapacity` parameter in `LZ4_compress*()`.
|
|
||||||
* When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail,
|
|
||||||
* in which case, the return code will be 0 (zero).
|
|
||||||
* The caller must be ready for these cases to happen,
|
|
||||||
* and typically design a backup scheme to send data uncompressed.
|
|
||||||
* The combination of both techniques can significantly reduce
|
|
||||||
* the amount of margin required for in-place compression.
|
|
||||||
*
|
|
||||||
* In-place compression can work in any buffer
|
|
||||||
* which size is >= (maxCompressedSize)
|
|
||||||
* with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success.
|
|
||||||
* LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX,
|
|
||||||
* so it's possible to reduce memory requirements by playing with them.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32)
|
|
||||||
#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */
|
|
||||||
|
|
||||||
#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */
|
|
||||||
# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */
|
|
||||||
#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* LZ4_STATIC_3504398509 */
|
|
||||||
#endif /* LZ4_STATIC_LINKING_ONLY */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef TRACY_LZ4_H_98237428734687
|
|
||||||
#define TRACY_LZ4_H_98237428734687
|
|
||||||
|
|
||||||
namespace tracy
|
|
||||||
{
|
|
||||||
|
|
||||||
/*-************************************************************
|
/*-************************************************************
|
||||||
* Private Definitions
|
* PRIVATE DEFINITIONS
|
||||||
**************************************************************
|
**************************************************************
|
||||||
* Do not use these definitions directly.
|
* Do not use these definitions directly.
|
||||||
* They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
|
* They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
|
||||||
* Accessing members will expose user code to API and/or ABI break in future versions of the library.
|
* Accessing members will expose code to API and/or ABI break in future versions of the library.
|
||||||
**************************************************************/
|
**************************************************************/
|
||||||
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
|
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
|
||||||
#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
|
#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
|
||||||
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
|
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
|
||||||
|
|
||||||
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||||
typedef int8_t LZ4_i8;
|
#include <stdint.h>
|
||||||
typedef uint8_t LZ4_byte;
|
|
||||||
typedef uint16_t LZ4_u16;
|
|
||||||
typedef uint32_t LZ4_u32;
|
|
||||||
#else
|
|
||||||
typedef signed char LZ4_i8;
|
|
||||||
typedef unsigned char LZ4_byte;
|
|
||||||
typedef unsigned short LZ4_u16;
|
|
||||||
typedef unsigned int LZ4_u32;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*! LZ4_stream_t :
|
|
||||||
* Never ever use below internal definitions directly !
|
|
||||||
* These definitions are not API/ABI safe, and may change in future versions.
|
|
||||||
* If you need static allocation, declare or allocate an LZ4_stream_t object.
|
|
||||||
**/
|
|
||||||
|
|
||||||
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
|
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
|
||||||
struct LZ4_stream_t_internal {
|
struct LZ4_stream_t_internal {
|
||||||
LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
|
uint32_t hashTable[LZ4_HASH_SIZE_U32];
|
||||||
const LZ4_byte* dictionary;
|
uint32_t currentOffset;
|
||||||
|
uint16_t dirty;
|
||||||
|
uint16_t tableType;
|
||||||
|
const uint8_t* dictionary;
|
||||||
const LZ4_stream_t_internal* dictCtx;
|
const LZ4_stream_t_internal* dictCtx;
|
||||||
LZ4_u32 currentOffset;
|
uint32_t dictSize;
|
||||||
LZ4_u32 tableType;
|
|
||||||
LZ4_u32 dictSize;
|
|
||||||
/* Implicit padding to ensure structure is aligned */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LZ4_STREAM_MINSIZE ((1UL << LZ4_MEMORY_USAGE) + 32) /* static size, for inter-version compatibility */
|
typedef struct {
|
||||||
union LZ4_stream_u {
|
const uint8_t* externalDict;
|
||||||
char minStateSize[LZ4_STREAM_MINSIZE];
|
size_t extDictSize;
|
||||||
LZ4_stream_t_internal internal_donotuse;
|
const uint8_t* prefixEnd;
|
||||||
}; /* previously typedef'd to LZ4_stream_t */
|
size_t prefixSize;
|
||||||
|
} LZ4_streamDecode_t_internal;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
|
||||||
|
struct LZ4_stream_t_internal {
|
||||||
|
unsigned int hashTable[LZ4_HASH_SIZE_U32];
|
||||||
|
unsigned int currentOffset;
|
||||||
|
unsigned short dirty;
|
||||||
|
unsigned short tableType;
|
||||||
|
const unsigned char* dictionary;
|
||||||
|
const LZ4_stream_t_internal* dictCtx;
|
||||||
|
unsigned int dictSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const unsigned char* externalDict;
|
||||||
|
const unsigned char* prefixEnd;
|
||||||
|
size_t extDictSize;
|
||||||
|
size_t prefixSize;
|
||||||
|
} LZ4_streamDecode_t_internal;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! LZ4_stream_t :
|
||||||
|
* information structure to track an LZ4 stream.
|
||||||
|
* LZ4_stream_t can also be created using LZ4_createStream(), which is recommended.
|
||||||
|
* The structure definition can be convenient for static allocation
|
||||||
|
* (on stack, or as part of larger structure).
|
||||||
|
* Init this structure with LZ4_initStream() before first use.
|
||||||
|
* note : only use this definition in association with static linking !
|
||||||
|
* this definition is not API/ABI safe, and may change in a future version.
|
||||||
|
*/
|
||||||
|
#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4 + ((sizeof(void*)==16) ? 4 : 0) /*AS-400*/ )
|
||||||
|
#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long))
|
||||||
|
union LZ4_stream_u {
|
||||||
|
unsigned long long table[LZ4_STREAMSIZE_U64];
|
||||||
|
LZ4_stream_t_internal internal_donotuse;
|
||||||
|
} ; /* previously typedef'd to LZ4_stream_t */
|
||||||
|
|
||||||
/*! LZ4_initStream() : v1.9.0+
|
/*! LZ4_initStream() : v1.9.0+
|
||||||
* An LZ4_stream_t structure must be initialized at least once.
|
* An LZ4_stream_t structure must be initialized at least once.
|
||||||
@ -714,30 +549,25 @@ union LZ4_stream_u {
|
|||||||
* In which case, the function will @return NULL.
|
* In which case, the function will @return NULL.
|
||||||
* Note2: An LZ4_stream_t structure guarantees correct alignment and size.
|
* Note2: An LZ4_stream_t structure guarantees correct alignment and size.
|
||||||
* Note3: Before v1.9.0, use LZ4_resetStream() instead
|
* Note3: Before v1.9.0, use LZ4_resetStream() instead
|
||||||
**/
|
*/
|
||||||
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
|
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
|
||||||
|
|
||||||
|
|
||||||
/*! LZ4_streamDecode_t :
|
/*! LZ4_streamDecode_t :
|
||||||
* Never ever use below internal definitions directly !
|
* information structure to track an LZ4 stream during decompression.
|
||||||
* These definitions are not API/ABI safe, and may change in future versions.
|
* init this structure using LZ4_setStreamDecode() before first use.
|
||||||
* If you need static allocation, declare or allocate an LZ4_streamDecode_t object.
|
* note : only use in association with static linking !
|
||||||
**/
|
* this definition is not API/ABI safe,
|
||||||
typedef struct {
|
* and may change in a future version !
|
||||||
const LZ4_byte* externalDict;
|
*/
|
||||||
const LZ4_byte* prefixEnd;
|
#define LZ4_STREAMDECODESIZE_U64 (4 + ((sizeof(void*)==16) ? 2 : 0) /*AS-400*/ )
|
||||||
size_t extDictSize;
|
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
|
||||||
size_t prefixSize;
|
|
||||||
} LZ4_streamDecode_t_internal;
|
|
||||||
|
|
||||||
#define LZ4_STREAMDECODE_MINSIZE 32
|
|
||||||
union LZ4_streamDecode_u {
|
union LZ4_streamDecode_u {
|
||||||
char minStateSize[LZ4_STREAMDECODE_MINSIZE];
|
unsigned long long table[LZ4_STREAMDECODESIZE_U64];
|
||||||
LZ4_streamDecode_t_internal internal_donotuse;
|
LZ4_streamDecode_t_internal internal_donotuse;
|
||||||
} ; /* previously typedef'd to LZ4_streamDecode_t */
|
} ; /* previously typedef'd to LZ4_streamDecode_t */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Obsolete Functions
|
* Obsolete Functions
|
||||||
**************************************/
|
**************************************/
|
||||||
@ -756,34 +586,34 @@ union LZ4_streamDecode_u {
|
|||||||
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
|
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
|
||||||
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
|
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
|
||||||
#else
|
#else
|
||||||
|
# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||||
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
||||||
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
|
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
|
||||||
|
# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__)
|
||||||
|
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||||
|
# elif (LZ4_GCC_VERSION >= 301)
|
||||||
|
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
|
||||||
# elif defined(_MSC_VER)
|
# elif defined(_MSC_VER)
|
||||||
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
|
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
|
||||||
# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))
|
|
||||||
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
|
|
||||||
# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)
|
|
||||||
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
|
|
||||||
# else
|
# else
|
||||||
# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")
|
# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
|
||||||
# define LZ4_DEPRECATED(message) /* disabled */
|
# define LZ4_DEPRECATED(message)
|
||||||
# endif
|
# endif
|
||||||
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
|
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
|
||||||
|
|
||||||
/*! Obsolete compression functions (since v1.7.3) */
|
/* Obsolete compression functions */
|
||||||
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize);
|
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* source, char* dest, int sourceSize);
|
||||||
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);
|
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
|
||||||
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
|
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
|
||||||
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||||
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
|
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
|
||||||
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||||
|
|
||||||
/*! Obsolete decompression functions (since v1.8.0) */
|
/* Obsolete decompression functions */
|
||||||
LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
|
LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
|
||||||
LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
|
LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
|
||||||
|
|
||||||
/* Obsolete streaming functions (since v1.7.0)
|
/* Obsolete streaming functions; degraded functionality; do not use!
|
||||||
* degraded functionality; do not use!
|
|
||||||
*
|
*
|
||||||
* In order to perform streaming compression, these functions depended on data
|
* In order to perform streaming compression, these functions depended on data
|
||||||
* that is no longer tracked in the state. They have been preserved as well as
|
* that is no longer tracked in the state. They have been preserved as well as
|
||||||
@ -797,22 +627,23 @@ LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStre
|
|||||||
LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
|
LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
|
||||||
LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
|
LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
|
||||||
|
|
||||||
/*! Obsolete streaming decoding functions (since v1.7.0) */
|
/* Obsolete streaming decoding functions */
|
||||||
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
|
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
|
||||||
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
|
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
|
||||||
|
|
||||||
/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) :
|
/*! LZ4_decompress_fast() : **unsafe!**
|
||||||
* These functions used to be faster than LZ4_decompress_safe(),
|
* These functions used to be faster than LZ4_decompress_safe(),
|
||||||
* but this is no longer the case. They are now slower.
|
* but it has changed, and they are now slower than LZ4_decompress_safe().
|
||||||
* This is because LZ4_decompress_fast() doesn't know the input size,
|
* This is because LZ4_decompress_fast() doesn't know the input size,
|
||||||
* and therefore must progress more cautiously into the input buffer to not read beyond the end of block.
|
* and therefore must progress more cautiously in the input buffer to not read beyond the end of block.
|
||||||
* On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.
|
* On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.
|
||||||
* As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.
|
* As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.
|
||||||
*
|
*
|
||||||
* The last remaining LZ4_decompress_fast() specificity is that
|
* The last remaining LZ4_decompress_fast() specificity is that
|
||||||
* it can decompress a block without knowing its compressed size.
|
* it can decompress a block without knowing its compressed size.
|
||||||
* Such functionality can be achieved in a more secure manner
|
* Such functionality could be achieved in a more secure manner,
|
||||||
* by employing LZ4_decompress_safe_partial().
|
* by also providing the maximum size of input buffer,
|
||||||
|
* but it would require new prototypes, and adaptation of the implementation to this new use case.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* originalSize : is the uncompressed size to regenerate.
|
* originalSize : is the uncompressed size to regenerate.
|
||||||
@ -827,6 +658,7 @@ LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4
|
|||||||
* But they may happen if input data is invalid (error or intentional tampering).
|
* But they may happen if input data is invalid (error or intentional tampering).
|
||||||
* As a consequence, use these functions in trusted environments with trusted data **only**.
|
* As a consequence, use these functions in trusted environments with trusted data **only**.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead")
|
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead")
|
||||||
LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
|
LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
|
||||||
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")
|
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")
|
||||||
@ -844,4 +676,4 @@ LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LZ4_H_98237428734687 */
|
#endif /* LZ4_H_2983827168210 */
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
LZ4 HC - High Compression Mode of LZ4
|
LZ4 HC - High Compression Mode of LZ4
|
||||||
Header File
|
Header File
|
||||||
Copyright (C) 2011-2020, Yann Collet.
|
Copyright (C) 2011-2017, Yann Collet.
|
||||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -38,6 +38,8 @@
|
|||||||
/* note : lz4hc requires lz4.h/lz4.c for compilation */
|
/* note : lz4hc requires lz4.h/lz4.c for compilation */
|
||||||
#include "tracy_lz4.hpp" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
|
#include "tracy_lz4.hpp" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
/* --- Useful constants --- */
|
/* --- Useful constants --- */
|
||||||
#define LZ4HC_CLEVEL_MIN 3
|
#define LZ4HC_CLEVEL_MIN 3
|
||||||
@ -45,8 +47,6 @@
|
|||||||
#define LZ4HC_CLEVEL_OPT_MIN 10
|
#define LZ4HC_CLEVEL_OPT_MIN 10
|
||||||
#define LZ4HC_CLEVEL_MAX 12
|
#define LZ4HC_CLEVEL_MAX 12
|
||||||
|
|
||||||
namespace tracy
|
|
||||||
{
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
* Block Compression
|
* Block Compression
|
||||||
@ -196,36 +196,63 @@ LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, in
|
|||||||
#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1)
|
#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1)
|
||||||
|
|
||||||
|
|
||||||
/* Never ever use these definitions directly !
|
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||||
* Declare or allocate an LZ4_streamHC_t instead.
|
#include <stdint.h>
|
||||||
**/
|
|
||||||
typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;
|
typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;
|
||||||
struct LZ4HC_CCtx_internal
|
struct LZ4HC_CCtx_internal
|
||||||
{
|
{
|
||||||
LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE];
|
uint32_t hashTable[LZ4HC_HASHTABLESIZE];
|
||||||
LZ4_u16 chainTable[LZ4HC_MAXD];
|
uint16_t chainTable[LZ4HC_MAXD];
|
||||||
const LZ4_byte* end; /* next block here to continue on current prefix */
|
const uint8_t* end; /* next block here to continue on current prefix */
|
||||||
const LZ4_byte* prefixStart; /* Indexes relative to this position */
|
const uint8_t* base; /* All index relative to this position */
|
||||||
const LZ4_byte* dictStart; /* alternate reference for extDict */
|
const uint8_t* dictBase; /* alternate base for extDict */
|
||||||
LZ4_u32 dictLimit; /* below that point, need extDict */
|
uint32_t dictLimit; /* below that point, need extDict */
|
||||||
LZ4_u32 lowLimit; /* below that point, no more dict */
|
uint32_t lowLimit; /* below that point, no more dict */
|
||||||
LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */
|
uint32_t nextToUpdate; /* index from which to continue dictionary update */
|
||||||
short compressionLevel;
|
short compressionLevel;
|
||||||
LZ4_i8 favorDecSpeed; /* favor decompression speed if this flag set,
|
int8_t favorDecSpeed; /* favor decompression speed if this flag set,
|
||||||
otherwise, favor compression ratio */
|
otherwise, favor compression ratio */
|
||||||
LZ4_i8 dirty; /* stream has to be fully reset if this flag is set */
|
int8_t dirty; /* stream has to be fully reset if this flag is set */
|
||||||
const LZ4HC_CCtx_internal* dictCtx;
|
const LZ4HC_CCtx_internal* dictCtx;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LZ4_STREAMHC_MINSIZE 262200 /* static size, for inter-version compatibility */
|
#else
|
||||||
|
|
||||||
|
typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;
|
||||||
|
struct LZ4HC_CCtx_internal
|
||||||
|
{
|
||||||
|
unsigned int hashTable[LZ4HC_HASHTABLESIZE];
|
||||||
|
unsigned short chainTable[LZ4HC_MAXD];
|
||||||
|
const unsigned char* end; /* next block here to continue on current prefix */
|
||||||
|
const unsigned char* base; /* All index relative to this position */
|
||||||
|
const unsigned char* dictBase; /* alternate base for extDict */
|
||||||
|
unsigned int dictLimit; /* below that point, need extDict */
|
||||||
|
unsigned int lowLimit; /* below that point, no more dict */
|
||||||
|
unsigned int nextToUpdate; /* index from which to continue dictionary update */
|
||||||
|
short compressionLevel;
|
||||||
|
char favorDecSpeed; /* favor decompression speed if this flag set,
|
||||||
|
otherwise, favor compression ratio */
|
||||||
|
char dirty; /* stream has to be fully reset if this flag is set */
|
||||||
|
const LZ4HC_CCtx_internal* dictCtx;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Do not use these definitions directly !
|
||||||
|
* Declare or allocate an LZ4_streamHC_t instead.
|
||||||
|
*/
|
||||||
|
#define LZ4_STREAMHCSIZE (4*LZ4HC_HASHTABLESIZE + 2*LZ4HC_MAXD + 56 + ((sizeof(void*)==16) ? 56 : 0) /* AS400*/ ) /* 262200 or 262256*/
|
||||||
|
#define LZ4_STREAMHCSIZE_SIZET (LZ4_STREAMHCSIZE / sizeof(size_t))
|
||||||
union LZ4_streamHC_u {
|
union LZ4_streamHC_u {
|
||||||
char minStateSize[LZ4_STREAMHC_MINSIZE];
|
size_t table[LZ4_STREAMHCSIZE_SIZET];
|
||||||
LZ4HC_CCtx_internal internal_donotuse;
|
LZ4HC_CCtx_internal internal_donotuse;
|
||||||
}; /* previously typedef'd to LZ4_streamHC_t */
|
}; /* previously typedef'd to LZ4_streamHC_t */
|
||||||
|
|
||||||
/* LZ4_streamHC_t :
|
/* LZ4_streamHC_t :
|
||||||
* This structure allows static allocation of LZ4 HC streaming state.
|
* This structure allows static allocation of LZ4 HC streaming state.
|
||||||
* This can be used to allocate statically on stack, or as part of a larger structure.
|
* This can be used to allocate statically, on state, or as part of a larger structure.
|
||||||
*
|
*
|
||||||
* Such state **must** be initialized using LZ4_initStreamHC() before first use.
|
* Such state **must** be initialized using LZ4_initStreamHC() before first use.
|
||||||
*
|
*
|
||||||
@ -240,7 +267,7 @@ union LZ4_streamHC_u {
|
|||||||
* Required before first use of a statically allocated LZ4_streamHC_t.
|
* Required before first use of a statically allocated LZ4_streamHC_t.
|
||||||
* Before v1.9.0 : use LZ4_resetStreamHC() instead
|
* Before v1.9.0 : use LZ4_resetStreamHC() instead
|
||||||
*/
|
*/
|
||||||
LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC(void* buffer, size_t size);
|
LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size);
|
||||||
|
|
||||||
|
|
||||||
/*-************************************
|
/*-************************************
|
||||||
@ -268,11 +295,9 @@ LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_comp
|
|||||||
* LZ4_slideInputBufferHC() will truncate the history of the stream, rather
|
* LZ4_slideInputBufferHC() will truncate the history of the stream, rather
|
||||||
* than preserve a window-sized chunk of history.
|
* than preserve a window-sized chunk of history.
|
||||||
*/
|
*/
|
||||||
#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
|
|
||||||
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer);
|
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer);
|
||||||
LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data);
|
|
||||||
#endif
|
|
||||||
LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
|
LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
|
||||||
|
LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data);
|
||||||
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
|
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
|
||||||
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||||
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void);
|
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void);
|
||||||
@ -289,6 +314,7 @@ LZ4_DEPRECATED("use LZ4_initStreamHC() instead") LZ4LIB_API int LZ4_resetStre
|
|||||||
*/
|
*/
|
||||||
LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);
|
LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LZ4_HC_H_19834876238432 */
|
#endif /* LZ4_HC_H_19834876238432 */
|
||||||
@ -300,14 +326,11 @@ LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionL
|
|||||||
* They should not be linked from DLL,
|
* They should not be linked from DLL,
|
||||||
* as there is no guarantee of API stability yet.
|
* as there is no guarantee of API stability yet.
|
||||||
* Prototypes will be promoted to "stable" status
|
* Prototypes will be promoted to "stable" status
|
||||||
* after successful usage in real-life scenarios.
|
* after successfull usage in real-life scenarios.
|
||||||
***************************************************/
|
***************************************************/
|
||||||
#ifdef LZ4_HC_STATIC_LINKING_ONLY /* protection macro */
|
#ifdef LZ4_HC_STATIC_LINKING_ONLY /* protection macro */
|
||||||
#ifndef TRACY_LZ4_HC_SLO_098092834
|
#ifndef LZ4_HC_SLO_098092834
|
||||||
#define TRACY_LZ4_HC_SLO_098092834
|
#define LZ4_HC_SLO_098092834
|
||||||
|
|
||||||
#define LZ4_STATIC_LINKING_ONLY /* LZ4LIB_STATIC_API */
|
|
||||||
#include "tracy_lz4.hpp"
|
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
@ -1,29 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
|
||||||
|
|
||||||
option(NO_ISA_EXTENSIONS "Disable ISA extensions (don't pass -march=native or -mcpu=native to the compiler)" OFF)
|
|
||||||
|
|
||||||
set(NO_STATISTICS OFF)
|
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/version.cmake)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
|
||||||
|
|
||||||
project(
|
|
||||||
tracy-csvexport
|
|
||||||
LANGUAGES C CXX
|
|
||||||
VERSION ${TRACY_VERSION_STRING}
|
|
||||||
)
|
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/config.cmake)
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake)
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake)
|
|
||||||
|
|
||||||
set(PROGRAM_FILES
|
|
||||||
src/csvexport.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${PROGRAM_FILES} ${COMMON_FILES} ${SERVER_FILES})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE TracyServer TracyGetOpt)
|
|
||||||
set_property(DIRECTORY ${CMAKE_CURRENT_LIST_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME})
|
|
||||||
|
|
||||||
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
@ -1,454 +0,0 @@
|
|||||||
#ifdef _WIN32
|
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cctype>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "../../server/TracyFileRead.hpp"
|
|
||||||
#include "../../server/TracyWorker.hpp"
|
|
||||||
#include "../../getopt/getopt.h"
|
|
||||||
|
|
||||||
void print_usage_exit(int e)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Extract statistics from a trace to a CSV format\n");
|
|
||||||
fprintf(stderr, "Usage:\n");
|
|
||||||
fprintf(stderr, " extract [OPTION...] <trace file>\n");
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fprintf(stderr, " -h, --help Print usage\n");
|
|
||||||
fprintf(stderr, " -f, --filter arg Filter zone names (default: "")\n");
|
|
||||||
fprintf(stderr, " -s, --sep arg CSV separator (default: ,)\n");
|
|
||||||
fprintf(stderr, " -c, --case Case sensitive filtering\n");
|
|
||||||
fprintf(stderr, " -e, --self Get self times\n");
|
|
||||||
fprintf(stderr, " -u, --unwrap Report each cpu zone event\n");
|
|
||||||
fprintf(stderr, " -g, --gpu Report each gpu zone event\n" );
|
|
||||||
fprintf(stderr, " -m, --messages Report only messages\n");
|
|
||||||
fprintf(stderr, " -p, --plot Report plot data (only with -u)\n");
|
|
||||||
|
|
||||||
exit(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Args {
|
|
||||||
const char* filter;
|
|
||||||
const char* separator;
|
|
||||||
const char* trace_file;
|
|
||||||
bool case_sensitive;
|
|
||||||
bool self_time;
|
|
||||||
bool unwrap;
|
|
||||||
bool show_gpu;
|
|
||||||
bool unwrapMessages;
|
|
||||||
bool plot;
|
|
||||||
};
|
|
||||||
|
|
||||||
Args parse_args(int argc, char** argv)
|
|
||||||
{
|
|
||||||
if (argc == 1)
|
|
||||||
{
|
|
||||||
print_usage_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Args args = { "", ",", "", false, false, false, false, false, false };
|
|
||||||
|
|
||||||
struct option long_opts[] = {
|
|
||||||
{ "help", no_argument, NULL, 'h' },
|
|
||||||
{ "filter", optional_argument, NULL, 'f' },
|
|
||||||
{ "sep", optional_argument, NULL, 's' },
|
|
||||||
{ "case", no_argument, NULL, 'c' },
|
|
||||||
{ "self", no_argument, NULL, 'e' },
|
|
||||||
{ "unwrap", no_argument, NULL, 'u' },
|
|
||||||
{ "gpu", no_argument, NULL, 'g' },
|
|
||||||
{ "messages", no_argument, NULL, 'm' },
|
|
||||||
{ "plot", no_argument, NULL, 'p' },
|
|
||||||
{ NULL, 0, NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
int c;
|
|
||||||
while ((c = getopt_long(argc, argv, "hf:s:ceugmp", long_opts, NULL)) != -1)
|
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 'h':
|
|
||||||
print_usage_exit(0);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
args.filter = optarg;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
args.separator = optarg;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
args.case_sensitive = true;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
args.self_time = true;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
args.unwrap = true;
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
args.show_gpu = true;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
args.unwrapMessages = true;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
args.plot = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
print_usage_exit(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc != optind + 1)
|
|
||||||
{
|
|
||||||
print_usage_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
args.trace_file = argv[optind];
|
|
||||||
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_substring(
|
|
||||||
const char* term,
|
|
||||||
const char* s,
|
|
||||||
bool case_sensitive = false
|
|
||||||
){
|
|
||||||
auto new_term = std::string(term);
|
|
||||||
auto new_s = std::string(s);
|
|
||||||
|
|
||||||
if (!case_sensitive) {
|
|
||||||
std::transform(
|
|
||||||
new_term.begin(),
|
|
||||||
new_term.end(),
|
|
||||||
new_term.begin(),
|
|
||||||
[](unsigned char c){ return std::tolower(c); }
|
|
||||||
);
|
|
||||||
|
|
||||||
std::transform(
|
|
||||||
new_s.begin(),
|
|
||||||
new_s.end(),
|
|
||||||
new_s.begin(),
|
|
||||||
[](unsigned char c){ return std::tolower(c); }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new_s.find(new_term) != std::string::npos;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* get_name(int32_t id, const tracy::Worker& worker)
|
|
||||||
{
|
|
||||||
auto& srcloc = worker.GetSourceLocation(id);
|
|
||||||
return worker.GetString(srcloc.name.active ? srcloc.name : srcloc.function);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::string join(const T& v, const char* sep) {
|
|
||||||
std::ostringstream s;
|
|
||||||
for (const auto& i : v) {
|
|
||||||
if (&i != &v[0]) {
|
|
||||||
s << sep;
|
|
||||||
}
|
|
||||||
s << i;
|
|
||||||
}
|
|
||||||
return s.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// From TracyView.cpp
|
|
||||||
int64_t GetZoneChildTimeFast(
|
|
||||||
const tracy::Worker& worker,
|
|
||||||
const tracy::ZoneEvent& zone
|
|
||||||
){
|
|
||||||
int64_t time = 0;
|
|
||||||
if( zone.HasChildren() )
|
|
||||||
{
|
|
||||||
auto& children = worker.GetZoneChildren( zone.Child() );
|
|
||||||
if( children.is_magic() )
|
|
||||||
{
|
|
||||||
auto& vec = *(tracy::Vector<tracy::ZoneEvent>*)&children;
|
|
||||||
for( auto& v : vec )
|
|
||||||
{
|
|
||||||
assert( v.IsEndValid() );
|
|
||||||
time += v.End() - v.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for( auto& v : children )
|
|
||||||
{
|
|
||||||
assert( v->IsEndValid() );
|
|
||||||
time += v->End() - v->Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (!AttachConsole(ATTACH_PARENT_PROCESS))
|
|
||||||
{
|
|
||||||
AllocConsole();
|
|
||||||
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Args args = parse_args(argc, argv);
|
|
||||||
|
|
||||||
auto f = std::unique_ptr<tracy::FileRead>(
|
|
||||||
tracy::FileRead::Open(args.trace_file)
|
|
||||||
);
|
|
||||||
if (!f)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Could not open file %s\n", args.trace_file);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto worker = tracy::Worker(*f);
|
|
||||||
|
|
||||||
if (args.unwrapMessages)
|
|
||||||
{
|
|
||||||
const auto& msgs = worker.GetMessages();
|
|
||||||
|
|
||||||
if (msgs.size() > 0)
|
|
||||||
{
|
|
||||||
std::vector<const char*> columnsForMessages;
|
|
||||||
columnsForMessages = {
|
|
||||||
"MessageName", "total_ns"
|
|
||||||
};
|
|
||||||
std::string headerForMessages = join(columnsForMessages, args.separator);
|
|
||||||
printf("%s\n", headerForMessages.data());
|
|
||||||
|
|
||||||
for(auto& it : msgs)
|
|
||||||
{
|
|
||||||
std::vector<std::string> values(columnsForMessages.size());
|
|
||||||
|
|
||||||
values[0] = worker.GetString(it->ref);
|
|
||||||
values[1] = std::to_string(it->time);
|
|
||||||
|
|
||||||
std::string row = join(values, args.separator);
|
|
||||||
printf("%s\n", row.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("There are currently no messages!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!worker.AreSourceLocationZonesReady())
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.show_gpu)
|
|
||||||
{
|
|
||||||
auto& gpu_slz = worker.GetGpuSourceLocationZones();
|
|
||||||
tracy::Vector<decltype( gpu_slz.begin() )> gpu_slz_selected;
|
|
||||||
gpu_slz_selected.reserve( gpu_slz.size() );
|
|
||||||
|
|
||||||
uint32_t total_cnt = 0;
|
|
||||||
for (auto it = gpu_slz.begin(); it != gpu_slz.end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->second.total != 0)
|
|
||||||
{
|
|
||||||
++total_cnt;
|
|
||||||
if (args.filter[0] == '\0')
|
|
||||||
{
|
|
||||||
gpu_slz_selected.push_back_no_space_check( it );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto name = get_name( it->first, worker );
|
|
||||||
if (is_substring( args.filter, name, args.case_sensitive))
|
|
||||||
{
|
|
||||||
gpu_slz_selected.push_back_no_space_check( it );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<const char*> columns;
|
|
||||||
columns = {"name", "src_file", "Time from start of program", "GPU execution time"};
|
|
||||||
|
|
||||||
std::string header = join(columns, args.separator);
|
|
||||||
printf("%s\n", header.data());
|
|
||||||
|
|
||||||
const auto last_time = worker.GetLastTime();
|
|
||||||
for (auto& it : gpu_slz_selected)
|
|
||||||
{
|
|
||||||
std::vector<std::string> values( columns.size() );
|
|
||||||
|
|
||||||
values[0] = get_name( it->first, worker );
|
|
||||||
|
|
||||||
const auto& srcloc = worker.GetSourceLocation( it->first );
|
|
||||||
values[1] = worker.GetString( srcloc.file );
|
|
||||||
|
|
||||||
const auto& zone_data = it->second;
|
|
||||||
for (const auto& zone_thread_data : zone_data.zones)
|
|
||||||
{
|
|
||||||
tracy::GpuEvent* gpu_event = zone_thread_data.Zone();
|
|
||||||
const auto start = gpu_event->GpuStart();
|
|
||||||
const auto end = gpu_event->GpuEnd();
|
|
||||||
|
|
||||||
values[2] = std::to_string( start );
|
|
||||||
|
|
||||||
auto timespan = end - start;
|
|
||||||
values[3] = std::to_string( timespan );
|
|
||||||
|
|
||||||
std::string row = join( values, args.separator );
|
|
||||||
printf( "%s\n", row.data() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& slz = worker.GetSourceLocationZones();
|
|
||||||
tracy::Vector<decltype(slz.begin())> slz_selected;
|
|
||||||
slz_selected.reserve(slz.size());
|
|
||||||
|
|
||||||
uint32_t total_cnt = 0;
|
|
||||||
for(auto it = slz.begin(); it != slz.end(); ++it)
|
|
||||||
{
|
|
||||||
if(it->second.total != 0)
|
|
||||||
{
|
|
||||||
++total_cnt;
|
|
||||||
if(args.filter[0] == '\0')
|
|
||||||
{
|
|
||||||
slz_selected.push_back_no_space_check(it);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto name = get_name(it->first, worker);
|
|
||||||
if(is_substring(args.filter, name, args.case_sensitive))
|
|
||||||
{
|
|
||||||
slz_selected.push_back_no_space_check(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<const char*> columns;
|
|
||||||
if (args.unwrap)
|
|
||||||
{
|
|
||||||
columns = {
|
|
||||||
"name", "src_file", "src_line", "ns_since_start", "exec_time_ns", "thread", "value"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
columns = {
|
|
||||||
"name", "src_file", "src_line", "total_ns", "total_perc",
|
|
||||||
"counts", "mean_ns", "min_ns", "max_ns", "std_ns"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
std::string header = join(columns, args.separator);
|
|
||||||
printf("%s\n", header.data());
|
|
||||||
|
|
||||||
const auto last_time = worker.GetLastTime();
|
|
||||||
for(auto& it : slz_selected)
|
|
||||||
{
|
|
||||||
std::vector<std::string> values(columns.size());
|
|
||||||
|
|
||||||
values[0] = get_name(it->first, worker);
|
|
||||||
|
|
||||||
const auto& srcloc = worker.GetSourceLocation(it->first);
|
|
||||||
values[1] = worker.GetString(srcloc.file);
|
|
||||||
values[2] = std::to_string(srcloc.line);
|
|
||||||
|
|
||||||
const auto& zone_data = it->second;
|
|
||||||
|
|
||||||
if (args.unwrap)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
for (const auto& zone_thread_data : zone_data.zones) {
|
|
||||||
const auto zone_event = zone_thread_data.Zone();
|
|
||||||
const auto tId = zone_thread_data.Thread();
|
|
||||||
const auto start = zone_event->Start();
|
|
||||||
const auto end = zone_event->End();
|
|
||||||
|
|
||||||
values[3] = std::to_string(start);
|
|
||||||
|
|
||||||
auto timespan = end - start;
|
|
||||||
if (args.self_time) {
|
|
||||||
timespan -= GetZoneChildTimeFast(worker, *zone_event);
|
|
||||||
}
|
|
||||||
values[4] = std::to_string(timespan);
|
|
||||||
values[5] = std::to_string(tId);
|
|
||||||
if (worker.HasZoneExtra(*zone_event)) {
|
|
||||||
const auto& text = worker.GetZoneExtra(*zone_event).text;
|
|
||||||
if (text.Active()) {
|
|
||||||
values[6] = worker.GetString(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string row = join(values, args.separator);
|
|
||||||
printf("%s\n", row.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto time = args.self_time ? zone_data.selfTotal : zone_data.total;
|
|
||||||
values[3] = std::to_string(time);
|
|
||||||
values[4] = std::to_string(100. * time / last_time);
|
|
||||||
|
|
||||||
values[5] = std::to_string(zone_data.zones.size());
|
|
||||||
|
|
||||||
const auto avg = (args.self_time ? zone_data.selfTotal : zone_data.total)
|
|
||||||
/ zone_data.zones.size();
|
|
||||||
values[6] = std::to_string(avg);
|
|
||||||
|
|
||||||
const auto tmin = args.self_time ? zone_data.selfMin : zone_data.min;
|
|
||||||
const auto tmax = args.self_time ? zone_data.selfMax : zone_data.max;
|
|
||||||
values[7] = std::to_string(tmin);
|
|
||||||
values[8] = std::to_string(tmax);
|
|
||||||
|
|
||||||
const auto sz = zone_data.zones.size();
|
|
||||||
const auto ss = zone_data.sumSq
|
|
||||||
- 2. * zone_data.total * avg
|
|
||||||
+ avg * avg * sz;
|
|
||||||
double std = 0;
|
|
||||||
if( sz > 1 )
|
|
||||||
std = sqrt(ss / (sz - 1));
|
|
||||||
values[9] = std::to_string(std);
|
|
||||||
|
|
||||||
std::string row = join(values, args.separator);
|
|
||||||
printf("%s\n", row.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(args.plot && args.unwrap)
|
|
||||||
{
|
|
||||||
auto& plots = worker.GetPlots();
|
|
||||||
for(const auto& plot : plots)
|
|
||||||
{
|
|
||||||
std::vector<std::string> values(columns.size());
|
|
||||||
values[0] = worker.GetString(plot->name);
|
|
||||||
|
|
||||||
for(const auto& val : plot->data)
|
|
||||||
{
|
|
||||||
if (args.unwrap)
|
|
||||||
{
|
|
||||||
values[3] = std::to_string(val.time.Val());
|
|
||||||
values[6] = std::to_string(val.val);
|
|
||||||
}
|
|
||||||
std::string row = join(values, args.separator);
|
|
||||||
printf("%s\n", row.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
370
doc/design.svg
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 139.17125 37.041668"
|
||||||
|
height="140"
|
||||||
|
width="526.00159">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<marker
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker6660"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto">
|
||||||
|
<path
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path6658" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker6158"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto">
|
||||||
|
<path
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path6156" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
style="overflow:visible"
|
||||||
|
id="Arrow1Send"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto">
|
||||||
|
<path
|
||||||
|
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path4694" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker5984"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto">
|
||||||
|
<path
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path5982" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="marker5482"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path5480"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="marker5472"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path5470"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker5378"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto">
|
||||||
|
<path
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path5376" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker5308"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto">
|
||||||
|
<path
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path5306" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
style="overflow:visible"
|
||||||
|
id="Arrow1Mend"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto">
|
||||||
|
<path
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path4688" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="marker5170"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path5168"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="marker4963"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path4961"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker6158-2"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto">
|
||||||
|
<path
|
||||||
|
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||||
|
id="path6156-2" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
transform="translate(-18.388332,-17.864582)"
|
||||||
|
id="layer1">
|
||||||
|
<g
|
||||||
|
id="g4666">
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect4607"
|
||||||
|
width="17.197916"
|
||||||
|
height="6.614583"
|
||||||
|
x="18.520834"
|
||||||
|
y="20.510416" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:2.82222223px;line-height:6.61458302px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="20.968229"
|
||||||
|
y="24.869841"
|
||||||
|
id="text4611"><tspan
|
||||||
|
id="tspan4609"
|
||||||
|
x="20.968229"
|
||||||
|
y="24.869841"
|
||||||
|
style="stroke-width:0.26458332px">Thread 1</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g4661">
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect4607-4"
|
||||||
|
width="17.197916"
|
||||||
|
height="6.6145835"
|
||||||
|
x="18.520834"
|
||||||
|
y="32.416668" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:2.82222223px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="20.979254"
|
||||||
|
y="36.776093"
|
||||||
|
id="text4611-8"><tspan
|
||||||
|
id="tspan4609-9"
|
||||||
|
x="20.979254"
|
||||||
|
y="36.776093"
|
||||||
|
style="stroke-width:0.26458332px">Thread 2</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g4671">
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect4607-8"
|
||||||
|
width="17.197916"
|
||||||
|
height="6.6145835"
|
||||||
|
x="18.520832"
|
||||||
|
y="44.322918" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:2.82222223px;line-height:6.61458349px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="20.951002"
|
||||||
|
y="48.682343"
|
||||||
|
id="text4611-89"><tspan
|
||||||
|
id="tspan4609-6"
|
||||||
|
x="20.951002"
|
||||||
|
y="48.682343"
|
||||||
|
style="stroke-width:0.26458332px">Thread 3</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g5096">
|
||||||
|
<ellipse
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path4644"
|
||||||
|
cx="67.775978"
|
||||||
|
cy="36.3787"
|
||||||
|
rx="10.583333"
|
||||||
|
ry="4.6302085" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:2.82222223px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="67.733261"
|
||||||
|
y="35.623535"
|
||||||
|
id="text4648"><tspan
|
||||||
|
id="tspan4646"
|
||||||
|
x="67.733261"
|
||||||
|
y="35.623535"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458332px">Tracy</tspan><tspan
|
||||||
|
x="67.733261"
|
||||||
|
y="39.151314"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458332px"
|
||||||
|
id="tspan4650">client</tspan></text>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="path4673"
|
||||||
|
d="m 37.041666,24.479166 19.84375,7.937502"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5472)" />
|
||||||
|
<path
|
||||||
|
id="path4675"
|
||||||
|
d="m 37.041666,46.968751 19.84375,-6.614584"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5482)" />
|
||||||
|
<path
|
||||||
|
id="path4677"
|
||||||
|
d="M 37.041667,36.385417 H 55.5625"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5378)" />
|
||||||
|
<path
|
||||||
|
id="path5059"
|
||||||
|
d="M 84.666667,17.864582 V 54.90625"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.05833327, 2.11666654;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
|
<g
|
||||||
|
id="g5106">
|
||||||
|
<ellipse
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path4644-1"
|
||||||
|
cx="101.98283"
|
||||||
|
cy="36.56768"
|
||||||
|
rx="10.583333"
|
||||||
|
ry="4.6302085" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:2.82222223px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="101.90772"
|
||||||
|
y="35.812515"
|
||||||
|
id="text4648-2"><tspan
|
||||||
|
id="tspan4646-5"
|
||||||
|
x="101.90772"
|
||||||
|
y="35.812515"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458332px">Tracy</tspan><tspan
|
||||||
|
x="101.90772"
|
||||||
|
y="39.340294"
|
||||||
|
style="text-align:center;text-anchor:middle;stroke-width:0.26458332px"
|
||||||
|
id="tspan4650-1">server</tspan></text>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="path5108"
|
||||||
|
d="M 79.375,37.708333 H 89.958333"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker6660)" />
|
||||||
|
<path
|
||||||
|
id="path5110"
|
||||||
|
d="M 89.958333,35.0625 H 79.375"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker5308)" />
|
||||||
|
<g
|
||||||
|
transform="translate(-2.64619,-1.3704153)"
|
||||||
|
id="g6152">
|
||||||
|
<ellipse
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path6114"
|
||||||
|
cx="128.98439"
|
||||||
|
cy="33.692333"
|
||||||
|
rx="4.6302085"
|
||||||
|
ry="1.2756696" />
|
||||||
|
<path
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
d="m 124.36251,41.677042 c -0.004,0.01582 -0.007,0.03168 -0.008,0.04754 5.3e-4,0.704384 2.07327,1.275328 4.62995,1.275373 2.55689,3.5e-5 4.62988,-0.570931 4.63048,-1.275373 -10e-4,-0.01585 -0.003,-0.03171 -0.006,-0.04754"
|
||||||
|
id="path6114-1" />
|
||||||
|
<path
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 124.35417,33.739583 v 8.021022"
|
||||||
|
id="path6138" />
|
||||||
|
<path
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 133.61458,33.739582 v 8.051744"
|
||||||
|
id="path6140" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:2.82222223px;line-height:6.61458302px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="126.89217"
|
||||||
|
y="39.409225"
|
||||||
|
id="text6144"><tspan
|
||||||
|
id="tspan6142"
|
||||||
|
x="126.89217"
|
||||||
|
y="39.409225"
|
||||||
|
style="stroke-width:0.26458332px">DB</tspan></text>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="path6154"
|
||||||
|
d="m 113.77082,36.385418 h 6.61459"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker6158)" />
|
||||||
|
<g
|
||||||
|
transform="translate(2.6458333,1.2715659e-6)"
|
||||||
|
id="g6241">
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect6232"
|
||||||
|
width="17.197916"
|
||||||
|
height="5.291667"
|
||||||
|
x="137.58333"
|
||||||
|
y="33.739582" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:2.82222223px;line-height:6.61458302px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="140.8851"
|
||||||
|
y="37.164005"
|
||||||
|
id="text6236"><tspan
|
||||||
|
id="tspan6234"
|
||||||
|
x="140.8851"
|
||||||
|
y="37.164005"
|
||||||
|
style="stroke-width:0.26458332px">Display</tspan></text>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="path6154-3"
|
||||||
|
d="m 132.29166,36.385417 h 6.61459"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker6158-2)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 15 KiB |
BIN
doc/issues/dxt1+alpha.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
doc/profiler.png
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 284 KiB |
Before Width: | Height: | Size: 250 KiB After Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 234 KiB |
706
dtl/Diff.hpp
@ -1,706 +0,0 @@
|
|||||||
/**
|
|
||||||
dtl -- Diff Template Library
|
|
||||||
|
|
||||||
In short, Diff Template Library is distributed under so called "BSD license",
|
|
||||||
|
|
||||||
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the authors nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* If you use this library, you must include dtl.hpp only. */
|
|
||||||
|
|
||||||
#ifndef DTL_DIFF_H
|
|
||||||
#define DTL_DIFF_H
|
|
||||||
|
|
||||||
namespace dtl {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* diff class template
|
|
||||||
* sequence must support random_access_iterator.
|
|
||||||
*/
|
|
||||||
template <typename elem, typename sequence = vector< elem >, typename comparator = Compare< elem > >
|
|
||||||
class Diff
|
|
||||||
{
|
|
||||||
private :
|
|
||||||
dtl_typedefs(elem, sequence)
|
|
||||||
sequence A;
|
|
||||||
sequence B;
|
|
||||||
size_t M;
|
|
||||||
size_t N;
|
|
||||||
size_t delta;
|
|
||||||
size_t offset;
|
|
||||||
long long *fp;
|
|
||||||
long long editDistance;
|
|
||||||
Lcs< elem > lcs;
|
|
||||||
Ses< elem > ses;
|
|
||||||
editPath path;
|
|
||||||
editPathCordinates pathCordinates;
|
|
||||||
bool swapped;
|
|
||||||
bool huge;
|
|
||||||
bool trivial;
|
|
||||||
bool editDistanceOnly;
|
|
||||||
uniHunkVec uniHunks;
|
|
||||||
comparator cmp;
|
|
||||||
long long ox;
|
|
||||||
long long oy;
|
|
||||||
public :
|
|
||||||
Diff () {}
|
|
||||||
|
|
||||||
Diff (const sequence& a,
|
|
||||||
const sequence& b) : A(a), B(b), ses(false) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Diff (const sequence& a,
|
|
||||||
const sequence& b,
|
|
||||||
bool deletesFirst) : A(a), B(b), ses(deletesFirst) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Diff (const sequence& a,
|
|
||||||
const sequence& b,
|
|
||||||
const comparator& comp) : A(a), B(b), ses(false), cmp(comp) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Diff (const sequence& a,
|
|
||||||
const sequence& b,
|
|
||||||
bool deleteFirst,
|
|
||||||
const comparator& comp) : A(a), B(b), ses(deleteFirst), cmp(comp) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
~Diff() {}
|
|
||||||
|
|
||||||
long long getEditDistance () const {
|
|
||||||
return editDistance;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lcs< elem > getLcs () const {
|
|
||||||
return lcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
elemVec getLcsVec () const {
|
|
||||||
return lcs.getSequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ses< elem > getSes () const {
|
|
||||||
return ses;
|
|
||||||
}
|
|
||||||
|
|
||||||
uniHunkVec getUniHunks () const {
|
|
||||||
return uniHunks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* These should be deprecated */
|
|
||||||
bool isHuge () const {
|
|
||||||
return huge;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onHuge () {
|
|
||||||
this->huge = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void offHuge () {
|
|
||||||
this->huge = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isUnserious () const {
|
|
||||||
return trivial;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onUnserious () {
|
|
||||||
this->trivial = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void offUnserious () {
|
|
||||||
this->trivial = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onOnlyEditDistance () {
|
|
||||||
this->editDistanceOnly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* These are the replacements for the above */
|
|
||||||
bool hugeEnabled () const {
|
|
||||||
return huge;
|
|
||||||
}
|
|
||||||
|
|
||||||
void enableHuge () {
|
|
||||||
this->huge = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void disableHuge () {
|
|
||||||
this->huge = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool trivialEnabled () const {
|
|
||||||
return trivial;
|
|
||||||
}
|
|
||||||
|
|
||||||
void enableTrivial () {
|
|
||||||
this->trivial = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void disableTrivial () {
|
|
||||||
this->trivial = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void editDistanceOnlyEnabled () {
|
|
||||||
this->editDistanceOnly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* patching with Unified Format Hunks
|
|
||||||
*/
|
|
||||||
sequence uniPatch (const sequence& seq) {
|
|
||||||
elemList seqLst(seq.begin(), seq.end());
|
|
||||||
sesElemVec shunk;
|
|
||||||
sesElemVec_iter vsesIt;
|
|
||||||
elemList_iter lstIt = seqLst.begin();
|
|
||||||
long long inc_dec_total = 0;
|
|
||||||
long long gap = 1;
|
|
||||||
for (uniHunkVec_iter it=uniHunks.begin();it!=uniHunks.end();++it) {
|
|
||||||
joinSesVec(shunk, it->common[0]);
|
|
||||||
joinSesVec(shunk, it->change);
|
|
||||||
joinSesVec(shunk, it->common[1]);
|
|
||||||
it->a += inc_dec_total;
|
|
||||||
inc_dec_total += it->inc_dec_count;
|
|
||||||
for (long long i=0;i<it->a - gap;++i) {
|
|
||||||
++lstIt;
|
|
||||||
}
|
|
||||||
gap = it->a + it->b + it->inc_dec_count;
|
|
||||||
vsesIt = shunk.begin();
|
|
||||||
while (vsesIt!=shunk.end()) {
|
|
||||||
switch (vsesIt->second.type) {
|
|
||||||
case SES_ADD :
|
|
||||||
seqLst.insert(lstIt, vsesIt->first);
|
|
||||||
break;
|
|
||||||
case SES_DELETE :
|
|
||||||
if (lstIt != seqLst.end()) {
|
|
||||||
lstIt = seqLst.erase(lstIt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SES_COMMON :
|
|
||||||
if (lstIt != seqLst.end()) {
|
|
||||||
++lstIt;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
// no fall-through
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++vsesIt;
|
|
||||||
}
|
|
||||||
shunk.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
sequence patchedSeq(seqLst.begin(), seqLst.end());
|
|
||||||
return patchedSeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* patching with Shortest Edit Script (SES)
|
|
||||||
*/
|
|
||||||
sequence patch (const sequence& seq) const {
|
|
||||||
sesElemVec sesSeq = ses.getSequence();
|
|
||||||
elemList seqLst(seq.begin(), seq.end());
|
|
||||||
elemList_iter lstIt = seqLst.begin();
|
|
||||||
for (sesElemVec_iter sesIt=sesSeq.begin();sesIt!=sesSeq.end();++sesIt) {
|
|
||||||
switch (sesIt->second.type) {
|
|
||||||
case SES_ADD :
|
|
||||||
seqLst.insert(lstIt, sesIt->first);
|
|
||||||
break;
|
|
||||||
case SES_DELETE :
|
|
||||||
lstIt = seqLst.erase(lstIt);
|
|
||||||
break;
|
|
||||||
case SES_COMMON :
|
|
||||||
++lstIt;
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
// no through
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sequence patchedSeq(seqLst.begin(), seqLst.end());
|
|
||||||
return patchedSeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* compose Longest Common Subsequence and Shortest Edit Script.
|
|
||||||
* The algorithm implemented here is based on "An O(NP) Sequence Comparison Algorithm"
|
|
||||||
* described by Sun Wu, Udi Manber and Gene Myers
|
|
||||||
*/
|
|
||||||
void compose() {
|
|
||||||
|
|
||||||
if (isHuge()) {
|
|
||||||
pathCordinates.reserve(MAX_CORDINATES_SIZE);
|
|
||||||
}
|
|
||||||
ox = 0;
|
|
||||||
oy = 0;
|
|
||||||
long long p = -1;
|
|
||||||
fp = new long long[M + N + 3];
|
|
||||||
fill(&fp[0], &fp[M + N + 3], -1);
|
|
||||||
path = editPath(M + N + 3);
|
|
||||||
fill(path.begin(), path.end(), -1);
|
|
||||||
ONP:
|
|
||||||
do {
|
|
||||||
++p;
|
|
||||||
for (long long k=-p;k<=static_cast<long long>(delta)-1;++k) {
|
|
||||||
fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]);
|
|
||||||
}
|
|
||||||
for (long long k=static_cast<long long>(delta)+p;k>=static_cast<long long>(delta)+1;--k) {
|
|
||||||
fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]);
|
|
||||||
}
|
|
||||||
fp[delta+offset] = snake(static_cast<long long>(delta), fp[delta-1+offset]+1, fp[delta+1+offset]);
|
|
||||||
} while (fp[delta+offset] != static_cast<long long>(N) && pathCordinates.size() < MAX_CORDINATES_SIZE);
|
|
||||||
|
|
||||||
editDistance += static_cast<long long>(delta) + 2 * p;
|
|
||||||
long long r = path[delta+offset];
|
|
||||||
P cordinate;
|
|
||||||
editPathCordinates epc(0);
|
|
||||||
|
|
||||||
// recording edit distance only
|
|
||||||
if (editDistanceOnly) {
|
|
||||||
delete[] this->fp;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(r != -1) {
|
|
||||||
cordinate.x = pathCordinates[(size_t)r].x;
|
|
||||||
cordinate.y = pathCordinates[(size_t)r].y;
|
|
||||||
epc.push_back(cordinate);
|
|
||||||
r = pathCordinates[(size_t)r].k;
|
|
||||||
}
|
|
||||||
|
|
||||||
// record Longest Common Subsequence & Shortest Edit Script
|
|
||||||
if (!recordSequence(epc)) {
|
|
||||||
pathCordinates.resize(0);
|
|
||||||
epc.resize(0);
|
|
||||||
p = -1;
|
|
||||||
goto ONP;
|
|
||||||
}
|
|
||||||
delete[] this->fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* print difference between A and B as an SES
|
|
||||||
*/
|
|
||||||
template < typename stream >
|
|
||||||
void printSES (stream& out) const {
|
|
||||||
sesElemVec ses_v = ses.getSequence();
|
|
||||||
for_each(ses_v.begin(), ses_v.end(), ChangePrinter< sesElem, stream >(out));
|
|
||||||
}
|
|
||||||
|
|
||||||
void printSES (ostream& out = cout) const {
|
|
||||||
printSES< ostream >(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* print differences given an SES
|
|
||||||
*/
|
|
||||||
template < typename stream >
|
|
||||||
static void printSES (const Ses< elem >& s, stream& out) {
|
|
||||||
sesElemVec ses_v = s.getSequence();
|
|
||||||
for_each(ses_v.begin(), ses_v.end(), ChangePrinter< sesElem, stream >(out));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void printSES (const Ses< elem >& s, ostream& out = cout) {
|
|
||||||
printSES< ostream >(s, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* print difference between A and B as an SES with custom printer
|
|
||||||
*/
|
|
||||||
template < typename stream, template < typename SEET, typename STRT > class PT >
|
|
||||||
void printSES (stream& out) const {
|
|
||||||
sesElemVec ses_v = ses.getSequence ();
|
|
||||||
for_each (ses_v.begin (), ses_v.end(), PT < sesElem, stream > (out));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* store difference between A and B as an SES with custom storage
|
|
||||||
*/
|
|
||||||
template < typename storedData, template < typename SEET, typename STRT > class ST >
|
|
||||||
void storeSES(storedData& sd) const {
|
|
||||||
sesElemVec ses_v = ses.getSequence();
|
|
||||||
for_each(ses_v.begin(), ses_v.end(), ST < sesElem, storedData >(sd));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* print difference between A and B in the Unified Format
|
|
||||||
*/
|
|
||||||
template < typename stream >
|
|
||||||
void printUnifiedFormat (stream& out) const {
|
|
||||||
for_each(uniHunks.begin(), uniHunks.end(), UniHunkPrinter< sesElem, stream >(out));
|
|
||||||
}
|
|
||||||
|
|
||||||
void printUnifiedFormat (ostream& out = cout) const {
|
|
||||||
printUnifiedFormat< ostream >(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* print unified format difference with given unified format hunks
|
|
||||||
*/
|
|
||||||
template < typename stream >
|
|
||||||
static void printUnifiedFormat (const uniHunkVec& hunks, stream& out) {
|
|
||||||
for_each(hunks.begin(), hunks.end(), UniHunkPrinter< sesElem >(out));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void printUnifiedFormat (const uniHunkVec& hunks, ostream& out = cout) {
|
|
||||||
printUnifiedFormat< ostream >(hunks, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* compose Unified Format Hunks from Shortest Edit Script
|
|
||||||
*/
|
|
||||||
void composeUnifiedHunks () {
|
|
||||||
sesElemVec common[2];
|
|
||||||
sesElemVec change;
|
|
||||||
sesElemVec ses_v = ses.getSequence();
|
|
||||||
long long l_cnt = 1;
|
|
||||||
long long length = distance(ses_v.begin(), ses_v.end());
|
|
||||||
long long middle = 0;
|
|
||||||
bool isMiddle, isAfter;
|
|
||||||
elemInfo einfo;
|
|
||||||
long long a, b, c, d; // @@ -a,b +c,d @@
|
|
||||||
long long inc_dec_count = 0;
|
|
||||||
uniHunk< sesElem > hunk;
|
|
||||||
sesElemVec adds;
|
|
||||||
sesElemVec deletes;
|
|
||||||
|
|
||||||
isMiddle = isAfter = false;
|
|
||||||
a = b = c = d = 0;
|
|
||||||
|
|
||||||
for (sesElemVec_iter it=ses_v.begin();it!=ses_v.end();++it, ++l_cnt) {
|
|
||||||
einfo = it->second;
|
|
||||||
switch (einfo.type) {
|
|
||||||
case SES_ADD :
|
|
||||||
middle = 0;
|
|
||||||
++inc_dec_count;
|
|
||||||
adds.push_back(*it);
|
|
||||||
if (!isMiddle) isMiddle = true;
|
|
||||||
if (isMiddle) ++d;
|
|
||||||
if (l_cnt >= length) {
|
|
||||||
joinSesVec(change, deletes);
|
|
||||||
joinSesVec(change, adds);
|
|
||||||
isAfter = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SES_DELETE :
|
|
||||||
middle = 0;
|
|
||||||
--inc_dec_count;
|
|
||||||
deletes.push_back(*it);
|
|
||||||
if (!isMiddle) isMiddle = true;
|
|
||||||
if (isMiddle) ++b;
|
|
||||||
if (l_cnt >= length) {
|
|
||||||
joinSesVec(change, deletes);
|
|
||||||
joinSesVec(change, adds);
|
|
||||||
isAfter = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SES_COMMON :
|
|
||||||
++b;++d;
|
|
||||||
if (common[1].empty() && adds.empty() && deletes.empty() && change.empty()) {
|
|
||||||
if (static_cast<long long>(common[0].size()) < DTL_CONTEXT_SIZE) {
|
|
||||||
if (a == 0 && c == 0) {
|
|
||||||
if (!wasSwapped()) {
|
|
||||||
a = einfo.beforeIdx;
|
|
||||||
c = einfo.afterIdx;
|
|
||||||
} else {
|
|
||||||
a = einfo.afterIdx;
|
|
||||||
c = einfo.beforeIdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
common[0].push_back(*it);
|
|
||||||
} else {
|
|
||||||
rotate(common[0].begin(), common[0].begin() + 1, common[0].end());
|
|
||||||
common[0].pop_back();
|
|
||||||
common[0].push_back(*it);
|
|
||||||
++a;++c;
|
|
||||||
--b;--d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isMiddle && !isAfter) {
|
|
||||||
++middle;
|
|
||||||
joinSesVec(change, deletes);
|
|
||||||
joinSesVec(change, adds);
|
|
||||||
change.push_back(*it);
|
|
||||||
if (middle >= DTL_SEPARATE_SIZE || l_cnt >= length) {
|
|
||||||
isAfter = true;
|
|
||||||
}
|
|
||||||
adds.clear();
|
|
||||||
deletes.clear();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
// no through
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// compose unified format hunk
|
|
||||||
if (isAfter && !change.empty()) {
|
|
||||||
sesElemVec_iter cit = it;
|
|
||||||
long long cnt = 0;
|
|
||||||
for (long long i=0;i<DTL_SEPARATE_SIZE && (cit != ses_v.end());++i, ++cit) {
|
|
||||||
if (cit->second.type == SES_COMMON) {
|
|
||||||
++cnt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cnt < DTL_SEPARATE_SIZE && l_cnt < length) {
|
|
||||||
middle = 0;
|
|
||||||
isAfter = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (static_cast<long long>(common[0].size()) >= DTL_SEPARATE_SIZE) {
|
|
||||||
long long c0size = static_cast<long long>(common[0].size());
|
|
||||||
rotate(common[0].begin(),
|
|
||||||
common[0].begin() + (size_t)c0size - DTL_SEPARATE_SIZE,
|
|
||||||
common[0].end());
|
|
||||||
for (long long i=0;i<c0size - DTL_SEPARATE_SIZE;++i) {
|
|
||||||
common[0].pop_back();
|
|
||||||
}
|
|
||||||
a += c0size - DTL_SEPARATE_SIZE;
|
|
||||||
c += c0size - DTL_SEPARATE_SIZE;
|
|
||||||
}
|
|
||||||
if (a == 0) ++a;
|
|
||||||
if (c == 0) ++c;
|
|
||||||
if (wasSwapped()) swap(a, c);
|
|
||||||
hunk.a = a;
|
|
||||||
hunk.b = b;
|
|
||||||
hunk.c = c;
|
|
||||||
hunk.d = d;
|
|
||||||
hunk.common[0] = common[0];
|
|
||||||
hunk.change = change;
|
|
||||||
hunk.common[1] = common[1];
|
|
||||||
hunk.inc_dec_count = inc_dec_count;
|
|
||||||
uniHunks.push_back(hunk);
|
|
||||||
isMiddle = false;
|
|
||||||
isAfter = false;
|
|
||||||
common[0].clear();
|
|
||||||
common[1].clear();
|
|
||||||
adds.clear();
|
|
||||||
deletes.clear();
|
|
||||||
change.clear();
|
|
||||||
a = b = c = d = middle = inc_dec_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* compose ses from stream
|
|
||||||
*/
|
|
||||||
template <typename stream>
|
|
||||||
static Ses< elem > composeSesFromStream (stream& st)
|
|
||||||
{
|
|
||||||
elem line;
|
|
||||||
Ses< elem > ret;
|
|
||||||
long long x_idx, y_idx;
|
|
||||||
x_idx = y_idx = 1;
|
|
||||||
while (getline(st, line)) {
|
|
||||||
elem mark(line.begin(), line.begin() + 1);
|
|
||||||
elem e(line.begin() + 1, line.end());
|
|
||||||
if (mark == SES_MARK_DELETE) {
|
|
||||||
ret.addSequence(e, x_idx, 0, SES_DELETE);
|
|
||||||
++x_idx;
|
|
||||||
} else if (mark == SES_MARK_ADD) {
|
|
||||||
ret.addSequence(e, y_idx, 0, SES_ADD);
|
|
||||||
++y_idx;
|
|
||||||
} else if (mark == SES_MARK_COMMON) {
|
|
||||||
ret.addSequence(e, x_idx, y_idx, SES_COMMON);
|
|
||||||
++x_idx;
|
|
||||||
++y_idx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private :
|
|
||||||
/**
|
|
||||||
* initialize
|
|
||||||
*/
|
|
||||||
void init () {
|
|
||||||
M = distance(A.begin(), A.end());
|
|
||||||
N = distance(B.begin(), B.end());
|
|
||||||
if (M < N) {
|
|
||||||
swapped = false;
|
|
||||||
} else {
|
|
||||||
swap(A, B);
|
|
||||||
swap(M, N);
|
|
||||||
swapped = true;
|
|
||||||
}
|
|
||||||
editDistance = 0;
|
|
||||||
delta = N - M;
|
|
||||||
offset = M + 1;
|
|
||||||
huge = false;
|
|
||||||
trivial = false;
|
|
||||||
editDistanceOnly = false;
|
|
||||||
fp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* search shortest path and record the path
|
|
||||||
*/
|
|
||||||
long long snake(const long long& k, const long long& above, const long long& below) {
|
|
||||||
long long r = above > below ? path[(size_t)k-1+offset] : path[(size_t)k+1+offset];
|
|
||||||
long long y = max(above, below);
|
|
||||||
long long x = y - k;
|
|
||||||
while ((size_t)x < M && (size_t)y < N && (swapped ? cmp.impl(B[(size_t)y], A[(size_t)x]) : cmp.impl(A[(size_t)x], B[(size_t)y]))) {
|
|
||||||
++x;++y;
|
|
||||||
}
|
|
||||||
|
|
||||||
path[(size_t)k+offset] = static_cast<long long>(pathCordinates.size());
|
|
||||||
if (!editDistanceOnly) {
|
|
||||||
P p;
|
|
||||||
p.x = x;p.y = y;p.k = r;
|
|
||||||
pathCordinates.push_back(p);
|
|
||||||
}
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* record SES and LCS
|
|
||||||
*/
|
|
||||||
bool recordSequence (const editPathCordinates& v) {
|
|
||||||
sequence_const_iter x(A.begin());
|
|
||||||
sequence_const_iter y(B.begin());
|
|
||||||
long long x_idx, y_idx; // line number for Unified Format
|
|
||||||
long long px_idx, py_idx; // cordinates
|
|
||||||
bool complete = false;
|
|
||||||
x_idx = y_idx = 1;
|
|
||||||
px_idx = py_idx = 0;
|
|
||||||
for (size_t i=v.size()-1;!complete;--i) {
|
|
||||||
while(px_idx < v[i].x || py_idx < v[i].y) {
|
|
||||||
if (v[i].y - v[i].x > py_idx - px_idx) {
|
|
||||||
if (!wasSwapped()) {
|
|
||||||
ses.addSequence(*y, 0, y_idx + oy, SES_ADD);
|
|
||||||
} else {
|
|
||||||
ses.addSequence(*y, y_idx + oy, 0, SES_DELETE);
|
|
||||||
}
|
|
||||||
++y;
|
|
||||||
++y_idx;
|
|
||||||
++py_idx;
|
|
||||||
} else if (v[i].y - v[i].x < py_idx - px_idx) {
|
|
||||||
if (!wasSwapped()) {
|
|
||||||
ses.addSequence(*x, x_idx + ox, 0, SES_DELETE);
|
|
||||||
} else {
|
|
||||||
ses.addSequence(*x, 0, x_idx + ox, SES_ADD);
|
|
||||||
}
|
|
||||||
++x;
|
|
||||||
++x_idx;
|
|
||||||
++px_idx;
|
|
||||||
} else {
|
|
||||||
if (!wasSwapped()) {
|
|
||||||
lcs.addSequence(*x);
|
|
||||||
ses.addSequence(*x, x_idx + ox, y_idx + oy, SES_COMMON);
|
|
||||||
} else {
|
|
||||||
lcs.addSequence(*y);
|
|
||||||
ses.addSequence(*y, y_idx + oy, x_idx + ox, SES_COMMON);
|
|
||||||
}
|
|
||||||
++x;
|
|
||||||
++y;
|
|
||||||
++x_idx;
|
|
||||||
++y_idx;
|
|
||||||
++px_idx;
|
|
||||||
++py_idx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == 0) complete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x_idx > static_cast<long long>(M) && y_idx > static_cast<long long>(N)) {
|
|
||||||
// all recording succeeded
|
|
||||||
} else {
|
|
||||||
// trivial difference
|
|
||||||
if (trivialEnabled()) {
|
|
||||||
if (!wasSwapped()) {
|
|
||||||
recordOddSequence(x_idx, M, x, SES_DELETE);
|
|
||||||
recordOddSequence(y_idx, N, y, SES_ADD);
|
|
||||||
} else {
|
|
||||||
recordOddSequence(x_idx, M, x, SES_ADD);
|
|
||||||
recordOddSequence(y_idx, N, y, SES_DELETE);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nontrivial difference
|
|
||||||
sequence A_(A.begin() + (size_t)x_idx - 1, A.end());
|
|
||||||
sequence B_(B.begin() + (size_t)y_idx - 1, B.end());
|
|
||||||
A = A_;
|
|
||||||
B = B_;
|
|
||||||
M = distance(A.begin(), A.end());
|
|
||||||
N = distance(B.begin(), B.end());
|
|
||||||
delta = N - M;
|
|
||||||
offset = M + 1;
|
|
||||||
delete[] fp;
|
|
||||||
fp = new long long[M + N + 3];
|
|
||||||
fill(&fp[0], &fp[M + N + 3], -1);
|
|
||||||
fill(path.begin(), path.end(), -1);
|
|
||||||
ox = x_idx - 1;
|
|
||||||
oy = y_idx - 1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* record odd sequence in SES
|
|
||||||
*/
|
|
||||||
void inline recordOddSequence (long long idx, long long length, sequence_const_iter it, const edit_t et) {
|
|
||||||
while(idx < length){
|
|
||||||
ses.addSequence(*it, idx, 0, et);
|
|
||||||
++it;
|
|
||||||
++idx;
|
|
||||||
++editDistance;
|
|
||||||
}
|
|
||||||
ses.addSequence(*it, idx, 0, et);
|
|
||||||
++editDistance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* join SES vectors
|
|
||||||
*/
|
|
||||||
void inline joinSesVec (sesElemVec& s1, sesElemVec& s2) const {
|
|
||||||
if (!s2.empty()) {
|
|
||||||
for (sesElemVec_iter vit=s2.begin();vit!=s2.end();++vit) {
|
|
||||||
s1.push_back(*vit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check if the sequences have been swapped
|
|
||||||
*/
|
|
||||||
bool inline wasSwapped () const {
|
|
||||||
return swapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DTL_DIFF_H
|
|
245
dtl/Diff3.hpp
@ -1,245 +0,0 @@
|
|||||||
/**
|
|
||||||
dtl -- Diff Template Library
|
|
||||||
|
|
||||||
In short, Diff Template Library is distributed under so called "BSD license",
|
|
||||||
|
|
||||||
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the authors nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* If you use this library, you must include dtl.hpp only. */
|
|
||||||
|
|
||||||
#ifndef DTL_DIFF3_H
|
|
||||||
#define DTL_DIFF3_H
|
|
||||||
|
|
||||||
namespace dtl {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* diff3 class template
|
|
||||||
* sequence must support random_access_iterator.
|
|
||||||
*/
|
|
||||||
template <typename elem, typename sequence = vector< elem >, typename comparator = Compare< elem > >
|
|
||||||
class Diff3
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
dtl_typedefs(elem, sequence)
|
|
||||||
sequence A;
|
|
||||||
sequence B;
|
|
||||||
sequence C;
|
|
||||||
sequence S;
|
|
||||||
Diff< elem, sequence, comparator > diff_ba;
|
|
||||||
Diff< elem, sequence, comparator > diff_bc;
|
|
||||||
bool conflict;
|
|
||||||
elem csepabegin;
|
|
||||||
elem csepa;
|
|
||||||
elem csepaend;
|
|
||||||
public :
|
|
||||||
Diff3 () {}
|
|
||||||
Diff3 (const sequence& a,
|
|
||||||
const sequence& b,
|
|
||||||
const sequence& c) : A(a), B(b), C(c),
|
|
||||||
diff_ba(b, a), diff_bc(b, c),
|
|
||||||
conflict(false) {}
|
|
||||||
|
|
||||||
~Diff3 () {}
|
|
||||||
|
|
||||||
bool isConflict () const {
|
|
||||||
return conflict;
|
|
||||||
}
|
|
||||||
|
|
||||||
sequence getMergedSequence () const {
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* merge changes B and C into A
|
|
||||||
*/
|
|
||||||
bool merge () {
|
|
||||||
if (diff_ba.getEditDistance() == 0) { // A == B
|
|
||||||
if (diff_bc.getEditDistance() == 0) { // A == B == C
|
|
||||||
S = B;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
S = C;
|
|
||||||
return true;
|
|
||||||
} else { // A != B
|
|
||||||
if (diff_bc.getEditDistance() == 0) { // A != B == C
|
|
||||||
S = A;
|
|
||||||
return true;
|
|
||||||
} else { // A != B != C
|
|
||||||
S = merge_();
|
|
||||||
if (isConflict()) { // conflict occured
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* compose differences
|
|
||||||
*/
|
|
||||||
void compose () {
|
|
||||||
diff_ba.compose();
|
|
||||||
diff_bc.compose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private :
|
|
||||||
/**
|
|
||||||
* merge implementation
|
|
||||||
*/
|
|
||||||
sequence merge_ () {
|
|
||||||
elemVec seq;
|
|
||||||
Ses< elem > ses_ba = diff_ba.getSes();
|
|
||||||
Ses< elem > ses_bc = diff_bc.getSes();
|
|
||||||
sesElemVec ses_ba_v = ses_ba.getSequence();
|
|
||||||
sesElemVec ses_bc_v = ses_bc.getSequence();
|
|
||||||
sesElemVec_iter ba_it = ses_ba_v.begin();
|
|
||||||
sesElemVec_iter bc_it = ses_bc_v.begin();
|
|
||||||
sesElemVec_iter ba_end = ses_ba_v.end();
|
|
||||||
sesElemVec_iter bc_end = ses_bc_v.end();
|
|
||||||
|
|
||||||
while (!isEnd(ba_end, ba_it) || !isEnd(bc_end, bc_it)) {
|
|
||||||
while (true) {
|
|
||||||
if (!isEnd(ba_end, ba_it) &&
|
|
||||||
!isEnd(bc_end, bc_it) &&
|
|
||||||
ba_it->first == bc_it->first &&
|
|
||||||
ba_it->second.type == SES_COMMON &&
|
|
||||||
bc_it->second.type == SES_COMMON) {
|
|
||||||
// do nothing
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!isEnd(ba_end, ba_it)) seq.push_back(ba_it->first);
|
|
||||||
else if (!isEnd(bc_end, bc_it)) seq.push_back(bc_it->first);
|
|
||||||
forwardUntilEnd(ba_end, ba_it);
|
|
||||||
forwardUntilEnd(bc_end, bc_it);
|
|
||||||
}
|
|
||||||
if (isEnd(ba_end, ba_it) || isEnd(bc_end, bc_it)) break;
|
|
||||||
if ( ba_it->second.type == SES_COMMON
|
|
||||||
&& bc_it->second.type == SES_DELETE) {
|
|
||||||
forwardUntilEnd(ba_end, ba_it);
|
|
||||||
forwardUntilEnd(bc_end, bc_it);
|
|
||||||
} else if (ba_it->second.type == SES_COMMON &&
|
|
||||||
bc_it->second.type == SES_ADD) {
|
|
||||||
seq.push_back(bc_it->first);
|
|
||||||
forwardUntilEnd(bc_end, bc_it);
|
|
||||||
} else if (ba_it->second.type == SES_DELETE &&
|
|
||||||
bc_it->second.type == SES_COMMON) {
|
|
||||||
forwardUntilEnd(ba_end, ba_it);
|
|
||||||
forwardUntilEnd(bc_end, bc_it);
|
|
||||||
} else if (ba_it->second.type == SES_DELETE &&
|
|
||||||
bc_it->second.type == SES_DELETE) {
|
|
||||||
if (ba_it->first == bc_it->first) {
|
|
||||||
forwardUntilEnd(ba_end, ba_it);
|
|
||||||
forwardUntilEnd(bc_end, bc_it);
|
|
||||||
} else {
|
|
||||||
// conflict
|
|
||||||
conflict = true;
|
|
||||||
return B;
|
|
||||||
}
|
|
||||||
} else if (ba_it->second.type == SES_DELETE &&
|
|
||||||
bc_it->second.type == SES_ADD) {
|
|
||||||
// conflict
|
|
||||||
conflict = true;
|
|
||||||
return B;
|
|
||||||
} else if (ba_it->second.type == SES_ADD &&
|
|
||||||
bc_it->second.type == SES_COMMON) {
|
|
||||||
seq.push_back(ba_it->first);
|
|
||||||
forwardUntilEnd(ba_end, ba_it);
|
|
||||||
} else if (ba_it->second.type == SES_ADD &&
|
|
||||||
bc_it->second.type == SES_DELETE) {
|
|
||||||
// conflict
|
|
||||||
conflict = true;
|
|
||||||
return B;
|
|
||||||
} else if (ba_it->second.type == SES_ADD &&
|
|
||||||
bc_it->second.type == SES_ADD) {
|
|
||||||
if (ba_it->first == bc_it->first) {
|
|
||||||
seq.push_back(ba_it->first);
|
|
||||||
forwardUntilEnd(ba_end, ba_it);
|
|
||||||
forwardUntilEnd(bc_end, bc_it);
|
|
||||||
} else {
|
|
||||||
// conflict
|
|
||||||
conflict = true;
|
|
||||||
return B;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isEnd(ba_end, ba_it)) {
|
|
||||||
addDecentSequence(bc_end, bc_it, seq);
|
|
||||||
} else if (isEnd(bc_end, bc_it)) {
|
|
||||||
addDecentSequence(ba_end, ba_it, seq);
|
|
||||||
}
|
|
||||||
|
|
||||||
sequence mergedSeq(seq.begin(), seq.end());
|
|
||||||
return mergedSeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* join elem vectors
|
|
||||||
*/
|
|
||||||
void inline joinElemVec (elemVec& s1, elemVec& s2) const {
|
|
||||||
if (!s2.empty()) {
|
|
||||||
for (elemVec_iter vit=s2.begin();vit!=s2.end();++vit) {
|
|
||||||
s1.push_back(*vit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check if sequence is at end
|
|
||||||
*/
|
|
||||||
template <typename T_iter>
|
|
||||||
bool inline isEnd (const T_iter& end, const T_iter& it) const {
|
|
||||||
return it == end ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* increment iterator until iterator is at end
|
|
||||||
*/
|
|
||||||
template <typename T_iter>
|
|
||||||
void inline forwardUntilEnd (const T_iter& end, T_iter& it) const {
|
|
||||||
if (!isEnd(end, it)) ++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add elements whose SES's type is ADD
|
|
||||||
*/
|
|
||||||
void inline addDecentSequence (const sesElemVec_iter& end, sesElemVec_iter& it, elemVec& seq) const {
|
|
||||||
while (!isEnd(end, it)) {
|
|
||||||
if (it->second.type == SES_ADD) seq.push_back(it->first);
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DTL_DIFF3_H
|
|
55
dtl/Lcs.hpp
@ -1,55 +0,0 @@
|
|||||||
/**
|
|
||||||
dtl -- Diff Template Library
|
|
||||||
|
|
||||||
In short, Diff Template Library is distributed under so called "BSD license",
|
|
||||||
|
|
||||||
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the authors nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* If you use this library, you must include dtl.hpp only. */
|
|
||||||
|
|
||||||
#ifndef DTL_LCS_H
|
|
||||||
#define DTL_LCS_H
|
|
||||||
|
|
||||||
namespace dtl {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Longest Common Subsequence template class
|
|
||||||
*/
|
|
||||||
template <typename elem>
|
|
||||||
class Lcs : public Sequence< elem >
|
|
||||||
{
|
|
||||||
public :
|
|
||||||
Lcs () {}
|
|
||||||
~Lcs () {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DTL_LCS_H
|
|
@ -1,65 +0,0 @@
|
|||||||
/**
|
|
||||||
dtl -- Diff Template Library
|
|
||||||
|
|
||||||
In short, Diff Template Library is distributed under so called "BSD license",
|
|
||||||
|
|
||||||
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the authors nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* If you use this library, you must include dtl.hpp only. */
|
|
||||||
|
|
||||||
#ifndef DTL_SEQUENCE_H
|
|
||||||
#define DTL_SEQUENCE_H
|
|
||||||
|
|
||||||
namespace dtl {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sequence class template
|
|
||||||
*/
|
|
||||||
template <typename elem>
|
|
||||||
class Sequence
|
|
||||||
{
|
|
||||||
public :
|
|
||||||
typedef vector< elem > elemVec;
|
|
||||||
Sequence () {}
|
|
||||||
virtual ~Sequence () {}
|
|
||||||
|
|
||||||
elemVec getSequence () const {
|
|
||||||
return sequence;
|
|
||||||
}
|
|
||||||
void addSequence (elem e) {
|
|
||||||
sequence.push_back(e);
|
|
||||||
}
|
|
||||||
protected :
|
|
||||||
elemVec sequence;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DTL_SEQUENCE_H
|
|
132
dtl/Ses.hpp
@ -1,132 +0,0 @@
|
|||||||
/**
|
|
||||||
dtl -- Diff Template Library
|
|
||||||
|
|
||||||
In short, Diff Template Library is distributed under so called "BSD license",
|
|
||||||
|
|
||||||
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the authors nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* If you use this library, you must include dtl.hpp only. */
|
|
||||||
|
|
||||||
#ifndef DTL_SES_H
|
|
||||||
#define DTL_SES_H
|
|
||||||
|
|
||||||
namespace dtl {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortest Edit Script template class
|
|
||||||
*/
|
|
||||||
template <typename elem>
|
|
||||||
class Ses : public Sequence< elem >
|
|
||||||
{
|
|
||||||
private :
|
|
||||||
typedef pair< elem, elemInfo > sesElem;
|
|
||||||
typedef vector< sesElem > sesElemVec;
|
|
||||||
public :
|
|
||||||
|
|
||||||
Ses () : onlyAdd(true), onlyDelete(true), onlyCopy(true), deletesFirst(false) {
|
|
||||||
nextDeleteIdx = 0;
|
|
||||||
}
|
|
||||||
Ses (bool moveDel) : onlyAdd(true), onlyDelete(true), onlyCopy(true), deletesFirst(moveDel) {
|
|
||||||
nextDeleteIdx = 0;
|
|
||||||
}
|
|
||||||
~Ses () {}
|
|
||||||
|
|
||||||
bool isOnlyAdd () const {
|
|
||||||
return onlyAdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOnlyDelete () const {
|
|
||||||
return onlyDelete;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOnlyCopy () const {
|
|
||||||
return onlyCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOnlyOneOperation () const {
|
|
||||||
return isOnlyAdd() || isOnlyDelete() || isOnlyCopy();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isChange () const {
|
|
||||||
return !onlyCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
using Sequence< elem >::addSequence;
|
|
||||||
void addSequence (elem e, long long beforeIdx, long long afterIdx, const edit_t type) {
|
|
||||||
elemInfo info;
|
|
||||||
info.beforeIdx = beforeIdx;
|
|
||||||
info.afterIdx = afterIdx;
|
|
||||||
info.type = type;
|
|
||||||
sesElem pe(e, info);
|
|
||||||
if (!deletesFirst) {
|
|
||||||
sequence.push_back(pe);
|
|
||||||
}
|
|
||||||
switch (type) {
|
|
||||||
case SES_DELETE:
|
|
||||||
onlyCopy = false;
|
|
||||||
onlyAdd = false;
|
|
||||||
if (deletesFirst) {
|
|
||||||
sequence.insert(sequence.begin() + nextDeleteIdx, pe);
|
|
||||||
nextDeleteIdx++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SES_COMMON:
|
|
||||||
onlyAdd = false;
|
|
||||||
onlyDelete = false;
|
|
||||||
if (deletesFirst) {
|
|
||||||
sequence.push_back(pe);
|
|
||||||
nextDeleteIdx = sequence.size();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SES_ADD:
|
|
||||||
onlyDelete = false;
|
|
||||||
onlyCopy = false;
|
|
||||||
if (deletesFirst) {
|
|
||||||
sequence.push_back(pe);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sesElemVec getSequence () const {
|
|
||||||
return sequence;
|
|
||||||
}
|
|
||||||
private :
|
|
||||||
sesElemVec sequence;
|
|
||||||
bool onlyAdd;
|
|
||||||
bool onlyDelete;
|
|
||||||
bool onlyCopy;
|
|
||||||
bool deletesFirst;
|
|
||||||
size_t nextDeleteIdx;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DTL_SES_H
|
|
47
dtl/dtl.hpp
@ -1,47 +0,0 @@
|
|||||||
/**
|
|
||||||
dtl -- Diff Template Library
|
|
||||||
|
|
||||||
In short, Diff Template Library is distributed under so called "BSD license",
|
|
||||||
|
|
||||||
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the authors nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DTL_H
|
|
||||||
#define DTL_H
|
|
||||||
|
|
||||||
#include "variables.hpp"
|
|
||||||
#include "functors.hpp"
|
|
||||||
#include "Sequence.hpp"
|
|
||||||
#include "Lcs.hpp"
|
|
||||||
#include "Ses.hpp"
|
|
||||||
#include "Diff.hpp"
|
|
||||||
#include "Diff3.hpp"
|
|
||||||
|
|
||||||
#endif // DTL_H
|
|