Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- third_party/tracy/.github/FUNDING.yml +1 -0
- third_party/tracy/.github/sponsor.png +0 -0
- third_party/tracy/.github/workflows/build.yml +78 -0
- third_party/tracy/.github/workflows/latex.yml +27 -0
- third_party/tracy/.github/workflows/linux.yml +75 -0
- third_party/tracy/cmake/CPM.cmake +1269 -0
- third_party/tracy/cmake/ECMFindModuleHelpers.cmake +300 -0
- third_party/tracy/cmake/FindWaylandScanner.cmake +170 -0
- third_party/tracy/cmake/config.cmake +56 -0
- third_party/tracy/cmake/server.cmake +39 -0
- third_party/tracy/cmake/vendor.cmake +238 -0
- third_party/tracy/cmake/version.cmake +24 -0
- third_party/tracy/csvexport/CMakeLists.txt +28 -0
- third_party/tracy/csvexport/src/csvexport.cpp +353 -0
- third_party/tracy/examples/OpenCLVectorAdd/CMakeLists.txt +17 -0
- third_party/tracy/examples/OpenCLVectorAdd/OpenCLVectorAdd.cpp +220 -0
- third_party/tracy/examples/ToyPathTracer/.gitignore +1 -0
- third_party/tracy/examples/ToyPathTracer/README +4 -0
- third_party/tracy/examples/ToyPathTracer/Source/Config.h +33 -0
- third_party/tracy/examples/ToyPathTracer/Source/MathSimd.h +192 -0
- third_party/tracy/examples/ToyPathTracer/Source/Maths.cpp +203 -0
- third_party/tracy/examples/ToyPathTracer/Source/Maths.h +436 -0
- third_party/tracy/examples/ToyPathTracer/Source/Test.cpp +392 -0
- third_party/tracy/examples/ToyPathTracer/Source/Test.h +17 -0
- third_party/tracy/examples/ToyPathTracer/Source/enkiTS/Atomics.h +79 -0
- third_party/tracy/examples/ToyPathTracer/Source/enkiTS/LockLessMultiReadPipe.h +240 -0
- third_party/tracy/examples/ToyPathTracer/Source/enkiTS/TaskScheduler.cpp +437 -0
- third_party/tracy/examples/ToyPathTracer/Source/enkiTS/TaskScheduler.h +177 -0
- third_party/tracy/examples/ToyPathTracer/Source/enkiTS/TaskScheduler_c.cpp +122 -0
- third_party/tracy/examples/ToyPathTracer/Source/enkiTS/TaskScheduler_c.h +104 -0
- third_party/tracy/examples/ToyPathTracer/Source/enkiTS/Threads.h +210 -0
- third_party/tracy/examples/ToyPathTracer/Windows/ComputeShader.hlsl +395 -0
- third_party/tracy/examples/ToyPathTracer/Windows/PixelShader.hlsl +15 -0
- third_party/tracy/examples/ToyPathTracer/Windows/TestCpu.sln +31 -0
- third_party/tracy/examples/ToyPathTracer/Windows/TestCpu.vcxproj +245 -0
- third_party/tracy/examples/ToyPathTracer/Windows/TestCpu.vcxproj.filters +67 -0
- third_party/tracy/examples/ToyPathTracer/Windows/TestWin.cpp +567 -0
- third_party/tracy/examples/ToyPathTracer/Windows/VertexShader.hlsl +13 -0
- third_party/tracy/examples/ToyPathTracer/license.md +24 -0
- third_party/tracy/examples/fibers.cpp +30 -0
- third_party/tracy/public/TracyClient.cpp +61 -0
- third_party/tracy/public/libbacktrace/alloc.cpp +174 -0
- third_party/tracy/public/libbacktrace/dwarf.cpp +0 -0
- third_party/tracy/public/libbacktrace/elf.cpp +0 -0
- third_party/tracy/public/libbacktrace/mmapio.cpp +115 -0
- third_party/tracy/public/libbacktrace/sort.cpp +113 -0
- third_party/tracy/public/libbacktrace/state.cpp +76 -0
- third_party/tracy/server/TracyCharUtil.hpp +76 -0
- third_party/tracy/server/TracyEvent.hpp +850 -0
- third_party/tracy/server/TracyFileHeader.hpp +22 -0
third_party/tracy/.github/FUNDING.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
github: wolfpld
|
third_party/tracy/.github/sponsor.png
ADDED
|
third_party/tracy/.github/workflows/build.yml
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: build
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches: [ master ]
|
| 6 |
+
pull_request:
|
| 7 |
+
branches: [ master ]
|
| 8 |
+
|
| 9 |
+
jobs:
|
| 10 |
+
build:
|
| 11 |
+
strategy:
|
| 12 |
+
matrix:
|
| 13 |
+
os: [ windows-latest, macos-latest ]
|
| 14 |
+
|
| 15 |
+
runs-on: ${{ matrix.os }}
|
| 16 |
+
continue-on-error: true
|
| 17 |
+
steps:
|
| 18 |
+
- uses: actions/checkout@v4
|
| 19 |
+
- if: startsWith(matrix.os, 'windows')
|
| 20 |
+
uses: microsoft/setup-msbuild@v2
|
| 21 |
+
- if: startsWith(matrix.os, 'windows')
|
| 22 |
+
uses: actions/setup-python@v2
|
| 23 |
+
with:
|
| 24 |
+
python-version: '3.x'
|
| 25 |
+
- if: startsWith(matrix.os, 'windows')
|
| 26 |
+
run: pip install meson ninja
|
| 27 |
+
- if: startsWith(matrix.os, 'macos')
|
| 28 |
+
name: Install macos dependencies
|
| 29 |
+
run: brew install pkg-config glfw meson
|
| 30 |
+
- name: Profiler GUI
|
| 31 |
+
run: |
|
| 32 |
+
cmake -B profiler/build -S profiler -DCMAKE_BUILD_TYPE=Release
|
| 33 |
+
cmake --build profiler/build --parallel --config Release
|
| 34 |
+
- name: Update utility
|
| 35 |
+
run: |
|
| 36 |
+
cmake -B update/build -S update -DCMAKE_BUILD_TYPE=Release
|
| 37 |
+
cmake --build update/build --parallel --config Release
|
| 38 |
+
- name: Capture utility
|
| 39 |
+
run: |
|
| 40 |
+
cmake -B capture/build -S capture -DCMAKE_BUILD_TYPE=Release
|
| 41 |
+
cmake --build capture/build --parallel --config Release
|
| 42 |
+
- name: Csvexport utility
|
| 43 |
+
run: |
|
| 44 |
+
cmake -B csvexport/build -S csvexport -DCMAKE_BUILD_TYPE=Release
|
| 45 |
+
cmake --build csvexport/build --parallel --config Release
|
| 46 |
+
- name: Import utilities
|
| 47 |
+
run: |
|
| 48 |
+
cmake -B import/build -S import -DCMAKE_BUILD_TYPE=Release
|
| 49 |
+
cmake --build import/build --parallel --config Release
|
| 50 |
+
- if: ${{ !startsWith(matrix.os, 'windows') }}
|
| 51 |
+
name: Library
|
| 52 |
+
run: meson setup -Dprefix=$GITHUB_WORKSPACE/bin/lib build && meson compile -C build && meson install -C build
|
| 53 |
+
- if: ${{ !startsWith(matrix.os, 'windows') }}
|
| 54 |
+
name: Find Artifacts
|
| 55 |
+
id: find_artifacts
|
| 56 |
+
run: |
|
| 57 |
+
mkdir -p bin
|
| 58 |
+
cp profiler/build/tracy-profiler bin
|
| 59 |
+
cp update/build/tracy-update bin
|
| 60 |
+
cp capture/build/tracy-capture bin
|
| 61 |
+
cp csvexport/build/tracy-csvexport bin
|
| 62 |
+
cp import/build/tracy-import-chrome bin
|
| 63 |
+
cp import/build/tracy-import-fuchsia bin
|
| 64 |
+
- if: startsWith(matrix.os, 'windows')
|
| 65 |
+
name: Find Artifacts
|
| 66 |
+
id: find_artifacts_windows
|
| 67 |
+
run: |
|
| 68 |
+
mkdir bin
|
| 69 |
+
copy profiler\build\Release\tracy-profiler.exe bin
|
| 70 |
+
copy update\build\Release\tracy-update.exe bin
|
| 71 |
+
copy capture\build\Release\tracy-capture.exe bin
|
| 72 |
+
copy csvexport\build\Release\tracy-csvexport.exe bin
|
| 73 |
+
copy import\build\Release\tracy-import-chrome.exe bin
|
| 74 |
+
copy import\build\Release\tracy-import-fuchsia.exe bin
|
| 75 |
+
- uses: actions/upload-artifact@v4
|
| 76 |
+
with:
|
| 77 |
+
name: ${{ matrix.os }}
|
| 78 |
+
path: bin
|
third_party/tracy/.github/workflows/latex.yml
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Manual
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches: [ master ]
|
| 6 |
+
pull_request:
|
| 7 |
+
branches: [ master ]
|
| 8 |
+
|
| 9 |
+
jobs:
|
| 10 |
+
build:
|
| 11 |
+
|
| 12 |
+
runs-on: ubuntu-latest
|
| 13 |
+
|
| 14 |
+
steps:
|
| 15 |
+
- uses: actions/checkout@v4
|
| 16 |
+
- name: Fix stupidity
|
| 17 |
+
run: |
|
| 18 |
+
cp LICENSE LICENSE.
|
| 19 |
+
- name: Compile LaTeX
|
| 20 |
+
uses: xu-cheng/latex-action@v3
|
| 21 |
+
with:
|
| 22 |
+
working_directory: manual
|
| 23 |
+
root_file: tracy.tex
|
| 24 |
+
- uses: actions/upload-artifact@v4
|
| 25 |
+
with:
|
| 26 |
+
name: manual
|
| 27 |
+
path: manual/tracy.pdf
|
third_party/tracy/.github/workflows/linux.yml
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: linux
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches: [ master ]
|
| 6 |
+
pull_request:
|
| 7 |
+
branches: [ master ]
|
| 8 |
+
|
| 9 |
+
jobs:
|
| 10 |
+
build:
|
| 11 |
+
runs-on: ubuntu-latest
|
| 12 |
+
container: archlinux:base-devel
|
| 13 |
+
steps:
|
| 14 |
+
- name: Install dependencies
|
| 15 |
+
run: pacman -Syu --noconfirm && pacman -S --noconfirm --needed freetype2 tbb debuginfod wayland dbus libxkbcommon libglvnd meson cmake git wayland-protocols nodejs
|
| 16 |
+
- uses: actions/checkout@v4
|
| 17 |
+
- name: Profiler GUI
|
| 18 |
+
run: |
|
| 19 |
+
cmake -B profiler/build -S profiler -DCMAKE_BUILD_TYPE=Release
|
| 20 |
+
cmake --build profiler/build --parallel
|
| 21 |
+
- name: Update utility
|
| 22 |
+
run: |
|
| 23 |
+
cmake -B update/build -S update -DCMAKE_BUILD_TYPE=Release
|
| 24 |
+
cmake --build update/build --parallel
|
| 25 |
+
- name: Capture utility
|
| 26 |
+
run: |
|
| 27 |
+
cmake -B capture/build -S capture -DCMAKE_BUILD_TYPE=Release
|
| 28 |
+
cmake --build capture/build --parallel
|
| 29 |
+
- name: Csvexport utility
|
| 30 |
+
run: |
|
| 31 |
+
cmake -B csvexport/build -S csvexport -DCMAKE_BUILD_TYPE=Release
|
| 32 |
+
cmake --build csvexport/build --parallel
|
| 33 |
+
- name: Import utilities
|
| 34 |
+
run: |
|
| 35 |
+
cmake -B import/build -S import -DCMAKE_BUILD_TYPE=Release
|
| 36 |
+
cmake --build import/build --parallel
|
| 37 |
+
- name: Library
|
| 38 |
+
run: meson setup -Dprefix=$GITHUB_WORKSPACE/bin/lib build && meson compile -C build && meson install -C build
|
| 39 |
+
- name: Test application
|
| 40 |
+
run: |
|
| 41 |
+
# test compilation with different flags
|
| 42 |
+
# we clean the build folder to reset cached variables between runs
|
| 43 |
+
cmake -B test/build -S test -DCMAKE_BUILD_TYPE=Release
|
| 44 |
+
cmake --build test/build --parallel
|
| 45 |
+
rm -rf test/build
|
| 46 |
+
|
| 47 |
+
# same with TRACY_ON_DEMAND
|
| 48 |
+
cmake -B test/build -S test -DCMAKE_BUILD_TYPE=Release -DTRACY_ON_DEMAND=ON .
|
| 49 |
+
cmake --build test/build --parallel
|
| 50 |
+
rm -rf test/build
|
| 51 |
+
|
| 52 |
+
# same with TRACY_DELAYED_INIT TRACY_MANUAL_LIFETIME
|
| 53 |
+
cmake -B test/build -S test -DCMAKE_BUILD_TYPE=Release -DTRACY_DELAYED_INIT=ON -DTRACY_MANUAL_LIFETIME=ON .
|
| 54 |
+
cmake --build test/build --parallel
|
| 55 |
+
rm -rf test/build
|
| 56 |
+
|
| 57 |
+
# same with TRACY_DEMANGLE
|
| 58 |
+
cmake -B test/build -S test -DCMAKE_BUILD_TYPE=Release -DTRACY_DEMANGLE=ON .
|
| 59 |
+
cmake --build test/build --parallel
|
| 60 |
+
rm -rf test/build
|
| 61 |
+
- name: Find Artifacts
|
| 62 |
+
id: find_artifacts
|
| 63 |
+
run: |
|
| 64 |
+
mkdir -p bin
|
| 65 |
+
cp profiler/build/tracy-profiler bin
|
| 66 |
+
cp update/build/tracy-update bin
|
| 67 |
+
cp capture/build/tracy-capture bin
|
| 68 |
+
cp csvexport/build/tracy-csvexport bin
|
| 69 |
+
cp import/build/tracy-import-chrome bin
|
| 70 |
+
cp import/build/tracy-import-fuchsia bin
|
| 71 |
+
strip bin/tracy-*
|
| 72 |
+
- uses: actions/upload-artifact@v4
|
| 73 |
+
with:
|
| 74 |
+
name: arch-linux
|
| 75 |
+
path: bin
|
third_party/tracy/cmake/CPM.cmake
ADDED
|
@@ -0,0 +1,1269 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CPM.cmake - CMake's missing package manager
|
| 2 |
+
# ===========================================
|
| 3 |
+
# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions.
|
| 4 |
+
#
|
| 5 |
+
# MIT License
|
| 6 |
+
# -----------
|
| 7 |
+
#[[
|
| 8 |
+
Copyright (c) 2019-2023 Lars Melchior and contributors
|
| 9 |
+
|
| 10 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 11 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 12 |
+
in the Software without restriction, including without limitation the rights
|
| 13 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 14 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 15 |
+
furnished to do so, subject to the following conditions:
|
| 16 |
+
|
| 17 |
+
The above copyright notice and this permission notice shall be included in all
|
| 18 |
+
copies or substantial portions of the Software.
|
| 19 |
+
|
| 20 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 21 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 22 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 23 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 24 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 25 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 26 |
+
SOFTWARE.
|
| 27 |
+
]]
|
| 28 |
+
|
| 29 |
+
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
|
| 30 |
+
|
| 31 |
+
# Initialize logging prefix
|
| 32 |
+
if(NOT CPM_INDENT)
|
| 33 |
+
set(CPM_INDENT
|
| 34 |
+
"CPM:"
|
| 35 |
+
CACHE INTERNAL ""
|
| 36 |
+
)
|
| 37 |
+
endif()
|
| 38 |
+
|
| 39 |
+
if(NOT COMMAND cpm_message)
|
| 40 |
+
function(cpm_message)
|
| 41 |
+
message(${ARGV})
|
| 42 |
+
endfunction()
|
| 43 |
+
endif()
|
| 44 |
+
|
| 45 |
+
set(CURRENT_CPM_VERSION 0.40.2)
|
| 46 |
+
|
| 47 |
+
get_filename_component(CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" REALPATH)
|
| 48 |
+
if(CPM_DIRECTORY)
|
| 49 |
+
if(NOT CPM_DIRECTORY STREQUAL CPM_CURRENT_DIRECTORY)
|
| 50 |
+
if(CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION)
|
| 51 |
+
message(
|
| 52 |
+
AUTHOR_WARNING
|
| 53 |
+
"${CPM_INDENT} \
|
| 54 |
+
A dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \
|
| 55 |
+
It is recommended to upgrade CPM to the most recent version. \
|
| 56 |
+
See https://github.com/cpm-cmake/CPM.cmake for more information."
|
| 57 |
+
)
|
| 58 |
+
endif()
|
| 59 |
+
if(${CMAKE_VERSION} VERSION_LESS "3.17.0")
|
| 60 |
+
include(FetchContent)
|
| 61 |
+
endif()
|
| 62 |
+
return()
|
| 63 |
+
endif()
|
| 64 |
+
|
| 65 |
+
get_property(
|
| 66 |
+
CPM_INITIALIZED GLOBAL ""
|
| 67 |
+
PROPERTY CPM_INITIALIZED
|
| 68 |
+
SET
|
| 69 |
+
)
|
| 70 |
+
if(CPM_INITIALIZED)
|
| 71 |
+
return()
|
| 72 |
+
endif()
|
| 73 |
+
endif()
|
| 74 |
+
|
| 75 |
+
if(CURRENT_CPM_VERSION MATCHES "development-version")
|
| 76 |
+
message(
|
| 77 |
+
WARNING "${CPM_INDENT} Your project is using an unstable development version of CPM.cmake. \
|
| 78 |
+
Please update to a recent release if possible. \
|
| 79 |
+
See https://github.com/cpm-cmake/CPM.cmake for details."
|
| 80 |
+
)
|
| 81 |
+
endif()
|
| 82 |
+
|
| 83 |
+
set_property(GLOBAL PROPERTY CPM_INITIALIZED true)
|
| 84 |
+
|
| 85 |
+
macro(cpm_set_policies)
|
| 86 |
+
# the policy allows us to change options without caching
|
| 87 |
+
cmake_policy(SET CMP0077 NEW)
|
| 88 |
+
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
| 89 |
+
|
| 90 |
+
# the policy allows us to change set(CACHE) without caching
|
| 91 |
+
if(POLICY CMP0126)
|
| 92 |
+
cmake_policy(SET CMP0126 NEW)
|
| 93 |
+
set(CMAKE_POLICY_DEFAULT_CMP0126 NEW)
|
| 94 |
+
endif()
|
| 95 |
+
|
| 96 |
+
# The policy uses the download time for timestamp, instead of the timestamp in the archive. This
|
| 97 |
+
# allows for proper rebuilds when a projects url changes
|
| 98 |
+
if(POLICY CMP0135)
|
| 99 |
+
cmake_policy(SET CMP0135 NEW)
|
| 100 |
+
set(CMAKE_POLICY_DEFAULT_CMP0135 NEW)
|
| 101 |
+
endif()
|
| 102 |
+
|
| 103 |
+
# treat relative git repository paths as being relative to the parent project's remote
|
| 104 |
+
if(POLICY CMP0150)
|
| 105 |
+
cmake_policy(SET CMP0150 NEW)
|
| 106 |
+
set(CMAKE_POLICY_DEFAULT_CMP0150 NEW)
|
| 107 |
+
endif()
|
| 108 |
+
endmacro()
|
| 109 |
+
cpm_set_policies()
|
| 110 |
+
|
| 111 |
+
option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies"
|
| 112 |
+
$ENV{CPM_USE_LOCAL_PACKAGES}
|
| 113 |
+
)
|
| 114 |
+
option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies"
|
| 115 |
+
$ENV{CPM_LOCAL_PACKAGES_ONLY}
|
| 116 |
+
)
|
| 117 |
+
option(CPM_DOWNLOAD_ALL "Always download dependencies from source" $ENV{CPM_DOWNLOAD_ALL})
|
| 118 |
+
option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package"
|
| 119 |
+
$ENV{CPM_DONT_UPDATE_MODULE_PATH}
|
| 120 |
+
)
|
| 121 |
+
option(CPM_DONT_CREATE_PACKAGE_LOCK "Don't create a package lock file in the binary path"
|
| 122 |
+
$ENV{CPM_DONT_CREATE_PACKAGE_LOCK}
|
| 123 |
+
)
|
| 124 |
+
option(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK
|
| 125 |
+
"Add all packages added through CPM.cmake to the package lock"
|
| 126 |
+
$ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK}
|
| 127 |
+
)
|
| 128 |
+
option(CPM_USE_NAMED_CACHE_DIRECTORIES
|
| 129 |
+
"Use additional directory of package name in cache on the most nested level."
|
| 130 |
+
$ENV{CPM_USE_NAMED_CACHE_DIRECTORIES}
|
| 131 |
+
)
|
| 132 |
+
|
| 133 |
+
set(CPM_VERSION
|
| 134 |
+
${CURRENT_CPM_VERSION}
|
| 135 |
+
CACHE INTERNAL ""
|
| 136 |
+
)
|
| 137 |
+
set(CPM_DIRECTORY
|
| 138 |
+
${CPM_CURRENT_DIRECTORY}
|
| 139 |
+
CACHE INTERNAL ""
|
| 140 |
+
)
|
| 141 |
+
set(CPM_FILE
|
| 142 |
+
${CMAKE_CURRENT_LIST_FILE}
|
| 143 |
+
CACHE INTERNAL ""
|
| 144 |
+
)
|
| 145 |
+
set(CPM_PACKAGES
|
| 146 |
+
""
|
| 147 |
+
CACHE INTERNAL ""
|
| 148 |
+
)
|
| 149 |
+
set(CPM_DRY_RUN
|
| 150 |
+
OFF
|
| 151 |
+
CACHE INTERNAL "Don't download or configure dependencies (for testing)"
|
| 152 |
+
)
|
| 153 |
+
|
| 154 |
+
if(DEFINED ENV{CPM_SOURCE_CACHE})
|
| 155 |
+
set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE})
|
| 156 |
+
else()
|
| 157 |
+
set(CPM_SOURCE_CACHE_DEFAULT OFF)
|
| 158 |
+
endif()
|
| 159 |
+
|
| 160 |
+
set(CPM_SOURCE_CACHE
|
| 161 |
+
${CPM_SOURCE_CACHE_DEFAULT}
|
| 162 |
+
CACHE PATH "Directory to download CPM dependencies"
|
| 163 |
+
)
|
| 164 |
+
|
| 165 |
+
if(NOT CPM_DONT_UPDATE_MODULE_PATH)
|
| 166 |
+
set(CPM_MODULE_PATH
|
| 167 |
+
"${CMAKE_BINARY_DIR}/CPM_modules"
|
| 168 |
+
CACHE INTERNAL ""
|
| 169 |
+
)
|
| 170 |
+
# remove old modules
|
| 171 |
+
file(REMOVE_RECURSE ${CPM_MODULE_PATH})
|
| 172 |
+
file(MAKE_DIRECTORY ${CPM_MODULE_PATH})
|
| 173 |
+
# locally added CPM modules should override global packages
|
| 174 |
+
set(CMAKE_MODULE_PATH "${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}")
|
| 175 |
+
endif()
|
| 176 |
+
|
| 177 |
+
if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)
|
| 178 |
+
set(CPM_PACKAGE_LOCK_FILE
|
| 179 |
+
"${CMAKE_BINARY_DIR}/cpm-package-lock.cmake"
|
| 180 |
+
CACHE INTERNAL ""
|
| 181 |
+
)
|
| 182 |
+
file(WRITE ${CPM_PACKAGE_LOCK_FILE}
|
| 183 |
+
"# CPM Package Lock\n# This file should be committed to version control\n\n"
|
| 184 |
+
)
|
| 185 |
+
endif()
|
| 186 |
+
|
| 187 |
+
include(FetchContent)
|
| 188 |
+
|
| 189 |
+
# Try to infer package name from git repository uri (path or url)
|
| 190 |
+
function(cpm_package_name_from_git_uri URI RESULT)
|
| 191 |
+
if("${URI}" MATCHES "([^/:]+)/?.git/?$")
|
| 192 |
+
set(${RESULT}
|
| 193 |
+
${CMAKE_MATCH_1}
|
| 194 |
+
PARENT_SCOPE
|
| 195 |
+
)
|
| 196 |
+
else()
|
| 197 |
+
unset(${RESULT} PARENT_SCOPE)
|
| 198 |
+
endif()
|
| 199 |
+
endfunction()
|
| 200 |
+
|
| 201 |
+
# Try to infer package name and version from a url
|
| 202 |
+
function(cpm_package_name_and_ver_from_url url outName outVer)
|
| 203 |
+
if(url MATCHES "[/\\?]([a-zA-Z0-9_\\.-]+)\\.(tar|tar\\.gz|tar\\.bz2|zip|ZIP)(\\?|/|$)")
|
| 204 |
+
# We matched an archive
|
| 205 |
+
set(filename "${CMAKE_MATCH_1}")
|
| 206 |
+
|
| 207 |
+
if(filename MATCHES "([a-zA-Z0-9_\\.-]+)[_-]v?(([0-9]+\\.)*[0-9]+[a-zA-Z0-9]*)")
|
| 208 |
+
# We matched <name>-<version> (ie foo-1.2.3)
|
| 209 |
+
set(${outName}
|
| 210 |
+
"${CMAKE_MATCH_1}"
|
| 211 |
+
PARENT_SCOPE
|
| 212 |
+
)
|
| 213 |
+
set(${outVer}
|
| 214 |
+
"${CMAKE_MATCH_2}"
|
| 215 |
+
PARENT_SCOPE
|
| 216 |
+
)
|
| 217 |
+
elseif(filename MATCHES "(([0-9]+\\.)+[0-9]+[a-zA-Z0-9]*)")
|
| 218 |
+
# We couldn't find a name, but we found a version
|
| 219 |
+
#
|
| 220 |
+
# In many cases (which we don't handle here) the url would look something like
|
| 221 |
+
# `irrelevant/ACTUAL_PACKAGE_NAME/irrelevant/1.2.3.zip`. In such a case we can't possibly
|
| 222 |
+
# distinguish the package name from the irrelevant bits. Moreover if we try to match the
|
| 223 |
+
# package name from the filename, we'd get bogus at best.
|
| 224 |
+
unset(${outName} PARENT_SCOPE)
|
| 225 |
+
set(${outVer}
|
| 226 |
+
"${CMAKE_MATCH_1}"
|
| 227 |
+
PARENT_SCOPE
|
| 228 |
+
)
|
| 229 |
+
else()
|
| 230 |
+
# Boldly assume that the file name is the package name.
|
| 231 |
+
#
|
| 232 |
+
# Yes, something like `irrelevant/ACTUAL_NAME/irrelevant/download.zip` will ruin our day, but
|
| 233 |
+
# such cases should be quite rare. No popular service does this... we think.
|
| 234 |
+
set(${outName}
|
| 235 |
+
"${filename}"
|
| 236 |
+
PARENT_SCOPE
|
| 237 |
+
)
|
| 238 |
+
unset(${outVer} PARENT_SCOPE)
|
| 239 |
+
endif()
|
| 240 |
+
else()
|
| 241 |
+
# No ideas yet what to do with non-archives
|
| 242 |
+
unset(${outName} PARENT_SCOPE)
|
| 243 |
+
unset(${outVer} PARENT_SCOPE)
|
| 244 |
+
endif()
|
| 245 |
+
endfunction()
|
| 246 |
+
|
| 247 |
+
function(cpm_find_package NAME VERSION)
|
| 248 |
+
string(REPLACE " " ";" EXTRA_ARGS "${ARGN}")
|
| 249 |
+
find_package(${NAME} ${VERSION} ${EXTRA_ARGS} QUIET)
|
| 250 |
+
if(${CPM_ARGS_NAME}_FOUND)
|
| 251 |
+
if(DEFINED ${CPM_ARGS_NAME}_VERSION)
|
| 252 |
+
set(VERSION ${${CPM_ARGS_NAME}_VERSION})
|
| 253 |
+
endif()
|
| 254 |
+
cpm_message(STATUS "${CPM_INDENT} Using local package ${CPM_ARGS_NAME}@${VERSION}")
|
| 255 |
+
CPMRegisterPackage(${CPM_ARGS_NAME} "${VERSION}")
|
| 256 |
+
set(CPM_PACKAGE_FOUND
|
| 257 |
+
YES
|
| 258 |
+
PARENT_SCOPE
|
| 259 |
+
)
|
| 260 |
+
else()
|
| 261 |
+
set(CPM_PACKAGE_FOUND
|
| 262 |
+
NO
|
| 263 |
+
PARENT_SCOPE
|
| 264 |
+
)
|
| 265 |
+
endif()
|
| 266 |
+
endfunction()
|
| 267 |
+
|
| 268 |
+
# Create a custom FindXXX.cmake module for a CPM package This prevents `find_package(NAME)` from
|
| 269 |
+
# finding the system library
|
| 270 |
+
function(cpm_create_module_file Name)
|
| 271 |
+
if(NOT CPM_DONT_UPDATE_MODULE_PATH)
|
| 272 |
+
# erase any previous modules
|
| 273 |
+
file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake
|
| 274 |
+
"include(\"${CPM_FILE}\")\n${ARGN}\nset(${Name}_FOUND TRUE)"
|
| 275 |
+
)
|
| 276 |
+
endif()
|
| 277 |
+
endfunction()
|
| 278 |
+
|
| 279 |
+
# Find a package locally or fallback to CPMAddPackage
|
| 280 |
+
function(CPMFindPackage)
|
| 281 |
+
set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS)
|
| 282 |
+
|
| 283 |
+
cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN})
|
| 284 |
+
|
| 285 |
+
if(NOT DEFINED CPM_ARGS_VERSION)
|
| 286 |
+
if(DEFINED CPM_ARGS_GIT_TAG)
|
| 287 |
+
cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION)
|
| 288 |
+
endif()
|
| 289 |
+
endif()
|
| 290 |
+
|
| 291 |
+
set(downloadPackage ${CPM_DOWNLOAD_ALL})
|
| 292 |
+
if(DEFINED CPM_DOWNLOAD_${CPM_ARGS_NAME})
|
| 293 |
+
set(downloadPackage ${CPM_DOWNLOAD_${CPM_ARGS_NAME}})
|
| 294 |
+
elseif(DEFINED ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}})
|
| 295 |
+
set(downloadPackage $ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}})
|
| 296 |
+
endif()
|
| 297 |
+
if(downloadPackage)
|
| 298 |
+
CPMAddPackage(${ARGN})
|
| 299 |
+
cpm_export_variables(${CPM_ARGS_NAME})
|
| 300 |
+
return()
|
| 301 |
+
endif()
|
| 302 |
+
|
| 303 |
+
cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})
|
| 304 |
+
|
| 305 |
+
if(NOT CPM_PACKAGE_FOUND)
|
| 306 |
+
CPMAddPackage(${ARGN})
|
| 307 |
+
cpm_export_variables(${CPM_ARGS_NAME})
|
| 308 |
+
endif()
|
| 309 |
+
|
| 310 |
+
endfunction()
|
| 311 |
+
|
| 312 |
+
# checks if a package has been added before
|
| 313 |
+
function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION)
|
| 314 |
+
if("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES)
|
| 315 |
+
CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION)
|
| 316 |
+
if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}")
|
| 317 |
+
message(
|
| 318 |
+
WARNING
|
| 319 |
+
"${CPM_INDENT} Requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION})."
|
| 320 |
+
)
|
| 321 |
+
endif()
|
| 322 |
+
cpm_get_fetch_properties(${CPM_ARGS_NAME})
|
| 323 |
+
set(${CPM_ARGS_NAME}_ADDED NO)
|
| 324 |
+
set(CPM_PACKAGE_ALREADY_ADDED
|
| 325 |
+
YES
|
| 326 |
+
PARENT_SCOPE
|
| 327 |
+
)
|
| 328 |
+
cpm_export_variables(${CPM_ARGS_NAME})
|
| 329 |
+
else()
|
| 330 |
+
set(CPM_PACKAGE_ALREADY_ADDED
|
| 331 |
+
NO
|
| 332 |
+
PARENT_SCOPE
|
| 333 |
+
)
|
| 334 |
+
endif()
|
| 335 |
+
endfunction()
|
| 336 |
+
|
| 337 |
+
# Parse the argument of CPMAddPackage in case a single one was provided and convert it to a list of
|
| 338 |
+
# arguments which can then be parsed idiomatically. For example gh:foo/bar@1.2.3 will be converted
|
| 339 |
+
# to: GITHUB_REPOSITORY;foo/bar;VERSION;1.2.3
|
| 340 |
+
function(cpm_parse_add_package_single_arg arg outArgs)
|
| 341 |
+
# Look for a scheme
|
| 342 |
+
if("${arg}" MATCHES "^([a-zA-Z]+):(.+)$")
|
| 343 |
+
string(TOLOWER "${CMAKE_MATCH_1}" scheme)
|
| 344 |
+
set(uri "${CMAKE_MATCH_2}")
|
| 345 |
+
|
| 346 |
+
# Check for CPM-specific schemes
|
| 347 |
+
if(scheme STREQUAL "gh")
|
| 348 |
+
set(out "GITHUB_REPOSITORY;${uri}")
|
| 349 |
+
set(packageType "git")
|
| 350 |
+
elseif(scheme STREQUAL "gl")
|
| 351 |
+
set(out "GITLAB_REPOSITORY;${uri}")
|
| 352 |
+
set(packageType "git")
|
| 353 |
+
elseif(scheme STREQUAL "bb")
|
| 354 |
+
set(out "BITBUCKET_REPOSITORY;${uri}")
|
| 355 |
+
set(packageType "git")
|
| 356 |
+
# A CPM-specific scheme was not found. Looks like this is a generic URL so try to determine
|
| 357 |
+
# type
|
| 358 |
+
elseif(arg MATCHES ".git/?(@|#|$)")
|
| 359 |
+
set(out "GIT_REPOSITORY;${arg}")
|
| 360 |
+
set(packageType "git")
|
| 361 |
+
else()
|
| 362 |
+
# Fall back to a URL
|
| 363 |
+
set(out "URL;${arg}")
|
| 364 |
+
set(packageType "archive")
|
| 365 |
+
|
| 366 |
+
# We could also check for SVN since FetchContent supports it, but SVN is so rare these days.
|
| 367 |
+
# We just won't bother with the additional complexity it will induce in this function. SVN is
|
| 368 |
+
# done by multi-arg
|
| 369 |
+
endif()
|
| 370 |
+
else()
|
| 371 |
+
if(arg MATCHES ".git/?(@|#|$)")
|
| 372 |
+
set(out "GIT_REPOSITORY;${arg}")
|
| 373 |
+
set(packageType "git")
|
| 374 |
+
else()
|
| 375 |
+
# Give up
|
| 376 |
+
message(FATAL_ERROR "${CPM_INDENT} Can't determine package type of '${arg}'")
|
| 377 |
+
endif()
|
| 378 |
+
endif()
|
| 379 |
+
|
| 380 |
+
# For all packages we interpret @... as version. Only replace the last occurrence. Thus URIs
|
| 381 |
+
# containing '@' can be used
|
| 382 |
+
string(REGEX REPLACE "@([^@]+)$" ";VERSION;\\1" out "${out}")
|
| 383 |
+
|
| 384 |
+
# Parse the rest according to package type
|
| 385 |
+
if(packageType STREQUAL "git")
|
| 386 |
+
# For git repos we interpret #... as a tag or branch or commit hash
|
| 387 |
+
string(REGEX REPLACE "#([^#]+)$" ";GIT_TAG;\\1" out "${out}")
|
| 388 |
+
elseif(packageType STREQUAL "archive")
|
| 389 |
+
# For archives we interpret #... as a URL hash.
|
| 390 |
+
string(REGEX REPLACE "#([^#]+)$" ";URL_HASH;\\1" out "${out}")
|
| 391 |
+
# We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url
|
| 392 |
+
# should do this at a later point
|
| 393 |
+
else()
|
| 394 |
+
# We should never get here. This is an assertion and hitting it means there's a problem with the
|
| 395 |
+
# code above. A packageType was set, but not handled by this if-else.
|
| 396 |
+
message(FATAL_ERROR "${CPM_INDENT} Unsupported package type '${packageType}' of '${arg}'")
|
| 397 |
+
endif()
|
| 398 |
+
|
| 399 |
+
set(${outArgs}
|
| 400 |
+
${out}
|
| 401 |
+
PARENT_SCOPE
|
| 402 |
+
)
|
| 403 |
+
endfunction()
|
| 404 |
+
|
| 405 |
+
# Check that the working directory for a git repo is clean
|
| 406 |
+
function(cpm_check_git_working_dir_is_clean repoPath gitTag isClean)
|
| 407 |
+
|
| 408 |
+
find_package(Git REQUIRED)
|
| 409 |
+
|
| 410 |
+
if(NOT GIT_EXECUTABLE)
|
| 411 |
+
# No git executable, assume directory is clean
|
| 412 |
+
set(${isClean}
|
| 413 |
+
TRUE
|
| 414 |
+
PARENT_SCOPE
|
| 415 |
+
)
|
| 416 |
+
return()
|
| 417 |
+
endif()
|
| 418 |
+
|
| 419 |
+
# check for uncommitted changes
|
| 420 |
+
execute_process(
|
| 421 |
+
COMMAND ${GIT_EXECUTABLE} status --porcelain
|
| 422 |
+
RESULT_VARIABLE resultGitStatus
|
| 423 |
+
OUTPUT_VARIABLE repoStatus
|
| 424 |
+
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET
|
| 425 |
+
WORKING_DIRECTORY ${repoPath}
|
| 426 |
+
)
|
| 427 |
+
if(resultGitStatus)
|
| 428 |
+
# not supposed to happen, assume clean anyway
|
| 429 |
+
message(WARNING "${CPM_INDENT} Calling git status on folder ${repoPath} failed")
|
| 430 |
+
set(${isClean}
|
| 431 |
+
TRUE
|
| 432 |
+
PARENT_SCOPE
|
| 433 |
+
)
|
| 434 |
+
return()
|
| 435 |
+
endif()
|
| 436 |
+
|
| 437 |
+
if(NOT "${repoStatus}" STREQUAL "")
|
| 438 |
+
set(${isClean}
|
| 439 |
+
FALSE
|
| 440 |
+
PARENT_SCOPE
|
| 441 |
+
)
|
| 442 |
+
return()
|
| 443 |
+
endif()
|
| 444 |
+
|
| 445 |
+
# check for committed changes
|
| 446 |
+
execute_process(
|
| 447 |
+
COMMAND ${GIT_EXECUTABLE} diff -s --exit-code ${gitTag}
|
| 448 |
+
RESULT_VARIABLE resultGitDiff
|
| 449 |
+
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_QUIET
|
| 450 |
+
WORKING_DIRECTORY ${repoPath}
|
| 451 |
+
)
|
| 452 |
+
|
| 453 |
+
if(${resultGitDiff} EQUAL 0)
|
| 454 |
+
set(${isClean}
|
| 455 |
+
TRUE
|
| 456 |
+
PARENT_SCOPE
|
| 457 |
+
)
|
| 458 |
+
else()
|
| 459 |
+
set(${isClean}
|
| 460 |
+
FALSE
|
| 461 |
+
PARENT_SCOPE
|
| 462 |
+
)
|
| 463 |
+
endif()
|
| 464 |
+
|
| 465 |
+
endfunction()
|
| 466 |
+
|
| 467 |
+
# Add PATCH_COMMAND to CPM_ARGS_UNPARSED_ARGUMENTS. This method consumes a list of files in ARGN
|
| 468 |
+
# then generates a `PATCH_COMMAND` appropriate for `ExternalProject_Add()`. This command is appended
|
| 469 |
+
# to the parent scope's `CPM_ARGS_UNPARSED_ARGUMENTS`.
|
| 470 |
+
function(cpm_add_patches)
|
| 471 |
+
# Return if no patch files are supplied.
|
| 472 |
+
if(NOT ARGN)
|
| 473 |
+
return()
|
| 474 |
+
endif()
|
| 475 |
+
|
| 476 |
+
# Find the patch program.
|
| 477 |
+
find_program(PATCH_EXECUTABLE patch)
|
| 478 |
+
if(WIN32 AND NOT PATCH_EXECUTABLE)
|
| 479 |
+
# The Windows git executable is distributed with patch.exe. Find the path to the executable, if
|
| 480 |
+
# it exists, then search `../usr/bin` and `../../usr/bin` for patch.exe.
|
| 481 |
+
find_package(Git QUIET)
|
| 482 |
+
if(GIT_EXECUTABLE)
|
| 483 |
+
get_filename_component(extra_search_path ${GIT_EXECUTABLE} DIRECTORY)
|
| 484 |
+
get_filename_component(extra_search_path_1up ${extra_search_path} DIRECTORY)
|
| 485 |
+
get_filename_component(extra_search_path_2up ${extra_search_path_1up} DIRECTORY)
|
| 486 |
+
find_program(
|
| 487 |
+
PATCH_EXECUTABLE patch HINTS "${extra_search_path_1up}/usr/bin"
|
| 488 |
+
"${extra_search_path_2up}/usr/bin"
|
| 489 |
+
)
|
| 490 |
+
endif()
|
| 491 |
+
endif()
|
| 492 |
+
if(NOT PATCH_EXECUTABLE)
|
| 493 |
+
message(FATAL_ERROR "Couldn't find `patch` executable to use with PATCHES keyword.")
|
| 494 |
+
endif()
|
| 495 |
+
|
| 496 |
+
# Create a temporary
|
| 497 |
+
set(temp_list ${CPM_ARGS_UNPARSED_ARGUMENTS})
|
| 498 |
+
|
| 499 |
+
# Ensure each file exists (or error out) and add it to the list.
|
| 500 |
+
set(first_item True)
|
| 501 |
+
foreach(PATCH_FILE ${ARGN})
|
| 502 |
+
# Make sure the patch file exists, if we can't find it, try again in the current directory.
|
| 503 |
+
if(NOT EXISTS "${PATCH_FILE}")
|
| 504 |
+
if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}")
|
| 505 |
+
message(FATAL_ERROR "Couldn't find patch file: '${PATCH_FILE}'")
|
| 506 |
+
endif()
|
| 507 |
+
set(PATCH_FILE "${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}")
|
| 508 |
+
endif()
|
| 509 |
+
|
| 510 |
+
# Convert to absolute path for use with patch file command.
|
| 511 |
+
get_filename_component(PATCH_FILE "${PATCH_FILE}" ABSOLUTE)
|
| 512 |
+
|
| 513 |
+
# The first patch entry must be preceded by "PATCH_COMMAND" while the following items are
|
| 514 |
+
# preceded by "&&".
|
| 515 |
+
if(first_item)
|
| 516 |
+
set(first_item False)
|
| 517 |
+
list(APPEND temp_list "PATCH_COMMAND")
|
| 518 |
+
else()
|
| 519 |
+
list(APPEND temp_list "&&")
|
| 520 |
+
endif()
|
| 521 |
+
# Add the patch command to the list
|
| 522 |
+
list(APPEND temp_list "${PATCH_EXECUTABLE}" "-p1" "<" "${PATCH_FILE}")
|
| 523 |
+
endforeach()
|
| 524 |
+
|
| 525 |
+
# Move temp out into parent scope.
|
| 526 |
+
set(CPM_ARGS_UNPARSED_ARGUMENTS
|
| 527 |
+
${temp_list}
|
| 528 |
+
PARENT_SCOPE
|
| 529 |
+
)
|
| 530 |
+
|
| 531 |
+
endfunction()
|
| 532 |
+
|
| 533 |
+
# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload
|
| 534 |
+
# FetchContent calls. As these are internal cmake properties, this method should be used carefully
|
| 535 |
+
# and may need modification in future CMake versions. Source:
|
| 536 |
+
# https://github.com/Kitware/CMake/blob/dc3d0b5a0a7d26d43d6cfeb511e224533b5d188f/Modules/FetchContent.cmake#L1152
|
| 537 |
+
function(cpm_override_fetchcontent contentName)
|
| 538 |
+
cmake_parse_arguments(PARSE_ARGV 1 arg "" "SOURCE_DIR;BINARY_DIR" "")
|
| 539 |
+
if(NOT "${arg_UNPARSED_ARGUMENTS}" STREQUAL "")
|
| 540 |
+
message(FATAL_ERROR "${CPM_INDENT} Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}")
|
| 541 |
+
endif()
|
| 542 |
+
|
| 543 |
+
string(TOLOWER ${contentName} contentNameLower)
|
| 544 |
+
set(prefix "_FetchContent_${contentNameLower}")
|
| 545 |
+
|
| 546 |
+
set(propertyName "${prefix}_sourceDir")
|
| 547 |
+
define_property(
|
| 548 |
+
GLOBAL
|
| 549 |
+
PROPERTY ${propertyName}
|
| 550 |
+
BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
|
| 551 |
+
FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
|
| 552 |
+
)
|
| 553 |
+
set_property(GLOBAL PROPERTY ${propertyName} "${arg_SOURCE_DIR}")
|
| 554 |
+
|
| 555 |
+
set(propertyName "${prefix}_binaryDir")
|
| 556 |
+
define_property(
|
| 557 |
+
GLOBAL
|
| 558 |
+
PROPERTY ${propertyName}
|
| 559 |
+
BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
|
| 560 |
+
FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
|
| 561 |
+
)
|
| 562 |
+
set_property(GLOBAL PROPERTY ${propertyName} "${arg_BINARY_DIR}")
|
| 563 |
+
|
| 564 |
+
set(propertyName "${prefix}_populated")
|
| 565 |
+
define_property(
|
| 566 |
+
GLOBAL
|
| 567 |
+
PROPERTY ${propertyName}
|
| 568 |
+
BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
|
| 569 |
+
FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
|
| 570 |
+
)
|
| 571 |
+
set_property(GLOBAL PROPERTY ${propertyName} TRUE)
|
| 572 |
+
endfunction()
|
| 573 |
+
|
| 574 |
+
# Download and add a package from source
|
| 575 |
+
function(CPMAddPackage)
|
| 576 |
+
cpm_set_policies()
|
| 577 |
+
|
| 578 |
+
list(LENGTH ARGN argnLength)
|
| 579 |
+
if(argnLength EQUAL 1)
|
| 580 |
+
cpm_parse_add_package_single_arg("${ARGN}" ARGN)
|
| 581 |
+
|
| 582 |
+
# The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM
|
| 583 |
+
set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;")
|
| 584 |
+
endif()
|
| 585 |
+
|
| 586 |
+
set(oneValueArgs
|
| 587 |
+
NAME
|
| 588 |
+
FORCE
|
| 589 |
+
VERSION
|
| 590 |
+
GIT_TAG
|
| 591 |
+
DOWNLOAD_ONLY
|
| 592 |
+
GITHUB_REPOSITORY
|
| 593 |
+
GITLAB_REPOSITORY
|
| 594 |
+
BITBUCKET_REPOSITORY
|
| 595 |
+
GIT_REPOSITORY
|
| 596 |
+
SOURCE_DIR
|
| 597 |
+
FIND_PACKAGE_ARGUMENTS
|
| 598 |
+
NO_CACHE
|
| 599 |
+
SYSTEM
|
| 600 |
+
GIT_SHALLOW
|
| 601 |
+
EXCLUDE_FROM_ALL
|
| 602 |
+
SOURCE_SUBDIR
|
| 603 |
+
CUSTOM_CACHE_KEY
|
| 604 |
+
)
|
| 605 |
+
|
| 606 |
+
set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES)
|
| 607 |
+
|
| 608 |
+
cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}")
|
| 609 |
+
|
| 610 |
+
# Set default values for arguments
|
| 611 |
+
|
| 612 |
+
if(NOT DEFINED CPM_ARGS_VERSION)
|
| 613 |
+
if(DEFINED CPM_ARGS_GIT_TAG)
|
| 614 |
+
cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION)
|
| 615 |
+
endif()
|
| 616 |
+
endif()
|
| 617 |
+
|
| 618 |
+
if(CPM_ARGS_DOWNLOAD_ONLY)
|
| 619 |
+
set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY})
|
| 620 |
+
else()
|
| 621 |
+
set(DOWNLOAD_ONLY NO)
|
| 622 |
+
endif()
|
| 623 |
+
|
| 624 |
+
if(DEFINED CPM_ARGS_GITHUB_REPOSITORY)
|
| 625 |
+
set(CPM_ARGS_GIT_REPOSITORY "https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git")
|
| 626 |
+
elseif(DEFINED CPM_ARGS_GITLAB_REPOSITORY)
|
| 627 |
+
set(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git")
|
| 628 |
+
elseif(DEFINED CPM_ARGS_BITBUCKET_REPOSITORY)
|
| 629 |
+
set(CPM_ARGS_GIT_REPOSITORY "https://bitbucket.org/${CPM_ARGS_BITBUCKET_REPOSITORY}.git")
|
| 630 |
+
endif()
|
| 631 |
+
|
| 632 |
+
if(DEFINED CPM_ARGS_GIT_REPOSITORY)
|
| 633 |
+
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY})
|
| 634 |
+
if(NOT DEFINED CPM_ARGS_GIT_TAG)
|
| 635 |
+
set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION})
|
| 636 |
+
endif()
|
| 637 |
+
|
| 638 |
+
# If a name wasn't provided, try to infer it from the git repo
|
| 639 |
+
if(NOT DEFINED CPM_ARGS_NAME)
|
| 640 |
+
cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME)
|
| 641 |
+
endif()
|
| 642 |
+
endif()
|
| 643 |
+
|
| 644 |
+
set(CPM_SKIP_FETCH FALSE)
|
| 645 |
+
|
| 646 |
+
if(DEFINED CPM_ARGS_GIT_TAG)
|
| 647 |
+
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG})
|
| 648 |
+
# If GIT_SHALLOW is explicitly specified, honor the value.
|
| 649 |
+
if(DEFINED CPM_ARGS_GIT_SHALLOW)
|
| 650 |
+
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW ${CPM_ARGS_GIT_SHALLOW})
|
| 651 |
+
endif()
|
| 652 |
+
endif()
|
| 653 |
+
|
| 654 |
+
if(DEFINED CPM_ARGS_URL)
|
| 655 |
+
# If a name or version aren't provided, try to infer them from the URL
|
| 656 |
+
list(GET CPM_ARGS_URL 0 firstUrl)
|
| 657 |
+
cpm_package_name_and_ver_from_url(${firstUrl} nameFromUrl verFromUrl)
|
| 658 |
+
# If we fail to obtain name and version from the first URL, we could try other URLs if any.
|
| 659 |
+
# However multiple URLs are expected to be quite rare, so for now we won't bother.
|
| 660 |
+
|
| 661 |
+
# If the caller provided their own name and version, they trump the inferred ones.
|
| 662 |
+
if(NOT DEFINED CPM_ARGS_NAME)
|
| 663 |
+
set(CPM_ARGS_NAME ${nameFromUrl})
|
| 664 |
+
endif()
|
| 665 |
+
if(NOT DEFINED CPM_ARGS_VERSION)
|
| 666 |
+
set(CPM_ARGS_VERSION ${verFromUrl})
|
| 667 |
+
endif()
|
| 668 |
+
|
| 669 |
+
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS URL "${CPM_ARGS_URL}")
|
| 670 |
+
endif()
|
| 671 |
+
|
| 672 |
+
# Check for required arguments
|
| 673 |
+
|
| 674 |
+
if(NOT DEFINED CPM_ARGS_NAME)
|
| 675 |
+
message(
|
| 676 |
+
FATAL_ERROR
|
| 677 |
+
"${CPM_INDENT} 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'"
|
| 678 |
+
)
|
| 679 |
+
endif()
|
| 680 |
+
|
| 681 |
+
# Check if package has been added before
|
| 682 |
+
cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}")
|
| 683 |
+
if(CPM_PACKAGE_ALREADY_ADDED)
|
| 684 |
+
cpm_export_variables(${CPM_ARGS_NAME})
|
| 685 |
+
return()
|
| 686 |
+
endif()
|
| 687 |
+
|
| 688 |
+
# Check for manual overrides
|
| 689 |
+
if(NOT CPM_ARGS_FORCE AND NOT "${CPM_${CPM_ARGS_NAME}_SOURCE}" STREQUAL "")
|
| 690 |
+
set(PACKAGE_SOURCE ${CPM_${CPM_ARGS_NAME}_SOURCE})
|
| 691 |
+
set(CPM_${CPM_ARGS_NAME}_SOURCE "")
|
| 692 |
+
CPMAddPackage(
|
| 693 |
+
NAME "${CPM_ARGS_NAME}"
|
| 694 |
+
SOURCE_DIR "${PACKAGE_SOURCE}"
|
| 695 |
+
EXCLUDE_FROM_ALL "${CPM_ARGS_EXCLUDE_FROM_ALL}"
|
| 696 |
+
SYSTEM "${CPM_ARGS_SYSTEM}"
|
| 697 |
+
PATCHES "${CPM_ARGS_PATCHES}"
|
| 698 |
+
OPTIONS "${CPM_ARGS_OPTIONS}"
|
| 699 |
+
SOURCE_SUBDIR "${CPM_ARGS_SOURCE_SUBDIR}"
|
| 700 |
+
DOWNLOAD_ONLY "${DOWNLOAD_ONLY}"
|
| 701 |
+
FORCE True
|
| 702 |
+
)
|
| 703 |
+
cpm_export_variables(${CPM_ARGS_NAME})
|
| 704 |
+
return()
|
| 705 |
+
endif()
|
| 706 |
+
|
| 707 |
+
# Check for available declaration
|
| 708 |
+
if(NOT CPM_ARGS_FORCE AND NOT "${CPM_DECLARATION_${CPM_ARGS_NAME}}" STREQUAL "")
|
| 709 |
+
set(declaration ${CPM_DECLARATION_${CPM_ARGS_NAME}})
|
| 710 |
+
set(CPM_DECLARATION_${CPM_ARGS_NAME} "")
|
| 711 |
+
CPMAddPackage(${declaration})
|
| 712 |
+
cpm_export_variables(${CPM_ARGS_NAME})
|
| 713 |
+
# checking again to ensure version and option compatibility
|
| 714 |
+
cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}")
|
| 715 |
+
return()
|
| 716 |
+
endif()
|
| 717 |
+
|
| 718 |
+
if(NOT CPM_ARGS_FORCE)
|
| 719 |
+
if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY)
|
| 720 |
+
cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})
|
| 721 |
+
|
| 722 |
+
if(CPM_PACKAGE_FOUND)
|
| 723 |
+
cpm_export_variables(${CPM_ARGS_NAME})
|
| 724 |
+
return()
|
| 725 |
+
endif()
|
| 726 |
+
|
| 727 |
+
if(CPM_LOCAL_PACKAGES_ONLY)
|
| 728 |
+
message(
|
| 729 |
+
SEND_ERROR
|
| 730 |
+
"${CPM_INDENT} ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})"
|
| 731 |
+
)
|
| 732 |
+
endif()
|
| 733 |
+
endif()
|
| 734 |
+
endif()
|
| 735 |
+
|
| 736 |
+
CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}")
|
| 737 |
+
|
| 738 |
+
if(DEFINED CPM_ARGS_GIT_TAG)
|
| 739 |
+
set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}")
|
| 740 |
+
elseif(DEFINED CPM_ARGS_SOURCE_DIR)
|
| 741 |
+
set(PACKAGE_INFO "${CPM_ARGS_SOURCE_DIR}")
|
| 742 |
+
else()
|
| 743 |
+
set(PACKAGE_INFO "${CPM_ARGS_VERSION}")
|
| 744 |
+
endif()
|
| 745 |
+
|
| 746 |
+
if(DEFINED FETCHCONTENT_BASE_DIR)
|
| 747 |
+
# respect user's FETCHCONTENT_BASE_DIR if set
|
| 748 |
+
set(CPM_FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR})
|
| 749 |
+
else()
|
| 750 |
+
set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps)
|
| 751 |
+
endif()
|
| 752 |
+
|
| 753 |
+
cpm_add_patches(${CPM_ARGS_PATCHES})
|
| 754 |
+
|
| 755 |
+
if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND)
|
| 756 |
+
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND})
|
| 757 |
+
elseif(DEFINED CPM_ARGS_SOURCE_DIR)
|
| 758 |
+
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR})
|
| 759 |
+
if(NOT IS_ABSOLUTE ${CPM_ARGS_SOURCE_DIR})
|
| 760 |
+
# Expand `CPM_ARGS_SOURCE_DIR` relative path. This is important because EXISTS doesn't work
|
| 761 |
+
# for relative paths.
|
| 762 |
+
get_filename_component(
|
| 763 |
+
source_directory ${CPM_ARGS_SOURCE_DIR} REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}
|
| 764 |
+
)
|
| 765 |
+
else()
|
| 766 |
+
set(source_directory ${CPM_ARGS_SOURCE_DIR})
|
| 767 |
+
endif()
|
| 768 |
+
if(NOT EXISTS ${source_directory})
|
| 769 |
+
string(TOLOWER ${CPM_ARGS_NAME} lower_case_name)
|
| 770 |
+
# remove timestamps so CMake will re-download the dependency
|
| 771 |
+
file(REMOVE_RECURSE "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild")
|
| 772 |
+
endif()
|
| 773 |
+
elseif(CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE)
|
| 774 |
+
string(TOLOWER ${CPM_ARGS_NAME} lower_case_name)
|
| 775 |
+
set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS})
|
| 776 |
+
list(SORT origin_parameters)
|
| 777 |
+
if(CPM_ARGS_CUSTOM_CACHE_KEY)
|
| 778 |
+
# Application set a custom unique directory name
|
| 779 |
+
set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${CPM_ARGS_CUSTOM_CACHE_KEY})
|
| 780 |
+
elseif(CPM_USE_NAMED_CACHE_DIRECTORIES)
|
| 781 |
+
string(SHA1 origin_hash "${origin_parameters};NEW_CACHE_STRUCTURE_TAG")
|
| 782 |
+
set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}/${CPM_ARGS_NAME})
|
| 783 |
+
else()
|
| 784 |
+
string(SHA1 origin_hash "${origin_parameters}")
|
| 785 |
+
set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash})
|
| 786 |
+
endif()
|
| 787 |
+
# Expand `download_directory` relative path. This is important because EXISTS doesn't work for
|
| 788 |
+
# relative paths.
|
| 789 |
+
get_filename_component(download_directory ${download_directory} ABSOLUTE)
|
| 790 |
+
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory})
|
| 791 |
+
|
| 792 |
+
if(CPM_SOURCE_CACHE)
|
| 793 |
+
file(LOCK ${download_directory}/../cmake.lock)
|
| 794 |
+
endif()
|
| 795 |
+
|
| 796 |
+
if(EXISTS ${download_directory})
|
| 797 |
+
if(CPM_SOURCE_CACHE)
|
| 798 |
+
file(LOCK ${download_directory}/../cmake.lock RELEASE)
|
| 799 |
+
endif()
|
| 800 |
+
|
| 801 |
+
cpm_store_fetch_properties(
|
| 802 |
+
${CPM_ARGS_NAME} "${download_directory}"
|
| 803 |
+
"${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build"
|
| 804 |
+
)
|
| 805 |
+
cpm_get_fetch_properties("${CPM_ARGS_NAME}")
|
| 806 |
+
|
| 807 |
+
if(DEFINED CPM_ARGS_GIT_TAG AND NOT (PATCH_COMMAND IN_LIST CPM_ARGS_UNPARSED_ARGUMENTS))
|
| 808 |
+
# warn if cache has been changed since checkout
|
| 809 |
+
cpm_check_git_working_dir_is_clean(${download_directory} ${CPM_ARGS_GIT_TAG} IS_CLEAN)
|
| 810 |
+
if(NOT ${IS_CLEAN})
|
| 811 |
+
message(
|
| 812 |
+
WARNING "${CPM_INDENT} Cache for ${CPM_ARGS_NAME} (${download_directory}) is dirty"
|
| 813 |
+
)
|
| 814 |
+
endif()
|
| 815 |
+
endif()
|
| 816 |
+
|
| 817 |
+
cpm_add_subdirectory(
|
| 818 |
+
"${CPM_ARGS_NAME}"
|
| 819 |
+
"${DOWNLOAD_ONLY}"
|
| 820 |
+
"${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"
|
| 821 |
+
"${${CPM_ARGS_NAME}_BINARY_DIR}"
|
| 822 |
+
"${CPM_ARGS_EXCLUDE_FROM_ALL}"
|
| 823 |
+
"${CPM_ARGS_SYSTEM}"
|
| 824 |
+
"${CPM_ARGS_OPTIONS}"
|
| 825 |
+
)
|
| 826 |
+
set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}")
|
| 827 |
+
|
| 828 |
+
# As the source dir is already cached/populated, we override the call to FetchContent.
|
| 829 |
+
set(CPM_SKIP_FETCH TRUE)
|
| 830 |
+
cpm_override_fetchcontent(
|
| 831 |
+
"${lower_case_name}" SOURCE_DIR "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"
|
| 832 |
+
BINARY_DIR "${${CPM_ARGS_NAME}_BINARY_DIR}"
|
| 833 |
+
)
|
| 834 |
+
|
| 835 |
+
else()
|
| 836 |
+
# Enable shallow clone when GIT_TAG is not a commit hash. Our guess may not be accurate, but
|
| 837 |
+
# it should guarantee no commit hash get mis-detected.
|
| 838 |
+
if(NOT DEFINED CPM_ARGS_GIT_SHALLOW)
|
| 839 |
+
cpm_is_git_tag_commit_hash("${CPM_ARGS_GIT_TAG}" IS_HASH)
|
| 840 |
+
if(NOT ${IS_HASH})
|
| 841 |
+
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW TRUE)
|
| 842 |
+
endif()
|
| 843 |
+
endif()
|
| 844 |
+
|
| 845 |
+
# remove timestamps so CMake will re-download the dependency
|
| 846 |
+
file(REMOVE_RECURSE ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild)
|
| 847 |
+
set(PACKAGE_INFO "${PACKAGE_INFO} to ${download_directory}")
|
| 848 |
+
endif()
|
| 849 |
+
endif()
|
| 850 |
+
|
| 851 |
+
cpm_create_module_file(${CPM_ARGS_NAME} "CPMAddPackage(\"${ARGN}\")")
|
| 852 |
+
|
| 853 |
+
if(CPM_PACKAGE_LOCK_ENABLED)
|
| 854 |
+
if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK)
|
| 855 |
+
cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")
|
| 856 |
+
elseif(CPM_ARGS_SOURCE_DIR)
|
| 857 |
+
cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory")
|
| 858 |
+
else()
|
| 859 |
+
cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")
|
| 860 |
+
endif()
|
| 861 |
+
endif()
|
| 862 |
+
|
| 863 |
+
cpm_message(
|
| 864 |
+
STATUS "${CPM_INDENT} Adding package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (${PACKAGE_INFO})"
|
| 865 |
+
)
|
| 866 |
+
|
| 867 |
+
if(NOT CPM_SKIP_FETCH)
|
| 868 |
+
# CMake 3.28 added EXCLUDE, SYSTEM (3.25), and SOURCE_SUBDIR (3.18) to FetchContent_Declare.
|
| 869 |
+
# Calling FetchContent_MakeAvailable will then internally forward these options to
|
| 870 |
+
# add_subdirectory. Up until these changes, we had to call FetchContent_Populate and
|
| 871 |
+
# add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30.
|
| 872 |
+
set(fetchContentDeclareExtraArgs "")
|
| 873 |
+
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0")
|
| 874 |
+
if(${CPM_ARGS_EXCLUDE_FROM_ALL})
|
| 875 |
+
list(APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL)
|
| 876 |
+
endif()
|
| 877 |
+
if(${CPM_ARGS_SYSTEM})
|
| 878 |
+
list(APPEND fetchContentDeclareExtraArgs SYSTEM)
|
| 879 |
+
endif()
|
| 880 |
+
if(DEFINED CPM_ARGS_SOURCE_SUBDIR)
|
| 881 |
+
list(APPEND fetchContentDeclareExtraArgs SOURCE_SUBDIR ${CPM_ARGS_SOURCE_SUBDIR})
|
| 882 |
+
endif()
|
| 883 |
+
# For CMake version <3.28 OPTIONS are parsed in cpm_add_subdirectory
|
| 884 |
+
if(CPM_ARGS_OPTIONS AND NOT DOWNLOAD_ONLY)
|
| 885 |
+
foreach(OPTION ${CPM_ARGS_OPTIONS})
|
| 886 |
+
cpm_parse_option("${OPTION}")
|
| 887 |
+
set(${OPTION_KEY} "${OPTION_VALUE}")
|
| 888 |
+
endforeach()
|
| 889 |
+
endif()
|
| 890 |
+
endif()
|
| 891 |
+
cpm_declare_fetch(
|
| 892 |
+
"${CPM_ARGS_NAME}" ${fetchContentDeclareExtraArgs} "${CPM_ARGS_UNPARSED_ARGUMENTS}"
|
| 893 |
+
)
|
| 894 |
+
|
| 895 |
+
cpm_fetch_package("${CPM_ARGS_NAME}" ${DOWNLOAD_ONLY} populated ${CPM_ARGS_UNPARSED_ARGUMENTS})
|
| 896 |
+
if(CPM_SOURCE_CACHE AND download_directory)
|
| 897 |
+
file(LOCK ${download_directory}/../cmake.lock RELEASE)
|
| 898 |
+
endif()
|
| 899 |
+
if(${populated} AND ${CMAKE_VERSION} VERSION_LESS "3.28.0")
|
| 900 |
+
cpm_add_subdirectory(
|
| 901 |
+
"${CPM_ARGS_NAME}"
|
| 902 |
+
"${DOWNLOAD_ONLY}"
|
| 903 |
+
"${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"
|
| 904 |
+
"${${CPM_ARGS_NAME}_BINARY_DIR}"
|
| 905 |
+
"${CPM_ARGS_EXCLUDE_FROM_ALL}"
|
| 906 |
+
"${CPM_ARGS_SYSTEM}"
|
| 907 |
+
"${CPM_ARGS_OPTIONS}"
|
| 908 |
+
)
|
| 909 |
+
endif()
|
| 910 |
+
cpm_get_fetch_properties("${CPM_ARGS_NAME}")
|
| 911 |
+
endif()
|
| 912 |
+
|
| 913 |
+
set(${CPM_ARGS_NAME}_ADDED YES)
|
| 914 |
+
cpm_export_variables("${CPM_ARGS_NAME}")
|
| 915 |
+
endfunction()
|
| 916 |
+
|
| 917 |
+
# Fetch a previously declared package
|
| 918 |
+
macro(CPMGetPackage Name)
|
| 919 |
+
if(DEFINED "CPM_DECLARATION_${Name}")
|
| 920 |
+
CPMAddPackage(NAME ${Name})
|
| 921 |
+
else()
|
| 922 |
+
message(SEND_ERROR "${CPM_INDENT} Cannot retrieve package ${Name}: no declaration available")
|
| 923 |
+
endif()
|
| 924 |
+
endmacro()
|
| 925 |
+
|
| 926 |
+
# export variables available to the caller to the parent scope expects ${CPM_ARGS_NAME} to be set
|
| 927 |
+
macro(cpm_export_variables name)
|
| 928 |
+
set(${name}_SOURCE_DIR
|
| 929 |
+
"${${name}_SOURCE_DIR}"
|
| 930 |
+
PARENT_SCOPE
|
| 931 |
+
)
|
| 932 |
+
set(${name}_BINARY_DIR
|
| 933 |
+
"${${name}_BINARY_DIR}"
|
| 934 |
+
PARENT_SCOPE
|
| 935 |
+
)
|
| 936 |
+
set(${name}_ADDED
|
| 937 |
+
"${${name}_ADDED}"
|
| 938 |
+
PARENT_SCOPE
|
| 939 |
+
)
|
| 940 |
+
set(CPM_LAST_PACKAGE_NAME
|
| 941 |
+
"${name}"
|
| 942 |
+
PARENT_SCOPE
|
| 943 |
+
)
|
| 944 |
+
endmacro()
|
| 945 |
+
|
| 946 |
+
# declares a package, so that any call to CPMAddPackage for the package name will use these
|
| 947 |
+
# arguments instead. Previous declarations will not be overridden.
|
| 948 |
+
macro(CPMDeclarePackage Name)
|
| 949 |
+
if(NOT DEFINED "CPM_DECLARATION_${Name}")
|
| 950 |
+
set("CPM_DECLARATION_${Name}" "${ARGN}")
|
| 951 |
+
endif()
|
| 952 |
+
endmacro()
|
| 953 |
+
|
| 954 |
+
function(cpm_add_to_package_lock Name)
|
| 955 |
+
if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)
|
| 956 |
+
cpm_prettify_package_arguments(PRETTY_ARGN false ${ARGN})
|
| 957 |
+
file(APPEND ${CPM_PACKAGE_LOCK_FILE} "# ${Name}\nCPMDeclarePackage(${Name}\n${PRETTY_ARGN})\n")
|
| 958 |
+
endif()
|
| 959 |
+
endfunction()
|
| 960 |
+
|
| 961 |
+
function(cpm_add_comment_to_package_lock Name)
|
| 962 |
+
if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)
|
| 963 |
+
cpm_prettify_package_arguments(PRETTY_ARGN true ${ARGN})
|
| 964 |
+
file(APPEND ${CPM_PACKAGE_LOCK_FILE}
|
| 965 |
+
"# ${Name} (unversioned)\n# CPMDeclarePackage(${Name}\n${PRETTY_ARGN}#)\n"
|
| 966 |
+
)
|
| 967 |
+
endif()
|
| 968 |
+
endfunction()
|
| 969 |
+
|
| 970 |
+
# includes the package lock file if it exists and creates a target `cpm-update-package-lock` to
|
| 971 |
+
# update it
|
| 972 |
+
macro(CPMUsePackageLock file)
|
| 973 |
+
if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)
|
| 974 |
+
get_filename_component(CPM_ABSOLUTE_PACKAGE_LOCK_PATH ${file} ABSOLUTE)
|
| 975 |
+
if(EXISTS ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH})
|
| 976 |
+
include(${CPM_ABSOLUTE_PACKAGE_LOCK_PATH})
|
| 977 |
+
endif()
|
| 978 |
+
if(NOT TARGET cpm-update-package-lock)
|
| 979 |
+
add_custom_target(
|
| 980 |
+
cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE}
|
| 981 |
+
${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}
|
| 982 |
+
)
|
| 983 |
+
endif()
|
| 984 |
+
set(CPM_PACKAGE_LOCK_ENABLED true)
|
| 985 |
+
endif()
|
| 986 |
+
endmacro()
|
| 987 |
+
|
| 988 |
+
# registers a package that has been added to CPM
|
| 989 |
+
function(CPMRegisterPackage PACKAGE VERSION)
|
| 990 |
+
list(APPEND CPM_PACKAGES ${PACKAGE})
|
| 991 |
+
set(CPM_PACKAGES
|
| 992 |
+
${CPM_PACKAGES}
|
| 993 |
+
CACHE INTERNAL ""
|
| 994 |
+
)
|
| 995 |
+
set("CPM_PACKAGE_${PACKAGE}_VERSION"
|
| 996 |
+
${VERSION}
|
| 997 |
+
CACHE INTERNAL ""
|
| 998 |
+
)
|
| 999 |
+
endfunction()
|
| 1000 |
+
|
| 1001 |
+
# retrieve the current version of the package to ${OUTPUT}
|
| 1002 |
+
function(CPMGetPackageVersion PACKAGE OUTPUT)
|
| 1003 |
+
set(${OUTPUT}
|
| 1004 |
+
"${CPM_PACKAGE_${PACKAGE}_VERSION}"
|
| 1005 |
+
PARENT_SCOPE
|
| 1006 |
+
)
|
| 1007 |
+
endfunction()
|
| 1008 |
+
|
| 1009 |
+
# declares a package in FetchContent_Declare
|
| 1010 |
+
function(cpm_declare_fetch PACKAGE)
|
| 1011 |
+
if(${CPM_DRY_RUN})
|
| 1012 |
+
cpm_message(STATUS "${CPM_INDENT} Package not declared (dry run)")
|
| 1013 |
+
return()
|
| 1014 |
+
endif()
|
| 1015 |
+
|
| 1016 |
+
FetchContent_Declare(${PACKAGE} ${ARGN})
|
| 1017 |
+
endfunction()
|
| 1018 |
+
|
| 1019 |
+
# returns properties for a package previously defined by cpm_declare_fetch
|
| 1020 |
+
function(cpm_get_fetch_properties PACKAGE)
|
| 1021 |
+
if(${CPM_DRY_RUN})
|
| 1022 |
+
return()
|
| 1023 |
+
endif()
|
| 1024 |
+
|
| 1025 |
+
set(${PACKAGE}_SOURCE_DIR
|
| 1026 |
+
"${CPM_PACKAGE_${PACKAGE}_SOURCE_DIR}"
|
| 1027 |
+
PARENT_SCOPE
|
| 1028 |
+
)
|
| 1029 |
+
set(${PACKAGE}_BINARY_DIR
|
| 1030 |
+
"${CPM_PACKAGE_${PACKAGE}_BINARY_DIR}"
|
| 1031 |
+
PARENT_SCOPE
|
| 1032 |
+
)
|
| 1033 |
+
endfunction()
|
| 1034 |
+
|
| 1035 |
+
function(cpm_store_fetch_properties PACKAGE source_dir binary_dir)
|
| 1036 |
+
if(${CPM_DRY_RUN})
|
| 1037 |
+
return()
|
| 1038 |
+
endif()
|
| 1039 |
+
|
| 1040 |
+
set(CPM_PACKAGE_${PACKAGE}_SOURCE_DIR
|
| 1041 |
+
"${source_dir}"
|
| 1042 |
+
CACHE INTERNAL ""
|
| 1043 |
+
)
|
| 1044 |
+
set(CPM_PACKAGE_${PACKAGE}_BINARY_DIR
|
| 1045 |
+
"${binary_dir}"
|
| 1046 |
+
CACHE INTERNAL ""
|
| 1047 |
+
)
|
| 1048 |
+
endfunction()
|
| 1049 |
+
|
| 1050 |
+
# adds a package as a subdirectory if viable, according to provided options
|
| 1051 |
+
function(
|
| 1052 |
+
cpm_add_subdirectory
|
| 1053 |
+
PACKAGE
|
| 1054 |
+
DOWNLOAD_ONLY
|
| 1055 |
+
SOURCE_DIR
|
| 1056 |
+
BINARY_DIR
|
| 1057 |
+
EXCLUDE
|
| 1058 |
+
SYSTEM
|
| 1059 |
+
OPTIONS
|
| 1060 |
+
)
|
| 1061 |
+
|
| 1062 |
+
if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt)
|
| 1063 |
+
set(addSubdirectoryExtraArgs "")
|
| 1064 |
+
if(EXCLUDE)
|
| 1065 |
+
list(APPEND addSubdirectoryExtraArgs EXCLUDE_FROM_ALL)
|
| 1066 |
+
endif()
|
| 1067 |
+
if("${SYSTEM}" AND "${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.25")
|
| 1068 |
+
# https://cmake.org/cmake/help/latest/prop_dir/SYSTEM.html#prop_dir:SYSTEM
|
| 1069 |
+
list(APPEND addSubdirectoryExtraArgs SYSTEM)
|
| 1070 |
+
endif()
|
| 1071 |
+
if(OPTIONS)
|
| 1072 |
+
foreach(OPTION ${OPTIONS})
|
| 1073 |
+
cpm_parse_option("${OPTION}")
|
| 1074 |
+
set(${OPTION_KEY} "${OPTION_VALUE}")
|
| 1075 |
+
endforeach()
|
| 1076 |
+
endif()
|
| 1077 |
+
set(CPM_OLD_INDENT "${CPM_INDENT}")
|
| 1078 |
+
set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:")
|
| 1079 |
+
add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs})
|
| 1080 |
+
set(CPM_INDENT "${CPM_OLD_INDENT}")
|
| 1081 |
+
endif()
|
| 1082 |
+
endfunction()
|
| 1083 |
+
|
| 1084 |
+
# downloads a previously declared package via FetchContent and exports the variables
|
| 1085 |
+
# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope
|
| 1086 |
+
function(cpm_fetch_package PACKAGE DOWNLOAD_ONLY populated)
|
| 1087 |
+
set(${populated}
|
| 1088 |
+
FALSE
|
| 1089 |
+
PARENT_SCOPE
|
| 1090 |
+
)
|
| 1091 |
+
if(${CPM_DRY_RUN})
|
| 1092 |
+
cpm_message(STATUS "${CPM_INDENT} Package ${PACKAGE} not fetched (dry run)")
|
| 1093 |
+
return()
|
| 1094 |
+
endif()
|
| 1095 |
+
|
| 1096 |
+
FetchContent_GetProperties(${PACKAGE})
|
| 1097 |
+
|
| 1098 |
+
string(TOLOWER "${PACKAGE}" lower_case_name)
|
| 1099 |
+
|
| 1100 |
+
if(NOT ${lower_case_name}_POPULATED)
|
| 1101 |
+
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.28.0")
|
| 1102 |
+
if(DOWNLOAD_ONLY)
|
| 1103 |
+
# MakeAvailable will call add_subdirectory internally which is not what we want when
|
| 1104 |
+
# DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the
|
| 1105 |
+
# build
|
| 1106 |
+
FetchContent_Populate(
|
| 1107 |
+
${PACKAGE}
|
| 1108 |
+
SOURCE_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-src"
|
| 1109 |
+
BINARY_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build"
|
| 1110 |
+
SUBBUILD_DIR "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild"
|
| 1111 |
+
${ARGN}
|
| 1112 |
+
)
|
| 1113 |
+
else()
|
| 1114 |
+
FetchContent_MakeAvailable(${PACKAGE})
|
| 1115 |
+
endif()
|
| 1116 |
+
else()
|
| 1117 |
+
FetchContent_Populate(${PACKAGE})
|
| 1118 |
+
endif()
|
| 1119 |
+
set(${populated}
|
| 1120 |
+
TRUE
|
| 1121 |
+
PARENT_SCOPE
|
| 1122 |
+
)
|
| 1123 |
+
endif()
|
| 1124 |
+
|
| 1125 |
+
cpm_store_fetch_properties(
|
| 1126 |
+
${CPM_ARGS_NAME} ${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR}
|
| 1127 |
+
)
|
| 1128 |
+
|
| 1129 |
+
set(${PACKAGE}_SOURCE_DIR
|
| 1130 |
+
${${lower_case_name}_SOURCE_DIR}
|
| 1131 |
+
PARENT_SCOPE
|
| 1132 |
+
)
|
| 1133 |
+
set(${PACKAGE}_BINARY_DIR
|
| 1134 |
+
${${lower_case_name}_BINARY_DIR}
|
| 1135 |
+
PARENT_SCOPE
|
| 1136 |
+
)
|
| 1137 |
+
endfunction()
|
| 1138 |
+
|
| 1139 |
+
# splits a package option
|
| 1140 |
+
function(cpm_parse_option OPTION)
|
| 1141 |
+
string(REGEX MATCH "^[^ ]+" OPTION_KEY "${OPTION}")
|
| 1142 |
+
string(LENGTH "${OPTION}" OPTION_LENGTH)
|
| 1143 |
+
string(LENGTH "${OPTION_KEY}" OPTION_KEY_LENGTH)
|
| 1144 |
+
if(OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH)
|
| 1145 |
+
# no value for key provided, assume user wants to set option to "ON"
|
| 1146 |
+
set(OPTION_VALUE "ON")
|
| 1147 |
+
else()
|
| 1148 |
+
math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1")
|
| 1149 |
+
string(SUBSTRING "${OPTION}" "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE)
|
| 1150 |
+
endif()
|
| 1151 |
+
set(OPTION_KEY
|
| 1152 |
+
"${OPTION_KEY}"
|
| 1153 |
+
PARENT_SCOPE
|
| 1154 |
+
)
|
| 1155 |
+
set(OPTION_VALUE
|
| 1156 |
+
"${OPTION_VALUE}"
|
| 1157 |
+
PARENT_SCOPE
|
| 1158 |
+
)
|
| 1159 |
+
endfunction()
|
| 1160 |
+
|
| 1161 |
+
# guesses the package version from a git tag
|
| 1162 |
+
function(cpm_get_version_from_git_tag GIT_TAG RESULT)
|
| 1163 |
+
string(LENGTH ${GIT_TAG} length)
|
| 1164 |
+
if(length EQUAL 40)
|
| 1165 |
+
# GIT_TAG is probably a git hash
|
| 1166 |
+
set(${RESULT}
|
| 1167 |
+
0
|
| 1168 |
+
PARENT_SCOPE
|
| 1169 |
+
)
|
| 1170 |
+
else()
|
| 1171 |
+
string(REGEX MATCH "v?([0123456789.]*).*" _ ${GIT_TAG})
|
| 1172 |
+
set(${RESULT}
|
| 1173 |
+
${CMAKE_MATCH_1}
|
| 1174 |
+
PARENT_SCOPE
|
| 1175 |
+
)
|
| 1176 |
+
endif()
|
| 1177 |
+
endfunction()
|
| 1178 |
+
|
| 1179 |
+
# guesses if the git tag is a commit hash or an actual tag or a branch name.
|
| 1180 |
+
function(cpm_is_git_tag_commit_hash GIT_TAG RESULT)
|
| 1181 |
+
string(LENGTH "${GIT_TAG}" length)
|
| 1182 |
+
# full hash has 40 characters, and short hash has at least 7 characters.
|
| 1183 |
+
if(length LESS 7 OR length GREATER 40)
|
| 1184 |
+
set(${RESULT}
|
| 1185 |
+
0
|
| 1186 |
+
PARENT_SCOPE
|
| 1187 |
+
)
|
| 1188 |
+
else()
|
| 1189 |
+
if(${GIT_TAG} MATCHES "^[a-fA-F0-9]+$")
|
| 1190 |
+
set(${RESULT}
|
| 1191 |
+
1
|
| 1192 |
+
PARENT_SCOPE
|
| 1193 |
+
)
|
| 1194 |
+
else()
|
| 1195 |
+
set(${RESULT}
|
| 1196 |
+
0
|
| 1197 |
+
PARENT_SCOPE
|
| 1198 |
+
)
|
| 1199 |
+
endif()
|
| 1200 |
+
endif()
|
| 1201 |
+
endfunction()
|
| 1202 |
+
|
| 1203 |
+
function(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT)
|
| 1204 |
+
set(oneValueArgs
|
| 1205 |
+
NAME
|
| 1206 |
+
FORCE
|
| 1207 |
+
VERSION
|
| 1208 |
+
GIT_TAG
|
| 1209 |
+
DOWNLOAD_ONLY
|
| 1210 |
+
GITHUB_REPOSITORY
|
| 1211 |
+
GITLAB_REPOSITORY
|
| 1212 |
+
BITBUCKET_REPOSITORY
|
| 1213 |
+
GIT_REPOSITORY
|
| 1214 |
+
SOURCE_DIR
|
| 1215 |
+
FIND_PACKAGE_ARGUMENTS
|
| 1216 |
+
NO_CACHE
|
| 1217 |
+
SYSTEM
|
| 1218 |
+
GIT_SHALLOW
|
| 1219 |
+
EXCLUDE_FROM_ALL
|
| 1220 |
+
SOURCE_SUBDIR
|
| 1221 |
+
)
|
| 1222 |
+
set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND)
|
| 1223 |
+
cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
| 1224 |
+
|
| 1225 |
+
foreach(oneArgName ${oneValueArgs})
|
| 1226 |
+
if(DEFINED CPM_ARGS_${oneArgName})
|
| 1227 |
+
if(${IS_IN_COMMENT})
|
| 1228 |
+
string(APPEND PRETTY_OUT_VAR "#")
|
| 1229 |
+
endif()
|
| 1230 |
+
if(${oneArgName} STREQUAL "SOURCE_DIR")
|
| 1231 |
+
string(REPLACE ${CMAKE_SOURCE_DIR} "\${CMAKE_SOURCE_DIR}" CPM_ARGS_${oneArgName}
|
| 1232 |
+
${CPM_ARGS_${oneArgName}}
|
| 1233 |
+
)
|
| 1234 |
+
endif()
|
| 1235 |
+
string(APPEND PRETTY_OUT_VAR " ${oneArgName} ${CPM_ARGS_${oneArgName}}\n")
|
| 1236 |
+
endif()
|
| 1237 |
+
endforeach()
|
| 1238 |
+
foreach(multiArgName ${multiValueArgs})
|
| 1239 |
+
if(DEFINED CPM_ARGS_${multiArgName})
|
| 1240 |
+
if(${IS_IN_COMMENT})
|
| 1241 |
+
string(APPEND PRETTY_OUT_VAR "#")
|
| 1242 |
+
endif()
|
| 1243 |
+
string(APPEND PRETTY_OUT_VAR " ${multiArgName}\n")
|
| 1244 |
+
foreach(singleOption ${CPM_ARGS_${multiArgName}})
|
| 1245 |
+
if(${IS_IN_COMMENT})
|
| 1246 |
+
string(APPEND PRETTY_OUT_VAR "#")
|
| 1247 |
+
endif()
|
| 1248 |
+
string(APPEND PRETTY_OUT_VAR " \"${singleOption}\"\n")
|
| 1249 |
+
endforeach()
|
| 1250 |
+
endif()
|
| 1251 |
+
endforeach()
|
| 1252 |
+
|
| 1253 |
+
if(NOT "${CPM_ARGS_UNPARSED_ARGUMENTS}" STREQUAL "")
|
| 1254 |
+
if(${IS_IN_COMMENT})
|
| 1255 |
+
string(APPEND PRETTY_OUT_VAR "#")
|
| 1256 |
+
endif()
|
| 1257 |
+
string(APPEND PRETTY_OUT_VAR " ")
|
| 1258 |
+
foreach(CPM_ARGS_UNPARSED_ARGUMENT ${CPM_ARGS_UNPARSED_ARGUMENTS})
|
| 1259 |
+
string(APPEND PRETTY_OUT_VAR " ${CPM_ARGS_UNPARSED_ARGUMENT}")
|
| 1260 |
+
endforeach()
|
| 1261 |
+
string(APPEND PRETTY_OUT_VAR "\n")
|
| 1262 |
+
endif()
|
| 1263 |
+
|
| 1264 |
+
set(${OUT_VAR}
|
| 1265 |
+
${PRETTY_OUT_VAR}
|
| 1266 |
+
PARENT_SCOPE
|
| 1267 |
+
)
|
| 1268 |
+
|
| 1269 |
+
endfunction()
|
third_party/tracy/cmake/ECMFindModuleHelpers.cmake
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#.rst:
|
| 2 |
+
# ECMFindModuleHelpers
|
| 3 |
+
# --------------------
|
| 4 |
+
#
|
| 5 |
+
# Helper macros for find modules: ecm_find_package_version_check(),
|
| 6 |
+
# ecm_find_package_parse_components() and
|
| 7 |
+
# ecm_find_package_handle_library_components().
|
| 8 |
+
#
|
| 9 |
+
# ::
|
| 10 |
+
#
|
| 11 |
+
# ecm_find_package_version_check(<name>)
|
| 12 |
+
#
|
| 13 |
+
# Prints warnings if the CMake version or the project's required CMake version
|
| 14 |
+
# is older than that required by extra-cmake-modules.
|
| 15 |
+
#
|
| 16 |
+
# ::
|
| 17 |
+
#
|
| 18 |
+
# ecm_find_package_parse_components(<name>
|
| 19 |
+
# RESULT_VAR <variable>
|
| 20 |
+
# KNOWN_COMPONENTS <component1> [<component2> [...]]
|
| 21 |
+
# [SKIP_DEPENDENCY_HANDLING])
|
| 22 |
+
#
|
| 23 |
+
# This macro will populate <variable> with a list of components found in
|
| 24 |
+
# <name>_FIND_COMPONENTS, after checking that all those components are in the
|
| 25 |
+
# list of KNOWN_COMPONENTS; if there are any unknown components, it will print
|
| 26 |
+
# an error or warning (depending on the value of <name>_FIND_REQUIRED) and call
|
| 27 |
+
# return().
|
| 28 |
+
#
|
| 29 |
+
# The order of components in <variable> is guaranteed to match the order they
|
| 30 |
+
# are listed in the KNOWN_COMPONENTS argument.
|
| 31 |
+
#
|
| 32 |
+
# If SKIP_DEPENDENCY_HANDLING is not set, for each component the variable
|
| 33 |
+
# <name>_<component>_component_deps will be checked for dependent components.
|
| 34 |
+
# If <component> is listed in <name>_FIND_COMPONENTS, then all its (transitive)
|
| 35 |
+
# dependencies will also be added to <variable>.
|
| 36 |
+
#
|
| 37 |
+
# ::
|
| 38 |
+
#
|
| 39 |
+
# ecm_find_package_handle_library_components(<name>
|
| 40 |
+
# COMPONENTS <component> [<component> [...]]
|
| 41 |
+
# [SKIP_DEPENDENCY_HANDLING])
|
| 42 |
+
# [SKIP_PKG_CONFIG])
|
| 43 |
+
#
|
| 44 |
+
# Creates an imported library target for each component. The operation of this
|
| 45 |
+
# macro depends on the presence of a number of CMake variables.
|
| 46 |
+
#
|
| 47 |
+
# The <name>_<component>_lib variable should contain the name of this library,
|
| 48 |
+
# and <name>_<component>_header variable should contain the name of a header
|
| 49 |
+
# file associated with it (whatever relative path is normally passed to
|
| 50 |
+
# '#include'). <name>_<component>_header_subdir variable can be used to specify
|
| 51 |
+
# which subdirectory of the include path the headers will be found in.
|
| 52 |
+
# ecm_find_package_components() will then search for the library
|
| 53 |
+
# and include directory (creating appropriate cache variables) and create an
|
| 54 |
+
# imported library target named <name>::<component>.
|
| 55 |
+
#
|
| 56 |
+
# Additional variables can be used to provide additional information:
|
| 57 |
+
#
|
| 58 |
+
# If SKIP_PKG_CONFIG, the <name>_<component>_pkg_config variable is set, and
|
| 59 |
+
# pkg-config is found, the pkg-config module given by
|
| 60 |
+
# <name>_<component>_pkg_config will be searched for and used to help locate the
|
| 61 |
+
# library and header file. It will also be used to set
|
| 62 |
+
# <name>_<component>_VERSION.
|
| 63 |
+
#
|
| 64 |
+
# Note that if version information is found via pkg-config,
|
| 65 |
+
# <name>_<component>_FIND_VERSION can be set to require a particular version
|
| 66 |
+
# for each component.
|
| 67 |
+
#
|
| 68 |
+
# If SKIP_DEPENDENCY_HANDLING is not set, the INTERFACE_LINK_LIBRARIES property
|
| 69 |
+
# of the imported target for <component> will be set to contain the imported
|
| 70 |
+
# targets for the components listed in <name>_<component>_component_deps.
|
| 71 |
+
# <component>_FOUND will also be set to false if any of the components in
|
| 72 |
+
# <name>_<component>_component_deps are not found. This requires the components
|
| 73 |
+
# in <name>_<component>_component_deps to be listed before <component> in the
|
| 74 |
+
# COMPONENTS argument.
|
| 75 |
+
#
|
| 76 |
+
# The following variables will be set:
|
| 77 |
+
#
|
| 78 |
+
# ``<name>_TARGETS``
|
| 79 |
+
# the imported targets
|
| 80 |
+
# ``<name>_LIBRARIES``
|
| 81 |
+
# the found libraries
|
| 82 |
+
# ``<name>_INCLUDE_DIRS``
|
| 83 |
+
# the combined required include directories for the components
|
| 84 |
+
# ``<name>_DEFINITIONS``
|
| 85 |
+
# the "other" CFLAGS provided by pkg-config, if any
|
| 86 |
+
# ``<name>_VERSION``
|
| 87 |
+
# the value of ``<name>_<component>_VERSION`` for the first component that
|
| 88 |
+
# has this variable set (note that components are searched for in the order
|
| 89 |
+
# they are passed to the macro), although if it is already set, it will not
|
| 90 |
+
# be altered
|
| 91 |
+
#
|
| 92 |
+
# Note that these variables are never cleared, so if
|
| 93 |
+
# ecm_find_package_handle_library_components() is called multiple times with
|
| 94 |
+
# different components (typically because of multiple find_package() calls) then
|
| 95 |
+
# ``<name>_TARGETS``, for example, will contain all the targets found in any
|
| 96 |
+
# call (although no duplicates).
|
| 97 |
+
#
|
| 98 |
+
# Since pre-1.0.0.
|
| 99 |
+
|
| 100 |
+
#=============================================================================
|
| 101 |
+
# Copyright 2014 Alex Merry <alex.merry@kde.org>
|
| 102 |
+
#
|
| 103 |
+
# Redistribution and use in source and binary forms, with or without
|
| 104 |
+
# modification, are permitted provided that the following conditions
|
| 105 |
+
# are met:
|
| 106 |
+
#
|
| 107 |
+
# 1. Redistributions of source code must retain the copyright
|
| 108 |
+
# notice, this list of conditions and the following disclaimer.
|
| 109 |
+
# 2. Redistributions in binary form must reproduce the copyright
|
| 110 |
+
# notice, this list of conditions and the following disclaimer in the
|
| 111 |
+
# documentation and/or other materials provided with the distribution.
|
| 112 |
+
# 3. The name of the author may not be used to endorse or promote products
|
| 113 |
+
# derived from this software without specific prior written permission.
|
| 114 |
+
#
|
| 115 |
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
| 116 |
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
| 117 |
+
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
| 118 |
+
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
| 119 |
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
| 120 |
+
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| 121 |
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| 122 |
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| 123 |
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
| 124 |
+
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| 125 |
+
|
| 126 |
+
macro(ecm_find_package_version_check module_name)
|
| 127 |
+
if(CMAKE_VERSION VERSION_LESS 2.8.12)
|
| 128 |
+
message(FATAL_ERROR "CMake 2.8.12 is required by Find${module_name}.cmake")
|
| 129 |
+
endif()
|
| 130 |
+
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
|
| 131 |
+
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use Find${module_name}.cmake")
|
| 132 |
+
endif()
|
| 133 |
+
endmacro()
|
| 134 |
+
|
| 135 |
+
macro(ecm_find_package_parse_components module_name)
|
| 136 |
+
set(ecm_fppc_options SKIP_DEPENDENCY_HANDLING)
|
| 137 |
+
set(ecm_fppc_oneValueArgs RESULT_VAR)
|
| 138 |
+
set(ecm_fppc_multiValueArgs KNOWN_COMPONENTS DEFAULT_COMPONENTS)
|
| 139 |
+
cmake_parse_arguments(ECM_FPPC "${ecm_fppc_options}" "${ecm_fppc_oneValueArgs}" "${ecm_fppc_multiValueArgs}" ${ARGN})
|
| 140 |
+
|
| 141 |
+
if(ECM_FPPC_UNPARSED_ARGUMENTS)
|
| 142 |
+
message(FATAL_ERROR "Unexpected arguments to ecm_find_package_parse_components: ${ECM_FPPC_UNPARSED_ARGUMENTS}")
|
| 143 |
+
endif()
|
| 144 |
+
if(NOT ECM_FPPC_RESULT_VAR)
|
| 145 |
+
message(FATAL_ERROR "Missing RESULT_VAR argument to ecm_find_package_parse_components")
|
| 146 |
+
endif()
|
| 147 |
+
if(NOT ECM_FPPC_KNOWN_COMPONENTS)
|
| 148 |
+
message(FATAL_ERROR "Missing KNOWN_COMPONENTS argument to ecm_find_package_parse_components")
|
| 149 |
+
endif()
|
| 150 |
+
if(NOT ECM_FPPC_DEFAULT_COMPONENTS)
|
| 151 |
+
set(ECM_FPPC_DEFAULT_COMPONENTS ${ECM_FPPC_KNOWN_COMPONENTS})
|
| 152 |
+
endif()
|
| 153 |
+
|
| 154 |
+
if(${module_name}_FIND_COMPONENTS)
|
| 155 |
+
set(ecm_fppc_requestedComps ${${module_name}_FIND_COMPONENTS})
|
| 156 |
+
|
| 157 |
+
if(NOT ECM_FPPC_SKIP_DEPENDENCY_HANDLING)
|
| 158 |
+
# Make sure deps are included
|
| 159 |
+
foreach(ecm_fppc_comp ${ecm_fppc_requestedComps})
|
| 160 |
+
foreach(ecm_fppc_dep_comp ${${module_name}_${ecm_fppc_comp}_component_deps})
|
| 161 |
+
list(FIND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}" ecm_fppc_index)
|
| 162 |
+
if("${ecm_fppc_index}" STREQUAL "-1")
|
| 163 |
+
if(NOT ${module_name}_FIND_QUIETLY)
|
| 164 |
+
message(STATUS "${module_name}: ${ecm_fppc_comp} requires ${${module_name}_${ecm_fppc_comp}_component_deps}")
|
| 165 |
+
endif()
|
| 166 |
+
list(APPEND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}")
|
| 167 |
+
endif()
|
| 168 |
+
endforeach()
|
| 169 |
+
endforeach()
|
| 170 |
+
else()
|
| 171 |
+
message(STATUS "Skipping dependency handling for ${module_name}")
|
| 172 |
+
endif()
|
| 173 |
+
list(REMOVE_DUPLICATES ecm_fppc_requestedComps)
|
| 174 |
+
|
| 175 |
+
# This makes sure components are listed in the same order as
|
| 176 |
+
# KNOWN_COMPONENTS (potentially important for inter-dependencies)
|
| 177 |
+
set(${ECM_FPPC_RESULT_VAR})
|
| 178 |
+
foreach(ecm_fppc_comp ${ECM_FPPC_KNOWN_COMPONENTS})
|
| 179 |
+
list(FIND ecm_fppc_requestedComps "${ecm_fppc_comp}" ecm_fppc_index)
|
| 180 |
+
if(NOT "${ecm_fppc_index}" STREQUAL "-1")
|
| 181 |
+
list(APPEND ${ECM_FPPC_RESULT_VAR} "${ecm_fppc_comp}")
|
| 182 |
+
list(REMOVE_AT ecm_fppc_requestedComps ${ecm_fppc_index})
|
| 183 |
+
endif()
|
| 184 |
+
endforeach()
|
| 185 |
+
# if there are any left, they are unknown components
|
| 186 |
+
if(ecm_fppc_requestedComps)
|
| 187 |
+
set(ecm_fppc_msgType STATUS)
|
| 188 |
+
if(${module_name}_FIND_REQUIRED)
|
| 189 |
+
set(ecm_fppc_msgType FATAL_ERROR)
|
| 190 |
+
endif()
|
| 191 |
+
if(NOT ${module_name}_FIND_QUIETLY)
|
| 192 |
+
message(${ecm_fppc_msgType} "${module_name}: requested unknown components ${ecm_fppc_requestedComps}")
|
| 193 |
+
endif()
|
| 194 |
+
return()
|
| 195 |
+
endif()
|
| 196 |
+
else()
|
| 197 |
+
set(${ECM_FPPC_RESULT_VAR} ${ECM_FPPC_DEFAULT_COMPONENTS})
|
| 198 |
+
endif()
|
| 199 |
+
endmacro()
|
| 200 |
+
|
| 201 |
+
macro(ecm_find_package_handle_library_components module_name)
|
| 202 |
+
set(ecm_fpwc_options SKIP_PKG_CONFIG SKIP_DEPENDENCY_HANDLING)
|
| 203 |
+
set(ecm_fpwc_oneValueArgs)
|
| 204 |
+
set(ecm_fpwc_multiValueArgs COMPONENTS)
|
| 205 |
+
cmake_parse_arguments(ECM_FPWC "${ecm_fpwc_options}" "${ecm_fpwc_oneValueArgs}" "${ecm_fpwc_multiValueArgs}" ${ARGN})
|
| 206 |
+
|
| 207 |
+
if(ECM_FPWC_UNPARSED_ARGUMENTS)
|
| 208 |
+
message(FATAL_ERROR "Unexpected arguments to ecm_find_package_handle_components: ${ECM_FPWC_UNPARSED_ARGUMENTS}")
|
| 209 |
+
endif()
|
| 210 |
+
if(NOT ECM_FPWC_COMPONENTS)
|
| 211 |
+
message(FATAL_ERROR "Missing COMPONENTS argument to ecm_find_package_handle_components")
|
| 212 |
+
endif()
|
| 213 |
+
|
| 214 |
+
include(FindPackageHandleStandardArgs)
|
| 215 |
+
find_package(PkgConfig QUIET)
|
| 216 |
+
foreach(ecm_fpwc_comp ${ECM_FPWC_COMPONENTS})
|
| 217 |
+
set(ecm_fpwc_dep_vars)
|
| 218 |
+
set(ecm_fpwc_dep_targets)
|
| 219 |
+
if(NOT SKIP_DEPENDENCY_HANDLING)
|
| 220 |
+
foreach(ecm_fpwc_dep ${${module_name}_${ecm_fpwc_comp}_component_deps})
|
| 221 |
+
list(APPEND ecm_fpwc_dep_vars "${module_name}_${ecm_fpwc_dep}_FOUND")
|
| 222 |
+
list(APPEND ecm_fpwc_dep_targets "${module_name}::${ecm_fpwc_dep}")
|
| 223 |
+
endforeach()
|
| 224 |
+
endif()
|
| 225 |
+
|
| 226 |
+
if(NOT ECM_FPWC_SKIP_PKG_CONFIG AND ${module_name}_${ecm_fpwc_comp}_pkg_config)
|
| 227 |
+
pkg_check_modules(PKG_${module_name}_${ecm_fpwc_comp} QUIET
|
| 228 |
+
${${module_name}_${ecm_fpwc_comp}_pkg_config})
|
| 229 |
+
endif()
|
| 230 |
+
|
| 231 |
+
find_path(${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
|
| 232 |
+
NAMES ${${module_name}_${ecm_fpwc_comp}_header}
|
| 233 |
+
HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_INCLUDE_DIRS}
|
| 234 |
+
PATH_SUFFIXES ${${module_name}_${ecm_fpwc_comp}_header_subdir}
|
| 235 |
+
)
|
| 236 |
+
find_library(${module_name}_${ecm_fpwc_comp}_LIBRARY
|
| 237 |
+
NAMES ${${module_name}_${ecm_fpwc_comp}_lib}
|
| 238 |
+
HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_LIBRARY_DIRS}
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
set(${module_name}_${ecm_fpwc_comp}_VERSION "${PKG_${module_name}_${ecm_fpwc_comp}_VERSION}")
|
| 242 |
+
if(NOT ${module_name}_VERSION)
|
| 243 |
+
set(${module_name}_VERSION ${${module_name}_${ecm_fpwc_comp}_VERSION})
|
| 244 |
+
endif()
|
| 245 |
+
|
| 246 |
+
set(_name_mismatched_arg)
|
| 247 |
+
if(NOT CMAKE_VERSION VERSION_LESS 3.17)
|
| 248 |
+
set(_name_mismatched_arg NAME_MISMATCHED)
|
| 249 |
+
endif()
|
| 250 |
+
find_package_handle_standard_args(${module_name}_${ecm_fpwc_comp}
|
| 251 |
+
FOUND_VAR
|
| 252 |
+
${module_name}_${ecm_fpwc_comp}_FOUND
|
| 253 |
+
REQUIRED_VARS
|
| 254 |
+
${module_name}_${ecm_fpwc_comp}_LIBRARY
|
| 255 |
+
${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
|
| 256 |
+
${ecm_fpwc_dep_vars}
|
| 257 |
+
VERSION_VAR
|
| 258 |
+
${module_name}_${ecm_fpwc_comp}_VERSION
|
| 259 |
+
${_name_mismatched_arg}
|
| 260 |
+
)
|
| 261 |
+
|
| 262 |
+
mark_as_advanced(
|
| 263 |
+
${module_name}_${ecm_fpwc_comp}_LIBRARY
|
| 264 |
+
${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR
|
| 265 |
+
)
|
| 266 |
+
|
| 267 |
+
if(${module_name}_${ecm_fpwc_comp}_FOUND)
|
| 268 |
+
list(APPEND ${module_name}_LIBRARIES
|
| 269 |
+
"${${module_name}_${ecm_fpwc_comp}_LIBRARY}")
|
| 270 |
+
list(APPEND ${module_name}_INCLUDE_DIRS
|
| 271 |
+
"${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}")
|
| 272 |
+
set(${module_name}_DEFINITIONS
|
| 273 |
+
${${module_name}_DEFINITIONS}
|
| 274 |
+
${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS})
|
| 275 |
+
if(NOT TARGET ${module_name}::${ecm_fpwc_comp})
|
| 276 |
+
add_library(${module_name}::${ecm_fpwc_comp} UNKNOWN IMPORTED)
|
| 277 |
+
set_target_properties(${module_name}::${ecm_fpwc_comp} PROPERTIES
|
| 278 |
+
IMPORTED_LOCATION "${${module_name}_${ecm_fpwc_comp}_LIBRARY}"
|
| 279 |
+
INTERFACE_COMPILE_OPTIONS "${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}"
|
| 280 |
+
INTERFACE_INCLUDE_DIRECTORIES "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}"
|
| 281 |
+
INTERFACE_LINK_LIBRARIES "${ecm_fpwc_dep_targets}"
|
| 282 |
+
)
|
| 283 |
+
endif()
|
| 284 |
+
list(APPEND ${module_name}_TARGETS
|
| 285 |
+
"${module_name}::${ecm_fpwc_comp}")
|
| 286 |
+
endif()
|
| 287 |
+
endforeach()
|
| 288 |
+
if(${module_name}_LIBRARIES)
|
| 289 |
+
list(REMOVE_DUPLICATES ${module_name}_LIBRARIES)
|
| 290 |
+
endif()
|
| 291 |
+
if(${module_name}_INCLUDE_DIRS)
|
| 292 |
+
list(REMOVE_DUPLICATES ${module_name}_INCLUDE_DIRS)
|
| 293 |
+
endif()
|
| 294 |
+
if(${module_name}_DEFINITIONS)
|
| 295 |
+
list(REMOVE_DUPLICATES ${module_name}_DEFINITIONS)
|
| 296 |
+
endif()
|
| 297 |
+
if(${module_name}_TARGETS)
|
| 298 |
+
list(REMOVE_DUPLICATES ${module_name}_TARGETS)
|
| 299 |
+
endif()
|
| 300 |
+
endmacro()
|
third_party/tracy/cmake/FindWaylandScanner.cmake
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#.rst:
|
| 2 |
+
# FindWaylandScanner
|
| 3 |
+
# ------------------
|
| 4 |
+
#
|
| 5 |
+
# Try to find wayland-scanner.
|
| 6 |
+
#
|
| 7 |
+
# If the wayland-scanner executable is not in your PATH, you can provide
|
| 8 |
+
# an alternative name or full path location with the ``WaylandScanner_EXECUTABLE``
|
| 9 |
+
# variable.
|
| 10 |
+
#
|
| 11 |
+
# This will define the following variables:
|
| 12 |
+
#
|
| 13 |
+
# ``WaylandScanner_FOUND``
|
| 14 |
+
# True if wayland-scanner is available.
|
| 15 |
+
#
|
| 16 |
+
# ``WaylandScanner_EXECUTABLE``
|
| 17 |
+
# The wayland-scanner executable.
|
| 18 |
+
#
|
| 19 |
+
# If ``WaylandScanner_FOUND`` is TRUE, it will also define the following imported
|
| 20 |
+
# target:
|
| 21 |
+
#
|
| 22 |
+
# ``Wayland::Scanner``
|
| 23 |
+
# The wayland-scanner executable.
|
| 24 |
+
#
|
| 25 |
+
# This module provides the following functions to generate C protocol
|
| 26 |
+
# implementations:
|
| 27 |
+
#
|
| 28 |
+
# - ``ecm_add_wayland_client_protocol``
|
| 29 |
+
# - ``ecm_add_wayland_server_protocol``
|
| 30 |
+
#
|
| 31 |
+
# ::
|
| 32 |
+
#
|
| 33 |
+
# ecm_add_wayland_client_protocol(<source_files_var>
|
| 34 |
+
# PROTOCOL <xmlfile>
|
| 35 |
+
# BASENAME <basename>)
|
| 36 |
+
#
|
| 37 |
+
# Generate Wayland client protocol files from ``<xmlfile>`` XML
|
| 38 |
+
# definition for the ``<basename>`` interface and append those files
|
| 39 |
+
# to ``<source_files_var>``.
|
| 40 |
+
#
|
| 41 |
+
# ::
|
| 42 |
+
#
|
| 43 |
+
# ecm_add_wayland_server_protocol(<source_files_var>
|
| 44 |
+
# PROTOCOL <xmlfile>
|
| 45 |
+
# BASENAME <basename>)
|
| 46 |
+
#
|
| 47 |
+
# Generate Wayland server protocol files from ``<xmlfile>`` XML
|
| 48 |
+
# definition for the ``<basename>`` interface and append those files
|
| 49 |
+
# to ``<source_files_var>``.
|
| 50 |
+
#
|
| 51 |
+
# Since 1.4.0.
|
| 52 |
+
|
| 53 |
+
#=============================================================================
|
| 54 |
+
# Copyright 2012-2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
| 55 |
+
#
|
| 56 |
+
# Redistribution and use in source and binary forms, with or without
|
| 57 |
+
# modification, are permitted provided that the following conditions
|
| 58 |
+
# are met:
|
| 59 |
+
#
|
| 60 |
+
# 1. Redistributions of source code must retain the copyright
|
| 61 |
+
# notice, this list of conditions and the following disclaimer.
|
| 62 |
+
# 2. Redistributions in binary form must reproduce the copyright
|
| 63 |
+
# notice, this list of conditions and the following disclaimer in the
|
| 64 |
+
# documentation and/or other materials provided with the distribution.
|
| 65 |
+
# 3. The name of the author may not be used to endorse or promote products
|
| 66 |
+
# derived from this software without specific prior written permission.
|
| 67 |
+
#
|
| 68 |
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
| 69 |
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
| 70 |
+
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
| 71 |
+
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
| 72 |
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
| 73 |
+
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| 74 |
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| 75 |
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| 76 |
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
| 77 |
+
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| 78 |
+
#=============================================================================
|
| 79 |
+
|
| 80 |
+
include(${CMAKE_CURRENT_LIST_DIR}/ECMFindModuleHelpers.cmake)
|
| 81 |
+
|
| 82 |
+
ecm_find_package_version_check(WaylandScanner)
|
| 83 |
+
|
| 84 |
+
# Find wayland-scanner
|
| 85 |
+
find_program(WaylandScanner_EXECUTABLE NAMES wayland-scanner)
|
| 86 |
+
|
| 87 |
+
include(FindPackageHandleStandardArgs)
|
| 88 |
+
find_package_handle_standard_args(WaylandScanner
|
| 89 |
+
FOUND_VAR
|
| 90 |
+
WaylandScanner_FOUND
|
| 91 |
+
REQUIRED_VARS
|
| 92 |
+
WaylandScanner_EXECUTABLE
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
mark_as_advanced(WaylandScanner_EXECUTABLE)
|
| 96 |
+
|
| 97 |
+
if(NOT TARGET Wayland::Scanner AND WaylandScanner_FOUND)
|
| 98 |
+
add_executable(Wayland::Scanner IMPORTED)
|
| 99 |
+
set_target_properties(Wayland::Scanner PROPERTIES
|
| 100 |
+
IMPORTED_LOCATION "${WaylandScanner_EXECUTABLE}"
|
| 101 |
+
)
|
| 102 |
+
endif()
|
| 103 |
+
|
| 104 |
+
include(FeatureSummary)
|
| 105 |
+
set_package_properties(WaylandScanner PROPERTIES
|
| 106 |
+
URL "https://wayland.freedesktop.org/"
|
| 107 |
+
DESCRIPTION "Executable that converts XML protocol files to C code"
|
| 108 |
+
)
|
| 109 |
+
|
| 110 |
+
function(ecm_add_wayland_client_protocol out_var)
|
| 111 |
+
# Parse arguments
|
| 112 |
+
set(oneValueArgs PROTOCOL BASENAME)
|
| 113 |
+
cmake_parse_arguments(ARGS "" "${oneValueArgs}" "" ${ARGN})
|
| 114 |
+
|
| 115 |
+
if(ARGS_UNPARSED_ARGUMENTS)
|
| 116 |
+
message(FATAL_ERROR "Unknown keywords given to ecm_add_wayland_client_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")
|
| 117 |
+
endif()
|
| 118 |
+
|
| 119 |
+
get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)
|
| 120 |
+
set(_client_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-client-protocol.h")
|
| 121 |
+
set(_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-protocol.c")
|
| 122 |
+
|
| 123 |
+
set_source_files_properties(${_client_header} GENERATED)
|
| 124 |
+
set_source_files_properties(${_code} GENERATED)
|
| 125 |
+
set_property(SOURCE ${_client_header} PROPERTY SKIP_AUTOMOC ON)
|
| 126 |
+
|
| 127 |
+
add_custom_command(OUTPUT "${_client_header}"
|
| 128 |
+
COMMAND ${WaylandScanner_EXECUTABLE} client-header ${_infile} ${_client_header}
|
| 129 |
+
DEPENDS ${WaylandScanner_EXECUTABLE} ${_infile}
|
| 130 |
+
VERBATIM
|
| 131 |
+
)
|
| 132 |
+
|
| 133 |
+
add_custom_command(OUTPUT "${_code}"
|
| 134 |
+
COMMAND ${WaylandScanner_EXECUTABLE} private-code ${_infile} ${_code}
|
| 135 |
+
DEPENDS ${WaylandScanner_EXECUTABLE} ${_infile} ${_client_header}
|
| 136 |
+
VERBATIM
|
| 137 |
+
)
|
| 138 |
+
|
| 139 |
+
list(APPEND ${out_var} "${_client_header}" "${_code}")
|
| 140 |
+
set(${out_var} ${${out_var}} PARENT_SCOPE)
|
| 141 |
+
endfunction()
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
function(ecm_add_wayland_server_protocol out_var)
|
| 145 |
+
# Parse arguments
|
| 146 |
+
set(oneValueArgs PROTOCOL BASENAME)
|
| 147 |
+
cmake_parse_arguments(ARGS "" "${oneValueArgs}" "" ${ARGN})
|
| 148 |
+
|
| 149 |
+
if(ARGS_UNPARSED_ARGUMENTS)
|
| 150 |
+
message(FATAL_ERROR "Unknown keywords given to ecm_add_wayland_server_protocol(): \"${ARGS_UNPARSED_ARGUMENTS}\"")
|
| 151 |
+
endif()
|
| 152 |
+
|
| 153 |
+
ecm_add_wayland_client_protocol(${out_var}
|
| 154 |
+
PROTOCOL ${ARGS_PROTOCOL}
|
| 155 |
+
BASENAME ${ARGS_BASENAME})
|
| 156 |
+
|
| 157 |
+
get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE)
|
| 158 |
+
set(_server_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-server-protocol.h")
|
| 159 |
+
set_property(SOURCE ${_server_header} PROPERTY SKIP_AUTOMOC ON)
|
| 160 |
+
set_source_files_properties(${_server_header} GENERATED)
|
| 161 |
+
|
| 162 |
+
add_custom_command(OUTPUT "${_server_header}"
|
| 163 |
+
COMMAND ${WaylandScanner_EXECUTABLE} server-header ${_infile} ${_server_header}
|
| 164 |
+
DEPENDS ${WaylandScanner_EXECUTABLE} ${_infile}
|
| 165 |
+
VERBATIM
|
| 166 |
+
)
|
| 167 |
+
|
| 168 |
+
list(APPEND ${out_var} "${_server_header}")
|
| 169 |
+
set(${out_var} ${${out_var}} PARENT_SCOPE)
|
| 170 |
+
endfunction()
|
third_party/tracy/cmake/config.cmake
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
if (NOT NO_ISA_EXTENSIONS)
|
| 2 |
+
include(CheckCXXCompilerFlag)
|
| 3 |
+
if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64")
|
| 4 |
+
CHECK_CXX_COMPILER_FLAG("-mcpu=native" COMPILER_SUPPORTS_MCPU_NATIVE)
|
| 5 |
+
if(COMPILER_SUPPORTS_MARCH_NATIVE)
|
| 6 |
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native")
|
| 7 |
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=native")
|
| 8 |
+
endif()
|
| 9 |
+
else()
|
| 10 |
+
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
|
| 11 |
+
if(COMPILER_SUPPORTS_MARCH_NATIVE)
|
| 12 |
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
|
| 13 |
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")
|
| 14 |
+
endif()
|
| 15 |
+
endif()
|
| 16 |
+
if(WIN32)
|
| 17 |
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2")
|
| 18 |
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:AVX2")
|
| 19 |
+
endif()
|
| 20 |
+
endif()
|
| 21 |
+
|
| 22 |
+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT LEGACY)
|
| 23 |
+
set(USE_WAYLAND ON)
|
| 24 |
+
else()
|
| 25 |
+
set(USE_WAYLAND OFF)
|
| 26 |
+
endif()
|
| 27 |
+
|
| 28 |
+
if(WIN32)
|
| 29 |
+
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN)
|
| 30 |
+
add_compile_options(/MP)
|
| 31 |
+
else()
|
| 32 |
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
|
| 33 |
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always")
|
| 34 |
+
endif()
|
| 35 |
+
|
| 36 |
+
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT EMSCRIPTEN)
|
| 37 |
+
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
| 38 |
+
endif()
|
| 39 |
+
|
| 40 |
+
if(EMSCRIPTEN)
|
| 41 |
+
add_compile_options(-pthread)
|
| 42 |
+
add_link_options(-pthread)
|
| 43 |
+
endif()
|
| 44 |
+
|
| 45 |
+
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT EMSCRIPTEN)
|
| 46 |
+
find_program(MOLD_LINKER mold)
|
| 47 |
+
if(MOLD_LINKER)
|
| 48 |
+
set(CMAKE_LINKER_TYPE "MOLD")
|
| 49 |
+
endif()
|
| 50 |
+
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
| 51 |
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-eliminate-unused-debug-types")
|
| 52 |
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-eliminate-unused-debug-types")
|
| 53 |
+
endif()
|
| 54 |
+
endif()
|
| 55 |
+
|
| 56 |
+
file(GENERATE OUTPUT .gitignore CONTENT "*")
|
third_party/tracy/cmake/server.cmake
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
set(TRACY_COMMON_DIR ${CMAKE_CURRENT_LIST_DIR}/../public/common)
|
| 2 |
+
|
| 3 |
+
set(TRACY_COMMON_SOURCES
|
| 4 |
+
tracy_lz4.cpp
|
| 5 |
+
tracy_lz4hc.cpp
|
| 6 |
+
TracySocket.cpp
|
| 7 |
+
TracyStackFrames.cpp
|
| 8 |
+
TracySystem.cpp
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
list(TRANSFORM TRACY_COMMON_SOURCES PREPEND "${TRACY_COMMON_DIR}/")
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
set(TRACY_SERVER_DIR ${CMAKE_CURRENT_LIST_DIR}/../server)
|
| 15 |
+
|
| 16 |
+
set(TRACY_SERVER_SOURCES
|
| 17 |
+
TracyMemory.cpp
|
| 18 |
+
TracyMmap.cpp
|
| 19 |
+
TracyPrint.cpp
|
| 20 |
+
TracySysUtil.cpp
|
| 21 |
+
TracyTaskDispatch.cpp
|
| 22 |
+
TracyTextureCompression.cpp
|
| 23 |
+
TracyThreadCompress.cpp
|
| 24 |
+
TracyWorker.cpp
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
list(TRANSFORM TRACY_SERVER_SOURCES PREPEND "${TRACY_SERVER_DIR}/")
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
add_library(TracyServer STATIC ${TRACY_COMMON_SOURCES} ${TRACY_SERVER_SOURCES})
|
| 31 |
+
target_include_directories(TracyServer PUBLIC ${TRACY_COMMON_DIR} ${TRACY_SERVER_DIR})
|
| 32 |
+
target_link_libraries(TracyServer PUBLIC TracyCapstone TracyZstd)
|
| 33 |
+
if(NO_STATISTICS)
|
| 34 |
+
target_compile_definitions(TracyServer PUBLIC TRACY_NO_STATISTICS)
|
| 35 |
+
endif()
|
| 36 |
+
|
| 37 |
+
if(NOT NO_PARALLEL_STL AND UNIX AND NOT APPLE AND NOT EMSCRIPTEN)
|
| 38 |
+
target_link_libraries(TracyServer PRIVATE TracyTbb)
|
| 39 |
+
endif()
|
third_party/tracy/cmake/vendor.cmake
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Vendor Specific CMake
|
| 2 |
+
# The Tracy project keeps most vendor source locally
|
| 3 |
+
|
| 4 |
+
set (ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../")
|
| 5 |
+
|
| 6 |
+
# Dependencies are taken from the system first and if not found, they are pulled with CPM and built from source
|
| 7 |
+
|
| 8 |
+
include(FindPkgConfig)
|
| 9 |
+
include(${CMAKE_CURRENT_LIST_DIR}/CPM.cmake)
|
| 10 |
+
|
| 11 |
+
option(DOWNLOAD_CAPSTONE "Force download capstone" ON)
|
| 12 |
+
option(DOWNLOAD_GLFW "Force download glfw" OFF)
|
| 13 |
+
option(DOWNLOAD_FREETYPE "Force download freetype" OFF)
|
| 14 |
+
|
| 15 |
+
# capstone
|
| 16 |
+
|
| 17 |
+
pkg_check_modules(CAPSTONE capstone)
|
| 18 |
+
if(CAPSTONE_FOUND AND NOT DOWNLOAD_CAPSTONE)
|
| 19 |
+
message(STATUS "Capstone found: ${CAPSTONE}")
|
| 20 |
+
add_library(TracyCapstone INTERFACE)
|
| 21 |
+
target_include_directories(TracyCapstone INTERFACE ${CAPSTONE_INCLUDE_DIRS})
|
| 22 |
+
target_link_libraries(TracyCapstone INTERFACE ${CAPSTONE_LINK_LIBRARIES})
|
| 23 |
+
else()
|
| 24 |
+
CPMAddPackage(
|
| 25 |
+
NAME capstone
|
| 26 |
+
GITHUB_REPOSITORY capstone-engine/capstone
|
| 27 |
+
GIT_TAG 5.0.3
|
| 28 |
+
)
|
| 29 |
+
add_library(TracyCapstone INTERFACE)
|
| 30 |
+
target_include_directories(TracyCapstone INTERFACE ${capstone_SOURCE_DIR}/include/capstone)
|
| 31 |
+
target_link_libraries(TracyCapstone INTERFACE capstone)
|
| 32 |
+
endif()
|
| 33 |
+
|
| 34 |
+
# GLFW
|
| 35 |
+
|
| 36 |
+
if(NOT USE_WAYLAND AND NOT EMSCRIPTEN)
|
| 37 |
+
pkg_check_modules(GLFW glfw3)
|
| 38 |
+
if (GLFW_FOUND AND NOT DOWNLOAD_GLFW)
|
| 39 |
+
add_library(TracyGlfw3 INTERFACE)
|
| 40 |
+
target_include_directories(TracyGlfw3 INTERFACE ${GLFW_INCLUDE_DIRS})
|
| 41 |
+
target_link_libraries(TracyGlfw3 INTERFACE ${GLFW_LINK_LIBRARIES})
|
| 42 |
+
else()
|
| 43 |
+
CPMAddPackage(
|
| 44 |
+
NAME glfw
|
| 45 |
+
GITHUB_REPOSITORY glfw/glfw
|
| 46 |
+
GIT_TAG 3.4
|
| 47 |
+
OPTIONS
|
| 48 |
+
"GLFW_BUILD_EXAMPLES OFF"
|
| 49 |
+
"GLFW_BUILD_TESTS OFF"
|
| 50 |
+
"GLFW_BUILD_DOCS OFF"
|
| 51 |
+
"GLFW_INSTALL OFF"
|
| 52 |
+
)
|
| 53 |
+
add_library(TracyGlfw3 INTERFACE)
|
| 54 |
+
target_link_libraries(TracyGlfw3 INTERFACE glfw)
|
| 55 |
+
endif()
|
| 56 |
+
endif()
|
| 57 |
+
|
| 58 |
+
# freetype
|
| 59 |
+
|
| 60 |
+
pkg_check_modules(FREETYPE freetype2)
|
| 61 |
+
if (FREETYPE_FOUND AND NOT DOWNLOAD_FREETYPE)
|
| 62 |
+
add_library(TracyFreetype INTERFACE)
|
| 63 |
+
target_include_directories(TracyFreetype INTERFACE ${FREETYPE_INCLUDE_DIRS})
|
| 64 |
+
target_link_libraries(TracyFreetype INTERFACE ${FREETYPE_LINK_LIBRARIES})
|
| 65 |
+
else()
|
| 66 |
+
CPMAddPackage(
|
| 67 |
+
NAME freetype
|
| 68 |
+
GITHUB_REPOSITORY freetype/freetype
|
| 69 |
+
GIT_TAG VER-2-13-2
|
| 70 |
+
OPTIONS
|
| 71 |
+
"FT_DISABLE_HARFBUZZ ON"
|
| 72 |
+
"FT_WITH_HARFBUZZ OFF"
|
| 73 |
+
)
|
| 74 |
+
add_library(TracyFreetype INTERFACE)
|
| 75 |
+
target_link_libraries(TracyFreetype INTERFACE freetype)
|
| 76 |
+
endif()
|
| 77 |
+
|
| 78 |
+
# zstd
|
| 79 |
+
|
| 80 |
+
set(ZSTD_DIR "${ROOT_DIR}/zstd")
|
| 81 |
+
|
| 82 |
+
set(ZSTD_SOURCES
|
| 83 |
+
decompress/zstd_ddict.c
|
| 84 |
+
decompress/zstd_decompress_block.c
|
| 85 |
+
decompress/huf_decompress.c
|
| 86 |
+
decompress/zstd_decompress.c
|
| 87 |
+
common/zstd_common.c
|
| 88 |
+
common/error_private.c
|
| 89 |
+
common/xxhash.c
|
| 90 |
+
common/entropy_common.c
|
| 91 |
+
common/debug.c
|
| 92 |
+
common/threading.c
|
| 93 |
+
common/pool.c
|
| 94 |
+
common/fse_decompress.c
|
| 95 |
+
compress/zstd_ldm.c
|
| 96 |
+
compress/zstd_compress_superblock.c
|
| 97 |
+
compress/zstd_opt.c
|
| 98 |
+
compress/zstd_compress_sequences.c
|
| 99 |
+
compress/fse_compress.c
|
| 100 |
+
compress/zstd_double_fast.c
|
| 101 |
+
compress/zstd_compress.c
|
| 102 |
+
compress/zstd_compress_literals.c
|
| 103 |
+
compress/hist.c
|
| 104 |
+
compress/zstdmt_compress.c
|
| 105 |
+
compress/zstd_lazy.c
|
| 106 |
+
compress/huf_compress.c
|
| 107 |
+
compress/zstd_fast.c
|
| 108 |
+
dictBuilder/zdict.c
|
| 109 |
+
dictBuilder/cover.c
|
| 110 |
+
dictBuilder/divsufsort.c
|
| 111 |
+
dictBuilder/fastcover.c
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
list(TRANSFORM ZSTD_SOURCES PREPEND "${ZSTD_DIR}/")
|
| 115 |
+
|
| 116 |
+
set_property(SOURCE ${ZSTD_DIR}/decompress/huf_decompress_amd64.S APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp")
|
| 117 |
+
|
| 118 |
+
add_library(TracyZstd STATIC ${ZSTD_SOURCES})
|
| 119 |
+
target_include_directories(TracyZstd PUBLIC ${ZSTD_DIR})
|
| 120 |
+
target_compile_definitions(TracyZstd PRIVATE ZSTD_DISABLE_ASM)
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
# Diff Template Library
|
| 124 |
+
|
| 125 |
+
set(DTL_DIR "${ROOT_DIR}/dtl")
|
| 126 |
+
file(GLOB_RECURSE DTL_HEADERS CONFIGURE_DEPENDS RELATIVE ${DTL_DIR} "*.hpp")
|
| 127 |
+
add_library(TracyDtl INTERFACE)
|
| 128 |
+
target_sources(TracyDtl INTERFACE ${DTL_HEADERS})
|
| 129 |
+
target_include_directories(TracyDtl INTERFACE ${DTL_DIR})
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
# Get Opt
|
| 133 |
+
|
| 134 |
+
set(GETOPT_DIR "${ROOT_DIR}/getopt")
|
| 135 |
+
set(GETOPT_SOURCES ${GETOPT_DIR}/getopt.c)
|
| 136 |
+
set(GETOPT_HEADERS ${GETOPT_DIR}/getopt.h)
|
| 137 |
+
add_library(TracyGetOpt STATIC ${GETOPT_SOURCES} ${GETOPT_HEADERS})
|
| 138 |
+
target_include_directories(TracyGetOpt PUBLIC ${GETOPT_DIR})
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
# ImGui
|
| 142 |
+
|
| 143 |
+
set(IMGUI_DIR "${ROOT_DIR}/imgui")
|
| 144 |
+
|
| 145 |
+
set(IMGUI_SOURCES
|
| 146 |
+
imgui_widgets.cpp
|
| 147 |
+
imgui_draw.cpp
|
| 148 |
+
imgui_demo.cpp
|
| 149 |
+
imgui.cpp
|
| 150 |
+
imgui_tables.cpp
|
| 151 |
+
misc/freetype/imgui_freetype.cpp
|
| 152 |
+
)
|
| 153 |
+
|
| 154 |
+
list(TRANSFORM IMGUI_SOURCES PREPEND "${IMGUI_DIR}/")
|
| 155 |
+
|
| 156 |
+
add_definitions(-DIMGUI_ENABLE_FREETYPE)
|
| 157 |
+
|
| 158 |
+
add_library(TracyImGui STATIC ${IMGUI_SOURCES})
|
| 159 |
+
target_include_directories(TracyImGui PUBLIC ${IMGUI_DIR})
|
| 160 |
+
target_link_libraries(TracyImGui PUBLIC TracyFreetype)
|
| 161 |
+
|
| 162 |
+
# NFD
|
| 163 |
+
|
| 164 |
+
if (NOT NO_FILESELECTOR AND NOT EMSCRIPTEN)
|
| 165 |
+
set(NFD_DIR "${ROOT_DIR}/nfd")
|
| 166 |
+
|
| 167 |
+
if (WIN32)
|
| 168 |
+
set(NFD_SOURCES "${NFD_DIR}/nfd_win.cpp")
|
| 169 |
+
elseif (APPLE)
|
| 170 |
+
set(NFD_SOURCES "${NFD_DIR}/nfd_cocoa.m")
|
| 171 |
+
else()
|
| 172 |
+
if (GTK_FILESELECTOR)
|
| 173 |
+
set(NFD_SOURCES "${NFD_DIR}/nfd_gtk.cpp")
|
| 174 |
+
else()
|
| 175 |
+
set(NFD_SOURCES "${NFD_DIR}/nfd_portal.cpp")
|
| 176 |
+
endif()
|
| 177 |
+
endif()
|
| 178 |
+
|
| 179 |
+
file(GLOB_RECURSE NFD_HEADERS CONFIGURE_DEPENDS RELATIVE ${NFD_DIR} "*.h")
|
| 180 |
+
add_library(TracyNfd STATIC ${NFD_SOURCES} ${NFD_HEADERS})
|
| 181 |
+
target_include_directories(TracyNfd PUBLIC ${NFD_DIR})
|
| 182 |
+
|
| 183 |
+
if (APPLE)
|
| 184 |
+
find_library(APPKIT_LIBRARY AppKit)
|
| 185 |
+
find_library(UNIFORMTYPEIDENTIFIERS_LIBRARY UniformTypeIdentifiers)
|
| 186 |
+
target_link_libraries(TracyNfd PUBLIC ${APPKIT_LIBRARY} ${UNIFORMTYPEIDENTIFIERS_LIBRARY})
|
| 187 |
+
elseif (UNIX)
|
| 188 |
+
if (GTK_FILESELECTOR)
|
| 189 |
+
pkg_check_modules(GTK3 gtk+-3.0)
|
| 190 |
+
if (NOT GTK3_FOUND)
|
| 191 |
+
message(FATAL_ERROR "GTK3 not found. Please install it or set TRACY_GTK_FILESELECTOR to OFF.")
|
| 192 |
+
endif()
|
| 193 |
+
add_library(TracyGtk3 INTERFACE)
|
| 194 |
+
target_include_directories(TracyGtk3 INTERFACE ${GTK3_INCLUDE_DIRS})
|
| 195 |
+
target_link_libraries(TracyGtk3 INTERFACE ${GTK3_LINK_LIBRARIES})
|
| 196 |
+
target_link_libraries(TracyNfd PUBLIC TracyGtk3)
|
| 197 |
+
else()
|
| 198 |
+
pkg_check_modules(DBUS dbus-1)
|
| 199 |
+
if (NOT DBUS_FOUND)
|
| 200 |
+
message(FATAL_ERROR "D-Bus not found. Please install it or set TRACY_GTK_FILESELECTOR to ON.")
|
| 201 |
+
endif()
|
| 202 |
+
add_library(TracyDbus INTERFACE)
|
| 203 |
+
target_include_directories(TracyDbus INTERFACE ${DBUS_INCLUDE_DIRS})
|
| 204 |
+
target_link_libraries(TracyDbus INTERFACE ${DBUS_LINK_LIBRARIES})
|
| 205 |
+
target_link_libraries(TracyNfd PUBLIC TracyDbus)
|
| 206 |
+
endif()
|
| 207 |
+
endif()
|
| 208 |
+
endif()
|
| 209 |
+
|
| 210 |
+
# TBB
|
| 211 |
+
if (NO_PARALLEL_STL)
|
| 212 |
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNO_PARALLEL_SORT")
|
| 213 |
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_PARALLEL_SORT")
|
| 214 |
+
else()
|
| 215 |
+
if (UNIX AND NOT APPLE AND NOT EMSCRIPTEN)
|
| 216 |
+
# Tracy does not use TBB directly, but the implementation of parallel algorithms
|
| 217 |
+
# in some versions of libstdc++ depends on TBB. When it does, you must
|
| 218 |
+
# explicitly link against -ltbb.
|
| 219 |
+
#
|
| 220 |
+
# Some distributions have pgk-config files for TBB, others don't.
|
| 221 |
+
|
| 222 |
+
pkg_check_modules(TBB tbb)
|
| 223 |
+
if (TBB_FOUND)
|
| 224 |
+
add_library(TracyTbb INTERFACE)
|
| 225 |
+
target_include_directories(TracyTbb INTERFACE ${TBB_INCLUDE_DIRS})
|
| 226 |
+
target_link_libraries(TracyTbb INTERFACE ${TBB_LINK_LIBRARIES})
|
| 227 |
+
else()
|
| 228 |
+
CPMAddPackage(
|
| 229 |
+
NAME tbb
|
| 230 |
+
GITHUB_REPOSITORY oneapi-src/oneTBB
|
| 231 |
+
GIT_TAG v2021.12.0-rc2
|
| 232 |
+
OPTIONS "TBB_TEST OFF"
|
| 233 |
+
)
|
| 234 |
+
add_library(TracyTbb INTERFACE)
|
| 235 |
+
target_link_libraries(TracyTbb INTERFACE tbb)
|
| 236 |
+
endif()
|
| 237 |
+
endif()
|
| 238 |
+
endif()
|
third_party/tracy/cmake/version.cmake
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cmake_minimum_required(VERSION 3.10)
|
| 2 |
+
|
| 3 |
+
message("Parsing public/common/TracyVersion.hpp file")
|
| 4 |
+
|
| 5 |
+
file(READ "${CMAKE_CURRENT_LIST_DIR}/../public/common/TracyVersion.hpp" version)
|
| 6 |
+
|
| 7 |
+
# Note: This looks for a specific pattern in TracyVersion.hpp, if it changes
|
| 8 |
+
# this needs updating.
|
| 9 |
+
string(REGEX MATCH "Major = ([0-9]+)" _ ${version})
|
| 10 |
+
|
| 11 |
+
# This works do to the above () subexpression selection. See
|
| 12 |
+
# https://cmake.org/cmake/help/latest/command/string.html#regex-match for more
|
| 13 |
+
# details
|
| 14 |
+
set(TRACY_VERSION_MAJOR ${CMAKE_MATCH_1})
|
| 15 |
+
|
| 16 |
+
string(REGEX MATCH "Minor = ([0-9]+)" _ ${version})
|
| 17 |
+
set(TRACY_VERSION_MINOR ${CMAKE_MATCH_1})
|
| 18 |
+
|
| 19 |
+
string(REGEX MATCH "Patch = ([0-9]+)" _ ${version})
|
| 20 |
+
set(TRACY_VERSION_PATCH ${CMAKE_MATCH_1})
|
| 21 |
+
|
| 22 |
+
set(TRACY_VERSION_STRING "${TRACY_VERSION_MAJOR}.${TRACY_VERSION_MINOR}.${TRACY_VERSION_PATCH}")
|
| 23 |
+
|
| 24 |
+
message("VERSION ${TRACY_VERSION_STRING}")
|
third_party/tracy/csvexport/CMakeLists.txt
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cmake_minimum_required(VERSION 3.16)
|
| 2 |
+
|
| 3 |
+
option(NO_ISA_EXTENSIONS "Disable ISA extensions (don't pass -march=native or -mcpu=native to the compiler)" OFF)
|
| 4 |
+
option(NO_PARALLEL_STL "Disable parallel STL" OFF)
|
| 5 |
+
|
| 6 |
+
set(NO_STATISTICS OFF)
|
| 7 |
+
|
| 8 |
+
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/version.cmake)
|
| 9 |
+
|
| 10 |
+
set(CMAKE_CXX_STANDARD 20)
|
| 11 |
+
|
| 12 |
+
project(
|
| 13 |
+
tracy-csvexport
|
| 14 |
+
LANGUAGES C CXX
|
| 15 |
+
VERSION ${TRACY_VERSION_STRING}
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/config.cmake)
|
| 19 |
+
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/vendor.cmake)
|
| 20 |
+
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/server.cmake)
|
| 21 |
+
|
| 22 |
+
set(PROGRAM_FILES
|
| 23 |
+
src/csvexport.cpp
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
add_executable(${PROJECT_NAME} ${PROGRAM_FILES} ${COMMON_FILES} ${SERVER_FILES})
|
| 27 |
+
target_link_libraries(${PROJECT_NAME} PRIVATE TracyServer TracyGetOpt)
|
| 28 |
+
set_property(DIRECTORY ${CMAKE_CURRENT_LIST_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME})
|
third_party/tracy/csvexport/src/csvexport.cpp
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#ifdef _WIN32
|
| 2 |
+
# include <windows.h>
|
| 3 |
+
#endif
|
| 4 |
+
|
| 5 |
+
#include <algorithm>
|
| 6 |
+
#include <cctype>
|
| 7 |
+
#include <fstream>
|
| 8 |
+
#include <iostream>
|
| 9 |
+
#include <sstream>
|
| 10 |
+
#include <string>
|
| 11 |
+
|
| 12 |
+
#include <math.h>
|
| 13 |
+
#include <stdio.h>
|
| 14 |
+
#include <stdint.h>
|
| 15 |
+
|
| 16 |
+
#include "../../server/TracyFileRead.hpp"
|
| 17 |
+
#include "../../server/TracyWorker.hpp"
|
| 18 |
+
#include "../../getopt/getopt.h"
|
| 19 |
+
|
| 20 |
+
void print_usage_exit(int e)
|
| 21 |
+
{
|
| 22 |
+
fprintf(stderr, "Extract statistics from a trace to a CSV format\n");
|
| 23 |
+
fprintf(stderr, "Usage:\n");
|
| 24 |
+
fprintf(stderr, " extract [OPTION...] <trace file>\n");
|
| 25 |
+
fprintf(stderr, "\n");
|
| 26 |
+
fprintf(stderr, " -h, --help Print usage\n");
|
| 27 |
+
fprintf(stderr, " -f, --filter arg Filter zone names (default: "")\n");
|
| 28 |
+
fprintf(stderr, " -s, --sep arg CSV separator (default: ,)\n");
|
| 29 |
+
fprintf(stderr, " -c, --case Case sensitive filtering\n");
|
| 30 |
+
fprintf(stderr, " -e, --self Get self times\n");
|
| 31 |
+
fprintf(stderr, " -u, --unwrap Report each zone event\n");
|
| 32 |
+
fprintf(stderr, " -m, --messages Report only messages\n");
|
| 33 |
+
|
| 34 |
+
exit(e);
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
struct Args {
|
| 38 |
+
const char* filter;
|
| 39 |
+
const char* separator;
|
| 40 |
+
const char* trace_file;
|
| 41 |
+
bool case_sensitive;
|
| 42 |
+
bool self_time;
|
| 43 |
+
bool unwrap;
|
| 44 |
+
bool unwrapMessages;
|
| 45 |
+
};
|
| 46 |
+
|
| 47 |
+
Args parse_args(int argc, char** argv)
|
| 48 |
+
{
|
| 49 |
+
if (argc == 1)
|
| 50 |
+
{
|
| 51 |
+
print_usage_exit(1);
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
Args args = { "", ",", "", false, false, false, false };
|
| 55 |
+
|
| 56 |
+
struct option long_opts[] = {
|
| 57 |
+
{ "help", no_argument, NULL, 'h' },
|
| 58 |
+
{ "filter", optional_argument, NULL, 'f' },
|
| 59 |
+
{ "sep", optional_argument, NULL, 's' },
|
| 60 |
+
{ "case", no_argument, NULL, 'c' },
|
| 61 |
+
{ "self", no_argument, NULL, 'e' },
|
| 62 |
+
{ "unwrap", no_argument, NULL, 'u' },
|
| 63 |
+
{ "messages", no_argument, NULL, 'm' },
|
| 64 |
+
{ NULL, 0, NULL, 0 }
|
| 65 |
+
};
|
| 66 |
+
|
| 67 |
+
int c;
|
| 68 |
+
while ((c = getopt_long(argc, argv, "hf:s:ceum", long_opts, NULL)) != -1)
|
| 69 |
+
{
|
| 70 |
+
switch (c)
|
| 71 |
+
{
|
| 72 |
+
case 'h':
|
| 73 |
+
print_usage_exit(0);
|
| 74 |
+
break;
|
| 75 |
+
case 'f':
|
| 76 |
+
args.filter = optarg;
|
| 77 |
+
break;
|
| 78 |
+
case 's':
|
| 79 |
+
args.separator = optarg;
|
| 80 |
+
break;
|
| 81 |
+
case 'c':
|
| 82 |
+
args.case_sensitive = true;
|
| 83 |
+
break;
|
| 84 |
+
case 'e':
|
| 85 |
+
args.self_time = true;
|
| 86 |
+
break;
|
| 87 |
+
case 'u':
|
| 88 |
+
args.unwrap = true;
|
| 89 |
+
break;
|
| 90 |
+
case 'm':
|
| 91 |
+
args.unwrapMessages = true;
|
| 92 |
+
break;
|
| 93 |
+
default:
|
| 94 |
+
print_usage_exit(1);
|
| 95 |
+
break;
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
if (argc != optind + 1)
|
| 100 |
+
{
|
| 101 |
+
print_usage_exit(1);
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
args.trace_file = argv[optind];
|
| 105 |
+
|
| 106 |
+
return args;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
bool is_substring(
|
| 110 |
+
const char* term,
|
| 111 |
+
const char* s,
|
| 112 |
+
bool case_sensitive = false
|
| 113 |
+
){
|
| 114 |
+
auto new_term = std::string(term);
|
| 115 |
+
auto new_s = std::string(s);
|
| 116 |
+
|
| 117 |
+
if (!case_sensitive) {
|
| 118 |
+
std::transform(
|
| 119 |
+
new_term.begin(),
|
| 120 |
+
new_term.end(),
|
| 121 |
+
new_term.begin(),
|
| 122 |
+
[](unsigned char c){ return std::tolower(c); }
|
| 123 |
+
);
|
| 124 |
+
|
| 125 |
+
std::transform(
|
| 126 |
+
new_s.begin(),
|
| 127 |
+
new_s.end(),
|
| 128 |
+
new_s.begin(),
|
| 129 |
+
[](unsigned char c){ return std::tolower(c); }
|
| 130 |
+
);
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
return new_s.find(new_term) != std::string::npos;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
const char* get_name(int32_t id, const tracy::Worker& worker)
|
| 137 |
+
{
|
| 138 |
+
auto& srcloc = worker.GetSourceLocation(id);
|
| 139 |
+
return worker.GetString(srcloc.name.active ? srcloc.name : srcloc.function);
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
template <typename T>
|
| 143 |
+
std::string join(const T& v, const char* sep) {
|
| 144 |
+
std::ostringstream s;
|
| 145 |
+
for (const auto& i : v) {
|
| 146 |
+
if (&i != &v[0]) {
|
| 147 |
+
s << sep;
|
| 148 |
+
}
|
| 149 |
+
s << i;
|
| 150 |
+
}
|
| 151 |
+
return s.str();
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
// From TracyView.cpp
|
| 155 |
+
int64_t GetZoneChildTimeFast(
|
| 156 |
+
const tracy::Worker& worker,
|
| 157 |
+
const tracy::ZoneEvent& zone
|
| 158 |
+
){
|
| 159 |
+
int64_t time = 0;
|
| 160 |
+
if( zone.HasChildren() )
|
| 161 |
+
{
|
| 162 |
+
auto& children = worker.GetZoneChildren( zone.Child() );
|
| 163 |
+
if( children.is_magic() )
|
| 164 |
+
{
|
| 165 |
+
auto& vec = *(tracy::Vector<tracy::ZoneEvent>*)&children;
|
| 166 |
+
for( auto& v : vec )
|
| 167 |
+
{
|
| 168 |
+
assert( v.IsEndValid() );
|
| 169 |
+
time += v.End() - v.Start();
|
| 170 |
+
}
|
| 171 |
+
}
|
| 172 |
+
else
|
| 173 |
+
{
|
| 174 |
+
for( auto& v : children )
|
| 175 |
+
{
|
| 176 |
+
assert( v->IsEndValid() );
|
| 177 |
+
time += v->End() - v->Start();
|
| 178 |
+
}
|
| 179 |
+
}
|
| 180 |
+
}
|
| 181 |
+
return time;
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
int main(int argc, char** argv)
|
| 185 |
+
{
|
| 186 |
+
#ifdef _WIN32
|
| 187 |
+
if (!AttachConsole(ATTACH_PARENT_PROCESS))
|
| 188 |
+
{
|
| 189 |
+
AllocConsole();
|
| 190 |
+
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
|
| 191 |
+
}
|
| 192 |
+
#endif
|
| 193 |
+
|
| 194 |
+
Args args = parse_args(argc, argv);
|
| 195 |
+
|
| 196 |
+
auto f = std::unique_ptr<tracy::FileRead>(
|
| 197 |
+
tracy::FileRead::Open(args.trace_file)
|
| 198 |
+
);
|
| 199 |
+
if (!f)
|
| 200 |
+
{
|
| 201 |
+
fprintf(stderr, "Could not open file %s\n", args.trace_file);
|
| 202 |
+
return 1;
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
auto worker = tracy::Worker(*f);
|
| 206 |
+
|
| 207 |
+
if (args.unwrapMessages)
|
| 208 |
+
{
|
| 209 |
+
const auto& msgs = worker.GetMessages();
|
| 210 |
+
|
| 211 |
+
if (msgs.size() > 0)
|
| 212 |
+
{
|
| 213 |
+
std::vector<const char*> columnsForMessages;
|
| 214 |
+
columnsForMessages = {
|
| 215 |
+
"MessageName", "total_ns"
|
| 216 |
+
};
|
| 217 |
+
std::string headerForMessages = join(columnsForMessages, args.separator);
|
| 218 |
+
printf("%s\n", headerForMessages.data());
|
| 219 |
+
|
| 220 |
+
for(auto& it : msgs)
|
| 221 |
+
{
|
| 222 |
+
std::vector<std::string> values(columnsForMessages.size());
|
| 223 |
+
|
| 224 |
+
values[0] = worker.GetString(it->ref);
|
| 225 |
+
values[1] = std::to_string(it->time);
|
| 226 |
+
|
| 227 |
+
std::string row = join(values, args.separator);
|
| 228 |
+
printf("%s\n", row.data());
|
| 229 |
+
}
|
| 230 |
+
}
|
| 231 |
+
else
|
| 232 |
+
{
|
| 233 |
+
printf("There are currently no messages!\n");
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
return 0;
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
while (!worker.AreSourceLocationZonesReady())
|
| 240 |
+
{
|
| 241 |
+
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
auto& slz = worker.GetSourceLocationZones();
|
| 245 |
+
tracy::Vector<decltype(slz.begin())> slz_selected;
|
| 246 |
+
slz_selected.reserve(slz.size());
|
| 247 |
+
|
| 248 |
+
uint32_t total_cnt = 0;
|
| 249 |
+
for(auto it = slz.begin(); it != slz.end(); ++it)
|
| 250 |
+
{
|
| 251 |
+
if(it->second.total != 0)
|
| 252 |
+
{
|
| 253 |
+
++total_cnt;
|
| 254 |
+
if(args.filter[0] == '\0')
|
| 255 |
+
{
|
| 256 |
+
slz_selected.push_back_no_space_check(it);
|
| 257 |
+
}
|
| 258 |
+
else
|
| 259 |
+
{
|
| 260 |
+
auto name = get_name(it->first, worker);
|
| 261 |
+
if(is_substring(args.filter, name, args.case_sensitive))
|
| 262 |
+
{
|
| 263 |
+
slz_selected.push_back_no_space_check(it);
|
| 264 |
+
}
|
| 265 |
+
}
|
| 266 |
+
}
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
std::vector<const char*> columns;
|
| 270 |
+
if (args.unwrap)
|
| 271 |
+
{
|
| 272 |
+
columns = {
|
| 273 |
+
"name", "src_file", "src_line", "ns_since_start", "exec_time_ns", "thread"
|
| 274 |
+
};
|
| 275 |
+
}
|
| 276 |
+
else
|
| 277 |
+
{
|
| 278 |
+
columns = {
|
| 279 |
+
"name", "src_file", "src_line", "total_ns", "total_perc",
|
| 280 |
+
"counts", "mean_ns", "min_ns", "max_ns", "std_ns"
|
| 281 |
+
};
|
| 282 |
+
}
|
| 283 |
+
std::string header = join(columns, args.separator);
|
| 284 |
+
printf("%s\n", header.data());
|
| 285 |
+
|
| 286 |
+
const auto last_time = worker.GetLastTime();
|
| 287 |
+
for(auto& it : slz_selected)
|
| 288 |
+
{
|
| 289 |
+
std::vector<std::string> values(columns.size());
|
| 290 |
+
|
| 291 |
+
values[0] = get_name(it->first, worker);
|
| 292 |
+
|
| 293 |
+
const auto& srcloc = worker.GetSourceLocation(it->first);
|
| 294 |
+
values[1] = worker.GetString(srcloc.file);
|
| 295 |
+
values[2] = std::to_string(srcloc.line);
|
| 296 |
+
|
| 297 |
+
const auto& zone_data = it->second;
|
| 298 |
+
|
| 299 |
+
if (args.unwrap)
|
| 300 |
+
{
|
| 301 |
+
int i = 0;
|
| 302 |
+
for (const auto& zone_thread_data : zone_data.zones) {
|
| 303 |
+
const auto zone_event = zone_thread_data.Zone();
|
| 304 |
+
const auto tId = zone_thread_data.Thread();
|
| 305 |
+
const auto start = zone_event->Start();
|
| 306 |
+
const auto end = zone_event->End();
|
| 307 |
+
|
| 308 |
+
values[3] = std::to_string(start);
|
| 309 |
+
|
| 310 |
+
auto timespan = end - start;
|
| 311 |
+
if (args.self_time) {
|
| 312 |
+
timespan -= GetZoneChildTimeFast(worker, *zone_event);
|
| 313 |
+
}
|
| 314 |
+
values[4] = std::to_string(timespan);
|
| 315 |
+
values[5] = std::to_string(tId);
|
| 316 |
+
|
| 317 |
+
std::string row = join(values, args.separator);
|
| 318 |
+
printf("%s\n", row.data());
|
| 319 |
+
}
|
| 320 |
+
}
|
| 321 |
+
else
|
| 322 |
+
{
|
| 323 |
+
const auto time = args.self_time ? zone_data.selfTotal : zone_data.total;
|
| 324 |
+
values[3] = std::to_string(time);
|
| 325 |
+
values[4] = std::to_string(100. * time / last_time);
|
| 326 |
+
|
| 327 |
+
values[5] = std::to_string(zone_data.zones.size());
|
| 328 |
+
|
| 329 |
+
const auto avg = (args.self_time ? zone_data.selfTotal : zone_data.total)
|
| 330 |
+
/ zone_data.zones.size();
|
| 331 |
+
values[6] = std::to_string(avg);
|
| 332 |
+
|
| 333 |
+
const auto tmin = args.self_time ? zone_data.selfMin : zone_data.min;
|
| 334 |
+
const auto tmax = args.self_time ? zone_data.selfMax : zone_data.max;
|
| 335 |
+
values[7] = std::to_string(tmin);
|
| 336 |
+
values[8] = std::to_string(tmax);
|
| 337 |
+
|
| 338 |
+
const auto sz = zone_data.zones.size();
|
| 339 |
+
const auto ss = zone_data.sumSq
|
| 340 |
+
- 2. * zone_data.total * avg
|
| 341 |
+
+ avg * avg * sz;
|
| 342 |
+
double std = 0;
|
| 343 |
+
if( sz > 1 )
|
| 344 |
+
std = sqrt(ss / (sz - 1));
|
| 345 |
+
values[9] = std::to_string(std);
|
| 346 |
+
|
| 347 |
+
std::string row = join(values, args.separator);
|
| 348 |
+
printf("%s\n", row.data());
|
| 349 |
+
}
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
return 0;
|
| 353 |
+
}
|
third_party/tracy/examples/OpenCLVectorAdd/CMakeLists.txt
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cmake_minimum_required(VERSION 3.10)
|
| 2 |
+
|
| 3 |
+
project(OpenCLVectorAdd)
|
| 4 |
+
|
| 5 |
+
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
| 6 |
+
find_package(Threads REQUIRED)
|
| 7 |
+
|
| 8 |
+
find_package(OpenCL REQUIRED)
|
| 9 |
+
|
| 10 |
+
add_executable(OpenCLVectorAdd OpenCLVectorAdd.cpp)
|
| 11 |
+
|
| 12 |
+
add_library(TracyClient STATIC ../../public/TracyClient.cpp
|
| 13 |
+
../../public/tracy/TracyOpenCL.hpp)
|
| 14 |
+
target_include_directories(TracyClient PUBLIC ../../public/tracy)
|
| 15 |
+
target_compile_definitions(TracyClient PUBLIC TRACY_ENABLE=1)
|
| 16 |
+
|
| 17 |
+
target_link_libraries(OpenCLVectorAdd PUBLIC OpenCL::OpenCL TracyClient ${CMAKE_DL_LIBS} Threads::Threads)
|
third_party/tracy/examples/OpenCLVectorAdd/OpenCLVectorAdd.cpp
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include <algorithm>
|
| 2 |
+
#include <iostream>
|
| 3 |
+
#include <cassert>
|
| 4 |
+
#include <string>
|
| 5 |
+
#include <vector>
|
| 6 |
+
#include <numeric>
|
| 7 |
+
|
| 8 |
+
#include <CL/cl.h>
|
| 9 |
+
|
| 10 |
+
#include <Tracy.hpp>
|
| 11 |
+
#include <TracyOpenCL.hpp>
|
| 12 |
+
|
| 13 |
+
#define CL_ASSERT(err) \
|
| 14 |
+
if((err) != CL_SUCCESS) \
|
| 15 |
+
{ \
|
| 16 |
+
std::cerr << "OpenCL Call Returned " << err << std::endl; \
|
| 17 |
+
assert(false); \
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
const char kernelSource[] =
|
| 21 |
+
" void __kernel vectorAdd(global float* C, global float* A, global float* B, int N) "
|
| 22 |
+
" { "
|
| 23 |
+
" int i = get_global_id(0); "
|
| 24 |
+
" if (i < N) { "
|
| 25 |
+
" C[i] = A[i] + B[i]; "
|
| 26 |
+
" } "
|
| 27 |
+
" } ";
|
| 28 |
+
|
| 29 |
+
int main()
|
| 30 |
+
{
|
| 31 |
+
cl_platform_id platform;
|
| 32 |
+
cl_device_id device;
|
| 33 |
+
cl_context context;
|
| 34 |
+
cl_command_queue commandQueue;
|
| 35 |
+
cl_kernel vectorAddKernel;
|
| 36 |
+
cl_program program;
|
| 37 |
+
cl_int err;
|
| 38 |
+
cl_mem bufferA, bufferB, bufferC;
|
| 39 |
+
|
| 40 |
+
TracyCLCtx tracyCLCtx;
|
| 41 |
+
|
| 42 |
+
{
|
| 43 |
+
ZoneScopedN("OpenCL Init");
|
| 44 |
+
|
| 45 |
+
cl_uint numPlatforms = 0;
|
| 46 |
+
CL_ASSERT(clGetPlatformIDs(0, nullptr, &numPlatforms));
|
| 47 |
+
|
| 48 |
+
if (numPlatforms == 0)
|
| 49 |
+
{
|
| 50 |
+
std::cerr << "Cannot find OpenCL platform to run this application" << std::endl;
|
| 51 |
+
return 1;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
CL_ASSERT(clGetPlatformIDs(1, &platform, nullptr));
|
| 55 |
+
|
| 56 |
+
size_t platformNameBufferSize = 0;
|
| 57 |
+
CL_ASSERT(clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, nullptr, &platformNameBufferSize));
|
| 58 |
+
std::string platformName(platformNameBufferSize, '\0');
|
| 59 |
+
CL_ASSERT(clGetPlatformInfo(platform, CL_PLATFORM_NAME, platformNameBufferSize, &platformName[0], nullptr));
|
| 60 |
+
|
| 61 |
+
std::cout << "OpenCL Platform: " << platformName << std::endl;
|
| 62 |
+
|
| 63 |
+
CL_ASSERT(clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, nullptr));
|
| 64 |
+
size_t deviceNameBufferSize = 0;
|
| 65 |
+
CL_ASSERT(clGetDeviceInfo(device, CL_DEVICE_NAME, 0, nullptr, &deviceNameBufferSize));
|
| 66 |
+
std::string deviceName(deviceNameBufferSize, '\0');
|
| 67 |
+
CL_ASSERT(clGetDeviceInfo(device, CL_DEVICE_NAME, deviceNameBufferSize, &deviceName[0], nullptr));
|
| 68 |
+
|
| 69 |
+
std::cout << "OpenCL Device: " << deviceName << std::endl;
|
| 70 |
+
|
| 71 |
+
err = CL_SUCCESS;
|
| 72 |
+
context = clCreateContext(nullptr, 1, &device, nullptr, nullptr, &err);
|
| 73 |
+
CL_ASSERT(err);
|
| 74 |
+
|
| 75 |
+
size_t kernelSourceLength = sizeof(kernelSource);
|
| 76 |
+
const char* kernelSourceArray = { kernelSource };
|
| 77 |
+
program = clCreateProgramWithSource(context, 1, &kernelSourceArray, &kernelSourceLength, &err);
|
| 78 |
+
CL_ASSERT(err);
|
| 79 |
+
|
| 80 |
+
if (clBuildProgram(program, 1, &device, nullptr, nullptr, nullptr) != CL_SUCCESS)
|
| 81 |
+
{
|
| 82 |
+
size_t programBuildLogBufferSize = 0;
|
| 83 |
+
CL_ASSERT(clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, nullptr, &programBuildLogBufferSize));
|
| 84 |
+
std::string programBuildLog(programBuildLogBufferSize, '\0');
|
| 85 |
+
CL_ASSERT(clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, programBuildLogBufferSize, &programBuildLog[0], nullptr));
|
| 86 |
+
std::clog << programBuildLog << std::endl;
|
| 87 |
+
return 1;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
vectorAddKernel = clCreateKernel(program, "vectorAdd", &err);
|
| 91 |
+
CL_ASSERT(err);
|
| 92 |
+
|
| 93 |
+
commandQueue = clCreateCommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE, &err);
|
| 94 |
+
CL_ASSERT(err);
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
tracyCLCtx = TracyCLContext(context, device);
|
| 98 |
+
|
| 99 |
+
size_t N = 10 * 1024 * 1024 / sizeof(float); // 10MB of floats
|
| 100 |
+
std::vector<float> hostA, hostB, hostC;
|
| 101 |
+
|
| 102 |
+
{
|
| 103 |
+
ZoneScopedN("Host Data Init");
|
| 104 |
+
hostA.resize(N);
|
| 105 |
+
hostB.resize(N);
|
| 106 |
+
hostC.resize(N);
|
| 107 |
+
|
| 108 |
+
std::iota(std::begin(hostA), std::end(hostA), 0.0f);
|
| 109 |
+
std::iota(std::begin(hostB), std::end(hostB), 0.0f);
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
{
|
| 113 |
+
ZoneScopedN("Host to Device Memory Copy");
|
| 114 |
+
|
| 115 |
+
bufferA = clCreateBuffer(context, CL_MEM_READ_WRITE, N * sizeof(float), nullptr, &err);
|
| 116 |
+
CL_ASSERT(err);
|
| 117 |
+
bufferB = clCreateBuffer(context, CL_MEM_READ_WRITE, N * sizeof(float), nullptr, &err);
|
| 118 |
+
CL_ASSERT(err);
|
| 119 |
+
bufferC = clCreateBuffer(context, CL_MEM_READ_WRITE, N * sizeof(float), nullptr, &err);
|
| 120 |
+
CL_ASSERT(err);
|
| 121 |
+
|
| 122 |
+
cl_event writeBufferAEvent, writeBufferBEvent;
|
| 123 |
+
{
|
| 124 |
+
ZoneScopedN("Write Buffer A");
|
| 125 |
+
TracyCLZoneS(tracyCLCtx, "Write BufferA", 5);
|
| 126 |
+
|
| 127 |
+
CL_ASSERT(clEnqueueWriteBuffer(commandQueue, bufferA, CL_FALSE, 0, N * sizeof(float), hostA.data(), 0, nullptr, &writeBufferAEvent));
|
| 128 |
+
|
| 129 |
+
TracyCLZoneSetEvent(writeBufferAEvent);
|
| 130 |
+
}
|
| 131 |
+
{
|
| 132 |
+
ZoneScopedN("Write Buffer B");
|
| 133 |
+
TracyCLZone(tracyCLCtx, "Write BufferB");
|
| 134 |
+
|
| 135 |
+
CL_ASSERT(clEnqueueWriteBuffer(commandQueue, bufferB, CL_FALSE, 0, N * sizeof(float), hostB.data(), 0, nullptr, &writeBufferBEvent));
|
| 136 |
+
|
| 137 |
+
TracyCLZoneSetEvent(writeBufferBEvent);
|
| 138 |
+
}
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
cl_int clN = static_cast<cl_int>(N);
|
| 142 |
+
const int numFrames = 10;
|
| 143 |
+
const int launchsPerFrame = 10;
|
| 144 |
+
constexpr int numLaunchs = numFrames * launchsPerFrame;
|
| 145 |
+
std::vector<cl_event> kernelLaunchEvts;
|
| 146 |
+
kernelLaunchEvts.reserve(numLaunchs);
|
| 147 |
+
for (int i = 0; i < numFrames; ++i)
|
| 148 |
+
{
|
| 149 |
+
FrameMark;
|
| 150 |
+
for (int j = 0; j < launchsPerFrame; ++j) {
|
| 151 |
+
ZoneScopedN("VectorAdd Kernel Launch");
|
| 152 |
+
TracyCLZoneC(tracyCLCtx, "VectorAdd Kernel", tracy::Color::Blue4);
|
| 153 |
+
|
| 154 |
+
CL_ASSERT(clSetKernelArg(vectorAddKernel, 0, sizeof(cl_mem), &bufferC));
|
| 155 |
+
CL_ASSERT(clSetKernelArg(vectorAddKernel, 1, sizeof(cl_mem), &bufferA));
|
| 156 |
+
CL_ASSERT(clSetKernelArg(vectorAddKernel, 2, sizeof(cl_mem), &bufferB));
|
| 157 |
+
CL_ASSERT(clSetKernelArg(vectorAddKernel, 3, sizeof(cl_int), &clN));
|
| 158 |
+
|
| 159 |
+
cl_event vectorAddKernelEvent;
|
| 160 |
+
CL_ASSERT(clEnqueueNDRangeKernel(commandQueue, vectorAddKernel, 1, nullptr, &N, nullptr, 0, nullptr, &vectorAddKernelEvent));
|
| 161 |
+
TracyCLZoneSetEvent(vectorAddKernelEvent);
|
| 162 |
+
CL_ASSERT(clRetainEvent(vectorAddKernelEvent));
|
| 163 |
+
kernelLaunchEvts.push_back(vectorAddKernelEvent);
|
| 164 |
+
std::cout << "VectorAdd Kernel Enqueued" << std::endl;
|
| 165 |
+
}
|
| 166 |
+
{
|
| 167 |
+
// Wait frame events to be finished
|
| 168 |
+
ZoneScopedN("clFinish");
|
| 169 |
+
CL_ASSERT(clFinish(commandQueue));
|
| 170 |
+
}
|
| 171 |
+
// You should collect on each 'frame' ends, so that streaming can be achieved.
|
| 172 |
+
TracyCLCollect(tracyCLCtx);
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
{
|
| 176 |
+
ZoneScopedN("Device to Host Memory Copy");
|
| 177 |
+
TracyCLZone(tracyCLCtx, "Read Buffer C");
|
| 178 |
+
|
| 179 |
+
cl_event readbufferCEvent;
|
| 180 |
+
CL_ASSERT(clEnqueueReadBuffer(commandQueue, bufferC, CL_TRUE, 0, N * sizeof(float), hostC.data(), 0, nullptr, &readbufferCEvent));
|
| 181 |
+
TracyCLZoneSetEvent(readbufferCEvent);
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
CL_ASSERT(clFinish(commandQueue));
|
| 185 |
+
std::vector<float> durations(kernelLaunchEvts.size());
|
| 186 |
+
for (int i=0; i<kernelLaunchEvts.size(); i++) {
|
| 187 |
+
cl_event evt = kernelLaunchEvts[i];
|
| 188 |
+
cl_ulong start;
|
| 189 |
+
cl_ulong end;
|
| 190 |
+
CL_ASSERT(clGetEventProfilingInfo(evt, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &start, nullptr));
|
| 191 |
+
CL_ASSERT(clGetEventProfilingInfo(evt, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &end, nullptr));
|
| 192 |
+
CL_ASSERT(clReleaseEvent(evt));
|
| 193 |
+
durations[i] = (end - start) * 0.001f;
|
| 194 |
+
std::cout << "VectorAdd Kernel " << i << " tooks " << static_cast<int>(durations[i]) << "us" << std::endl;
|
| 195 |
+
};
|
| 196 |
+
float avg = std::accumulate(durations.cbegin(), durations.cend(), 0.0f) / durations.size();
|
| 197 |
+
float stddev2 = std::accumulate(durations.cbegin(), durations.cend(), 0.0f, [avg](const float& acc, const float& v) {
|
| 198 |
+
auto d = v - avg;
|
| 199 |
+
return acc + d*d;
|
| 200 |
+
}) / (durations.size() - 1.0f);
|
| 201 |
+
std::cout << "VectorAdd runtime avg: " << avg << "us, std: " << sqrt(stddev2) << "us over " << numLaunchs << " runs." << std::endl;
|
| 202 |
+
|
| 203 |
+
// User should ensure all events are finished, in this case, collect after the clFinish will do the trick.
|
| 204 |
+
TracyCLCollect(tracyCLCtx);
|
| 205 |
+
|
| 206 |
+
{
|
| 207 |
+
ZoneScopedN("Checking results");
|
| 208 |
+
|
| 209 |
+
for (int i = 0; i < N; ++i)
|
| 210 |
+
{
|
| 211 |
+
assert(hostC[i] == hostA[i] + hostB[i]);
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
std::cout << "Results are correct!" << std::endl;
|
| 216 |
+
|
| 217 |
+
TracyCLDestroy(tracyCLCtx);
|
| 218 |
+
|
| 219 |
+
return 0;
|
| 220 |
+
}
|
third_party/tracy/examples/ToyPathTracer/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Windows/Compiled*Shader.h
|
third_party/tracy/examples/ToyPathTracer/README
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
https://github.com/aras-p/ToyPathTracer
|
| 2 |
+
|
| 3 |
+
Modified to render only 10 frames. Client part requires 12 GB, server part
|
| 4 |
+
requires 6.4 GB.
|
third_party/tracy/examples/ToyPathTracer/Source/Config.h
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
#if defined(__APPLE__) && !defined(__METAL_VERSION__)
|
| 3 |
+
#include <TargetConditionals.h>
|
| 4 |
+
#endif
|
| 5 |
+
|
| 6 |
+
#define kBackbufferWidth 1280
|
| 7 |
+
#define kBackbufferHeight 720
|
| 8 |
+
|
| 9 |
+
#if defined(__EMSCRIPTEN__)
|
| 10 |
+
#define CPU_CAN_DO_SIMD 0
|
| 11 |
+
#define CPU_CAN_DO_THREADS 0
|
| 12 |
+
#else
|
| 13 |
+
#define CPU_CAN_DO_SIMD 1
|
| 14 |
+
#define CPU_CAN_DO_THREADS 1
|
| 15 |
+
#endif
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
#define DO_SAMPLES_PER_PIXEL 4
|
| 19 |
+
#define DO_ANIMATE_SMOOTHING 0.9f
|
| 20 |
+
#define DO_LIGHT_SAMPLING 1
|
| 21 |
+
#define DO_MITSUBA_COMPARE 0
|
| 22 |
+
|
| 23 |
+
// Should path tracing be done on the GPU with a compute shader?
|
| 24 |
+
#define DO_COMPUTE_GPU 0
|
| 25 |
+
#define kCSGroupSizeX 8
|
| 26 |
+
#define kCSGroupSizeY 8
|
| 27 |
+
#define kCSMaxObjects 64
|
| 28 |
+
|
| 29 |
+
// Should float3 struct use SSE/NEON?
|
| 30 |
+
#define DO_FLOAT3_WITH_SIMD (!(DO_COMPUTE_GPU) && CPU_CAN_DO_SIMD && 1)
|
| 31 |
+
|
| 32 |
+
// Should HitSpheres function use SSE/NEON?
|
| 33 |
+
#define DO_HIT_SPHERES_SIMD (CPU_CAN_DO_SIMD && 1)
|
third_party/tracy/examples/ToyPathTracer/Source/MathSimd.h
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#if defined(_MSC_VER)
|
| 4 |
+
#define VM_INLINE __forceinline
|
| 5 |
+
#else
|
| 6 |
+
#define VM_INLINE __attribute__((unused, always_inline, nodebug)) inline
|
| 7 |
+
#endif
|
| 8 |
+
|
| 9 |
+
#define kSimdWidth 4
|
| 10 |
+
|
| 11 |
+
#if !defined(__arm__) && !defined(__arm64__) && !defined(__EMSCRIPTEN__)
|
| 12 |
+
|
| 13 |
+
// ---- SSE implementation
|
| 14 |
+
|
| 15 |
+
#include <xmmintrin.h>
|
| 16 |
+
#include <emmintrin.h>
|
| 17 |
+
#include <smmintrin.h>
|
| 18 |
+
|
| 19 |
+
#define SHUFFLE4(V, X,Y,Z,W) float4(_mm_shuffle_ps((V).m, (V).m, _MM_SHUFFLE(W,Z,Y,X)))
|
| 20 |
+
|
| 21 |
+
struct float4
|
| 22 |
+
{
|
| 23 |
+
VM_INLINE float4() {}
|
| 24 |
+
VM_INLINE explicit float4(const float *p) { m = _mm_loadu_ps(p); }
|
| 25 |
+
VM_INLINE explicit float4(float x, float y, float z, float w) { m = _mm_set_ps(w, z, y, x); }
|
| 26 |
+
VM_INLINE explicit float4(float v) { m = _mm_set_ps1(v); }
|
| 27 |
+
VM_INLINE explicit float4(__m128 v) { m = v; }
|
| 28 |
+
|
| 29 |
+
VM_INLINE float getX() const { return _mm_cvtss_f32(m); }
|
| 30 |
+
VM_INLINE float getY() const { return _mm_cvtss_f32(_mm_shuffle_ps(m, m, _MM_SHUFFLE(1, 1, 1, 1))); }
|
| 31 |
+
VM_INLINE float getZ() const { return _mm_cvtss_f32(_mm_shuffle_ps(m, m, _MM_SHUFFLE(2, 2, 2, 2))); }
|
| 32 |
+
VM_INLINE float getW() const { return _mm_cvtss_f32(_mm_shuffle_ps(m, m, _MM_SHUFFLE(3, 3, 3, 3))); }
|
| 33 |
+
|
| 34 |
+
__m128 m;
|
| 35 |
+
};
|
| 36 |
+
|
| 37 |
+
typedef float4 bool4;
|
| 38 |
+
|
| 39 |
+
VM_INLINE float4 operator+ (float4 a, float4 b) { a.m = _mm_add_ps(a.m, b.m); return a; }
|
| 40 |
+
VM_INLINE float4 operator- (float4 a, float4 b) { a.m = _mm_sub_ps(a.m, b.m); return a; }
|
| 41 |
+
VM_INLINE float4 operator* (float4 a, float4 b) { a.m = _mm_mul_ps(a.m, b.m); return a; }
|
| 42 |
+
VM_INLINE bool4 operator==(float4 a, float4 b) { a.m = _mm_cmpeq_ps(a.m, b.m); return a; }
|
| 43 |
+
VM_INLINE bool4 operator!=(float4 a, float4 b) { a.m = _mm_cmpneq_ps(a.m, b.m); return a; }
|
| 44 |
+
VM_INLINE bool4 operator< (float4 a, float4 b) { a.m = _mm_cmplt_ps(a.m, b.m); return a; }
|
| 45 |
+
VM_INLINE bool4 operator> (float4 a, float4 b) { a.m = _mm_cmpgt_ps(a.m, b.m); return a; }
|
| 46 |
+
VM_INLINE bool4 operator<=(float4 a, float4 b) { a.m = _mm_cmple_ps(a.m, b.m); return a; }
|
| 47 |
+
VM_INLINE bool4 operator>=(float4 a, float4 b) { a.m = _mm_cmpge_ps(a.m, b.m); return a; }
|
| 48 |
+
VM_INLINE bool4 operator&(bool4 a, bool4 b) { a.m = _mm_and_ps(a.m, b.m); return a; }
|
| 49 |
+
VM_INLINE bool4 operator|(bool4 a, bool4 b) { a.m = _mm_or_ps(a.m, b.m); return a; }
|
| 50 |
+
VM_INLINE float4 operator- (float4 a) { a.m = _mm_xor_ps(a.m, _mm_set1_ps(-0.0f)); return a; }
|
| 51 |
+
VM_INLINE float4 min(float4 a, float4 b) { a.m = _mm_min_ps(a.m, b.m); return a; }
|
| 52 |
+
VM_INLINE float4 max(float4 a, float4 b) { a.m = _mm_max_ps(a.m, b.m); return a; }
|
| 53 |
+
|
| 54 |
+
VM_INLINE float hmin(float4 v)
|
| 55 |
+
{
|
| 56 |
+
v = min(v, SHUFFLE4(v, 2, 3, 0, 0));
|
| 57 |
+
v = min(v, SHUFFLE4(v, 1, 0, 0, 0));
|
| 58 |
+
return v.getX();
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
// Returns a 4-bit code where bit0..bit3 is X..W
|
| 62 |
+
VM_INLINE unsigned mask(float4 v) { return _mm_movemask_ps(v.m); }
|
| 63 |
+
// Once we have a comparison, we can branch based on its results:
|
| 64 |
+
VM_INLINE bool any(bool4 v) { return mask(v) != 0; }
|
| 65 |
+
VM_INLINE bool all(bool4 v) { return mask(v) == 15; }
|
| 66 |
+
|
| 67 |
+
// "select", i.e. hibit(cond) ? b : a
|
| 68 |
+
// on SSE4.1 and up this can be done easily via "blend" instruction;
|
| 69 |
+
// on older SSEs has to do a bunch of hoops, see
|
| 70 |
+
// https://fgiesen.wordpress.com/2016/04/03/sse-mind-the-gap/
|
| 71 |
+
|
| 72 |
+
VM_INLINE float4 select(float4 a, float4 b, bool4 cond)
|
| 73 |
+
{
|
| 74 |
+
#if defined(__SSE4_1__) || defined(_MSC_VER) // on windows assume we always have SSE4.1
|
| 75 |
+
a.m = _mm_blendv_ps(a.m, b.m, cond.m);
|
| 76 |
+
#else
|
| 77 |
+
__m128 d = _mm_castsi128_ps(_mm_srai_epi32(_mm_castps_si128(cond.m), 31));
|
| 78 |
+
a.m = _mm_or_ps(_mm_and_ps(d, b.m), _mm_andnot_ps(d, a.m));
|
| 79 |
+
#endif
|
| 80 |
+
return a;
|
| 81 |
+
}
|
| 82 |
+
VM_INLINE __m128i select(__m128i a, __m128i b, bool4 cond)
|
| 83 |
+
{
|
| 84 |
+
#if defined(__SSE4_1__) || defined(_MSC_VER) // on windows assume we always have SSE4.1
|
| 85 |
+
return _mm_blendv_epi8(a, b, _mm_castps_si128(cond.m));
|
| 86 |
+
#else
|
| 87 |
+
__m128i d = _mm_srai_epi32(_mm_castps_si128(cond.m), 31);
|
| 88 |
+
return _mm_or_si128(_mm_and_si128(d, b), _mm_andnot_si128(d, a));
|
| 89 |
+
#endif
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
VM_INLINE float4 sqrtf(float4 v) { return float4(_mm_sqrt_ps(v.m)); }
|
| 93 |
+
|
| 94 |
+
#elif !defined(__EMSCRIPTEN__)
|
| 95 |
+
|
| 96 |
+
// ---- NEON implementation
|
| 97 |
+
|
| 98 |
+
#define USE_NEON 1
|
| 99 |
+
#include <arm_neon.h>
|
| 100 |
+
|
| 101 |
+
struct float4
|
| 102 |
+
{
|
| 103 |
+
VM_INLINE float4() {}
|
| 104 |
+
VM_INLINE explicit float4(const float *p) { m = vld1q_f32(p); }
|
| 105 |
+
VM_INLINE explicit float4(float x, float y, float z, float w) { float v[4] = {x, y, z, w}; m = vld1q_f32(v); }
|
| 106 |
+
VM_INLINE explicit float4(float v) { m = vdupq_n_f32(v); }
|
| 107 |
+
VM_INLINE explicit float4(float32x4_t v) { m = v; }
|
| 108 |
+
|
| 109 |
+
VM_INLINE float getX() const { return vgetq_lane_f32(m, 0); }
|
| 110 |
+
VM_INLINE float getY() const { return vgetq_lane_f32(m, 1); }
|
| 111 |
+
VM_INLINE float getZ() const { return vgetq_lane_f32(m, 2); }
|
| 112 |
+
VM_INLINE float getW() const { return vgetq_lane_f32(m, 3); }
|
| 113 |
+
|
| 114 |
+
float32x4_t m;
|
| 115 |
+
};
|
| 116 |
+
|
| 117 |
+
typedef float4 bool4;
|
| 118 |
+
|
| 119 |
+
VM_INLINE float4 operator+ (float4 a, float4 b) { a.m = vaddq_f32(a.m, b.m); return a; }
|
| 120 |
+
VM_INLINE float4 operator- (float4 a, float4 b) { a.m = vsubq_f32(a.m, b.m); return a; }
|
| 121 |
+
VM_INLINE float4 operator* (float4 a, float4 b) { a.m = vmulq_f32(a.m, b.m); return a; }
|
| 122 |
+
VM_INLINE bool4 operator==(float4 a, float4 b) { a.m = vceqq_f32(a.m, b.m); return a; }
|
| 123 |
+
VM_INLINE bool4 operator!=(float4 a, float4 b) { a.m = a.m = vmvnq_u32(vceqq_f32(a.m, b.m)); return a; }
|
| 124 |
+
VM_INLINE bool4 operator< (float4 a, float4 b) { a.m = vcltq_f32(a.m, b.m); return a; }
|
| 125 |
+
VM_INLINE bool4 operator> (float4 a, float4 b) { a.m = vcgtq_f32(a.m, b.m); return a; }
|
| 126 |
+
VM_INLINE bool4 operator<=(float4 a, float4 b) { a.m = vcleq_f32(a.m, b.m); return a; }
|
| 127 |
+
VM_INLINE bool4 operator>=(float4 a, float4 b) { a.m = vcgeq_f32(a.m, b.m); return a; }
|
| 128 |
+
VM_INLINE bool4 operator&(bool4 a, bool4 b) { a.m = vandq_u32(a.m, b.m); return a; }
|
| 129 |
+
VM_INLINE bool4 operator|(bool4 a, bool4 b) { a.m = vorrq_u32(a.m, b.m); return a; }
|
| 130 |
+
VM_INLINE float4 operator- (float4 a) { a.m = vnegq_f32(a.m); return a; }
|
| 131 |
+
VM_INLINE float4 min(float4 a, float4 b) { a.m = vminq_f32(a.m, b.m); return a; }
|
| 132 |
+
VM_INLINE float4 max(float4 a, float4 b) { a.m = vmaxq_f32(a.m, b.m); return a; }
|
| 133 |
+
|
| 134 |
+
VM_INLINE float hmin(float4 v)
|
| 135 |
+
{
|
| 136 |
+
float32x2_t minOfHalfs = vpmin_f32(vget_low_f32(v.m), vget_high_f32(v.m));
|
| 137 |
+
float32x2_t minOfMinOfHalfs = vpmin_f32(minOfHalfs, minOfHalfs);
|
| 138 |
+
return vget_lane_f32(minOfMinOfHalfs, 0);
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
// Returns a 4-bit code where bit0..bit3 is X..W
|
| 142 |
+
VM_INLINE unsigned mask(float4 v)
|
| 143 |
+
{
|
| 144 |
+
static const uint32x4_t movemask = { 1, 2, 4, 8 };
|
| 145 |
+
static const uint32x4_t highbit = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
|
| 146 |
+
uint32x4_t t0 = vreinterpretq_u32_f32(v.m);
|
| 147 |
+
uint32x4_t t1 = vtstq_u32(t0, highbit);
|
| 148 |
+
uint32x4_t t2 = vandq_u32(t1, movemask);
|
| 149 |
+
uint32x2_t t3 = vorr_u32(vget_low_u32(t2), vget_high_u32(t2));
|
| 150 |
+
return vget_lane_u32(t3, 0) | vget_lane_u32(t3, 1);
|
| 151 |
+
}
|
| 152 |
+
// Once we have a comparison, we can branch based on its results:
|
| 153 |
+
VM_INLINE bool any(bool4 v) { return mask(v) != 0; }
|
| 154 |
+
VM_INLINE bool all(bool4 v) { return mask(v) == 15; }
|
| 155 |
+
|
| 156 |
+
// "select", i.e. hibit(cond) ? b : a
|
| 157 |
+
// on SSE4.1 and up this can be done easily via "blend" instruction;
|
| 158 |
+
// on older SSEs has to do a bunch of hoops, see
|
| 159 |
+
// https://fgiesen.wordpress.com/2016/04/03/sse-mind-the-gap/
|
| 160 |
+
|
| 161 |
+
VM_INLINE float4 select(float4 a, float4 b, bool4 cond)
|
| 162 |
+
{
|
| 163 |
+
a.m = vbslq_f32(cond.m, b.m, a.m);
|
| 164 |
+
return a;
|
| 165 |
+
}
|
| 166 |
+
VM_INLINE int32x4_t select(int32x4_t a, int32x4_t b, bool4 cond)
|
| 167 |
+
{
|
| 168 |
+
return vbslq_f32(cond.m, b, a);
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
VM_INLINE float4 sqrtf(float4 v)
|
| 172 |
+
{
|
| 173 |
+
float32x4_t V = v.m;
|
| 174 |
+
float32x4_t S0 = vrsqrteq_f32(V);
|
| 175 |
+
float32x4_t P0 = vmulq_f32( V, S0 );
|
| 176 |
+
float32x4_t R0 = vrsqrtsq_f32( P0, S0 );
|
| 177 |
+
float32x4_t S1 = vmulq_f32( S0, R0 );
|
| 178 |
+
float32x4_t P1 = vmulq_f32( V, S1 );
|
| 179 |
+
float32x4_t R1 = vrsqrtsq_f32( P1, S1 );
|
| 180 |
+
float32x4_t S2 = vmulq_f32( S1, R1 );
|
| 181 |
+
float32x4_t P2 = vmulq_f32( V, S2 );
|
| 182 |
+
float32x4_t R2 = vrsqrtsq_f32( P2, S2 );
|
| 183 |
+
float32x4_t S3 = vmulq_f32( S2, R2 );
|
| 184 |
+
return float4(vmulq_f32(V, S3));
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
VM_INLINE float4 splatX(float32x4_t v) { return float4(vdupq_lane_f32(vget_low_f32(v), 0)); }
|
| 188 |
+
VM_INLINE float4 splatY(float32x4_t v) { return float4(vdupq_lane_f32(vget_low_f32(v), 1)); }
|
| 189 |
+
VM_INLINE float4 splatZ(float32x4_t v) { return float4(vdupq_lane_f32(vget_high_f32(v), 0)); }
|
| 190 |
+
VM_INLINE float4 splatW(float32x4_t v) { return float4(vdupq_lane_f32(vget_high_f32(v), 1)); }
|
| 191 |
+
|
| 192 |
+
#endif
|
third_party/tracy/examples/ToyPathTracer/Source/Maths.cpp
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "Maths.h"
|
| 2 |
+
#include <stdlib.h>
|
| 3 |
+
#include <stdint.h>
|
| 4 |
+
|
| 5 |
+
static uint32_t XorShift32(uint32_t& state)
|
| 6 |
+
{
|
| 7 |
+
uint32_t x = state;
|
| 8 |
+
x ^= x << 13;
|
| 9 |
+
x ^= x >> 17;
|
| 10 |
+
x ^= x << 15;
|
| 11 |
+
state = x;
|
| 12 |
+
return x;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
float RandomFloat01(uint32_t& state)
|
| 16 |
+
{
|
| 17 |
+
return (XorShift32(state) & 0xFFFFFF) / 16777216.0f;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
float3 RandomInUnitDisk(uint32_t& state)
|
| 21 |
+
{
|
| 22 |
+
float3 p;
|
| 23 |
+
do
|
| 24 |
+
{
|
| 25 |
+
p = 2.0 * float3(RandomFloat01(state),RandomFloat01(state),0) - float3(1,1,0);
|
| 26 |
+
} while (dot(p,p) >= 1.0);
|
| 27 |
+
return p;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
float3 RandomInUnitSphere(uint32_t& state)
|
| 31 |
+
{
|
| 32 |
+
float3 p;
|
| 33 |
+
do {
|
| 34 |
+
p = 2.0*float3(RandomFloat01(state),RandomFloat01(state),RandomFloat01(state)) - float3(1,1,1);
|
| 35 |
+
} while (sqLength(p) >= 1.0);
|
| 36 |
+
return p;
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
float3 RandomUnitVector(uint32_t& state)
|
| 40 |
+
{
|
| 41 |
+
float z = RandomFloat01(state) * 2.0f - 1.0f;
|
| 42 |
+
float a = RandomFloat01(state) * 2.0f * kPI;
|
| 43 |
+
float r = sqrtf(1.0f - z * z);
|
| 44 |
+
float x = r * cosf(a);
|
| 45 |
+
float y = r * sinf(a);
|
| 46 |
+
return float3(x, y, z);
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
int HitSpheres(const Ray& r, const SpheresSoA& spheres, float tMin, float tMax, Hit& outHit)
|
| 51 |
+
{
|
| 52 |
+
#if DO_HIT_SPHERES_SIMD
|
| 53 |
+
float4 hitT = float4(tMax);
|
| 54 |
+
#if USE_NEON
|
| 55 |
+
int32x4_t id = vdupq_n_s32(-1);
|
| 56 |
+
#else
|
| 57 |
+
__m128i id = _mm_set1_epi32(-1);
|
| 58 |
+
#endif
|
| 59 |
+
|
| 60 |
+
#if DO_FLOAT3_WITH_SIMD && !USE_NEON
|
| 61 |
+
float4 rOrigX = SHUFFLE4(r.orig, 0, 0, 0, 0);
|
| 62 |
+
float4 rOrigY = SHUFFLE4(r.orig, 1, 1, 1, 1);
|
| 63 |
+
float4 rOrigZ = SHUFFLE4(r.orig, 2, 2, 2, 2);
|
| 64 |
+
float4 rDirX = SHUFFLE4(r.dir, 0, 0, 0, 0);
|
| 65 |
+
float4 rDirY = SHUFFLE4(r.dir, 1, 1, 1, 1);
|
| 66 |
+
float4 rDirZ = SHUFFLE4(r.dir, 2, 2, 2, 2);
|
| 67 |
+
#elif DO_FLOAT3_WITH_SIMD
|
| 68 |
+
float4 rOrigX = splatX(r.orig.m);
|
| 69 |
+
float4 rOrigY = splatY(r.orig.m);
|
| 70 |
+
float4 rOrigZ = splatZ(r.orig.m);
|
| 71 |
+
float4 rDirX = splatX(r.dir.m);
|
| 72 |
+
float4 rDirY = splatY(r.dir.m);
|
| 73 |
+
float4 rDirZ = splatZ(r.dir.m);
|
| 74 |
+
#else
|
| 75 |
+
float4 rOrigX = float4(r.orig.x);
|
| 76 |
+
float4 rOrigY = float4(r.orig.y);
|
| 77 |
+
float4 rOrigZ = float4(r.orig.z);
|
| 78 |
+
float4 rDirX = float4(r.dir.x);
|
| 79 |
+
float4 rDirY = float4(r.dir.y);
|
| 80 |
+
float4 rDirZ = float4(r.dir.z);
|
| 81 |
+
#endif
|
| 82 |
+
float4 tMin4 = float4(tMin);
|
| 83 |
+
#if USE_NEON
|
| 84 |
+
int32x4_t curId = vcombine_u32(vcreate_u32(0ULL | (1ULL<<32)), vcreate_u32(2ULL | (3ULL<<32)));
|
| 85 |
+
#else
|
| 86 |
+
__m128i curId = _mm_set_epi32(3, 2, 1, 0);
|
| 87 |
+
#endif
|
| 88 |
+
// process 4 spheres at once
|
| 89 |
+
for (int i = 0; i < spheres.simdCount; i += kSimdWidth)
|
| 90 |
+
{
|
| 91 |
+
// load data for 4 spheres
|
| 92 |
+
float4 sCenterX = float4(spheres.centerX + i);
|
| 93 |
+
float4 sCenterY = float4(spheres.centerY + i);
|
| 94 |
+
float4 sCenterZ = float4(spheres.centerZ + i);
|
| 95 |
+
float4 sSqRadius = float4(spheres.sqRadius + i);
|
| 96 |
+
// note: we flip this vector and calculate -b (nb) since that happens to be slightly preferable computationally
|
| 97 |
+
float4 coX = sCenterX - rOrigX;
|
| 98 |
+
float4 coY = sCenterY - rOrigY;
|
| 99 |
+
float4 coZ = sCenterZ - rOrigZ;
|
| 100 |
+
float4 nb = coX * rDirX + coY * rDirY + coZ * rDirZ;
|
| 101 |
+
float4 c = coX * coX + coY * coY + coZ * coZ - sSqRadius;
|
| 102 |
+
float4 discr = nb * nb - c;
|
| 103 |
+
bool4 discrPos = discr > float4(0.0f);
|
| 104 |
+
// if ray hits any of the 4 spheres
|
| 105 |
+
if (any(discrPos))
|
| 106 |
+
{
|
| 107 |
+
float4 discrSq = sqrtf(discr);
|
| 108 |
+
|
| 109 |
+
// ray could hit spheres at t0 & t1
|
| 110 |
+
float4 t0 = nb - discrSq;
|
| 111 |
+
float4 t1 = nb + discrSq;
|
| 112 |
+
|
| 113 |
+
float4 t = select(t1, t0, t0 > tMin4); // if t0 is above min, take it (since it's the earlier hit); else try t1.
|
| 114 |
+
bool4 msk = discrPos & (t > tMin4) & (t < hitT);
|
| 115 |
+
// if hit, take it
|
| 116 |
+
id = select(id, curId, msk);
|
| 117 |
+
hitT = select(hitT, t, msk);
|
| 118 |
+
}
|
| 119 |
+
#if USE_NEON
|
| 120 |
+
curId = vaddq_s32(curId, vdupq_n_s32(kSimdWidth));
|
| 121 |
+
#else
|
| 122 |
+
curId = _mm_add_epi32(curId, _mm_set1_epi32(kSimdWidth));
|
| 123 |
+
#endif
|
| 124 |
+
}
|
| 125 |
+
// now we have up to 4 hits, find and return closest one
|
| 126 |
+
float minT = hmin(hitT);
|
| 127 |
+
if (minT < tMax) // any actual hits?
|
| 128 |
+
{
|
| 129 |
+
int minMask = mask(hitT == float4(minT));
|
| 130 |
+
if (minMask != 0)
|
| 131 |
+
{
|
| 132 |
+
int id_scalar[4];
|
| 133 |
+
float hitT_scalar[4];
|
| 134 |
+
#if USE_NEON
|
| 135 |
+
vst1q_s32(id_scalar, id);
|
| 136 |
+
vst1q_f32(hitT_scalar, hitT.m);
|
| 137 |
+
#else
|
| 138 |
+
_mm_storeu_si128((__m128i *)id_scalar, id);
|
| 139 |
+
_mm_storeu_ps(hitT_scalar, hitT.m);
|
| 140 |
+
#endif
|
| 141 |
+
|
| 142 |
+
// In general, you would do this with a bit scan (first set/trailing zero count).
|
| 143 |
+
// But who cares, it's only 16 options.
|
| 144 |
+
static const int laneId[16] =
|
| 145 |
+
{
|
| 146 |
+
0, 0, 1, 0, // 00xx
|
| 147 |
+
2, 0, 1, 0, // 01xx
|
| 148 |
+
3, 0, 1, 0, // 10xx
|
| 149 |
+
2, 0, 1, 0, // 11xx
|
| 150 |
+
};
|
| 151 |
+
|
| 152 |
+
int lane = laneId[minMask];
|
| 153 |
+
int hitId = id_scalar[lane];
|
| 154 |
+
float finalHitT = hitT_scalar[lane];
|
| 155 |
+
|
| 156 |
+
outHit.pos = r.pointAt(finalHitT);
|
| 157 |
+
outHit.normal = (outHit.pos - float3(spheres.centerX[hitId], spheres.centerY[hitId], spheres.centerZ[hitId])) * spheres.invRadius[hitId];
|
| 158 |
+
outHit.t = finalHitT;
|
| 159 |
+
return hitId;
|
| 160 |
+
}
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
return -1;
|
| 164 |
+
|
| 165 |
+
#else // #if DO_HIT_SPHERES_SIMD
|
| 166 |
+
|
| 167 |
+
float hitT = tMax;
|
| 168 |
+
int id = -1;
|
| 169 |
+
for (int i = 0; i < spheres.count; ++i)
|
| 170 |
+
{
|
| 171 |
+
float coX = spheres.centerX[i] - r.orig.getX();
|
| 172 |
+
float coY = spheres.centerY[i] - r.orig.getY();
|
| 173 |
+
float coZ = spheres.centerZ[i] - r.orig.getZ();
|
| 174 |
+
float nb = coX * r.dir.getX() + coY * r.dir.getY() + coZ * r.dir.getZ();
|
| 175 |
+
float c = coX * coX + coY * coY + coZ * coZ - spheres.sqRadius[i];
|
| 176 |
+
float discr = nb * nb - c;
|
| 177 |
+
if (discr > 0)
|
| 178 |
+
{
|
| 179 |
+
float discrSq = sqrtf(discr);
|
| 180 |
+
|
| 181 |
+
// Try earlier t
|
| 182 |
+
float t = nb - discrSq;
|
| 183 |
+
if (t <= tMin) // before min, try later t!
|
| 184 |
+
t = nb + discrSq;
|
| 185 |
+
|
| 186 |
+
if (t > tMin && t < hitT)
|
| 187 |
+
{
|
| 188 |
+
id = i;
|
| 189 |
+
hitT = t;
|
| 190 |
+
}
|
| 191 |
+
}
|
| 192 |
+
}
|
| 193 |
+
if (id != -1)
|
| 194 |
+
{
|
| 195 |
+
outHit.pos = r.pointAt(hitT);
|
| 196 |
+
outHit.normal = (outHit.pos - float3(spheres.centerX[id], spheres.centerY[id], spheres.centerZ[id])) * spheres.invRadius[id];
|
| 197 |
+
outHit.t = hitT;
|
| 198 |
+
return id;
|
| 199 |
+
}
|
| 200 |
+
else
|
| 201 |
+
return -1;
|
| 202 |
+
#endif // #else of #if DO_HIT_SPHERES_SIMD
|
| 203 |
+
}
|
third_party/tracy/examples/ToyPathTracer/Source/Maths.h
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <math.h>
|
| 4 |
+
#include <assert.h>
|
| 5 |
+
#include <stdint.h>
|
| 6 |
+
#include "Config.h"
|
| 7 |
+
#include "MathSimd.h"
|
| 8 |
+
|
| 9 |
+
#define kPI 3.1415926f
|
| 10 |
+
|
| 11 |
+
// SSE/SIMD vector largely based on http://www.codersnotes.com/notes/maths-lib-2016/
|
| 12 |
+
#if DO_FLOAT3_WITH_SIMD
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
#if !defined(__arm__) && !defined(__arm64__)
|
| 16 |
+
|
| 17 |
+
// ---- SSE implementation
|
| 18 |
+
|
| 19 |
+
// SHUFFLE3(v, 0,1,2) leaves the vector unchanged (v.xyz).
|
| 20 |
+
// SHUFFLE3(v, 0,0,0) splats the X (v.xxx).
|
| 21 |
+
#define SHUFFLE3(V, X,Y,Z) float3(_mm_shuffle_ps((V).m, (V).m, _MM_SHUFFLE(Z,Z,Y,X)))
|
| 22 |
+
|
| 23 |
+
struct float3
|
| 24 |
+
{
|
| 25 |
+
VM_INLINE float3() {}
|
| 26 |
+
VM_INLINE explicit float3(const float *p) { m = _mm_set_ps(p[2], p[2], p[1], p[0]); }
|
| 27 |
+
VM_INLINE explicit float3(float x, float y, float z) { m = _mm_set_ps(z, z, y, x); }
|
| 28 |
+
VM_INLINE explicit float3(float v) { m = _mm_set1_ps(v); }
|
| 29 |
+
VM_INLINE explicit float3(__m128 v) { m = v; }
|
| 30 |
+
|
| 31 |
+
VM_INLINE float getX() const { return _mm_cvtss_f32(m); }
|
| 32 |
+
VM_INLINE float getY() const { return _mm_cvtss_f32(_mm_shuffle_ps(m, m, _MM_SHUFFLE(1, 1, 1, 1))); }
|
| 33 |
+
VM_INLINE float getZ() const { return _mm_cvtss_f32(_mm_shuffle_ps(m, m, _MM_SHUFFLE(2, 2, 2, 2))); }
|
| 34 |
+
|
| 35 |
+
VM_INLINE float3 yzx() const { return SHUFFLE3(*this, 1, 2, 0); }
|
| 36 |
+
VM_INLINE float3 zxy() const { return SHUFFLE3(*this, 2, 0, 1); }
|
| 37 |
+
|
| 38 |
+
VM_INLINE void store(float *p) const { p[0] = getX(); p[1] = getY(); p[2] = getZ(); }
|
| 39 |
+
|
| 40 |
+
void setX(float x)
|
| 41 |
+
{
|
| 42 |
+
m = _mm_move_ss(m, _mm_set_ss(x));
|
| 43 |
+
}
|
| 44 |
+
void setY(float y)
|
| 45 |
+
{
|
| 46 |
+
__m128 t = _mm_move_ss(m, _mm_set_ss(y));
|
| 47 |
+
t = _mm_shuffle_ps(t, t, _MM_SHUFFLE(3, 2, 0, 0));
|
| 48 |
+
m = _mm_move_ss(t, m);
|
| 49 |
+
}
|
| 50 |
+
void setZ(float z)
|
| 51 |
+
{
|
| 52 |
+
__m128 t = _mm_move_ss(m, _mm_set_ss(z));
|
| 53 |
+
t = _mm_shuffle_ps(t, t, _MM_SHUFFLE(3, 0, 1, 0));
|
| 54 |
+
m = _mm_move_ss(t, m);
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
__m128 m;
|
| 58 |
+
};
|
| 59 |
+
|
| 60 |
+
typedef float3 bool3;
|
| 61 |
+
|
| 62 |
+
VM_INLINE float3 operator+ (float3 a, float3 b) { a.m = _mm_add_ps(a.m, b.m); return a; }
|
| 63 |
+
VM_INLINE float3 operator- (float3 a, float3 b) { a.m = _mm_sub_ps(a.m, b.m); return a; }
|
| 64 |
+
VM_INLINE float3 operator* (float3 a, float3 b) { a.m = _mm_mul_ps(a.m, b.m); return a; }
|
| 65 |
+
VM_INLINE float3 operator/ (float3 a, float3 b) { a.m = _mm_div_ps(a.m, b.m); return a; }
|
| 66 |
+
VM_INLINE float3 operator* (float3 a, float b) { a.m = _mm_mul_ps(a.m, _mm_set1_ps(b)); return a; }
|
| 67 |
+
VM_INLINE float3 operator/ (float3 a, float b) { a.m = _mm_div_ps(a.m, _mm_set1_ps(b)); return a; }
|
| 68 |
+
VM_INLINE float3 operator* (float a, float3 b) { b.m = _mm_mul_ps(_mm_set1_ps(a), b.m); return b; }
|
| 69 |
+
VM_INLINE float3 operator/ (float a, float3 b) { b.m = _mm_div_ps(_mm_set1_ps(a), b.m); return b; }
|
| 70 |
+
VM_INLINE float3& operator+= (float3 &a, float3 b) { a = a + b; return a; }
|
| 71 |
+
VM_INLINE float3& operator-= (float3 &a, float3 b) { a = a - b; return a; }
|
| 72 |
+
VM_INLINE float3& operator*= (float3 &a, float3 b) { a = a * b; return a; }
|
| 73 |
+
VM_INLINE float3& operator/= (float3 &a, float3 b) { a = a / b; return a; }
|
| 74 |
+
VM_INLINE float3& operator*= (float3 &a, float b) { a = a * b; return a; }
|
| 75 |
+
VM_INLINE float3& operator/= (float3 &a, float b) { a = a / b; return a; }
|
| 76 |
+
VM_INLINE bool3 operator==(float3 a, float3 b) { a.m = _mm_cmpeq_ps(a.m, b.m); return a; }
|
| 77 |
+
VM_INLINE bool3 operator!=(float3 a, float3 b) { a.m = _mm_cmpneq_ps(a.m, b.m); return a; }
|
| 78 |
+
VM_INLINE bool3 operator< (float3 a, float3 b) { a.m = _mm_cmplt_ps(a.m, b.m); return a; }
|
| 79 |
+
VM_INLINE bool3 operator> (float3 a, float3 b) { a.m = _mm_cmpgt_ps(a.m, b.m); return a; }
|
| 80 |
+
VM_INLINE bool3 operator<=(float3 a, float3 b) { a.m = _mm_cmple_ps(a.m, b.m); return a; }
|
| 81 |
+
VM_INLINE bool3 operator>=(float3 a, float3 b) { a.m = _mm_cmpge_ps(a.m, b.m); return a; }
|
| 82 |
+
VM_INLINE float3 min(float3 a, float3 b) { a.m = _mm_min_ps(a.m, b.m); return a; }
|
| 83 |
+
VM_INLINE float3 max(float3 a, float3 b) { a.m = _mm_max_ps(a.m, b.m); return a; }
|
| 84 |
+
|
| 85 |
+
VM_INLINE float3 operator- (float3 a) { return float3(_mm_setzero_ps()) - a; }
|
| 86 |
+
|
| 87 |
+
VM_INLINE float hmin(float3 v)
|
| 88 |
+
{
|
| 89 |
+
v = min(v, SHUFFLE3(v, 1, 0, 2));
|
| 90 |
+
return min(v, SHUFFLE3(v, 2, 0, 1)).getX();
|
| 91 |
+
}
|
| 92 |
+
VM_INLINE float hmax(float3 v)
|
| 93 |
+
{
|
| 94 |
+
v = max(v, SHUFFLE3(v, 1, 0, 2));
|
| 95 |
+
return max(v, SHUFFLE3(v, 2, 0, 1)).getX();
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
VM_INLINE float3 cross(float3 a, float3 b)
|
| 99 |
+
{
|
| 100 |
+
// x <- a.y*b.z - a.z*b.y
|
| 101 |
+
// y <- a.z*b.x - a.x*b.z
|
| 102 |
+
// z <- a.x*b.y - a.y*b.x
|
| 103 |
+
// We can save a shuffle by grouping it in this wacky order:
|
| 104 |
+
return (a.zxy()*b - a*b.zxy()).zxy();
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
// Returns a 3-bit code where bit0..bit2 is X..Z
|
| 108 |
+
VM_INLINE unsigned mask(float3 v) { return _mm_movemask_ps(v.m) & 7; }
|
| 109 |
+
// Once we have a comparison, we can branch based on its results:
|
| 110 |
+
VM_INLINE bool any(bool3 v) { return mask(v) != 0; }
|
| 111 |
+
VM_INLINE bool all(bool3 v) { return mask(v) == 7; }
|
| 112 |
+
|
| 113 |
+
VM_INLINE float3 clamp(float3 t, float3 a, float3 b) { return min(max(t, a), b); }
|
| 114 |
+
VM_INLINE float sum(float3 v) { return v.getX() + v.getY() + v.getZ(); }
|
| 115 |
+
VM_INLINE float dot(float3 a, float3 b) { return sum(a*b); }
|
| 116 |
+
|
| 117 |
+
#else // #if !defined(__arm__) && !defined(__arm64__)
|
| 118 |
+
|
| 119 |
+
// ---- NEON implementation
|
| 120 |
+
|
| 121 |
+
#include <arm_neon.h>
|
| 122 |
+
|
| 123 |
+
struct float3
|
| 124 |
+
{
|
| 125 |
+
VM_INLINE float3() {}
|
| 126 |
+
VM_INLINE explicit float3(const float *p) { float v[4] = {p[0], p[1], p[2], 0}; m = vld1q_f32(v); }
|
| 127 |
+
VM_INLINE explicit float3(float x, float y, float z) { float v[4] = {x, y, z, 0}; m = vld1q_f32(v); }
|
| 128 |
+
VM_INLINE explicit float3(float v) { m = vdupq_n_f32(v); }
|
| 129 |
+
VM_INLINE explicit float3(float32x4_t v) { m = v; }
|
| 130 |
+
|
| 131 |
+
VM_INLINE float getX() const { return vgetq_lane_f32(m, 0); }
|
| 132 |
+
VM_INLINE float getY() const { return vgetq_lane_f32(m, 1); }
|
| 133 |
+
VM_INLINE float getZ() const { return vgetq_lane_f32(m, 2); }
|
| 134 |
+
|
| 135 |
+
VM_INLINE float3 yzx() const
|
| 136 |
+
{
|
| 137 |
+
float32x2_t low = vget_low_f32(m);
|
| 138 |
+
float32x4_t yzx = vcombine_f32(vext_f32(low, vget_high_f32(m), 1), low);
|
| 139 |
+
return float3(yzx);
|
| 140 |
+
}
|
| 141 |
+
VM_INLINE float3 zxy() const
|
| 142 |
+
{
|
| 143 |
+
float32x4_t p = m;
|
| 144 |
+
p = vuzpq_f32(vreinterpretq_f32_s32(vextq_s32(vreinterpretq_s32_f32(p), vreinterpretq_s32_f32(p), 1)), p).val[1];
|
| 145 |
+
return float3(p);
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
VM_INLINE void store(float *p) const { p[0] = getX(); p[1] = getY(); p[2] = getZ(); }
|
| 149 |
+
|
| 150 |
+
void setX(float x)
|
| 151 |
+
{
|
| 152 |
+
m = vsetq_lane_f32(x, m, 0);
|
| 153 |
+
}
|
| 154 |
+
void setY(float y)
|
| 155 |
+
{
|
| 156 |
+
m = vsetq_lane_f32(y, m, 1);
|
| 157 |
+
}
|
| 158 |
+
void setZ(float z)
|
| 159 |
+
{
|
| 160 |
+
m = vsetq_lane_f32(z, m, 2);
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
float32x4_t m;
|
| 164 |
+
};
|
| 165 |
+
|
| 166 |
+
typedef float3 bool3;
|
| 167 |
+
|
| 168 |
+
VM_INLINE float32x4_t rcp_2(float32x4_t v)
|
| 169 |
+
{
|
| 170 |
+
float32x4_t e = vrecpeq_f32(v);
|
| 171 |
+
e = vmulq_f32(vrecpsq_f32(e, v), e);
|
| 172 |
+
e = vmulq_f32(vrecpsq_f32(e, v), e);
|
| 173 |
+
return e;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
VM_INLINE float3 operator+ (float3 a, float3 b) { a.m = vaddq_f32(a.m, b.m); return a; }
|
| 177 |
+
VM_INLINE float3 operator- (float3 a, float3 b) { a.m = vsubq_f32(a.m, b.m); return a; }
|
| 178 |
+
VM_INLINE float3 operator* (float3 a, float3 b) { a.m = vmulq_f32(a.m, b.m); return a; }
|
| 179 |
+
VM_INLINE float3 operator/ (float3 a, float3 b) { float32x4_t recip = rcp_2(b.m); a.m = vmulq_f32(a.m, recip); return a; }
|
| 180 |
+
VM_INLINE float3 operator* (float3 a, float b) { a.m = vmulq_f32(a.m, vdupq_n_f32(b)); return a; }
|
| 181 |
+
VM_INLINE float3 operator/ (float3 a, float b) { float32x4_t recip = rcp_2(vdupq_n_f32(b)); a.m = vmulq_f32(a.m, recip); return a; }
|
| 182 |
+
VM_INLINE float3 operator* (float a, float3 b) { b.m = vmulq_f32(vdupq_n_f32(a), b.m); return b; }
|
| 183 |
+
VM_INLINE float3 operator/ (float a, float3 b) { float32x4_t recip = rcp_2(b.m); b.m = vmulq_f32(vdupq_n_f32(a), recip); return b; }
|
| 184 |
+
VM_INLINE float3& operator+= (float3 &a, float3 b) { a = a + b; return a; }
|
| 185 |
+
VM_INLINE float3& operator-= (float3 &a, float3 b) { a = a - b; return a; }
|
| 186 |
+
VM_INLINE float3& operator*= (float3 &a, float3 b) { a = a * b; return a; }
|
| 187 |
+
VM_INLINE float3& operator/= (float3 &a, float3 b) { a = a / b; return a; }
|
| 188 |
+
VM_INLINE float3& operator*= (float3 &a, float b) { a = a * b; return a; }
|
| 189 |
+
VM_INLINE float3& operator/= (float3 &a, float b) { a = a / b; return a; }
|
| 190 |
+
VM_INLINE bool3 operator==(float3 a, float3 b) { a.m = vceqq_f32(a.m, b.m); return a; }
|
| 191 |
+
VM_INLINE bool3 operator!=(float3 a, float3 b) { a.m = vmvnq_u32(vceqq_f32(a.m, b.m)); return a; }
|
| 192 |
+
VM_INLINE bool3 operator< (float3 a, float3 b) { a.m = vcltq_f32(a.m, b.m); return a; }
|
| 193 |
+
VM_INLINE bool3 operator> (float3 a, float3 b) { a.m = vcgtq_f32(a.m, b.m); return a; }
|
| 194 |
+
VM_INLINE bool3 operator<=(float3 a, float3 b) { a.m = vcleq_f32(a.m, b.m); return a; }
|
| 195 |
+
VM_INLINE bool3 operator>=(float3 a, float3 b) { a.m = vcgeq_f32(a.m, b.m); return a; }
|
| 196 |
+
VM_INLINE float3 min(float3 a, float3 b) { a.m = vminq_f32(a.m, b.m); return a; }
|
| 197 |
+
VM_INLINE float3 max(float3 a, float3 b) { a.m = vmaxq_f32(a.m, b.m); return a; }
|
| 198 |
+
|
| 199 |
+
VM_INLINE float3 operator- (float3 a) { a.m = vnegq_f32(a.m); return a; }
|
| 200 |
+
|
| 201 |
+
VM_INLINE float hmin(float3 v)
|
| 202 |
+
{
|
| 203 |
+
float32x2_t minOfHalfs = vpmin_f32(vget_low_f32(v.m), vget_high_f32(v.m));
|
| 204 |
+
float32x2_t minOfMinOfHalfs = vpmin_f32(minOfHalfs, minOfHalfs);
|
| 205 |
+
return vget_lane_f32(minOfMinOfHalfs, 0);
|
| 206 |
+
}
|
| 207 |
+
VM_INLINE float hmax(float3 v)
|
| 208 |
+
{
|
| 209 |
+
float32x2_t maxOfHalfs = vpmax_f32(vget_low_f32(v.m), vget_high_f32(v.m));
|
| 210 |
+
float32x2_t maxOfMaxOfHalfs = vpmax_f32(maxOfHalfs, maxOfHalfs);
|
| 211 |
+
return vget_lane_f32(maxOfMaxOfHalfs, 0);
|
| 212 |
+
}
|
| 213 |
+
|
| 214 |
+
VM_INLINE float3 cross(float3 a, float3 b)
|
| 215 |
+
{
|
| 216 |
+
// x <- a.y*b.z - a.z*b.y
|
| 217 |
+
// y <- a.z*b.x - a.x*b.z
|
| 218 |
+
// z <- a.x*b.y - a.y*b.x
|
| 219 |
+
// We can save a shuffle by grouping it in this wacky order:
|
| 220 |
+
return (a.zxy()*b - a*b.zxy()).zxy();
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
// Returns a 3-bit code where bit0..bit2 is X..Z
|
| 224 |
+
VM_INLINE unsigned mask(float3 v)
|
| 225 |
+
{
|
| 226 |
+
static const uint32x4_t movemask = { 1, 2, 4, 8 };
|
| 227 |
+
static const uint32x4_t highbit = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
|
| 228 |
+
uint32x4_t t0 = vreinterpretq_u32_f32(v.m);
|
| 229 |
+
uint32x4_t t1 = vtstq_u32(t0, highbit);
|
| 230 |
+
uint32x4_t t2 = vandq_u32(t1, movemask);
|
| 231 |
+
uint32x2_t t3 = vorr_u32(vget_low_u32(t2), vget_high_u32(t2));
|
| 232 |
+
return vget_lane_u32(t3, 0) | vget_lane_u32(t3, 1);
|
| 233 |
+
}
|
| 234 |
+
// Once we have a comparison, we can branch based on its results:
|
| 235 |
+
VM_INLINE bool any(bool3 v) { return mask(v) != 0; }
|
| 236 |
+
VM_INLINE bool all(bool3 v) { return mask(v) == 7; }
|
| 237 |
+
|
| 238 |
+
VM_INLINE float3 clamp(float3 t, float3 a, float3 b) { return min(max(t, a), b); }
|
| 239 |
+
VM_INLINE float sum(float3 v) { return v.getX() + v.getY() + v.getZ(); }
|
| 240 |
+
VM_INLINE float dot(float3 a, float3 b) { return sum(a*b); }
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
#endif // #else of #if !defined(__arm__) && !defined(__arm64__)
|
| 244 |
+
|
| 245 |
+
#else // #if DO_FLOAT3_WITH_SIMD
|
| 246 |
+
|
| 247 |
+
// ---- Simple scalar C implementation
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
struct float3
|
| 251 |
+
{
|
| 252 |
+
float3() : x(0), y(0), z(0) {}
|
| 253 |
+
float3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {}
|
| 254 |
+
|
| 255 |
+
float3 operator-() const { return float3(-x, -y, -z); }
|
| 256 |
+
float3& operator+=(const float3& o) { x+=o.x; y+=o.y; z+=o.z; return *this; }
|
| 257 |
+
float3& operator-=(const float3& o) { x-=o.x; y-=o.y; z-=o.z; return *this; }
|
| 258 |
+
float3& operator*=(const float3& o) { x*=o.x; y*=o.y; z*=o.z; return *this; }
|
| 259 |
+
float3& operator*=(float o) { x*=o; y*=o; z*=o; return *this; }
|
| 260 |
+
|
| 261 |
+
VM_INLINE float getX() const { return x; }
|
| 262 |
+
VM_INLINE float getY() const { return y; }
|
| 263 |
+
VM_INLINE float getZ() const { return z; }
|
| 264 |
+
VM_INLINE void setX(float x_) { x = x_; }
|
| 265 |
+
VM_INLINE void setY(float y_) { y = y_; }
|
| 266 |
+
VM_INLINE void setZ(float z_) { z = z_; }
|
| 267 |
+
VM_INLINE void store(float *p) const { p[0] = getX(); p[1] = getY(); p[2] = getZ(); }
|
| 268 |
+
|
| 269 |
+
float x, y, z;
|
| 270 |
+
};
|
| 271 |
+
|
| 272 |
+
VM_INLINE float3 operator+(const float3& a, const float3& b) { return float3(a.x+b.x,a.y+b.y,a.z+b.z); }
|
| 273 |
+
VM_INLINE float3 operator-(const float3& a, const float3& b) { return float3(a.x-b.x,a.y-b.y,a.z-b.z); }
|
| 274 |
+
VM_INLINE float3 operator*(const float3& a, const float3& b) { return float3(a.x*b.x,a.y*b.y,a.z*b.z); }
|
| 275 |
+
VM_INLINE float3 operator*(const float3& a, float b) { return float3(a.x*b,a.y*b,a.z*b); }
|
| 276 |
+
VM_INLINE float3 operator*(float a, const float3& b) { return float3(a*b.x,a*b.y,a*b.z); }
|
| 277 |
+
VM_INLINE float dot(const float3& a, const float3& b) { return a.x*b.x+a.y*b.y+a.z*b.z; }
|
| 278 |
+
VM_INLINE float3 cross(const float3& a, const float3& b)
|
| 279 |
+
{
|
| 280 |
+
return float3(
|
| 281 |
+
a.y*b.z - a.z*b.y,
|
| 282 |
+
-(a.x*b.z - a.z*b.x),
|
| 283 |
+
a.x*b.y - a.y*b.x
|
| 284 |
+
);
|
| 285 |
+
}
|
| 286 |
+
#endif // #else of #if DO_FLOAT3_WITH_SIMD
|
| 287 |
+
|
| 288 |
+
VM_INLINE float length(float3 v) { return sqrtf(dot(v, v)); }
|
| 289 |
+
VM_INLINE float sqLength(float3 v) { return dot(v, v); }
|
| 290 |
+
VM_INLINE float3 normalize(float3 v) { return v * (1.0f / length(v)); }
|
| 291 |
+
VM_INLINE float3 lerp(float3 a, float3 b, float t) { return a + (b-a)*t; }
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
inline void AssertUnit(float3 v)
|
| 295 |
+
{
|
| 296 |
+
assert(fabsf(sqLength(v) - 1.0f) < 0.01f);
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
inline float3 reflect(float3 v, float3 n)
|
| 300 |
+
{
|
| 301 |
+
return v - 2*dot(v,n)*n;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
inline bool refract(float3 v, float3 n, float nint, float3& outRefracted)
|
| 305 |
+
{
|
| 306 |
+
AssertUnit(v);
|
| 307 |
+
float dt = dot(v, n);
|
| 308 |
+
float discr = 1.0f - nint*nint*(1-dt*dt);
|
| 309 |
+
if (discr > 0)
|
| 310 |
+
{
|
| 311 |
+
outRefracted = nint * (v - n*dt) - n*sqrtf(discr);
|
| 312 |
+
return true;
|
| 313 |
+
}
|
| 314 |
+
return false;
|
| 315 |
+
}
|
| 316 |
+
inline float schlick(float cosine, float ri)
|
| 317 |
+
{
|
| 318 |
+
float r0 = (1-ri) / (1+ri);
|
| 319 |
+
r0 = r0*r0;
|
| 320 |
+
return r0 + (1-r0)*powf(1-cosine, 5);
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
struct Ray
|
| 324 |
+
{
|
| 325 |
+
Ray() {}
|
| 326 |
+
Ray(float3 orig_, float3 dir_) : orig(orig_), dir(dir_) { AssertUnit(dir); }
|
| 327 |
+
|
| 328 |
+
float3 pointAt(float t) const { return orig + dir * t; }
|
| 329 |
+
|
| 330 |
+
float3 orig;
|
| 331 |
+
float3 dir;
|
| 332 |
+
};
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
struct Hit
|
| 336 |
+
{
|
| 337 |
+
float3 pos;
|
| 338 |
+
float3 normal;
|
| 339 |
+
float t;
|
| 340 |
+
};
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
struct Sphere
|
| 344 |
+
{
|
| 345 |
+
Sphere() : radius(1.0f), invRadius(0.0f) {}
|
| 346 |
+
Sphere(float3 center_, float radius_) : center(center_), radius(radius_), invRadius(0.0f) {}
|
| 347 |
+
|
| 348 |
+
void UpdateDerivedData() { invRadius = 1.0f/radius; }
|
| 349 |
+
|
| 350 |
+
float3 center;
|
| 351 |
+
float radius;
|
| 352 |
+
float invRadius;
|
| 353 |
+
};
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
// data for all spheres in a "structure of arrays" layout
|
| 357 |
+
struct SpheresSoA
|
| 358 |
+
{
|
| 359 |
+
SpheresSoA(int c)
|
| 360 |
+
{
|
| 361 |
+
count = c;
|
| 362 |
+
// we'll be processing spheres in kSimdWidth chunks, so make sure to allocate
|
| 363 |
+
// enough space
|
| 364 |
+
simdCount = (c + (kSimdWidth - 1)) / kSimdWidth * kSimdWidth;
|
| 365 |
+
centerX = new float[simdCount];
|
| 366 |
+
centerY = new float[simdCount];
|
| 367 |
+
centerZ = new float[simdCount];
|
| 368 |
+
sqRadius = new float[simdCount];
|
| 369 |
+
invRadius = new float[simdCount];
|
| 370 |
+
// set all data to "impossible sphere" state
|
| 371 |
+
for (int i = count; i < simdCount; ++i)
|
| 372 |
+
{
|
| 373 |
+
centerX[i] = centerY[i] = centerZ[i] = 10000.0f;
|
| 374 |
+
sqRadius[i] = 0.0f;
|
| 375 |
+
invRadius[i] = 0.0f;
|
| 376 |
+
}
|
| 377 |
+
}
|
| 378 |
+
~SpheresSoA()
|
| 379 |
+
{
|
| 380 |
+
delete[] centerX;
|
| 381 |
+
delete[] centerY;
|
| 382 |
+
delete[] centerZ;
|
| 383 |
+
delete[] sqRadius;
|
| 384 |
+
delete[] invRadius;
|
| 385 |
+
}
|
| 386 |
+
float* centerX;
|
| 387 |
+
float* centerY;
|
| 388 |
+
float* centerZ;
|
| 389 |
+
float* sqRadius;
|
| 390 |
+
float* invRadius;
|
| 391 |
+
int simdCount;
|
| 392 |
+
int count;
|
| 393 |
+
};
|
| 394 |
+
|
| 395 |
+
|
| 396 |
+
int HitSpheres(const Ray& r, const SpheresSoA& spheres, float tMin, float tMax, Hit& outHit);
|
| 397 |
+
|
| 398 |
+
float RandomFloat01(uint32_t& state);
|
| 399 |
+
float3 RandomInUnitDisk(uint32_t& state);
|
| 400 |
+
float3 RandomInUnitSphere(uint32_t& state);
|
| 401 |
+
float3 RandomUnitVector(uint32_t& state);
|
| 402 |
+
|
| 403 |
+
struct Camera
|
| 404 |
+
{
|
| 405 |
+
Camera() {}
|
| 406 |
+
// vfov is top to bottom in degrees
|
| 407 |
+
Camera(const float3& lookFrom, const float3& lookAt, const float3& vup, float vfov, float aspect, float aperture, float focusDist)
|
| 408 |
+
{
|
| 409 |
+
lensRadius = aperture / 2;
|
| 410 |
+
float theta = vfov*kPI/180;
|
| 411 |
+
float halfHeight = tanf(theta/2);
|
| 412 |
+
float halfWidth = aspect * halfHeight;
|
| 413 |
+
origin = lookFrom;
|
| 414 |
+
w = normalize(lookFrom - lookAt);
|
| 415 |
+
u = normalize(cross(vup, w));
|
| 416 |
+
v = cross(w, u);
|
| 417 |
+
lowerLeftCorner = origin - halfWidth*focusDist*u - halfHeight*focusDist*v - focusDist*w;
|
| 418 |
+
horizontal = 2*halfWidth*focusDist*u;
|
| 419 |
+
vertical = 2*halfHeight*focusDist*v;
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
Ray GetRay(float s, float t, uint32_t& state) const
|
| 423 |
+
{
|
| 424 |
+
float3 rd = lensRadius * RandomInUnitDisk(state);
|
| 425 |
+
float3 offset = u * rd.getX() + v * rd.getY();
|
| 426 |
+
return Ray(origin + offset, normalize(lowerLeftCorner + s*horizontal + t*vertical - origin - offset));
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
float3 origin;
|
| 430 |
+
float3 lowerLeftCorner;
|
| 431 |
+
float3 horizontal;
|
| 432 |
+
float3 vertical;
|
| 433 |
+
float3 u, v, w;
|
| 434 |
+
float lensRadius;
|
| 435 |
+
};
|
| 436 |
+
|
third_party/tracy/examples/ToyPathTracer/Source/Test.cpp
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "Config.h"
|
| 2 |
+
#include "Test.h"
|
| 3 |
+
#include "Maths.h"
|
| 4 |
+
#include <algorithm>
|
| 5 |
+
#if CPU_CAN_DO_THREADS
|
| 6 |
+
#include "enkiTS/TaskScheduler_c.h"
|
| 7 |
+
#include <thread>
|
| 8 |
+
#endif
|
| 9 |
+
#include <atomic>
|
| 10 |
+
|
| 11 |
+
#include "../../../public/tracy/Tracy.hpp"
|
| 12 |
+
|
| 13 |
+
// 46 spheres (2 emissive) when enabled; 9 spheres (1 emissive) when disabled
|
| 14 |
+
#define DO_BIG_SCENE 1
|
| 15 |
+
|
| 16 |
+
static Sphere s_Spheres[] =
|
| 17 |
+
{
|
| 18 |
+
{float3(0,-100.5,-1), 100},
|
| 19 |
+
{float3(2,0,-1), 0.5f},
|
| 20 |
+
{float3(0,0,-1), 0.5f},
|
| 21 |
+
{float3(-2,0,-1), 0.5f},
|
| 22 |
+
{float3(2,0,1), 0.5f},
|
| 23 |
+
{float3(0,0,1), 0.5f},
|
| 24 |
+
{float3(-2,0,1), 0.5f},
|
| 25 |
+
{float3(0.5f,1,0.5f), 0.5f},
|
| 26 |
+
{float3(-1.5f,1.5f,0.f), 0.3f},
|
| 27 |
+
#if DO_BIG_SCENE
|
| 28 |
+
{float3(4,0,-3), 0.5f}, {float3(3,0,-3), 0.5f}, {float3(2,0,-3), 0.5f}, {float3(1,0,-3), 0.5f}, {float3(0,0,-3), 0.5f}, {float3(-1,0,-3), 0.5f}, {float3(-2,0,-3), 0.5f}, {float3(-3,0,-3), 0.5f}, {float3(-4,0,-3), 0.5f},
|
| 29 |
+
{float3(4,0,-4), 0.5f}, {float3(3,0,-4), 0.5f}, {float3(2,0,-4), 0.5f}, {float3(1,0,-4), 0.5f}, {float3(0,0,-4), 0.5f}, {float3(-1,0,-4), 0.5f}, {float3(-2,0,-4), 0.5f}, {float3(-3,0,-4), 0.5f}, {float3(-4,0,-4), 0.5f},
|
| 30 |
+
{float3(4,0,-5), 0.5f}, {float3(3,0,-5), 0.5f}, {float3(2,0,-5), 0.5f}, {float3(1,0,-5), 0.5f}, {float3(0,0,-5), 0.5f}, {float3(-1,0,-5), 0.5f}, {float3(-2,0,-5), 0.5f}, {float3(-3,0,-5), 0.5f}, {float3(-4,0,-5), 0.5f},
|
| 31 |
+
{float3(4,0,-6), 0.5f}, {float3(3,0,-6), 0.5f}, {float3(2,0,-6), 0.5f}, {float3(1,0,-6), 0.5f}, {float3(0,0,-6), 0.5f}, {float3(-1,0,-6), 0.5f}, {float3(-2,0,-6), 0.5f}, {float3(-3,0,-6), 0.5f}, {float3(-4,0,-6), 0.5f},
|
| 32 |
+
{float3(1.5f,1.5f,-2), 0.3f},
|
| 33 |
+
#endif // #if DO_BIG_SCENE
|
| 34 |
+
};
|
| 35 |
+
const int kSphereCount = sizeof(s_Spheres) / sizeof(s_Spheres[0]);
|
| 36 |
+
|
| 37 |
+
static SpheresSoA s_SpheresSoA(kSphereCount);
|
| 38 |
+
|
| 39 |
+
struct Material
|
| 40 |
+
{
|
| 41 |
+
enum Type { Lambert, Metal, Dielectric };
|
| 42 |
+
Type type;
|
| 43 |
+
float3 albedo;
|
| 44 |
+
float3 emissive;
|
| 45 |
+
float roughness;
|
| 46 |
+
float ri;
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
static Material s_SphereMats[kSphereCount] =
|
| 50 |
+
{
|
| 51 |
+
{ Material::Lambert, float3(0.8f, 0.8f, 0.8f), float3(0,0,0), 0, 0, },
|
| 52 |
+
{ Material::Lambert, float3(0.8f, 0.4f, 0.4f), float3(0,0,0), 0, 0, },
|
| 53 |
+
{ Material::Lambert, float3(0.4f, 0.8f, 0.4f), float3(0,0,0), 0, 0, },
|
| 54 |
+
{ Material::Metal, float3(0.4f, 0.4f, 0.8f), float3(0,0,0), 0, 0 },
|
| 55 |
+
{ Material::Metal, float3(0.4f, 0.8f, 0.4f), float3(0,0,0), 0, 0 },
|
| 56 |
+
{ Material::Metal, float3(0.4f, 0.8f, 0.4f), float3(0,0,0), 0.2f, 0 },
|
| 57 |
+
{ Material::Metal, float3(0.4f, 0.8f, 0.4f), float3(0,0,0), 0.6f, 0 },
|
| 58 |
+
{ Material::Dielectric, float3(0.4f, 0.4f, 0.4f), float3(0,0,0), 0, 1.5f },
|
| 59 |
+
{ Material::Lambert, float3(0.8f, 0.6f, 0.2f), float3(30,25,15), 0, 0 },
|
| 60 |
+
#if DO_BIG_SCENE
|
| 61 |
+
{ Material::Lambert, float3(0.1f, 0.1f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.2f, 0.2f, 0.2f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.3f, 0.3f, 0.3f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.4f, 0.4f, 0.4f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.5f, 0.5f, 0.5f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.6f, 0.6f, 0.6f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.7f, 0.7f, 0.7f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.8f, 0.8f, 0.8f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.9f, 0.9f, 0.9f), float3(0,0,0), 0, 0, },
|
| 62 |
+
{ Material::Metal, float3(0.1f, 0.1f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.2f, 0.2f, 0.2f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.3f, 0.3f, 0.3f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.4f, 0.4f, 0.4f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.5f, 0.5f, 0.5f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.6f, 0.6f, 0.6f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.7f, 0.7f, 0.7f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.8f, 0.8f, 0.8f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.9f, 0.9f, 0.9f), float3(0,0,0), 0, 0, },
|
| 63 |
+
{ Material::Metal, float3(0.8f, 0.1f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.8f, 0.5f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.8f, 0.8f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.4f, 0.8f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.1f, 0.8f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.1f, 0.8f, 0.5f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.1f, 0.8f, 0.8f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.1f, 0.1f, 0.8f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.5f, 0.1f, 0.8f), float3(0,0,0), 0, 0, },
|
| 64 |
+
{ Material::Lambert, float3(0.8f, 0.1f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.8f, 0.5f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.8f, 0.8f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.4f, 0.8f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.1f, 0.8f, 0.1f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.1f, 0.8f, 0.5f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.1f, 0.8f, 0.8f), float3(0,0,0), 0, 0, }, { Material::Lambert, float3(0.1f, 0.1f, 0.8f), float3(0,0,0), 0, 0, }, { Material::Metal, float3(0.5f, 0.1f, 0.8f), float3(0,0,0), 0, 0, },
|
| 65 |
+
{ Material::Lambert, float3(0.1f, 0.2f, 0.5f), float3(3,10,20), 0, 0 },
|
| 66 |
+
#endif
|
| 67 |
+
};
|
| 68 |
+
|
| 69 |
+
static int s_EmissiveSpheres[kSphereCount];
|
| 70 |
+
static int s_EmissiveSphereCount;
|
| 71 |
+
|
| 72 |
+
static Camera s_Cam;
|
| 73 |
+
|
| 74 |
+
const float kMinT = 0.001f;
|
| 75 |
+
const float kMaxT = 1.0e7f;
|
| 76 |
+
const int kMaxDepth = 10;
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
bool HitWorld(const Ray& r, float tMin, float tMax, Hit& outHit, int& outID)
|
| 80 |
+
{
|
| 81 |
+
outID = HitSpheres(r, s_SpheresSoA, tMin, tMax, outHit);
|
| 82 |
+
return outID != -1;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
static bool Scatter(const Material& mat, const Ray& r_in, const Hit& rec, float3& attenuation, Ray& scattered, float3& outLightE, int& inoutRayCount, uint32_t& state)
|
| 87 |
+
{
|
| 88 |
+
ZoneScoped;
|
| 89 |
+
outLightE = float3(0,0,0);
|
| 90 |
+
if (mat.type == Material::Lambert)
|
| 91 |
+
{
|
| 92 |
+
// random point on unit sphere that is tangent to the hit point
|
| 93 |
+
float3 target = rec.pos + rec.normal + RandomUnitVector(state);
|
| 94 |
+
scattered = Ray(rec.pos, normalize(target - rec.pos));
|
| 95 |
+
attenuation = mat.albedo;
|
| 96 |
+
|
| 97 |
+
// sample lights
|
| 98 |
+
#if DO_LIGHT_SAMPLING
|
| 99 |
+
for (int j = 0; j < s_EmissiveSphereCount; ++j)
|
| 100 |
+
{
|
| 101 |
+
int i = s_EmissiveSpheres[j];
|
| 102 |
+
const Material& smat = s_SphereMats[i];
|
| 103 |
+
if (&mat == &smat)
|
| 104 |
+
continue; // skip self
|
| 105 |
+
const Sphere& s = s_Spheres[i];
|
| 106 |
+
|
| 107 |
+
// create a random direction towards sphere
|
| 108 |
+
// coord system for sampling: sw, su, sv
|
| 109 |
+
float3 sw = normalize(s.center - rec.pos);
|
| 110 |
+
float3 su = normalize(cross(fabs(sw.getX())>0.01f ? float3(0,1,0):float3(1,0,0), sw));
|
| 111 |
+
float3 sv = cross(sw, su);
|
| 112 |
+
// sample sphere by solid angle
|
| 113 |
+
float cosAMax = sqrtf(1.0f - s.radius*s.radius / sqLength(rec.pos-s.center));
|
| 114 |
+
float eps1 = RandomFloat01(state), eps2 = RandomFloat01(state);
|
| 115 |
+
float cosA = 1.0f - eps1 + eps1 * cosAMax;
|
| 116 |
+
float sinA = sqrtf(1.0f - cosA*cosA);
|
| 117 |
+
float phi = 2 * kPI * eps2;
|
| 118 |
+
float3 l = su * (cosf(phi) * sinA) + sv * (sinf(phi) * sinA) + sw * cosA;
|
| 119 |
+
//l = normalize(l); // NOTE(fg): This is already normalized, by construction.
|
| 120 |
+
|
| 121 |
+
// shoot shadow ray
|
| 122 |
+
Hit lightHit;
|
| 123 |
+
int hitID;
|
| 124 |
+
++inoutRayCount;
|
| 125 |
+
if (HitWorld(Ray(rec.pos, l), kMinT, kMaxT, lightHit, hitID) && hitID == i)
|
| 126 |
+
{
|
| 127 |
+
float omega = 2 * kPI * (1-cosAMax);
|
| 128 |
+
|
| 129 |
+
float3 rdir = r_in.dir;
|
| 130 |
+
AssertUnit(rdir);
|
| 131 |
+
float3 nl = dot(rec.normal, rdir) < 0 ? rec.normal : -rec.normal;
|
| 132 |
+
outLightE += (mat.albedo * smat.emissive) * (std::max(0.0f, dot(l, nl)) * omega / kPI);
|
| 133 |
+
}
|
| 134 |
+
}
|
| 135 |
+
#endif
|
| 136 |
+
return true;
|
| 137 |
+
}
|
| 138 |
+
else if (mat.type == Material::Metal)
|
| 139 |
+
{
|
| 140 |
+
AssertUnit(r_in.dir); AssertUnit(rec.normal);
|
| 141 |
+
float3 refl = reflect(r_in.dir, rec.normal);
|
| 142 |
+
// reflected ray, and random inside of sphere based on roughness
|
| 143 |
+
float roughness = mat.roughness;
|
| 144 |
+
#if DO_MITSUBA_COMPARE
|
| 145 |
+
roughness = 0; // until we get better BRDF for metals
|
| 146 |
+
#endif
|
| 147 |
+
scattered = Ray(rec.pos, normalize(refl + roughness*RandomInUnitSphere(state)));
|
| 148 |
+
attenuation = mat.albedo;
|
| 149 |
+
return dot(scattered.dir, rec.normal) > 0;
|
| 150 |
+
}
|
| 151 |
+
else if (mat.type == Material::Dielectric)
|
| 152 |
+
{
|
| 153 |
+
AssertUnit(r_in.dir); AssertUnit(rec.normal);
|
| 154 |
+
float3 outwardN;
|
| 155 |
+
float3 rdir = r_in.dir;
|
| 156 |
+
float3 refl = reflect(rdir, rec.normal);
|
| 157 |
+
float nint;
|
| 158 |
+
attenuation = float3(1,1,1);
|
| 159 |
+
float3 refr;
|
| 160 |
+
float reflProb;
|
| 161 |
+
float cosine;
|
| 162 |
+
if (dot(rdir, rec.normal) > 0)
|
| 163 |
+
{
|
| 164 |
+
outwardN = -rec.normal;
|
| 165 |
+
nint = mat.ri;
|
| 166 |
+
cosine = mat.ri * dot(rdir, rec.normal);
|
| 167 |
+
}
|
| 168 |
+
else
|
| 169 |
+
{
|
| 170 |
+
outwardN = rec.normal;
|
| 171 |
+
nint = 1.0f / mat.ri;
|
| 172 |
+
cosine = -dot(rdir, rec.normal);
|
| 173 |
+
}
|
| 174 |
+
if (refract(rdir, outwardN, nint, refr))
|
| 175 |
+
{
|
| 176 |
+
reflProb = schlick(cosine, mat.ri);
|
| 177 |
+
}
|
| 178 |
+
else
|
| 179 |
+
{
|
| 180 |
+
reflProb = 1;
|
| 181 |
+
}
|
| 182 |
+
if (RandomFloat01(state) < reflProb)
|
| 183 |
+
scattered = Ray(rec.pos, normalize(refl));
|
| 184 |
+
else
|
| 185 |
+
scattered = Ray(rec.pos, normalize(refr));
|
| 186 |
+
}
|
| 187 |
+
else
|
| 188 |
+
{
|
| 189 |
+
attenuation = float3(1,0,1);
|
| 190 |
+
return false;
|
| 191 |
+
}
|
| 192 |
+
return true;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
static float3 Trace(const Ray& r, int depth, int& inoutRayCount, uint32_t& state, bool doMaterialE = true)
|
| 196 |
+
{
|
| 197 |
+
ZoneScoped;
|
| 198 |
+
Hit rec;
|
| 199 |
+
int id = 0;
|
| 200 |
+
++inoutRayCount;
|
| 201 |
+
if (HitWorld(r, kMinT, kMaxT, rec, id))
|
| 202 |
+
{
|
| 203 |
+
Ray scattered;
|
| 204 |
+
float3 attenuation;
|
| 205 |
+
float3 lightE;
|
| 206 |
+
const Material& mat = s_SphereMats[id];
|
| 207 |
+
float3 matE = mat.emissive;
|
| 208 |
+
if (depth < kMaxDepth && Scatter(mat, r, rec, attenuation, scattered, lightE, inoutRayCount, state))
|
| 209 |
+
{
|
| 210 |
+
#if DO_LIGHT_SAMPLING
|
| 211 |
+
if (!doMaterialE) matE = float3(0,0,0); // don't add material emission if told so
|
| 212 |
+
// dor Lambert materials, we just did explicit light (emissive) sampling and already
|
| 213 |
+
// for their contribution, so if next ray bounce hits the light again, don't add
|
| 214 |
+
// emission
|
| 215 |
+
doMaterialE = (mat.type != Material::Lambert);
|
| 216 |
+
#endif
|
| 217 |
+
return matE + lightE + attenuation * Trace(scattered, depth+1, inoutRayCount, state, doMaterialE);
|
| 218 |
+
}
|
| 219 |
+
else
|
| 220 |
+
{
|
| 221 |
+
return matE;
|
| 222 |
+
}
|
| 223 |
+
}
|
| 224 |
+
else
|
| 225 |
+
{
|
| 226 |
+
// sky
|
| 227 |
+
#if DO_MITSUBA_COMPARE
|
| 228 |
+
return float3(0.15f,0.21f,0.3f); // easier compare with Mitsuba's constant environment light
|
| 229 |
+
#else
|
| 230 |
+
float3 unitDir = r.dir;
|
| 231 |
+
float t = 0.5f*(unitDir.getY() + 1.0f);
|
| 232 |
+
return ((1.0f-t)*float3(1.0f, 1.0f, 1.0f) + t*float3(0.5f, 0.7f, 1.0f)) * 0.3f;
|
| 233 |
+
#endif
|
| 234 |
+
}
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
#if CPU_CAN_DO_THREADS
|
| 238 |
+
static enkiTaskScheduler* g_TS;
|
| 239 |
+
#endif
|
| 240 |
+
|
| 241 |
+
void InitializeTest()
|
| 242 |
+
{
|
| 243 |
+
ZoneScoped;
|
| 244 |
+
#if CPU_CAN_DO_THREADS
|
| 245 |
+
g_TS = enkiNewTaskScheduler();
|
| 246 |
+
enkiInitTaskSchedulerNumThreads(g_TS, std::max<int>( 2, std::thread::hardware_concurrency() - 2));
|
| 247 |
+
#endif
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
void ShutdownTest()
|
| 251 |
+
{
|
| 252 |
+
ZoneScoped;
|
| 253 |
+
#if CPU_CAN_DO_THREADS
|
| 254 |
+
enkiDeleteTaskScheduler(g_TS);
|
| 255 |
+
#endif
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
struct JobData
|
| 259 |
+
{
|
| 260 |
+
float time;
|
| 261 |
+
int frameCount;
|
| 262 |
+
int screenWidth, screenHeight;
|
| 263 |
+
float* backbuffer;
|
| 264 |
+
Camera* cam;
|
| 265 |
+
std::atomic<int> rayCount;
|
| 266 |
+
unsigned testFlags;
|
| 267 |
+
};
|
| 268 |
+
|
| 269 |
+
static void TraceRowJob(uint32_t start, uint32_t end, uint32_t threadnum, void* data_)
|
| 270 |
+
{
|
| 271 |
+
ZoneScoped;
|
| 272 |
+
JobData& data = *(JobData*)data_;
|
| 273 |
+
float* backbuffer = data.backbuffer + start * data.screenWidth * 4;
|
| 274 |
+
float invWidth = 1.0f / data.screenWidth;
|
| 275 |
+
float invHeight = 1.0f / data.screenHeight;
|
| 276 |
+
float lerpFac = float(data.frameCount) / float(data.frameCount+1);
|
| 277 |
+
if (data.testFlags & kFlagAnimate)
|
| 278 |
+
lerpFac *= DO_ANIMATE_SMOOTHING;
|
| 279 |
+
if (!(data.testFlags & kFlagProgressive))
|
| 280 |
+
lerpFac = 0;
|
| 281 |
+
int rayCount = 0;
|
| 282 |
+
for (uint32_t y = start; y < end; ++y)
|
| 283 |
+
{
|
| 284 |
+
uint32_t state = (y * 9781 + data.frameCount * 6271) | 1;
|
| 285 |
+
for (int x = 0; x < data.screenWidth; ++x)
|
| 286 |
+
{
|
| 287 |
+
float3 col(0, 0, 0);
|
| 288 |
+
for (int s = 0; s < DO_SAMPLES_PER_PIXEL; s++)
|
| 289 |
+
{
|
| 290 |
+
float u = float(x + RandomFloat01(state)) * invWidth;
|
| 291 |
+
float v = float(y + RandomFloat01(state)) * invHeight;
|
| 292 |
+
Ray r = data.cam->GetRay(u, v, state);
|
| 293 |
+
col += Trace(r, 0, rayCount, state);
|
| 294 |
+
}
|
| 295 |
+
col *= 1.0f / float(DO_SAMPLES_PER_PIXEL);
|
| 296 |
+
|
| 297 |
+
float3 prev(backbuffer[0], backbuffer[1], backbuffer[2]);
|
| 298 |
+
col = prev * lerpFac + col * (1-lerpFac);
|
| 299 |
+
col.store(backbuffer);
|
| 300 |
+
backbuffer += 4;
|
| 301 |
+
}
|
| 302 |
+
}
|
| 303 |
+
data.rayCount += rayCount;
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
void UpdateTest(float time, int frameCount, int screenWidth, int screenHeight, unsigned testFlags)
|
| 307 |
+
{
|
| 308 |
+
ZoneScoped;
|
| 309 |
+
if (testFlags & kFlagAnimate)
|
| 310 |
+
{
|
| 311 |
+
s_Spheres[1].center.setY(cosf(time) + 1.0f);
|
| 312 |
+
s_Spheres[8].center.setZ(sinf(time)*0.3f);
|
| 313 |
+
}
|
| 314 |
+
float3 lookfrom(0, 2, 3);
|
| 315 |
+
float3 lookat(0, 0, 0);
|
| 316 |
+
float distToFocus = 3;
|
| 317 |
+
#if DO_MITSUBA_COMPARE
|
| 318 |
+
float aperture = 0.0f;
|
| 319 |
+
#else
|
| 320 |
+
float aperture = 0.1f;
|
| 321 |
+
#endif
|
| 322 |
+
#if DO_BIG_SCENE
|
| 323 |
+
aperture *= 0.2f;
|
| 324 |
+
#endif
|
| 325 |
+
|
| 326 |
+
s_EmissiveSphereCount = 0;
|
| 327 |
+
for (int i = 0; i < kSphereCount; ++i)
|
| 328 |
+
{
|
| 329 |
+
Sphere& s = s_Spheres[i];
|
| 330 |
+
s.UpdateDerivedData();
|
| 331 |
+
s_SpheresSoA.centerX[i] = s.center.getX();
|
| 332 |
+
s_SpheresSoA.centerY[i] = s.center.getY();
|
| 333 |
+
s_SpheresSoA.centerZ[i] = s.center.getZ();
|
| 334 |
+
s_SpheresSoA.sqRadius[i] = s.radius * s.radius;
|
| 335 |
+
s_SpheresSoA.invRadius[i] = s.invRadius;
|
| 336 |
+
|
| 337 |
+
// Remember IDs of emissive spheres (light sources)
|
| 338 |
+
const Material& smat = s_SphereMats[i];
|
| 339 |
+
if (smat.emissive.getX() > 0 || smat.emissive.getY() > 0 || smat.emissive.getZ() > 0)
|
| 340 |
+
{
|
| 341 |
+
s_EmissiveSpheres[s_EmissiveSphereCount] = i;
|
| 342 |
+
s_EmissiveSphereCount++;
|
| 343 |
+
}
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
s_Cam = Camera(lookfrom, lookat, float3(0, 1, 0), 60, float(screenWidth) / float(screenHeight), aperture, distToFocus);
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
void DrawTest(float time, int frameCount, int screenWidth, int screenHeight, float* backbuffer, int& outRayCount, unsigned testFlags)
|
| 350 |
+
{
|
| 351 |
+
ZoneScoped;
|
| 352 |
+
JobData args;
|
| 353 |
+
args.time = time;
|
| 354 |
+
args.frameCount = frameCount;
|
| 355 |
+
args.screenWidth = screenWidth;
|
| 356 |
+
args.screenHeight = screenHeight;
|
| 357 |
+
args.backbuffer = backbuffer;
|
| 358 |
+
args.cam = &s_Cam;
|
| 359 |
+
args.testFlags = testFlags;
|
| 360 |
+
args.rayCount = 0;
|
| 361 |
+
|
| 362 |
+
#if CPU_CAN_DO_THREADS
|
| 363 |
+
enkiTaskSet* task = enkiCreateTaskSet(g_TS, TraceRowJob);
|
| 364 |
+
bool threaded = true;
|
| 365 |
+
enkiAddTaskSetToPipeMinRange(g_TS, task, &args, screenHeight, threaded ? 4 : screenHeight);
|
| 366 |
+
enkiWaitForTaskSet(g_TS, task);
|
| 367 |
+
enkiDeleteTaskSet(task);
|
| 368 |
+
#else
|
| 369 |
+
TraceRowJob(0, screenHeight, 0, &args);
|
| 370 |
+
#endif
|
| 371 |
+
|
| 372 |
+
outRayCount = args.rayCount;
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
void GetObjectCount(int& outCount, int& outObjectSize, int& outMaterialSize, int& outCamSize)
|
| 376 |
+
{
|
| 377 |
+
ZoneScoped;
|
| 378 |
+
outCount = kSphereCount;
|
| 379 |
+
outObjectSize = sizeof(Sphere);
|
| 380 |
+
outMaterialSize = sizeof(Material);
|
| 381 |
+
outCamSize = sizeof(Camera);
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
void GetSceneDesc(void* outObjects, void* outMaterials, void* outCam, void* outEmissives, int* outEmissiveCount)
|
| 385 |
+
{
|
| 386 |
+
ZoneScoped;
|
| 387 |
+
memcpy(outObjects, s_Spheres, kSphereCount * sizeof(s_Spheres[0]));
|
| 388 |
+
memcpy(outMaterials, s_SphereMats, kSphereCount * sizeof(s_SphereMats[0]));
|
| 389 |
+
memcpy(outCam, &s_Cam, sizeof(s_Cam));
|
| 390 |
+
memcpy(outEmissives, s_EmissiveSpheres, s_EmissiveSphereCount * sizeof(s_EmissiveSpheres[0]));
|
| 391 |
+
*outEmissiveCount = s_EmissiveSphereCount;
|
| 392 |
+
}
|
third_party/tracy/examples/ToyPathTracer/Source/Test.h
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <stdint.h>
|
| 3 |
+
|
| 4 |
+
enum TestFlags
|
| 5 |
+
{
|
| 6 |
+
kFlagAnimate = (1 << 0),
|
| 7 |
+
kFlagProgressive = (1 << 1),
|
| 8 |
+
};
|
| 9 |
+
|
| 10 |
+
void InitializeTest();
|
| 11 |
+
void ShutdownTest();
|
| 12 |
+
|
| 13 |
+
void UpdateTest(float time, int frameCount, int screenWidth, int screenHeight, unsigned testFlags);
|
| 14 |
+
void DrawTest(float time, int frameCount, int screenWidth, int screenHeight, float* backbuffer, int& outRayCount, unsigned testFlags);
|
| 15 |
+
|
| 16 |
+
void GetObjectCount(int& outCount, int& outObjectSize, int& outMaterialSize, int& outCamSize);
|
| 17 |
+
void GetSceneDesc(void* outObjects, void* outMaterials, void* outCam, void* outEmissives, int* outEmissiveCount);
|
third_party/tracy/examples/ToyPathTracer/Source/enkiTS/Atomics.h
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (c) 2013 Doug Binks
|
| 2 |
+
//
|
| 3 |
+
// This software is provided 'as-is', without any express or implied
|
| 4 |
+
// warranty. In no event will the authors be held liable for any damages
|
| 5 |
+
// arising from the use of this software.
|
| 6 |
+
//
|
| 7 |
+
// Permission is granted to anyone to use this software for any purpose,
|
| 8 |
+
// including commercial applications, and to alter it and redistribute it
|
| 9 |
+
// freely, subject to the following restrictions:
|
| 10 |
+
//
|
| 11 |
+
// 1. The origin of this software must not be misrepresented; you must not
|
| 12 |
+
// claim that you wrote the original software. If you use this software
|
| 13 |
+
// in a product, an acknowledgement in the product documentation would be
|
| 14 |
+
// appreciated but is not required.
|
| 15 |
+
// 2. Altered source versions must be plainly marked as such, and must not be
|
| 16 |
+
// misrepresented as being the original software.
|
| 17 |
+
// 3. This notice may not be removed or altered from any source distribution.
|
| 18 |
+
|
| 19 |
+
#pragma once
|
| 20 |
+
|
| 21 |
+
#include <stdint.h>
|
| 22 |
+
|
| 23 |
+
#ifdef _WIN32
|
| 24 |
+
#define WIN32_LEAN_AND_MEAN
|
| 25 |
+
#include <Windows.h>
|
| 26 |
+
#undef GetObject
|
| 27 |
+
#include <intrin.h>
|
| 28 |
+
|
| 29 |
+
extern "C" void _ReadWriteBarrier();
|
| 30 |
+
#pragma intrinsic(_ReadWriteBarrier)
|
| 31 |
+
#pragma intrinsic(_InterlockedCompareExchange)
|
| 32 |
+
#pragma intrinsic(_InterlockedExchangeAdd)
|
| 33 |
+
|
| 34 |
+
// Memory Barriers to prevent CPU and Compiler re-ordering
|
| 35 |
+
#define BASE_MEMORYBARRIER_ACQUIRE() _ReadWriteBarrier()
|
| 36 |
+
#define BASE_MEMORYBARRIER_RELEASE() _ReadWriteBarrier()
|
| 37 |
+
#define BASE_ALIGN(x) __declspec( align( x ) )
|
| 38 |
+
|
| 39 |
+
#else
|
| 40 |
+
#define BASE_MEMORYBARRIER_ACQUIRE() __asm__ __volatile__("": : :"memory")
|
| 41 |
+
#define BASE_MEMORYBARRIER_RELEASE() __asm__ __volatile__("": : :"memory")
|
| 42 |
+
#define BASE_ALIGN(x) __attribute__ ((aligned( x )))
|
| 43 |
+
#endif
|
| 44 |
+
|
| 45 |
+
namespace enki
|
| 46 |
+
{
|
| 47 |
+
// Atomically performs: if( *pDest == compareWith ) { *pDest = swapTo; }
|
| 48 |
+
// returns old *pDest (so if successfull, returns compareWith)
|
| 49 |
+
inline uint32_t AtomicCompareAndSwap( volatile uint32_t* pDest, uint32_t swapTo, uint32_t compareWith )
|
| 50 |
+
{
|
| 51 |
+
#ifdef _WIN32
|
| 52 |
+
// assumes two's complement - unsigned / signed conversion leads to same bit pattern
|
| 53 |
+
return _InterlockedCompareExchange( (volatile long*)pDest,swapTo, compareWith );
|
| 54 |
+
#else
|
| 55 |
+
return __sync_val_compare_and_swap( pDest, compareWith, swapTo );
|
| 56 |
+
#endif
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
inline uint64_t AtomicCompareAndSwap( volatile uint64_t* pDest, uint64_t swapTo, uint64_t compareWith )
|
| 60 |
+
{
|
| 61 |
+
#ifdef _WIN32
|
| 62 |
+
// assumes two's complement - unsigned / signed conversion leads to same bit pattern
|
| 63 |
+
return _InterlockedCompareExchange64( (__int64 volatile*)pDest, swapTo, compareWith );
|
| 64 |
+
#else
|
| 65 |
+
return __sync_val_compare_and_swap( pDest, compareWith, swapTo );
|
| 66 |
+
#endif
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
// Atomically performs: tmp = *pDest; *pDest += value; return tmp;
|
| 70 |
+
inline int32_t AtomicAdd( volatile int32_t* pDest, int32_t value )
|
| 71 |
+
{
|
| 72 |
+
#ifdef _WIN32
|
| 73 |
+
return _InterlockedExchangeAdd( (long*)pDest, value );
|
| 74 |
+
#else
|
| 75 |
+
return __sync_fetch_and_add( pDest, value );
|
| 76 |
+
#endif
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
}
|
third_party/tracy/examples/ToyPathTracer/Source/enkiTS/LockLessMultiReadPipe.h
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (c) 2013 Doug Binks
|
| 2 |
+
//
|
| 3 |
+
// This software is provided 'as-is', without any express or implied
|
| 4 |
+
// warranty. In no event will the authors be held liable for any damages
|
| 5 |
+
// arising from the use of this software.
|
| 6 |
+
//
|
| 7 |
+
// Permission is granted to anyone to use this software for any purpose,
|
| 8 |
+
// including commercial applications, and to alter it and redistribute it
|
| 9 |
+
// freely, subject to the following restrictions:
|
| 10 |
+
//
|
| 11 |
+
// 1. The origin of this software must not be misrepresented; you must not
|
| 12 |
+
// claim that you wrote the original software. If you use this software
|
| 13 |
+
// in a product, an acknowledgement in the product documentation would be
|
| 14 |
+
// appreciated but is not required.
|
| 15 |
+
// 2. Altered source versions must be plainly marked as such, and must not be
|
| 16 |
+
// misrepresented as being the original software.
|
| 17 |
+
// 3. This notice may not be removed or altered from any source distribution.
|
| 18 |
+
|
| 19 |
+
#pragma once
|
| 20 |
+
|
| 21 |
+
#include <stdint.h>
|
| 22 |
+
#include <assert.h>
|
| 23 |
+
|
| 24 |
+
#include "Atomics.h"
|
| 25 |
+
#include <string.h>
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
namespace enki
|
| 29 |
+
{
|
| 30 |
+
// LockLessMultiReadPipe - Single writer, multiple reader thread safe pipe using (semi) lockless programming
|
| 31 |
+
// Readers can only read from the back of the pipe
|
| 32 |
+
// The single writer can write to the front of the pipe, and read from both ends (a writer can be a reader)
|
| 33 |
+
// for many of the principles used here, see http://msdn.microsoft.com/en-us/library/windows/desktop/ee418650(v=vs.85).aspx
|
| 34 |
+
// Note: using log2 sizes so we do not need to clamp (multi-operation)
|
| 35 |
+
// T is the contained type
|
| 36 |
+
// Note this is not true lockless as the use of flags as a form of lock state.
|
| 37 |
+
template<uint8_t cSizeLog2, typename T> class LockLessMultiReadPipe
|
| 38 |
+
{
|
| 39 |
+
public:
|
| 40 |
+
LockLessMultiReadPipe();
|
| 41 |
+
~LockLessMultiReadPipe() {}
|
| 42 |
+
|
| 43 |
+
// ReaderTryReadBack returns false if we were unable to read
|
| 44 |
+
// This is thread safe for both multiple readers and the writer
|
| 45 |
+
bool ReaderTryReadBack( T* pOut );
|
| 46 |
+
|
| 47 |
+
// WriterTryReadFront returns false if we were unable to read
|
| 48 |
+
// This is thread safe for the single writer, but should not be called by readers
|
| 49 |
+
bool WriterTryReadFront( T* pOut );
|
| 50 |
+
|
| 51 |
+
// WriterTryWriteFront returns false if we were unable to write
|
| 52 |
+
// This is thread safe for the single writer, but should not be called by readers
|
| 53 |
+
bool WriterTryWriteFront( const T& in );
|
| 54 |
+
|
| 55 |
+
// IsPipeEmpty() is a utility function, not intended for general use
|
| 56 |
+
// Should only be used very prudently.
|
| 57 |
+
bool IsPipeEmpty() const
|
| 58 |
+
{
|
| 59 |
+
return 0 == m_WriteIndex - m_ReadCount;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
void Clear()
|
| 63 |
+
{
|
| 64 |
+
m_WriteIndex = 0;
|
| 65 |
+
m_ReadIndex = 0;
|
| 66 |
+
m_ReadCount = 0;
|
| 67 |
+
memset( (void*)m_Flags, 0, sizeof( m_Flags ) );
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
private:
|
| 71 |
+
const static uint32_t ms_cSize = ( 1 << cSizeLog2 );
|
| 72 |
+
const static uint32_t ms_cIndexMask = ms_cSize - 1;
|
| 73 |
+
const static uint32_t FLAG_INVALID = 0xFFFFFFFF; // 32bit for CAS
|
| 74 |
+
const static uint32_t FLAG_CAN_WRITE = 0x00000000; // 32bit for CAS
|
| 75 |
+
const static uint32_t FLAG_CAN_READ = 0x11111111; // 32bit for CAS
|
| 76 |
+
|
| 77 |
+
T m_Buffer[ ms_cSize ];
|
| 78 |
+
|
| 79 |
+
// read and write indexes allow fast access to the pipe, but actual access
|
| 80 |
+
// controlled by the access flags.
|
| 81 |
+
volatile uint32_t BASE_ALIGN(4) m_WriteIndex;
|
| 82 |
+
volatile uint32_t BASE_ALIGN(4) m_ReadCount;
|
| 83 |
+
volatile uint32_t m_Flags[ ms_cSize ];
|
| 84 |
+
volatile uint32_t BASE_ALIGN(4) m_ReadIndex;
|
| 85 |
+
};
|
| 86 |
+
|
| 87 |
+
template<uint8_t cSizeLog2, typename T> inline
|
| 88 |
+
LockLessMultiReadPipe<cSizeLog2,T>::LockLessMultiReadPipe()
|
| 89 |
+
: m_WriteIndex(0)
|
| 90 |
+
, m_ReadIndex(0)
|
| 91 |
+
, m_ReadCount(0)
|
| 92 |
+
{
|
| 93 |
+
assert( cSizeLog2 < 32 );
|
| 94 |
+
memset( (void*)m_Flags, 0, sizeof( m_Flags ) );
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
template<uint8_t cSizeLog2, typename T> inline
|
| 98 |
+
bool LockLessMultiReadPipe<cSizeLog2,T>::ReaderTryReadBack( T* pOut )
|
| 99 |
+
{
|
| 100 |
+
|
| 101 |
+
uint32_t actualReadIndex;
|
| 102 |
+
|
| 103 |
+
uint32_t readCount = m_ReadCount;
|
| 104 |
+
|
| 105 |
+
// We get hold of read index for consistency,
|
| 106 |
+
// and do first pass starting at read count
|
| 107 |
+
uint32_t readIndexToUse = readCount;
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
while(true)
|
| 111 |
+
{
|
| 112 |
+
|
| 113 |
+
uint32_t writeIndex = m_WriteIndex;
|
| 114 |
+
// power of two sizes ensures we can use a simple calc without modulus
|
| 115 |
+
uint32_t numInPipe = writeIndex - readCount;
|
| 116 |
+
if( 0 == numInPipe )
|
| 117 |
+
{
|
| 118 |
+
return false;
|
| 119 |
+
}
|
| 120 |
+
if( readIndexToUse >= writeIndex )
|
| 121 |
+
{
|
| 122 |
+
// move back to start
|
| 123 |
+
readIndexToUse = m_ReadIndex;
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
// power of two sizes ensures we can perform AND for a modulus
|
| 128 |
+
actualReadIndex = readIndexToUse & ms_cIndexMask;
|
| 129 |
+
|
| 130 |
+
// Multiple potential readers mean we should check if the data is valid,
|
| 131 |
+
// using an atomic compare exchange
|
| 132 |
+
uint32_t previous = AtomicCompareAndSwap( &m_Flags[ actualReadIndex ], FLAG_INVALID, FLAG_CAN_READ );
|
| 133 |
+
if( FLAG_CAN_READ == previous )
|
| 134 |
+
{
|
| 135 |
+
break;
|
| 136 |
+
}
|
| 137 |
+
++readIndexToUse;
|
| 138 |
+
|
| 139 |
+
//update known readcount
|
| 140 |
+
readCount = m_ReadCount;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
// we update the read index using an atomic add, as we've only read one piece of data.
|
| 144 |
+
// this ensure consistency of the read index, and the above loop ensures readers
|
| 145 |
+
// only read from unread data
|
| 146 |
+
AtomicAdd( (volatile int32_t*)&m_ReadCount, 1 );
|
| 147 |
+
|
| 148 |
+
BASE_MEMORYBARRIER_ACQUIRE();
|
| 149 |
+
// now read data, ensuring we do so after above reads & CAS
|
| 150 |
+
*pOut = m_Buffer[ actualReadIndex ];
|
| 151 |
+
|
| 152 |
+
m_Flags[ actualReadIndex ] = FLAG_CAN_WRITE;
|
| 153 |
+
|
| 154 |
+
return true;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
template<uint8_t cSizeLog2, typename T> inline
|
| 158 |
+
bool LockLessMultiReadPipe<cSizeLog2,T>::WriterTryReadFront( T* pOut )
|
| 159 |
+
{
|
| 160 |
+
uint32_t writeIndex = m_WriteIndex;
|
| 161 |
+
uint32_t frontReadIndex = writeIndex;
|
| 162 |
+
|
| 163 |
+
// Multiple potential readers mean we should check if the data is valid,
|
| 164 |
+
// using an atomic compare exchange - which acts as a form of lock (so not quite lockless really).
|
| 165 |
+
uint32_t previous = FLAG_INVALID;
|
| 166 |
+
uint32_t actualReadIndex = 0;
|
| 167 |
+
while( true )
|
| 168 |
+
{
|
| 169 |
+
// power of two sizes ensures we can use a simple calc without modulus
|
| 170 |
+
uint32_t readCount = m_ReadCount;
|
| 171 |
+
uint32_t numInPipe = writeIndex - readCount;
|
| 172 |
+
if( 0 == numInPipe || 0 == frontReadIndex )
|
| 173 |
+
{
|
| 174 |
+
// frontReadIndex can get to 0 here if that item was just being read by another thread.
|
| 175 |
+
m_ReadIndex = readCount;
|
| 176 |
+
return false;
|
| 177 |
+
}
|
| 178 |
+
--frontReadIndex;
|
| 179 |
+
actualReadIndex = frontReadIndex & ms_cIndexMask;
|
| 180 |
+
previous = AtomicCompareAndSwap( &m_Flags[ actualReadIndex ], FLAG_INVALID, FLAG_CAN_READ );
|
| 181 |
+
if( FLAG_CAN_READ == previous )
|
| 182 |
+
{
|
| 183 |
+
break;
|
| 184 |
+
}
|
| 185 |
+
else if( m_ReadIndex >= frontReadIndex )
|
| 186 |
+
{
|
| 187 |
+
return false;
|
| 188 |
+
}
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
// now read data, ensuring we do so after above reads & CAS
|
| 192 |
+
*pOut = m_Buffer[ actualReadIndex ];
|
| 193 |
+
|
| 194 |
+
m_Flags[ actualReadIndex ] = FLAG_CAN_WRITE;
|
| 195 |
+
|
| 196 |
+
BASE_MEMORYBARRIER_RELEASE();
|
| 197 |
+
|
| 198 |
+
// 32-bit aligned stores are atomic, and writer owns the write index
|
| 199 |
+
// we only move one back as this is as many as we have read, not where we have read from.
|
| 200 |
+
--m_WriteIndex;
|
| 201 |
+
return true;
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
template<uint8_t cSizeLog2, typename T> inline
|
| 206 |
+
bool LockLessMultiReadPipe<cSizeLog2,T>::WriterTryWriteFront( const T& in )
|
| 207 |
+
{
|
| 208 |
+
// The writer 'owns' the write index, and readers can only reduce
|
| 209 |
+
// the amount of data in the pipe.
|
| 210 |
+
// We get hold of both values for consistency and to reduce false sharing
|
| 211 |
+
// impacting more than one access
|
| 212 |
+
uint32_t writeIndex = m_WriteIndex;
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
// power of two sizes ensures we can perform AND for a modulus
|
| 216 |
+
uint32_t actualWriteIndex = writeIndex & ms_cIndexMask;
|
| 217 |
+
|
| 218 |
+
// a reader may still be reading this item, as there are multiple readers
|
| 219 |
+
if( m_Flags[ actualWriteIndex ] != FLAG_CAN_WRITE )
|
| 220 |
+
{
|
| 221 |
+
return false; // still being read, so have caught up with tail.
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
// as we are the only writer we can update the data without atomics
|
| 226 |
+
// whilst the write index has not been updated
|
| 227 |
+
m_Buffer[ actualWriteIndex ] = in;
|
| 228 |
+
m_Flags[ actualWriteIndex ] = FLAG_CAN_READ;
|
| 229 |
+
|
| 230 |
+
// We need to ensure the above writes occur prior to updating the write index,
|
| 231 |
+
// otherwise another thread might read before it's finished
|
| 232 |
+
BASE_MEMORYBARRIER_RELEASE();
|
| 233 |
+
|
| 234 |
+
// 32-bit aligned stores are atomic, and the writer controls the write index
|
| 235 |
+
++writeIndex;
|
| 236 |
+
m_WriteIndex = writeIndex;
|
| 237 |
+
return true;
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
}
|
third_party/tracy/examples/ToyPathTracer/Source/enkiTS/TaskScheduler.cpp
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (c) 2013 Doug Binks
|
| 2 |
+
//
|
| 3 |
+
// This software is provided 'as-is', without any express or implied
|
| 4 |
+
// warranty. In no event will the authors be held liable for any damages
|
| 5 |
+
// arising from the use of this software.
|
| 6 |
+
//
|
| 7 |
+
// Permission is granted to anyone to use this software for any purpose,
|
| 8 |
+
// including commercial applications, and to alter it and redistribute it
|
| 9 |
+
// freely, subject to the following restrictions:
|
| 10 |
+
//
|
| 11 |
+
// 1. The origin of this software must not be misrepresented; you must not
|
| 12 |
+
// claim that you wrote the original software. If you use this software
|
| 13 |
+
// in a product, an acknowledgement in the product documentation would be
|
| 14 |
+
// appreciated but is not required.
|
| 15 |
+
// 2. Altered source versions must be plainly marked as such, and must not be
|
| 16 |
+
// misrepresented as being the original software.
|
| 17 |
+
// 3. This notice may not be removed or altered from any source distribution.
|
| 18 |
+
|
| 19 |
+
#include <assert.h>
|
| 20 |
+
|
| 21 |
+
#include "TaskScheduler.h"
|
| 22 |
+
#include "LockLessMultiReadPipe.h"
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
using namespace enki;
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
static const uint32_t PIPESIZE_LOG2 = 8;
|
| 30 |
+
static const uint32_t SPIN_COUNT = 100;
|
| 31 |
+
static const uint32_t SPIN_BACKOFF_MULTIPLIER = 10;
|
| 32 |
+
static const uint32_t MAX_NUM_INITIAL_PARTITIONS = 8;
|
| 33 |
+
|
| 34 |
+
// each software thread gets it's own copy of gtl_threadNum, so this is safe to use as a static variable
|
| 35 |
+
static THREAD_LOCAL uint32_t gtl_threadNum = 0;
|
| 36 |
+
|
| 37 |
+
namespace enki
|
| 38 |
+
{
|
| 39 |
+
struct SubTaskSet
|
| 40 |
+
{
|
| 41 |
+
ITaskSet* pTask;
|
| 42 |
+
TaskSetPartition partition;
|
| 43 |
+
};
|
| 44 |
+
|
| 45 |
+
// we derive class TaskPipe rather than typedef to get forward declaration working easily
|
| 46 |
+
class TaskPipe : public LockLessMultiReadPipe<PIPESIZE_LOG2,enki::SubTaskSet> {};
|
| 47 |
+
|
| 48 |
+
struct ThreadArgs
|
| 49 |
+
{
|
| 50 |
+
uint32_t threadNum;
|
| 51 |
+
TaskScheduler* pTaskScheduler;
|
| 52 |
+
};
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
namespace
|
| 56 |
+
{
|
| 57 |
+
SubTaskSet SplitTask( SubTaskSet& subTask_, uint32_t rangeToSplit_ )
|
| 58 |
+
{
|
| 59 |
+
SubTaskSet splitTask = subTask_;
|
| 60 |
+
uint32_t rangeLeft = subTask_.partition.end - subTask_.partition.start;
|
| 61 |
+
|
| 62 |
+
if( rangeToSplit_ > rangeLeft )
|
| 63 |
+
{
|
| 64 |
+
rangeToSplit_ = rangeLeft;
|
| 65 |
+
}
|
| 66 |
+
splitTask.partition.end = subTask_.partition.start + rangeToSplit_;
|
| 67 |
+
subTask_.partition.start = splitTask.partition.end;
|
| 68 |
+
return splitTask;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
#if defined _WIN32
|
| 72 |
+
#if defined _M_IX86 || defined _M_X64
|
| 73 |
+
#pragma intrinsic(_mm_pause)
|
| 74 |
+
inline void Pause() { _mm_pause(); }
|
| 75 |
+
#endif
|
| 76 |
+
#elif defined __i386__ || defined __x86_64__
|
| 77 |
+
inline void Pause() { __asm__ __volatile__("pause;"); }
|
| 78 |
+
#else
|
| 79 |
+
inline void Pause() { ;} // may have NOP or yield equiv
|
| 80 |
+
#endif
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
static void SafeCallback(ProfilerCallbackFunc func_, uint32_t threadnum_)
|
| 85 |
+
{
|
| 86 |
+
if( func_ )
|
| 87 |
+
{
|
| 88 |
+
func_(threadnum_);
|
| 89 |
+
}
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
ProfilerCallbacks* TaskScheduler::GetProfilerCallbacks()
|
| 93 |
+
{
|
| 94 |
+
return &m_ProfilerCallbacks;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
THREADFUNC_DECL TaskScheduler::TaskingThreadFunction( void* pArgs )
|
| 98 |
+
{
|
| 99 |
+
ThreadArgs args = *(ThreadArgs*)pArgs;
|
| 100 |
+
uint32_t threadNum = args.threadNum;
|
| 101 |
+
TaskScheduler* pTS = args.pTaskScheduler;
|
| 102 |
+
gtl_threadNum = threadNum;
|
| 103 |
+
|
| 104 |
+
SafeCallback( pTS->m_ProfilerCallbacks.threadStart, threadNum );
|
| 105 |
+
|
| 106 |
+
uint32_t spinCount = 0;
|
| 107 |
+
uint32_t hintPipeToCheck_io = threadNum + 1; // does not need to be clamped.
|
| 108 |
+
while( pTS->m_bRunning )
|
| 109 |
+
{
|
| 110 |
+
if(!pTS->TryRunTask( threadNum, hintPipeToCheck_io ) )
|
| 111 |
+
{
|
| 112 |
+
// no tasks, will spin then wait
|
| 113 |
+
++spinCount;
|
| 114 |
+
if( spinCount > SPIN_COUNT )
|
| 115 |
+
{
|
| 116 |
+
pTS->WaitForTasks( threadNum );
|
| 117 |
+
spinCount = 0;
|
| 118 |
+
}
|
| 119 |
+
else
|
| 120 |
+
{
|
| 121 |
+
uint32_t spinBackoffCount = spinCount * SPIN_BACKOFF_MULTIPLIER;
|
| 122 |
+
while( spinBackoffCount )
|
| 123 |
+
{
|
| 124 |
+
Pause();
|
| 125 |
+
--spinBackoffCount;
|
| 126 |
+
}
|
| 127 |
+
}
|
| 128 |
+
}
|
| 129 |
+
else
|
| 130 |
+
{
|
| 131 |
+
spinCount = 0;
|
| 132 |
+
}
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
AtomicAdd( &pTS->m_NumThreadsRunning, -1 );
|
| 136 |
+
SafeCallback( pTS->m_ProfilerCallbacks.threadStop, threadNum );
|
| 137 |
+
|
| 138 |
+
return 0;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
void TaskScheduler::StartThreads()
|
| 143 |
+
{
|
| 144 |
+
if( m_bHaveThreads )
|
| 145 |
+
{
|
| 146 |
+
return;
|
| 147 |
+
}
|
| 148 |
+
m_bRunning = true;
|
| 149 |
+
|
| 150 |
+
SemaphoreCreate( m_NewTaskSemaphore );
|
| 151 |
+
|
| 152 |
+
// we create one less thread than m_NumThreads as the main thread counts as one
|
| 153 |
+
m_pThreadNumStore = new ThreadArgs[m_NumThreads];
|
| 154 |
+
m_pThreadIDs = new threadid_t[m_NumThreads];
|
| 155 |
+
m_pThreadNumStore[0].threadNum = 0;
|
| 156 |
+
m_pThreadNumStore[0].pTaskScheduler = this;
|
| 157 |
+
m_pThreadIDs[0] = 0;
|
| 158 |
+
m_NumThreadsWaiting = 0;
|
| 159 |
+
m_NumThreadsRunning = 1;// acount for main thread
|
| 160 |
+
for( uint32_t thread = 1; thread < m_NumThreads; ++thread )
|
| 161 |
+
{
|
| 162 |
+
m_pThreadNumStore[thread].threadNum = thread;
|
| 163 |
+
m_pThreadNumStore[thread].pTaskScheduler = this;
|
| 164 |
+
ThreadCreate( &m_pThreadIDs[thread], TaskingThreadFunction, &m_pThreadNumStore[thread] );
|
| 165 |
+
++m_NumThreadsRunning;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
// ensure we have sufficient tasks to equally fill either all threads including main
|
| 169 |
+
// or just the threads we've launched, this is outside the firstinit as we want to be able
|
| 170 |
+
// to runtime change it
|
| 171 |
+
if( 1 == m_NumThreads )
|
| 172 |
+
{
|
| 173 |
+
m_NumPartitions = 1;
|
| 174 |
+
m_NumInitialPartitions = 1;
|
| 175 |
+
}
|
| 176 |
+
else
|
| 177 |
+
{
|
| 178 |
+
m_NumPartitions = m_NumThreads * (m_NumThreads - 1);
|
| 179 |
+
m_NumInitialPartitions = m_NumThreads - 1;
|
| 180 |
+
if( m_NumInitialPartitions > MAX_NUM_INITIAL_PARTITIONS )
|
| 181 |
+
{
|
| 182 |
+
m_NumInitialPartitions = MAX_NUM_INITIAL_PARTITIONS;
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
m_bHaveThreads = true;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
void TaskScheduler::StopThreads( bool bWait_ )
|
| 190 |
+
{
|
| 191 |
+
if( m_bHaveThreads )
|
| 192 |
+
{
|
| 193 |
+
// wait for them threads quit before deleting data
|
| 194 |
+
m_bRunning = false;
|
| 195 |
+
while( bWait_ && m_NumThreadsRunning > 1 )
|
| 196 |
+
{
|
| 197 |
+
// keep firing event to ensure all threads pick up state of m_bRunning
|
| 198 |
+
SemaphoreSignal( m_NewTaskSemaphore, m_NumThreadsRunning );
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
for( uint32_t thread = 1; thread < m_NumThreads; ++thread )
|
| 202 |
+
{
|
| 203 |
+
ThreadTerminate( m_pThreadIDs[thread] );
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
m_NumThreads = 0;
|
| 207 |
+
delete[] m_pThreadNumStore;
|
| 208 |
+
delete[] m_pThreadIDs;
|
| 209 |
+
m_pThreadNumStore = 0;
|
| 210 |
+
m_pThreadIDs = 0;
|
| 211 |
+
SemaphoreClose( m_NewTaskSemaphore );
|
| 212 |
+
|
| 213 |
+
m_bHaveThreads = false;
|
| 214 |
+
m_NumThreadsWaiting = 0;
|
| 215 |
+
m_NumThreadsRunning = 0;
|
| 216 |
+
}
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
bool TaskScheduler::TryRunTask( uint32_t threadNum, uint32_t& hintPipeToCheck_io_ )
|
| 220 |
+
{
|
| 221 |
+
// check for tasks
|
| 222 |
+
SubTaskSet subTask;
|
| 223 |
+
bool bHaveTask = m_pPipesPerThread[ threadNum ].WriterTryReadFront( &subTask );
|
| 224 |
+
|
| 225 |
+
uint32_t threadToCheck = hintPipeToCheck_io_;
|
| 226 |
+
uint32_t checkCount = 0;
|
| 227 |
+
while( !bHaveTask && checkCount < m_NumThreads )
|
| 228 |
+
{
|
| 229 |
+
threadToCheck = ( hintPipeToCheck_io_ + checkCount ) % m_NumThreads;
|
| 230 |
+
if( threadToCheck != threadNum )
|
| 231 |
+
{
|
| 232 |
+
bHaveTask = m_pPipesPerThread[ threadToCheck ].ReaderTryReadBack( &subTask );
|
| 233 |
+
}
|
| 234 |
+
++checkCount;
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
if( bHaveTask )
|
| 238 |
+
{
|
| 239 |
+
// update hint, will preserve value unless actually got task from another thread.
|
| 240 |
+
hintPipeToCheck_io_ = threadToCheck;
|
| 241 |
+
|
| 242 |
+
uint32_t partitionSize = subTask.partition.end - subTask.partition.start;
|
| 243 |
+
if( subTask.pTask->m_RangeToRun < partitionSize )
|
| 244 |
+
{
|
| 245 |
+
SubTaskSet taskToRun = SplitTask( subTask, subTask.pTask->m_RangeToRun );
|
| 246 |
+
SplitAndAddTask( gtl_threadNum, subTask, subTask.pTask->m_RangeToRun, 0 );
|
| 247 |
+
taskToRun.pTask->ExecuteRange( taskToRun.partition, threadNum );
|
| 248 |
+
AtomicAdd( &taskToRun.pTask->m_RunningCount, -1 );
|
| 249 |
+
}
|
| 250 |
+
else
|
| 251 |
+
{
|
| 252 |
+
|
| 253 |
+
// the task has already been divided up by AddTaskSetToPipe, so just run it
|
| 254 |
+
subTask.pTask->ExecuteRange( subTask.partition, threadNum );
|
| 255 |
+
AtomicAdd( &subTask.pTask->m_RunningCount, -1 );
|
| 256 |
+
}
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
return bHaveTask;
|
| 260 |
+
|
| 261 |
+
}
|
| 262 |
+
|
| 263 |
+
void TaskScheduler::WaitForTasks( uint32_t threadNum )
|
| 264 |
+
{
|
| 265 |
+
// We incrememt the number of threads waiting here in order
|
| 266 |
+
// to ensure that the check for tasks occurs after the increment
|
| 267 |
+
// to prevent a task being added after a check, then the thread waiting.
|
| 268 |
+
// This will occasionally result in threads being mistakenly awoken,
|
| 269 |
+
// but they will then go back to sleep.
|
| 270 |
+
AtomicAdd( &m_NumThreadsWaiting, 1 );
|
| 271 |
+
|
| 272 |
+
bool bHaveTasks = false;
|
| 273 |
+
for( uint32_t thread = 0; thread < m_NumThreads; ++thread )
|
| 274 |
+
{
|
| 275 |
+
if( !m_pPipesPerThread[ thread ].IsPipeEmpty() )
|
| 276 |
+
{
|
| 277 |
+
bHaveTasks = true;
|
| 278 |
+
break;
|
| 279 |
+
}
|
| 280 |
+
}
|
| 281 |
+
if( !bHaveTasks )
|
| 282 |
+
{
|
| 283 |
+
SafeCallback( m_ProfilerCallbacks.waitStart, threadNum );
|
| 284 |
+
SemaphoreWait( m_NewTaskSemaphore );
|
| 285 |
+
SafeCallback( m_ProfilerCallbacks.waitStop, threadNum );
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
int32_t prev = AtomicAdd( &m_NumThreadsWaiting, -1 );
|
| 289 |
+
assert( prev != 0 );
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
void TaskScheduler::WakeThreads()
|
| 293 |
+
{
|
| 294 |
+
SemaphoreSignal( m_NewTaskSemaphore, m_NumThreadsWaiting );
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
void TaskScheduler::SplitAndAddTask( uint32_t threadNum_, SubTaskSet subTask_,
|
| 298 |
+
uint32_t rangeToSplit_, int32_t runningCountOffset_ )
|
| 299 |
+
{
|
| 300 |
+
int32_t numAdded = 0;
|
| 301 |
+
while( subTask_.partition.start != subTask_.partition.end )
|
| 302 |
+
{
|
| 303 |
+
SubTaskSet taskToAdd = SplitTask( subTask_, rangeToSplit_ );
|
| 304 |
+
|
| 305 |
+
// add the partition to the pipe
|
| 306 |
+
++numAdded;
|
| 307 |
+
if( !m_pPipesPerThread[ gtl_threadNum ].WriterTryWriteFront( taskToAdd ) )
|
| 308 |
+
{
|
| 309 |
+
if( numAdded > 1 )
|
| 310 |
+
{
|
| 311 |
+
WakeThreads();
|
| 312 |
+
}
|
| 313 |
+
// alter range to run the appropriate fraction
|
| 314 |
+
if( taskToAdd.pTask->m_RangeToRun < rangeToSplit_ )
|
| 315 |
+
{
|
| 316 |
+
taskToAdd.partition.end = taskToAdd.partition.start + taskToAdd.pTask->m_RangeToRun;
|
| 317 |
+
subTask_.partition.start = taskToAdd.partition.end;
|
| 318 |
+
}
|
| 319 |
+
taskToAdd.pTask->ExecuteRange( taskToAdd.partition, threadNum_ );
|
| 320 |
+
--numAdded;
|
| 321 |
+
}
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
// increment running count by number added
|
| 325 |
+
AtomicAdd( &subTask_.pTask->m_RunningCount, numAdded + runningCountOffset_ );
|
| 326 |
+
|
| 327 |
+
WakeThreads();
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
void TaskScheduler::AddTaskSetToPipe( ITaskSet* pTaskSet )
|
| 331 |
+
{
|
| 332 |
+
// set running count to -1 to guarantee it won't be found complete until all subtasks added
|
| 333 |
+
pTaskSet->m_RunningCount = -1;
|
| 334 |
+
|
| 335 |
+
// divide task up and add to pipe
|
| 336 |
+
pTaskSet->m_RangeToRun = pTaskSet->m_SetSize / m_NumPartitions;
|
| 337 |
+
if( pTaskSet->m_RangeToRun < pTaskSet->m_MinRange ) { pTaskSet->m_RangeToRun = pTaskSet->m_MinRange; }
|
| 338 |
+
|
| 339 |
+
uint32_t rangeToSplit = pTaskSet->m_SetSize / m_NumInitialPartitions;
|
| 340 |
+
if( rangeToSplit < pTaskSet->m_MinRange ) { rangeToSplit = pTaskSet->m_MinRange; }
|
| 341 |
+
|
| 342 |
+
SubTaskSet subTask;
|
| 343 |
+
subTask.pTask = pTaskSet;
|
| 344 |
+
subTask.partition.start = 0;
|
| 345 |
+
subTask.partition.end = pTaskSet->m_SetSize;
|
| 346 |
+
SplitAndAddTask( gtl_threadNum, subTask, rangeToSplit, 1 );
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
void TaskScheduler::WaitforTaskSet( const ITaskSet* pTaskSet )
|
| 350 |
+
{
|
| 351 |
+
uint32_t hintPipeToCheck_io = gtl_threadNum + 1; // does not need to be clamped.
|
| 352 |
+
if( pTaskSet )
|
| 353 |
+
{
|
| 354 |
+
while( pTaskSet->m_RunningCount )
|
| 355 |
+
{
|
| 356 |
+
TryRunTask( gtl_threadNum, hintPipeToCheck_io );
|
| 357 |
+
// should add a spin then wait for task completion event.
|
| 358 |
+
}
|
| 359 |
+
}
|
| 360 |
+
else
|
| 361 |
+
{
|
| 362 |
+
TryRunTask( gtl_threadNum, hintPipeToCheck_io );
|
| 363 |
+
}
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
void TaskScheduler::WaitforAll()
|
| 367 |
+
{
|
| 368 |
+
bool bHaveTasks = true;
|
| 369 |
+
uint32_t hintPipeToCheck_io = gtl_threadNum + 1; // does not need to be clamped.
|
| 370 |
+
int32_t threadsRunning = m_NumThreadsRunning - 1;
|
| 371 |
+
while( bHaveTasks || m_NumThreadsWaiting < threadsRunning )
|
| 372 |
+
{
|
| 373 |
+
TryRunTask( gtl_threadNum, hintPipeToCheck_io );
|
| 374 |
+
bHaveTasks = false;
|
| 375 |
+
for( uint32_t thread = 0; thread < m_NumThreads; ++thread )
|
| 376 |
+
{
|
| 377 |
+
if( !m_pPipesPerThread[ thread ].IsPipeEmpty() )
|
| 378 |
+
{
|
| 379 |
+
bHaveTasks = true;
|
| 380 |
+
break;
|
| 381 |
+
}
|
| 382 |
+
}
|
| 383 |
+
}
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
void TaskScheduler::WaitforAllAndShutdown()
|
| 387 |
+
{
|
| 388 |
+
WaitforAll();
|
| 389 |
+
StopThreads(true);
|
| 390 |
+
delete[] m_pPipesPerThread;
|
| 391 |
+
m_pPipesPerThread = 0;
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
uint32_t TaskScheduler::GetNumTaskThreads() const
|
| 395 |
+
{
|
| 396 |
+
return m_NumThreads;
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
+
TaskScheduler::TaskScheduler()
|
| 400 |
+
: m_pPipesPerThread(NULL)
|
| 401 |
+
, m_NumThreads(0)
|
| 402 |
+
, m_pThreadNumStore(NULL)
|
| 403 |
+
, m_pThreadIDs(NULL)
|
| 404 |
+
, m_bRunning(false)
|
| 405 |
+
, m_NumThreadsRunning(0)
|
| 406 |
+
, m_NumThreadsWaiting(0)
|
| 407 |
+
, m_NumPartitions(0)
|
| 408 |
+
, m_bHaveThreads(false)
|
| 409 |
+
{
|
| 410 |
+
memset(&m_ProfilerCallbacks, 0, sizeof(m_ProfilerCallbacks));
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
TaskScheduler::~TaskScheduler()
|
| 414 |
+
{
|
| 415 |
+
StopThreads( true ); // Stops threads, waiting for them.
|
| 416 |
+
|
| 417 |
+
delete[] m_pPipesPerThread;
|
| 418 |
+
m_pPipesPerThread = 0;
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
void TaskScheduler::Initialize( uint32_t numThreads_ )
|
| 422 |
+
{
|
| 423 |
+
assert( numThreads_ );
|
| 424 |
+
StopThreads( true ); // Stops threads, waiting for them.
|
| 425 |
+
delete[] m_pPipesPerThread;
|
| 426 |
+
|
| 427 |
+
m_NumThreads = numThreads_;
|
| 428 |
+
|
| 429 |
+
m_pPipesPerThread = new TaskPipe[ m_NumThreads ];
|
| 430 |
+
|
| 431 |
+
StartThreads();
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
void TaskScheduler::Initialize()
|
| 435 |
+
{
|
| 436 |
+
Initialize( GetNumHardwareThreads() );
|
| 437 |
+
}
|
third_party/tracy/examples/ToyPathTracer/Source/enkiTS/TaskScheduler.h
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (c) 2013 Doug Binks
|
| 2 |
+
//
|
| 3 |
+
// This software is provided 'as-is', without any express or implied
|
| 4 |
+
// warranty. In no event will the authors be held liable for any damages
|
| 5 |
+
// arising from the use of this software.
|
| 6 |
+
//
|
| 7 |
+
// Permission is granted to anyone to use this software for any purpose,
|
| 8 |
+
// including commercial applications, and to alter it and redistribute it
|
| 9 |
+
// freely, subject to the following restrictions:
|
| 10 |
+
//
|
| 11 |
+
// 1. The origin of this software must not be misrepresented; you must not
|
| 12 |
+
// claim that you wrote the original software. If you use this software
|
| 13 |
+
// in a product, an acknowledgement in the product documentation would be
|
| 14 |
+
// appreciated but is not required.
|
| 15 |
+
// 2. Altered source versions must be plainly marked as such, and must not be
|
| 16 |
+
// misrepresented as being the original software.
|
| 17 |
+
// 3. This notice may not be removed or altered from any source distribution.
|
| 18 |
+
|
| 19 |
+
#pragma once
|
| 20 |
+
|
| 21 |
+
#include <stdint.h>
|
| 22 |
+
#include "Threads.h"
|
| 23 |
+
|
| 24 |
+
namespace enki
|
| 25 |
+
{
|
| 26 |
+
|
| 27 |
+
struct TaskSetPartition
|
| 28 |
+
{
|
| 29 |
+
uint32_t start;
|
| 30 |
+
uint32_t end;
|
| 31 |
+
};
|
| 32 |
+
|
| 33 |
+
class TaskScheduler;
|
| 34 |
+
class TaskPipe;
|
| 35 |
+
struct ThreadArgs;
|
| 36 |
+
struct SubTaskSet;
|
| 37 |
+
|
| 38 |
+
// Subclass ITaskSet to create tasks.
|
| 39 |
+
// TaskSets can be re-used, but check
|
| 40 |
+
class ITaskSet
|
| 41 |
+
{
|
| 42 |
+
public:
|
| 43 |
+
ITaskSet()
|
| 44 |
+
: m_SetSize(1)
|
| 45 |
+
, m_MinRange(1)
|
| 46 |
+
, m_RunningCount(0)
|
| 47 |
+
, m_RangeToRun(1)
|
| 48 |
+
{}
|
| 49 |
+
|
| 50 |
+
ITaskSet( uint32_t setSize_ )
|
| 51 |
+
: m_SetSize( setSize_ )
|
| 52 |
+
, m_MinRange(1)
|
| 53 |
+
, m_RunningCount(0)
|
| 54 |
+
, m_RangeToRun(1)
|
| 55 |
+
{}
|
| 56 |
+
|
| 57 |
+
ITaskSet( uint32_t setSize_, uint32_t minRange_ )
|
| 58 |
+
: m_SetSize( setSize_ )
|
| 59 |
+
, m_MinRange( minRange_ )
|
| 60 |
+
, m_RunningCount(0)
|
| 61 |
+
, m_RangeToRun(minRange_)
|
| 62 |
+
{}
|
| 63 |
+
|
| 64 |
+
// Execute range should be overloaded to process tasks. It will be called with a
|
| 65 |
+
// range_ where range.start >= 0; range.start < range.end; and range.end < m_SetSize;
|
| 66 |
+
// The range values should be mapped so that linearly processing them in order is cache friendly
|
| 67 |
+
// i.e. neighbouring values should be close together.
|
| 68 |
+
// threadnum should not be used for changing processing of data, it's intended purpose
|
| 69 |
+
// is to allow per-thread data buckets for output.
|
| 70 |
+
virtual void ExecuteRange( TaskSetPartition range, uint32_t threadnum ) = 0;
|
| 71 |
+
|
| 72 |
+
// Size of set - usually the number of data items to be processed, see ExecuteRange. Defaults to 1
|
| 73 |
+
uint32_t m_SetSize;
|
| 74 |
+
|
| 75 |
+
// Minimum size of of TaskSetPartition range when splitting a task set into partitions.
|
| 76 |
+
// This should be set to a value which results in computation effort of at least 10k
|
| 77 |
+
// clock cycles to minimize tast scheduler overhead.
|
| 78 |
+
// NOTE: The last partition will be smaller than m_MinRange if m_SetSize is not a multiple
|
| 79 |
+
// of m_MinRange.
|
| 80 |
+
// Also known as grain size in literature.
|
| 81 |
+
uint32_t m_MinRange;
|
| 82 |
+
|
| 83 |
+
bool GetIsComplete()
|
| 84 |
+
{
|
| 85 |
+
return 0 == m_RunningCount;
|
| 86 |
+
}
|
| 87 |
+
private:
|
| 88 |
+
friend class TaskScheduler;
|
| 89 |
+
volatile int32_t m_RunningCount;
|
| 90 |
+
uint32_t m_RangeToRun;
|
| 91 |
+
};
|
| 92 |
+
|
| 93 |
+
// TaskScheduler implements several callbacks intended for profilers
|
| 94 |
+
typedef void (*ProfilerCallbackFunc)( uint32_t threadnum_ );
|
| 95 |
+
struct ProfilerCallbacks
|
| 96 |
+
{
|
| 97 |
+
ProfilerCallbackFunc threadStart;
|
| 98 |
+
ProfilerCallbackFunc threadStop;
|
| 99 |
+
ProfilerCallbackFunc waitStart;
|
| 100 |
+
ProfilerCallbackFunc waitStop;
|
| 101 |
+
};
|
| 102 |
+
|
| 103 |
+
class TaskScheduler
|
| 104 |
+
{
|
| 105 |
+
public:
|
| 106 |
+
TaskScheduler();
|
| 107 |
+
~TaskScheduler();
|
| 108 |
+
|
| 109 |
+
// Call either Initialize() or Initialize( numThreads_ ) before adding tasks.
|
| 110 |
+
|
| 111 |
+
// Initialize() will create GetNumHardwareThreads()-1 threads, which is
|
| 112 |
+
// sufficient to fill the system when including the main thread.
|
| 113 |
+
// Initialize can be called multiple times - it will wait for completion
|
| 114 |
+
// before re-initializing.
|
| 115 |
+
void Initialize();
|
| 116 |
+
|
| 117 |
+
// Initialize( numThreads_ ) - numThreads_ (must be > 0)
|
| 118 |
+
// will create numThreads_-1 threads, as thread 0 is
|
| 119 |
+
// the thread on which the initialize was called.
|
| 120 |
+
void Initialize( uint32_t numThreads_ );
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
// Adds the TaskSet to pipe and returns if the pipe is not full.
|
| 124 |
+
// If the pipe is full, pTaskSet is run.
|
| 125 |
+
// should only be called from main thread, or within a task
|
| 126 |
+
void AddTaskSetToPipe( ITaskSet* pTaskSet );
|
| 127 |
+
|
| 128 |
+
// Runs the TaskSets in pipe until true == pTaskSet->GetIsComplete();
|
| 129 |
+
// should only be called from thread which created the taskscheduler , or within a task
|
| 130 |
+
// if called with 0 it will try to run tasks, and return if none available.
|
| 131 |
+
void WaitforTaskSet( const ITaskSet* pTaskSet );
|
| 132 |
+
|
| 133 |
+
// Waits for all task sets to complete - not guaranteed to work unless we know we
|
| 134 |
+
// are in a situation where tasks aren't being continuosly added.
|
| 135 |
+
void WaitforAll();
|
| 136 |
+
|
| 137 |
+
// Waits for all task sets to complete and shutdown threads - not guaranteed to work unless we know we
|
| 138 |
+
// are in a situation where tasks aren't being continuosly added.
|
| 139 |
+
void WaitforAllAndShutdown();
|
| 140 |
+
|
| 141 |
+
// Returns the number of threads created for running tasks + 1
|
| 142 |
+
// to account for the main thread.
|
| 143 |
+
uint32_t GetNumTaskThreads() const;
|
| 144 |
+
|
| 145 |
+
// Returns the ProfilerCallbacks structure so that it can be modified to
|
| 146 |
+
// set the callbacks.
|
| 147 |
+
ProfilerCallbacks* GetProfilerCallbacks();
|
| 148 |
+
|
| 149 |
+
private:
|
| 150 |
+
static THREADFUNC_DECL TaskingThreadFunction( void* pArgs );
|
| 151 |
+
void WaitForTasks( uint32_t threadNum );
|
| 152 |
+
bool TryRunTask( uint32_t threadNum, uint32_t& hintPipeToCheck_io_ );
|
| 153 |
+
void StartThreads();
|
| 154 |
+
void StopThreads( bool bWait_ );
|
| 155 |
+
void SplitAndAddTask( uint32_t threadNum_, SubTaskSet subTask_,
|
| 156 |
+
uint32_t rangeToSplit_, int32_t runningCountOffset_ );
|
| 157 |
+
void WakeThreads();
|
| 158 |
+
|
| 159 |
+
TaskPipe* m_pPipesPerThread;
|
| 160 |
+
|
| 161 |
+
uint32_t m_NumThreads;
|
| 162 |
+
ThreadArgs* m_pThreadNumStore;
|
| 163 |
+
threadid_t* m_pThreadIDs;
|
| 164 |
+
volatile bool m_bRunning;
|
| 165 |
+
volatile int32_t m_NumThreadsRunning;
|
| 166 |
+
volatile int32_t m_NumThreadsWaiting;
|
| 167 |
+
uint32_t m_NumPartitions;
|
| 168 |
+
uint32_t m_NumInitialPartitions;
|
| 169 |
+
semaphoreid_t m_NewTaskSemaphore;
|
| 170 |
+
bool m_bHaveThreads;
|
| 171 |
+
ProfilerCallbacks m_ProfilerCallbacks;
|
| 172 |
+
|
| 173 |
+
TaskScheduler( const TaskScheduler& nocopy );
|
| 174 |
+
TaskScheduler& operator=( const TaskScheduler& nocopy );
|
| 175 |
+
};
|
| 176 |
+
|
| 177 |
+
}
|
third_party/tracy/examples/ToyPathTracer/Source/enkiTS/TaskScheduler_c.cpp
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (c) 2013 Doug Binks
|
| 2 |
+
//
|
| 3 |
+
// This software is provided 'as-is', without any express or implied
|
| 4 |
+
// warranty. In no event will the authors be held liable for any damages
|
| 5 |
+
// arising from the use of this software.
|
| 6 |
+
//
|
| 7 |
+
// Permission is granted to anyone to use this software for any purpose,
|
| 8 |
+
// including commercial applications, and to alter it and redistribute it
|
| 9 |
+
// freely, subject to the following restrictions:
|
| 10 |
+
//
|
| 11 |
+
// 1. The origin of this software must not be misrepresented; you must not
|
| 12 |
+
// claim that you wrote the original software. If you use this software
|
| 13 |
+
// in a product, an acknowledgement in the product documentation would be
|
| 14 |
+
// appreciated but is not required.
|
| 15 |
+
// 2. Altered source versions must be plainly marked as such, and must not be
|
| 16 |
+
// misrepresented as being the original software.
|
| 17 |
+
// 3. This notice may not be removed or altered from any source distribution.
|
| 18 |
+
|
| 19 |
+
#include "TaskScheduler_c.h"
|
| 20 |
+
#include "TaskScheduler.h"
|
| 21 |
+
|
| 22 |
+
#include <assert.h>
|
| 23 |
+
|
| 24 |
+
using namespace enki;
|
| 25 |
+
|
| 26 |
+
struct enkiTaskScheduler : TaskScheduler
|
| 27 |
+
{
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
struct enkiTaskSet : ITaskSet
|
| 31 |
+
{
|
| 32 |
+
enkiTaskSet( enkiTaskExecuteRange taskFun_ ) : taskFun(taskFun_), pArgs(NULL) {}
|
| 33 |
+
|
| 34 |
+
virtual void ExecuteRange( TaskSetPartition range, uint32_t threadnum )
|
| 35 |
+
{
|
| 36 |
+
taskFun( range.start, range.end, threadnum, pArgs );
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
enkiTaskExecuteRange taskFun;
|
| 40 |
+
void* pArgs;
|
| 41 |
+
};
|
| 42 |
+
|
| 43 |
+
enkiTaskScheduler* enkiNewTaskScheduler()
|
| 44 |
+
{
|
| 45 |
+
enkiTaskScheduler* pETS = new enkiTaskScheduler();
|
| 46 |
+
return pETS;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
void enkiInitTaskScheduler( enkiTaskScheduler* pETS_ )
|
| 50 |
+
{
|
| 51 |
+
pETS_->Initialize();
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
void enkiInitTaskSchedulerNumThreads( enkiTaskScheduler* pETS_, uint32_t numThreads_ )
|
| 55 |
+
{
|
| 56 |
+
pETS_->Initialize( numThreads_ );
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
void enkiDeleteTaskScheduler( enkiTaskScheduler* pETS_ )
|
| 60 |
+
{
|
| 61 |
+
delete pETS_;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
enkiTaskSet* enkiCreateTaskSet( enkiTaskScheduler* pETS_, enkiTaskExecuteRange taskFunc_ )
|
| 65 |
+
{
|
| 66 |
+
return new enkiTaskSet( taskFunc_ );
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
void enkiDeleteTaskSet( enkiTaskSet* pTaskSet_ )
|
| 70 |
+
{
|
| 71 |
+
delete pTaskSet_;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
void enkiAddTaskSetToPipe( enkiTaskScheduler* pETS_, enkiTaskSet* pTaskSet_, void* pArgs_, uint32_t setSize_ )
|
| 75 |
+
{
|
| 76 |
+
assert( pTaskSet_ );
|
| 77 |
+
assert( pTaskSet_->taskFun );
|
| 78 |
+
|
| 79 |
+
pTaskSet_->m_SetSize = setSize_;
|
| 80 |
+
pTaskSet_->pArgs = pArgs_;
|
| 81 |
+
pETS_->AddTaskSetToPipe( pTaskSet_ );
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
void enkiAddTaskSetToPipeMinRange(enkiTaskScheduler * pETS_, enkiTaskSet * pTaskSet_, void * pArgs_, uint32_t setSize_, uint32_t minRange_)
|
| 85 |
+
{
|
| 86 |
+
assert( pTaskSet_ );
|
| 87 |
+
assert( pTaskSet_->taskFun );
|
| 88 |
+
|
| 89 |
+
pTaskSet_->m_SetSize = setSize_;
|
| 90 |
+
pTaskSet_->m_MinRange = minRange_;
|
| 91 |
+
pTaskSet_->pArgs = pArgs_;
|
| 92 |
+
pETS_->AddTaskSetToPipe( pTaskSet_ );
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
int enkiIsTaskSetComplete( enkiTaskScheduler* pETS_, enkiTaskSet* pTaskSet_ )
|
| 96 |
+
{
|
| 97 |
+
assert( pTaskSet_ );
|
| 98 |
+
return ( pTaskSet_->GetIsComplete() ) ? 1 : 0;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
void enkiWaitForTaskSet( enkiTaskScheduler* pETS_, enkiTaskSet* pTaskSet_ )
|
| 102 |
+
{
|
| 103 |
+
pETS_->WaitforTaskSet( pTaskSet_ );
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
void enkiWaitForAll( enkiTaskScheduler* pETS_ )
|
| 107 |
+
{
|
| 108 |
+
pETS_->WaitforAll();
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
uint32_t enkiGetNumTaskThreads( enkiTaskScheduler* pETS_ )
|
| 113 |
+
{
|
| 114 |
+
return pETS_->GetNumTaskThreads();
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
enkiProfilerCallbacks* enkiGetProfilerCallbacks( enkiTaskScheduler* pETS_ )
|
| 118 |
+
{
|
| 119 |
+
assert( sizeof(enkiProfilerCallbacks) == sizeof(enki::ProfilerCallbacks) );
|
| 120 |
+
return (enkiProfilerCallbacks*)pETS_->GetProfilerCallbacks();
|
| 121 |
+
}
|
| 122 |
+
|
third_party/tracy/examples/ToyPathTracer/Source/enkiTS/TaskScheduler_c.h
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (c) 2013 Doug Binks
|
| 2 |
+
//
|
| 3 |
+
// This software is provided 'as-is', without any express or implied
|
| 4 |
+
// warranty. In no event will the authors be held liable for any damages
|
| 5 |
+
// arising from the use of this software.
|
| 6 |
+
//
|
| 7 |
+
// Permission is granted to anyone to use this software for any purpose,
|
| 8 |
+
// including commercial applications, and to alter it and redistribute it
|
| 9 |
+
// freely, subject to the following restrictions:
|
| 10 |
+
//
|
| 11 |
+
// 1. The origin of this software must not be misrepresented; you must not
|
| 12 |
+
// claim that you wrote the original software. If you use this software
|
| 13 |
+
// in a product, an acknowledgement in the product documentation would be
|
| 14 |
+
// appreciated but is not required.
|
| 15 |
+
// 2. Altered source versions must be plainly marked as such, and must not be
|
| 16 |
+
// misrepresented as being the original software.
|
| 17 |
+
// 3. This notice may not be removed or altered from any source distribution.
|
| 18 |
+
|
| 19 |
+
#pragma once
|
| 20 |
+
|
| 21 |
+
#ifdef __cplusplus
|
| 22 |
+
extern "C" {
|
| 23 |
+
#endif
|
| 24 |
+
|
| 25 |
+
#include <stdint.h>
|
| 26 |
+
|
| 27 |
+
typedef struct enkiTaskScheduler enkiTaskScheduler;
|
| 28 |
+
typedef struct enkiTaskSet enkiTaskSet;
|
| 29 |
+
|
| 30 |
+
typedef void (* enkiTaskExecuteRange)( uint32_t start_, uint32_t end, uint32_t threadnum_, void* pArgs_ );
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
// Create a new task scheduler
|
| 34 |
+
enkiTaskScheduler* enkiNewTaskScheduler();
|
| 35 |
+
|
| 36 |
+
// Initialize task scheduler - will create GetNumHardwareThreads()-1 threads, which is
|
| 37 |
+
// sufficient to fill the system when including the main thread.
|
| 38 |
+
// Initialize can be called multiple times - it will wait for completion
|
| 39 |
+
// before re-initializing.
|
| 40 |
+
void enkiInitTaskScheduler( enkiTaskScheduler* pETS_ );
|
| 41 |
+
|
| 42 |
+
// Initialize a task scheduler with numThreads_ (must be > 0)
|
| 43 |
+
// will create numThreads_-1 threads, as thread 0 is
|
| 44 |
+
// the thread on which the initialize was called.
|
| 45 |
+
void enkiInitTaskSchedulerNumThreads( enkiTaskScheduler* pETS_, uint32_t numThreads_ );
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
// Delete a task scheduler
|
| 49 |
+
void enkiDeleteTaskScheduler( enkiTaskScheduler* pETS_ );
|
| 50 |
+
|
| 51 |
+
// Create a task set.
|
| 52 |
+
enkiTaskSet* enkiCreateTaskSet( enkiTaskScheduler* pETS_, enkiTaskExecuteRange taskFunc_ );
|
| 53 |
+
|
| 54 |
+
// Delete a task set.
|
| 55 |
+
void enkiDeleteTaskSet( enkiTaskSet* pTaskSet_ );
|
| 56 |
+
|
| 57 |
+
// Schedule the task
|
| 58 |
+
void enkiAddTaskSetToPipe( enkiTaskScheduler* pETS_, enkiTaskSet* pTaskSet_,
|
| 59 |
+
void* pArgs_, uint32_t setSize_ );
|
| 60 |
+
|
| 61 |
+
// Schedule the task with a minimum range.
|
| 62 |
+
// This should be set to a value which results in computation effort of at least 10k
|
| 63 |
+
// clock cycles to minimize tast scheduler overhead.
|
| 64 |
+
// NOTE: The last partition will be smaller than m_MinRange if m_SetSize is not a multiple
|
| 65 |
+
// of m_MinRange.
|
| 66 |
+
// Also known as grain size in literature.
|
| 67 |
+
void enkiAddTaskSetToPipeMinRange( enkiTaskScheduler* pETS_, enkiTaskSet* pTaskSet_,
|
| 68 |
+
void* pArgs_, uint32_t setSize_, uint32_t minRange_ );
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
// Check if TaskSet is complete. Doesn't wait. Returns 1 if complete, 0 if not.
|
| 72 |
+
int enkiIsTaskSetComplete( enkiTaskScheduler* pETS_, enkiTaskSet* pTaskSet_ );
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
// Wait for a given task.
|
| 76 |
+
// should only be called from thread which created the taskscheduler , or within a task
|
| 77 |
+
// if called with 0 it will try to run tasks, and return if none available.
|
| 78 |
+
void enkiWaitForTaskSet( enkiTaskScheduler* pETS_, enkiTaskSet* pTaskSet_ );
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
// Waits for all task sets to complete - not guaranteed to work unless we know we
|
| 82 |
+
// are in a situation where tasks aren't being continuosly added.
|
| 83 |
+
void enkiWaitForAll( enkiTaskScheduler* pETS_ );
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
// get number of threads
|
| 87 |
+
uint32_t enkiGetNumTaskThreads( enkiTaskScheduler* pETS_ );
|
| 88 |
+
|
| 89 |
+
// TaskScheduler implements several callbacks intended for profilers
|
| 90 |
+
typedef void (*enkiProfilerCallbackFunc)( uint32_t threadnum_ );
|
| 91 |
+
struct enkiProfilerCallbacks
|
| 92 |
+
{
|
| 93 |
+
enkiProfilerCallbackFunc threadStart;
|
| 94 |
+
enkiProfilerCallbackFunc threadStop;
|
| 95 |
+
enkiProfilerCallbackFunc waitStart;
|
| 96 |
+
enkiProfilerCallbackFunc waitStop;
|
| 97 |
+
};
|
| 98 |
+
|
| 99 |
+
// Get the callback structure so it can be set
|
| 100 |
+
struct enkiProfilerCallbacks* enkiGetProfilerCallbacks( enkiTaskScheduler* pETS_ );
|
| 101 |
+
|
| 102 |
+
#ifdef __cplusplus
|
| 103 |
+
}
|
| 104 |
+
#endif
|
third_party/tracy/examples/ToyPathTracer/Source/enkiTS/Threads.h
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (c) 2013 Doug Binks
|
| 2 |
+
//
|
| 3 |
+
// This software is provided 'as-is', without any express or implied
|
| 4 |
+
// warranty. In no event will the authors be held liable for any damages
|
| 5 |
+
// arising from the use of this software.
|
| 6 |
+
//
|
| 7 |
+
// Permission is granted to anyone to use this software for any purpose,
|
| 8 |
+
// including commercial applications, and to alter it and redistribute it
|
| 9 |
+
// freely, subject to the following restrictions:
|
| 10 |
+
//
|
| 11 |
+
// 1. The origin of this software must not be misrepresented; you must not
|
| 12 |
+
// claim that you wrote the original software. If you use this software
|
| 13 |
+
// in a product, an acknowledgement in the product documentation would be
|
| 14 |
+
// appreciated but is not required.
|
| 15 |
+
// 2. Altered source versions must be plainly marked as such, and must not be
|
| 16 |
+
// misrepresented as being the original software.
|
| 17 |
+
// 3. This notice may not be removed or altered from any source distribution.
|
| 18 |
+
|
| 19 |
+
#pragma once
|
| 20 |
+
|
| 21 |
+
#include <stdint.h>
|
| 22 |
+
#include <assert.h>
|
| 23 |
+
|
| 24 |
+
#ifdef _WIN32
|
| 25 |
+
|
| 26 |
+
#include "Atomics.h"
|
| 27 |
+
|
| 28 |
+
#define WIN32_LEAN_AND_MEAN
|
| 29 |
+
#include <Windows.h>
|
| 30 |
+
|
| 31 |
+
#define THREADFUNC_DECL DWORD WINAPI
|
| 32 |
+
#define THREAD_LOCAL __declspec( thread )
|
| 33 |
+
|
| 34 |
+
namespace enki
|
| 35 |
+
{
|
| 36 |
+
typedef HANDLE threadid_t;
|
| 37 |
+
|
| 38 |
+
// declare the thread start function as:
|
| 39 |
+
// THREADFUNC_DECL MyThreadStart( void* pArg );
|
| 40 |
+
inline bool ThreadCreate( threadid_t* returnid, DWORD ( WINAPI *StartFunc) (void* ), void* pArg )
|
| 41 |
+
{
|
| 42 |
+
// posix equiv pthread_create
|
| 43 |
+
DWORD threadid;
|
| 44 |
+
*returnid = CreateThread( 0, 0, StartFunc, pArg, 0, &threadid );
|
| 45 |
+
return *returnid != NULL;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
inline bool ThreadTerminate( threadid_t threadid )
|
| 49 |
+
{
|
| 50 |
+
// posix equiv pthread_cancel
|
| 51 |
+
return CloseHandle( threadid ) == 0;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
inline uint32_t GetNumHardwareThreads()
|
| 55 |
+
{
|
| 56 |
+
SYSTEM_INFO sysInfo;
|
| 57 |
+
GetSystemInfo(&sysInfo);
|
| 58 |
+
return sysInfo.dwNumberOfProcessors;
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
#else // posix
|
| 63 |
+
|
| 64 |
+
#include <pthread.h>
|
| 65 |
+
#include <unistd.h>
|
| 66 |
+
#define THREADFUNC_DECL void*
|
| 67 |
+
#define THREAD_LOCAL __thread
|
| 68 |
+
|
| 69 |
+
namespace enki
|
| 70 |
+
{
|
| 71 |
+
typedef pthread_t threadid_t;
|
| 72 |
+
|
| 73 |
+
// declare the thread start function as:
|
| 74 |
+
// THREADFUNC_DECL MyThreadStart( void* pArg );
|
| 75 |
+
inline bool ThreadCreate( threadid_t* returnid, void* ( *StartFunc) (void* ), void* pArg )
|
| 76 |
+
{
|
| 77 |
+
// posix equiv pthread_create
|
| 78 |
+
int32_t retval = pthread_create( returnid, NULL, StartFunc, pArg );
|
| 79 |
+
|
| 80 |
+
return retval == 0;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
inline bool ThreadTerminate( threadid_t threadid )
|
| 84 |
+
{
|
| 85 |
+
// posix equiv pthread_cancel
|
| 86 |
+
return pthread_cancel( threadid ) == 0;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
inline uint32_t GetNumHardwareThreads()
|
| 90 |
+
{
|
| 91 |
+
return (uint32_t)sysconf( _SC_NPROCESSORS_ONLN );
|
| 92 |
+
}
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
#endif // posix
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
// Semaphore implementation
|
| 99 |
+
#ifdef _WIN32
|
| 100 |
+
|
| 101 |
+
namespace enki
|
| 102 |
+
{
|
| 103 |
+
struct semaphoreid_t
|
| 104 |
+
{
|
| 105 |
+
HANDLE sem;
|
| 106 |
+
};
|
| 107 |
+
|
| 108 |
+
inline void SemaphoreCreate( semaphoreid_t& semaphoreid )
|
| 109 |
+
{
|
| 110 |
+
semaphoreid.sem = CreateSemaphore(NULL, 0, MAXLONG, NULL );
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
inline void SemaphoreClose( semaphoreid_t& semaphoreid )
|
| 114 |
+
{
|
| 115 |
+
CloseHandle( semaphoreid.sem );
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
inline void SemaphoreWait( semaphoreid_t& semaphoreid )
|
| 119 |
+
{
|
| 120 |
+
DWORD retval = WaitForSingleObject( semaphoreid.sem, INFINITE );
|
| 121 |
+
|
| 122 |
+
assert( retval != WAIT_FAILED );
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
inline void SemaphoreSignal( semaphoreid_t& semaphoreid, int32_t countWaiting )
|
| 126 |
+
{
|
| 127 |
+
if( countWaiting )
|
| 128 |
+
{
|
| 129 |
+
ReleaseSemaphore( semaphoreid.sem, countWaiting, NULL );
|
| 130 |
+
}
|
| 131 |
+
}
|
| 132 |
+
}
|
| 133 |
+
#elif defined(__MACH__)
|
| 134 |
+
|
| 135 |
+
// OS X does not have POSIX semaphores
|
| 136 |
+
// see https://developer.apple.com/library/content/documentation/Darwin/Conceptual/KernelProgramming/synchronization/synchronization.html
|
| 137 |
+
#include <mach/mach.h>
|
| 138 |
+
|
| 139 |
+
namespace enki
|
| 140 |
+
{
|
| 141 |
+
|
| 142 |
+
struct semaphoreid_t
|
| 143 |
+
{
|
| 144 |
+
semaphore_t sem;
|
| 145 |
+
};
|
| 146 |
+
|
| 147 |
+
inline void SemaphoreCreate( semaphoreid_t& semaphoreid )
|
| 148 |
+
{
|
| 149 |
+
semaphore_create( mach_task_self(), &semaphoreid.sem, SYNC_POLICY_FIFO, 0 );
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
inline void SemaphoreClose( semaphoreid_t& semaphoreid )
|
| 153 |
+
{
|
| 154 |
+
semaphore_destroy( mach_task_self(), semaphoreid.sem );
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
inline void SemaphoreWait( semaphoreid_t& semaphoreid )
|
| 158 |
+
{
|
| 159 |
+
semaphore_wait( semaphoreid.sem );
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
inline void SemaphoreSignal( semaphoreid_t& semaphoreid, int32_t countWaiting )
|
| 163 |
+
{
|
| 164 |
+
while( countWaiting-- > 0 )
|
| 165 |
+
{
|
| 166 |
+
semaphore_signal( semaphoreid.sem );
|
| 167 |
+
}
|
| 168 |
+
}
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
#else // POSIX
|
| 172 |
+
|
| 173 |
+
#include <semaphore.h>
|
| 174 |
+
|
| 175 |
+
namespace enki
|
| 176 |
+
{
|
| 177 |
+
|
| 178 |
+
struct semaphoreid_t
|
| 179 |
+
{
|
| 180 |
+
sem_t sem;
|
| 181 |
+
};
|
| 182 |
+
|
| 183 |
+
inline void SemaphoreCreate( semaphoreid_t& semaphoreid )
|
| 184 |
+
{
|
| 185 |
+
int err = sem_init( &semaphoreid.sem, 0, 0 );
|
| 186 |
+
assert( err == 0 );
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
inline void SemaphoreClose( semaphoreid_t& semaphoreid )
|
| 190 |
+
{
|
| 191 |
+
sem_destroy( &semaphoreid.sem );
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
inline void SemaphoreWait( semaphoreid_t& semaphoreid )
|
| 195 |
+
{
|
| 196 |
+
int err = sem_wait( &semaphoreid.sem );
|
| 197 |
+
assert( err == 0 );
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
inline void SemaphoreSignal( semaphoreid_t& semaphoreid, int32_t countWaiting )
|
| 201 |
+
{
|
| 202 |
+
while( countWaiting-- > 0 )
|
| 203 |
+
{
|
| 204 |
+
sem_post( &semaphoreid.sem );
|
| 205 |
+
}
|
| 206 |
+
}
|
| 207 |
+
}
|
| 208 |
+
#endif
|
| 209 |
+
|
| 210 |
+
|
third_party/tracy/examples/ToyPathTracer/Windows/ComputeShader.hlsl
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "../Source/Config.h"
|
| 2 |
+
|
| 3 |
+
inline uint RNG(inout uint state)
|
| 4 |
+
{
|
| 5 |
+
uint x = state;
|
| 6 |
+
x ^= x << 13;
|
| 7 |
+
x ^= x >> 17;
|
| 8 |
+
x ^= x << 15;
|
| 9 |
+
state = x;
|
| 10 |
+
return x;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
float RandomFloat01(inout uint state)
|
| 14 |
+
{
|
| 15 |
+
return (RNG(state) & 0xFFFFFF) / 16777216.0f;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
float3 RandomInUnitDisk(inout uint state)
|
| 19 |
+
{
|
| 20 |
+
float a = RandomFloat01(state) * 2.0f * 3.1415926f;
|
| 21 |
+
float2 xy = float2(cos(a), sin(a));
|
| 22 |
+
xy *= sqrt(RandomFloat01(state));
|
| 23 |
+
return float3(xy, 0);
|
| 24 |
+
}
|
| 25 |
+
float3 RandomInUnitSphere(inout uint state)
|
| 26 |
+
{
|
| 27 |
+
float z = RandomFloat01(state) * 2.0f - 1.0f;
|
| 28 |
+
float t = RandomFloat01(state) * 2.0f * 3.1415926f;
|
| 29 |
+
float r = sqrt(max(0.0, 1.0f - z * z));
|
| 30 |
+
float x = r * cos(t);
|
| 31 |
+
float y = r * sin(t);
|
| 32 |
+
float3 res = float3(x, y, z);
|
| 33 |
+
res *= pow(RandomFloat01(state), 1.0 / 3.0);
|
| 34 |
+
return res;
|
| 35 |
+
}
|
| 36 |
+
float3 RandomUnitVector(inout uint state)
|
| 37 |
+
{
|
| 38 |
+
float z = RandomFloat01(state) * 2.0f - 1.0f;
|
| 39 |
+
float a = RandomFloat01(state) * 2.0f * 3.1415926f;
|
| 40 |
+
float r = sqrt(1.0f - z * z);
|
| 41 |
+
float x = r * cos(a);
|
| 42 |
+
float y = r * sin(a);
|
| 43 |
+
return float3(x, y, z);
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
struct Ray
|
| 49 |
+
{
|
| 50 |
+
float3 orig;
|
| 51 |
+
float3 dir;
|
| 52 |
+
};
|
| 53 |
+
Ray MakeRay(float3 orig_, float3 dir_) { Ray r; r.orig = orig_; r.dir = dir_; return r; }
|
| 54 |
+
float3 RayPointAt(Ray r, float t) { return r.orig + r.dir * t; }
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
inline bool refract(float3 v, float3 n, float nint, out float3 outRefracted)
|
| 58 |
+
{
|
| 59 |
+
float dt = dot(v, n);
|
| 60 |
+
float discr = 1.0f - nint * nint*(1 - dt * dt);
|
| 61 |
+
if (discr > 0)
|
| 62 |
+
{
|
| 63 |
+
outRefracted = nint * (v - n * dt) - n * sqrt(discr);
|
| 64 |
+
return true;
|
| 65 |
+
}
|
| 66 |
+
return false;
|
| 67 |
+
}
|
| 68 |
+
inline float schlick(float cosine, float ri)
|
| 69 |
+
{
|
| 70 |
+
float r0 = (1 - ri) / (1 + ri);
|
| 71 |
+
r0 = r0 * r0;
|
| 72 |
+
// note: saturate to guard against possible tiny negative numbers
|
| 73 |
+
return r0 + (1 - r0)*pow(saturate(1 - cosine), 5);
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
struct Hit
|
| 77 |
+
{
|
| 78 |
+
float3 pos;
|
| 79 |
+
float3 normal;
|
| 80 |
+
float t;
|
| 81 |
+
};
|
| 82 |
+
|
| 83 |
+
struct Sphere
|
| 84 |
+
{
|
| 85 |
+
float3 center;
|
| 86 |
+
float radius;
|
| 87 |
+
float invRadius;
|
| 88 |
+
};
|
| 89 |
+
|
| 90 |
+
#define MatLambert 0
|
| 91 |
+
#define MatMetal 1
|
| 92 |
+
#define MatDielectric 2
|
| 93 |
+
|
| 94 |
+
struct Material
|
| 95 |
+
{
|
| 96 |
+
int type;
|
| 97 |
+
float3 albedo;
|
| 98 |
+
float3 emissive;
|
| 99 |
+
float roughness;
|
| 100 |
+
float ri;
|
| 101 |
+
};
|
| 102 |
+
|
| 103 |
+
groupshared Sphere s_GroupSpheres[kCSMaxObjects];
|
| 104 |
+
groupshared Material s_GroupMaterials[kCSMaxObjects];
|
| 105 |
+
groupshared int s_GroupEmissives[kCSMaxObjects];
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
struct Camera
|
| 109 |
+
{
|
| 110 |
+
float3 origin;
|
| 111 |
+
float3 lowerLeftCorner;
|
| 112 |
+
float3 horizontal;
|
| 113 |
+
float3 vertical;
|
| 114 |
+
float3 u, v, w;
|
| 115 |
+
float lensRadius;
|
| 116 |
+
};
|
| 117 |
+
|
| 118 |
+
Ray CameraGetRay(Camera cam, float s, float t, inout uint state)
|
| 119 |
+
{
|
| 120 |
+
float3 rd = cam.lensRadius * RandomInUnitDisk(state);
|
| 121 |
+
float3 offset = cam.u * rd.x + cam.v * rd.y;
|
| 122 |
+
return MakeRay(cam.origin + offset, normalize(cam.lowerLeftCorner + s * cam.horizontal + t * cam.vertical - cam.origin - offset));
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
int HitSpheres(Ray r, int sphereCount, float tMin, float tMax, inout Hit outHit)
|
| 127 |
+
{
|
| 128 |
+
float hitT = tMax;
|
| 129 |
+
int id = -1;
|
| 130 |
+
for (int i = 0; i < sphereCount; ++i)
|
| 131 |
+
{
|
| 132 |
+
Sphere s = s_GroupSpheres[i];
|
| 133 |
+
float3 co = s.center - r.orig;
|
| 134 |
+
float nb = dot(co, r.dir);
|
| 135 |
+
float c = dot(co, co) - s.radius*s.radius;
|
| 136 |
+
float discr = nb * nb - c;
|
| 137 |
+
if (discr > 0)
|
| 138 |
+
{
|
| 139 |
+
float discrSq = sqrt(discr);
|
| 140 |
+
|
| 141 |
+
// Try earlier t
|
| 142 |
+
float t = nb - discrSq;
|
| 143 |
+
if (t <= tMin) // before min, try later t!
|
| 144 |
+
t = nb + discrSq;
|
| 145 |
+
|
| 146 |
+
if (t > tMin && t < hitT)
|
| 147 |
+
{
|
| 148 |
+
id = i;
|
| 149 |
+
hitT = t;
|
| 150 |
+
}
|
| 151 |
+
}
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
if (id != -1)
|
| 155 |
+
{
|
| 156 |
+
outHit.pos = RayPointAt(r, hitT);
|
| 157 |
+
outHit.normal = (outHit.pos - s_GroupSpheres[id].center) * s_GroupSpheres[id].invRadius;
|
| 158 |
+
outHit.t = hitT;
|
| 159 |
+
}
|
| 160 |
+
return id;
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
struct Params
|
| 164 |
+
{
|
| 165 |
+
Camera cam;
|
| 166 |
+
int sphereCount;
|
| 167 |
+
int screenWidth;
|
| 168 |
+
int screenHeight;
|
| 169 |
+
int frames;
|
| 170 |
+
float invWidth;
|
| 171 |
+
float invHeight;
|
| 172 |
+
float lerpFac;
|
| 173 |
+
int emissiveCount;
|
| 174 |
+
};
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
#define kMinT 0.001f
|
| 178 |
+
#define kMaxT 1.0e7f
|
| 179 |
+
#define kMaxDepth 10
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
static int HitWorld(int sphereCount, Ray r, float tMin, float tMax, inout Hit outHit)
|
| 183 |
+
{
|
| 184 |
+
return HitSpheres(r, sphereCount, tMin, tMax, outHit);
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
static bool Scatter(int sphereCount, int emissiveCount, int matID, Ray r_in, Hit rec, out float3 attenuation, out Ray scattered, out float3 outLightE, inout int inoutRayCount, inout uint state)
|
| 189 |
+
{
|
| 190 |
+
outLightE = float3(0, 0, 0);
|
| 191 |
+
Material mat = s_GroupMaterials[matID];
|
| 192 |
+
if (mat.type == MatLambert)
|
| 193 |
+
{
|
| 194 |
+
// random point on unit sphere that is tangent to the hit point
|
| 195 |
+
float3 target = rec.pos + rec.normal + RandomUnitVector(state);
|
| 196 |
+
scattered = MakeRay(rec.pos, normalize(target - rec.pos));
|
| 197 |
+
attenuation = mat.albedo;
|
| 198 |
+
|
| 199 |
+
// sample lights
|
| 200 |
+
#if DO_LIGHT_SAMPLING
|
| 201 |
+
for (int j = 0; j < emissiveCount; ++j)
|
| 202 |
+
{
|
| 203 |
+
int i = s_GroupEmissives[j];
|
| 204 |
+
if (matID == i)
|
| 205 |
+
continue; // skip self
|
| 206 |
+
Material smat = s_GroupMaterials[i];
|
| 207 |
+
Sphere s = s_GroupSpheres[i];
|
| 208 |
+
|
| 209 |
+
// create a random direction towards sphere
|
| 210 |
+
// coord system for sampling: sw, su, sv
|
| 211 |
+
float3 sw = normalize(s.center - rec.pos);
|
| 212 |
+
float3 su = normalize(cross(abs(sw.x)>0.01f ? float3(0, 1, 0) : float3(1, 0, 0), sw));
|
| 213 |
+
float3 sv = cross(sw, su);
|
| 214 |
+
// sample sphere by solid angle
|
| 215 |
+
float cosAMax = sqrt(1.0f - s.radius*s.radius / dot(rec.pos - s.center, rec.pos - s.center));
|
| 216 |
+
float eps1 = RandomFloat01(state), eps2 = RandomFloat01(state);
|
| 217 |
+
float cosA = 1.0f - eps1 + eps1 * cosAMax;
|
| 218 |
+
float sinA = sqrt(1.0f - cosA * cosA);
|
| 219 |
+
float phi = 2 * 3.1415926 * eps2;
|
| 220 |
+
float3 l = su * cos(phi) * sinA + sv * sin(phi) * sinA + sw * cosA;
|
| 221 |
+
|
| 222 |
+
// shoot shadow ray
|
| 223 |
+
Hit lightHit;
|
| 224 |
+
++inoutRayCount;
|
| 225 |
+
int hitID = HitWorld(sphereCount, MakeRay(rec.pos, l), kMinT, kMaxT, lightHit);
|
| 226 |
+
if (hitID == i)
|
| 227 |
+
{
|
| 228 |
+
float omega = 2 * 3.1415926 * (1 - cosAMax);
|
| 229 |
+
|
| 230 |
+
float3 rdir = r_in.dir;
|
| 231 |
+
float3 nl = dot(rec.normal, rdir) < 0 ? rec.normal : -rec.normal;
|
| 232 |
+
outLightE += (mat.albedo * smat.emissive) * (max(0.0f, dot(l, nl)) * omega / 3.1415926);
|
| 233 |
+
}
|
| 234 |
+
}
|
| 235 |
+
#endif
|
| 236 |
+
return true;
|
| 237 |
+
}
|
| 238 |
+
else if (mat.type == MatMetal)
|
| 239 |
+
{
|
| 240 |
+
float3 refl = reflect(r_in.dir, rec.normal);
|
| 241 |
+
// reflected ray, and random inside of sphere based on roughness
|
| 242 |
+
float roughness = mat.roughness;
|
| 243 |
+
#if DO_MITSUBA_COMPARE
|
| 244 |
+
roughness = 0; // until we get better BRDF for metals
|
| 245 |
+
#endif
|
| 246 |
+
scattered = MakeRay(rec.pos, normalize(refl + roughness*RandomInUnitSphere(state)));
|
| 247 |
+
attenuation = mat.albedo;
|
| 248 |
+
return dot(scattered.dir, rec.normal) > 0;
|
| 249 |
+
}
|
| 250 |
+
else if (mat.type == MatDielectric)
|
| 251 |
+
{
|
| 252 |
+
float3 outwardN;
|
| 253 |
+
float3 rdir = r_in.dir;
|
| 254 |
+
float3 refl = reflect(rdir, rec.normal);
|
| 255 |
+
float nint;
|
| 256 |
+
attenuation = float3(1, 1, 1);
|
| 257 |
+
float3 refr;
|
| 258 |
+
float reflProb;
|
| 259 |
+
float cosine;
|
| 260 |
+
if (dot(rdir, rec.normal) > 0)
|
| 261 |
+
{
|
| 262 |
+
outwardN = -rec.normal;
|
| 263 |
+
nint = mat.ri;
|
| 264 |
+
cosine = mat.ri * dot(rdir, rec.normal);
|
| 265 |
+
}
|
| 266 |
+
else
|
| 267 |
+
{
|
| 268 |
+
outwardN = rec.normal;
|
| 269 |
+
nint = 1.0f / mat.ri;
|
| 270 |
+
cosine = -dot(rdir, rec.normal);
|
| 271 |
+
}
|
| 272 |
+
if (refract(rdir, outwardN, nint, refr))
|
| 273 |
+
{
|
| 274 |
+
reflProb = schlick(cosine, mat.ri);
|
| 275 |
+
}
|
| 276 |
+
else
|
| 277 |
+
{
|
| 278 |
+
reflProb = 1;
|
| 279 |
+
}
|
| 280 |
+
if (RandomFloat01(state) < reflProb)
|
| 281 |
+
scattered = MakeRay(rec.pos, normalize(refl));
|
| 282 |
+
else
|
| 283 |
+
scattered = MakeRay(rec.pos, normalize(refr));
|
| 284 |
+
}
|
| 285 |
+
else
|
| 286 |
+
{
|
| 287 |
+
attenuation = float3(1, 0, 1);
|
| 288 |
+
scattered = MakeRay(float3(0,0,0), float3(0, 0, 1));
|
| 289 |
+
return false;
|
| 290 |
+
}
|
| 291 |
+
return true;
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
static float3 Trace(int sphereCount, int emissiveCount, Ray r, inout int inoutRayCount, inout uint state)
|
| 295 |
+
{
|
| 296 |
+
float3 col = 0;
|
| 297 |
+
float3 curAtten = 1;
|
| 298 |
+
bool doMaterialE = true;
|
| 299 |
+
// GPUs don't support recursion, so do tracing iterations in a loop up to max depth
|
| 300 |
+
for (int depth = 0; depth < kMaxDepth; ++depth)
|
| 301 |
+
{
|
| 302 |
+
Hit rec;
|
| 303 |
+
++inoutRayCount;
|
| 304 |
+
int id = HitWorld(sphereCount, r, kMinT, kMaxT, rec);
|
| 305 |
+
if (id >= 0)
|
| 306 |
+
{
|
| 307 |
+
Ray scattered;
|
| 308 |
+
float3 attenuation;
|
| 309 |
+
float3 lightE;
|
| 310 |
+
Material mat = s_GroupMaterials[id];
|
| 311 |
+
float3 matE = mat.emissive;
|
| 312 |
+
if (Scatter(sphereCount, emissiveCount, id, r, rec, attenuation, scattered, lightE, inoutRayCount, state))
|
| 313 |
+
{
|
| 314 |
+
#if DO_LIGHT_SAMPLING
|
| 315 |
+
if (!doMaterialE) matE = 0;
|
| 316 |
+
doMaterialE = (mat.type != MatLambert);
|
| 317 |
+
#endif
|
| 318 |
+
col += curAtten * (matE + lightE);
|
| 319 |
+
curAtten *= attenuation;
|
| 320 |
+
r = scattered;
|
| 321 |
+
}
|
| 322 |
+
else
|
| 323 |
+
{
|
| 324 |
+
col += curAtten * matE;
|
| 325 |
+
break;
|
| 326 |
+
}
|
| 327 |
+
}
|
| 328 |
+
else
|
| 329 |
+
{
|
| 330 |
+
// sky
|
| 331 |
+
#if DO_MITSUBA_COMPARE
|
| 332 |
+
col += curAtten * float3(0.15f, 0.21f, 0.3f); // easier compare with Mitsuba's constant environment light
|
| 333 |
+
#else
|
| 334 |
+
float3 unitDir = r.dir;
|
| 335 |
+
float t = 0.5f*(unitDir.y + 1.0f);
|
| 336 |
+
float3 skyCol = ((1.0f - t)*float3(1.0f, 1.0f, 1.0f) + t * float3(0.5f, 0.7f, 1.0f)) * 0.3f;
|
| 337 |
+
col += curAtten * skyCol;
|
| 338 |
+
#endif
|
| 339 |
+
break;
|
| 340 |
+
}
|
| 341 |
+
}
|
| 342 |
+
return col;
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
Texture2D srcImage : register(t0);
|
| 346 |
+
RWTexture2D<float4> dstImage : register(u0);
|
| 347 |
+
StructuredBuffer<Sphere> g_Spheres : register(t1);
|
| 348 |
+
StructuredBuffer<Material> g_Materials : register(t2);
|
| 349 |
+
StructuredBuffer<Params> g_Params : register(t3);
|
| 350 |
+
StructuredBuffer<int> g_Emissives : register(t4);
|
| 351 |
+
RWByteAddressBuffer g_OutRayCount : register(u1);
|
| 352 |
+
|
| 353 |
+
[numthreads(kCSGroupSizeX, kCSGroupSizeY, 1)]
|
| 354 |
+
void main(uint3 gid : SV_DispatchThreadID, uint3 tid : SV_GroupThreadID)
|
| 355 |
+
{
|
| 356 |
+
// First, move scene data (spheres, materials, emissive indices) into group shared
|
| 357 |
+
// memory. Do this in parallel; each thread in group copies its own chunk of data.
|
| 358 |
+
uint threadID = tid.y * kCSGroupSizeX + tid.x;
|
| 359 |
+
uint groupSize = kCSGroupSizeX * kCSGroupSizeY;
|
| 360 |
+
uint objCount = g_Params[0].sphereCount;
|
| 361 |
+
uint myObjCount = (objCount + groupSize - 1) / groupSize;
|
| 362 |
+
uint myObjStart = threadID * myObjCount;
|
| 363 |
+
for (uint io = myObjStart; io < myObjStart + myObjCount; ++io)
|
| 364 |
+
{
|
| 365 |
+
if (io < objCount)
|
| 366 |
+
{
|
| 367 |
+
s_GroupSpheres[io] = g_Spheres[io];
|
| 368 |
+
s_GroupMaterials[io] = g_Materials[io];
|
| 369 |
+
}
|
| 370 |
+
if (io < g_Params[0].emissiveCount)
|
| 371 |
+
{
|
| 372 |
+
s_GroupEmissives[io] = g_Emissives[io];
|
| 373 |
+
}
|
| 374 |
+
}
|
| 375 |
+
GroupMemoryBarrierWithGroupSync();
|
| 376 |
+
|
| 377 |
+
int rayCount = 0;
|
| 378 |
+
float3 col = 0;
|
| 379 |
+
Params params = g_Params[0];
|
| 380 |
+
uint rngState = (gid.x * 1973 + gid.y * 9277 + params.frames * 26699) | 1;
|
| 381 |
+
for (int s = 0; s < DO_SAMPLES_PER_PIXEL; s++)
|
| 382 |
+
{
|
| 383 |
+
float u = float(gid.x + RandomFloat01(rngState)) * params.invWidth;
|
| 384 |
+
float v = float(gid.y + RandomFloat01(rngState)) * params.invHeight;
|
| 385 |
+
Ray r = CameraGetRay(params.cam, u, v, rngState);
|
| 386 |
+
col += Trace(params.sphereCount, params.emissiveCount, r, rayCount, rngState);
|
| 387 |
+
}
|
| 388 |
+
col *= 1.0f / float(DO_SAMPLES_PER_PIXEL);
|
| 389 |
+
|
| 390 |
+
float3 prev = srcImage.Load(int3(gid.xy,0)).rgb;
|
| 391 |
+
col = lerp(col, prev, params.lerpFac);
|
| 392 |
+
dstImage[gid.xy] = float4(col, 1);
|
| 393 |
+
|
| 394 |
+
g_OutRayCount.InterlockedAdd(0, rayCount);
|
| 395 |
+
}
|
third_party/tracy/examples/ToyPathTracer/Windows/PixelShader.hlsl
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
float3 LinearToSRGB(float3 rgb)
|
| 2 |
+
{
|
| 3 |
+
rgb = max(rgb, float3(0, 0, 0));
|
| 4 |
+
return max(1.055 * pow(rgb, 0.416666667) - 0.055, 0.0);
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
Texture2D tex : register(t0);
|
| 8 |
+
SamplerState smp : register(s0);
|
| 9 |
+
|
| 10 |
+
float4 main(float2 uv : TEXCOORD0) : SV_Target
|
| 11 |
+
{
|
| 12 |
+
float3 col = tex.Sample(smp, uv).rgb;
|
| 13 |
+
col = LinearToSRGB(col);
|
| 14 |
+
return float4(col, 1.0f);
|
| 15 |
+
}
|
third_party/tracy/examples/ToyPathTracer/Windows/TestCpu.sln
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Microsoft Visual Studio Solution File, Format Version 12.00
|
| 3 |
+
# Visual Studio Version 16
|
| 4 |
+
VisualStudioVersion = 16.0.30907.101
|
| 5 |
+
MinimumVisualStudioVersion = 10.0.40219.1
|
| 6 |
+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCpu", "TestCpu.vcxproj", "{4F84B756-87F5-4B92-827B-DA087DAE1900}"
|
| 7 |
+
EndProject
|
| 8 |
+
Global
|
| 9 |
+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
| 10 |
+
Debug|x64 = Debug|x64
|
| 11 |
+
Debug|x86 = Debug|x86
|
| 12 |
+
Release|x64 = Release|x64
|
| 13 |
+
Release|x86 = Release|x86
|
| 14 |
+
EndGlobalSection
|
| 15 |
+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
| 16 |
+
{4F84B756-87F5-4B92-827B-DA087DAE1900}.Debug|x64.ActiveCfg = Debug|x64
|
| 17 |
+
{4F84B756-87F5-4B92-827B-DA087DAE1900}.Debug|x64.Build.0 = Debug|x64
|
| 18 |
+
{4F84B756-87F5-4B92-827B-DA087DAE1900}.Debug|x86.ActiveCfg = Debug|Win32
|
| 19 |
+
{4F84B756-87F5-4B92-827B-DA087DAE1900}.Debug|x86.Build.0 = Debug|Win32
|
| 20 |
+
{4F84B756-87F5-4B92-827B-DA087DAE1900}.Release|x64.ActiveCfg = Release|x64
|
| 21 |
+
{4F84B756-87F5-4B92-827B-DA087DAE1900}.Release|x64.Build.0 = Release|x64
|
| 22 |
+
{4F84B756-87F5-4B92-827B-DA087DAE1900}.Release|x86.ActiveCfg = Release|Win32
|
| 23 |
+
{4F84B756-87F5-4B92-827B-DA087DAE1900}.Release|x86.Build.0 = Release|Win32
|
| 24 |
+
EndGlobalSection
|
| 25 |
+
GlobalSection(SolutionProperties) = preSolution
|
| 26 |
+
HideSolutionNode = FALSE
|
| 27 |
+
EndGlobalSection
|
| 28 |
+
GlobalSection(ExtensibilityGlobals) = postSolution
|
| 29 |
+
SolutionGuid = {067FB780-37B8-465E-AD7E-E7B238B9C04F}
|
| 30 |
+
EndGlobalSection
|
| 31 |
+
EndGlobal
|
third_party/tracy/examples/ToyPathTracer/Windows/TestCpu.vcxproj
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
| 2 |
+
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
| 3 |
+
<ItemGroup Label="ProjectConfigurations">
|
| 4 |
+
<ProjectConfiguration Include="Debug|Win32">
|
| 5 |
+
<Configuration>Debug</Configuration>
|
| 6 |
+
<Platform>Win32</Platform>
|
| 7 |
+
</ProjectConfiguration>
|
| 8 |
+
<ProjectConfiguration Include="Release|Win32">
|
| 9 |
+
<Configuration>Release</Configuration>
|
| 10 |
+
<Platform>Win32</Platform>
|
| 11 |
+
</ProjectConfiguration>
|
| 12 |
+
<ProjectConfiguration Include="Debug|x64">
|
| 13 |
+
<Configuration>Debug</Configuration>
|
| 14 |
+
<Platform>x64</Platform>
|
| 15 |
+
</ProjectConfiguration>
|
| 16 |
+
<ProjectConfiguration Include="Release|x64">
|
| 17 |
+
<Configuration>Release</Configuration>
|
| 18 |
+
<Platform>x64</Platform>
|
| 19 |
+
</ProjectConfiguration>
|
| 20 |
+
</ItemGroup>
|
| 21 |
+
<PropertyGroup Label="Globals">
|
| 22 |
+
<VCProjectVersion>15.0</VCProjectVersion>
|
| 23 |
+
<ProjectGuid>{4F84B756-87F5-4B92-827B-DA087DAE1900}</ProjectGuid>
|
| 24 |
+
<Keyword>Win32Proj</Keyword>
|
| 25 |
+
<RootNamespace>TestCpu</RootNamespace>
|
| 26 |
+
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
| 27 |
+
</PropertyGroup>
|
| 28 |
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
| 29 |
+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
| 30 |
+
<ConfigurationType>Application</ConfigurationType>
|
| 31 |
+
<UseDebugLibraries>true</UseDebugLibraries>
|
| 32 |
+
<PlatformToolset>v143</PlatformToolset>
|
| 33 |
+
<CharacterSet>Unicode</CharacterSet>
|
| 34 |
+
</PropertyGroup>
|
| 35 |
+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
| 36 |
+
<ConfigurationType>Application</ConfigurationType>
|
| 37 |
+
<UseDebugLibraries>false</UseDebugLibraries>
|
| 38 |
+
<PlatformToolset>v143</PlatformToolset>
|
| 39 |
+
<WholeProgramOptimization>true</WholeProgramOptimization>
|
| 40 |
+
<CharacterSet>Unicode</CharacterSet>
|
| 41 |
+
</PropertyGroup>
|
| 42 |
+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
| 43 |
+
<ConfigurationType>Application</ConfigurationType>
|
| 44 |
+
<UseDebugLibraries>true</UseDebugLibraries>
|
| 45 |
+
<PlatformToolset>v143</PlatformToolset>
|
| 46 |
+
<CharacterSet>Unicode</CharacterSet>
|
| 47 |
+
</PropertyGroup>
|
| 48 |
+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
| 49 |
+
<ConfigurationType>Application</ConfigurationType>
|
| 50 |
+
<UseDebugLibraries>false</UseDebugLibraries>
|
| 51 |
+
<PlatformToolset>v143</PlatformToolset>
|
| 52 |
+
<WholeProgramOptimization>true</WholeProgramOptimization>
|
| 53 |
+
<CharacterSet>Unicode</CharacterSet>
|
| 54 |
+
</PropertyGroup>
|
| 55 |
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
| 56 |
+
<ImportGroup Label="ExtensionSettings">
|
| 57 |
+
</ImportGroup>
|
| 58 |
+
<ImportGroup Label="Shared">
|
| 59 |
+
</ImportGroup>
|
| 60 |
+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
| 61 |
+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
| 62 |
+
</ImportGroup>
|
| 63 |
+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
| 64 |
+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
| 65 |
+
</ImportGroup>
|
| 66 |
+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
| 67 |
+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
| 68 |
+
</ImportGroup>
|
| 69 |
+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
| 70 |
+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
| 71 |
+
</ImportGroup>
|
| 72 |
+
<PropertyGroup Label="UserMacros" />
|
| 73 |
+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
| 74 |
+
<LinkIncremental>true</LinkIncremental>
|
| 75 |
+
</PropertyGroup>
|
| 76 |
+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
| 77 |
+
<LinkIncremental>true</LinkIncremental>
|
| 78 |
+
</PropertyGroup>
|
| 79 |
+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
| 80 |
+
<LinkIncremental>false</LinkIncremental>
|
| 81 |
+
</PropertyGroup>
|
| 82 |
+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
| 83 |
+
<LinkIncremental>false</LinkIncremental>
|
| 84 |
+
</PropertyGroup>
|
| 85 |
+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
| 86 |
+
<ClCompile>
|
| 87 |
+
<WarningLevel>Level3</WarningLevel>
|
| 88 |
+
<Optimization>Disabled</Optimization>
|
| 89 |
+
<SDLCheck>true</SDLCheck>
|
| 90 |
+
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
| 91 |
+
<ConformanceMode>true</ConformanceMode>
|
| 92 |
+
<CallingConvention>VectorCall</CallingConvention>
|
| 93 |
+
<FloatingPointModel>Fast</FloatingPointModel>
|
| 94 |
+
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
| 95 |
+
</ClCompile>
|
| 96 |
+
<Link>
|
| 97 |
+
<SubSystem>Windows</SubSystem>
|
| 98 |
+
<GenerateDebugInformation>true</GenerateDebugInformation>
|
| 99 |
+
<AdditionalDependencies>d3d11.lib;kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
| 100 |
+
</Link>
|
| 101 |
+
</ItemDefinitionGroup>
|
| 102 |
+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
| 103 |
+
<ClCompile>
|
| 104 |
+
<WarningLevel>Level3</WarningLevel>
|
| 105 |
+
<Optimization>Disabled</Optimization>
|
| 106 |
+
<SDLCheck>true</SDLCheck>
|
| 107 |
+
<PreprocessorDefinitions>TRACY_ENABLE;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
| 108 |
+
<ConformanceMode>true</ConformanceMode>
|
| 109 |
+
<CallingConvention>VectorCall</CallingConvention>
|
| 110 |
+
<FloatingPointModel>Fast</FloatingPointModel>
|
| 111 |
+
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
| 112 |
+
</ClCompile>
|
| 113 |
+
<Link>
|
| 114 |
+
<SubSystem>Windows</SubSystem>
|
| 115 |
+
<GenerateDebugInformation>true</GenerateDebugInformation>
|
| 116 |
+
<AdditionalDependencies>d3d11.lib;kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
| 117 |
+
</Link>
|
| 118 |
+
</ItemDefinitionGroup>
|
| 119 |
+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
| 120 |
+
<ClCompile>
|
| 121 |
+
<WarningLevel>Level3</WarningLevel>
|
| 122 |
+
<Optimization>MaxSpeed</Optimization>
|
| 123 |
+
<FunctionLevelLinking>true</FunctionLevelLinking>
|
| 124 |
+
<IntrinsicFunctions>true</IntrinsicFunctions>
|
| 125 |
+
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
| 126 |
+
<ConformanceMode>true</ConformanceMode>
|
| 127 |
+
<ExceptionHandling>false</ExceptionHandling>
|
| 128 |
+
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
| 129 |
+
<BufferSecurityCheck>false</BufferSecurityCheck>
|
| 130 |
+
<CallingConvention>VectorCall</CallingConvention>
|
| 131 |
+
<FloatingPointModel>Fast</FloatingPointModel>
|
| 132 |
+
</ClCompile>
|
| 133 |
+
<Link>
|
| 134 |
+
<SubSystem>Windows</SubSystem>
|
| 135 |
+
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
| 136 |
+
<OptimizeReferences>true</OptimizeReferences>
|
| 137 |
+
<GenerateDebugInformation>true</GenerateDebugInformation>
|
| 138 |
+
<AdditionalDependencies>d3d11.lib;kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
| 139 |
+
</Link>
|
| 140 |
+
</ItemDefinitionGroup>
|
| 141 |
+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
| 142 |
+
<ClCompile>
|
| 143 |
+
<WarningLevel>Level3</WarningLevel>
|
| 144 |
+
<Optimization>MaxSpeed</Optimization>
|
| 145 |
+
<FunctionLevelLinking>true</FunctionLevelLinking>
|
| 146 |
+
<IntrinsicFunctions>true</IntrinsicFunctions>
|
| 147 |
+
<PreprocessorDefinitions>TRACY_ENABLE;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
| 148 |
+
<ConformanceMode>true</ConformanceMode>
|
| 149 |
+
<ExceptionHandling>false</ExceptionHandling>
|
| 150 |
+
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
| 151 |
+
<BufferSecurityCheck>false</BufferSecurityCheck>
|
| 152 |
+
<CallingConvention>VectorCall</CallingConvention>
|
| 153 |
+
<FloatingPointModel>Fast</FloatingPointModel>
|
| 154 |
+
</ClCompile>
|
| 155 |
+
<Link>
|
| 156 |
+
<SubSystem>Windows</SubSystem>
|
| 157 |
+
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
| 158 |
+
<OptimizeReferences>true</OptimizeReferences>
|
| 159 |
+
<GenerateDebugInformation>true</GenerateDebugInformation>
|
| 160 |
+
<AdditionalDependencies>d3d11.lib;kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
| 161 |
+
</Link>
|
| 162 |
+
</ItemDefinitionGroup>
|
| 163 |
+
<ItemGroup>
|
| 164 |
+
<ClCompile Include="..\..\..\public\TracyClient.cpp" />
|
| 165 |
+
<ClCompile Include="..\Source\enkiTS\TaskScheduler.cpp" />
|
| 166 |
+
<ClCompile Include="..\Source\enkiTS\TaskScheduler_c.cpp" />
|
| 167 |
+
<ClCompile Include="..\Source\Maths.cpp" />
|
| 168 |
+
<ClCompile Include="..\Source\Test.cpp" />
|
| 169 |
+
<ClCompile Include="TestWin.cpp" />
|
| 170 |
+
</ItemGroup>
|
| 171 |
+
<ItemGroup>
|
| 172 |
+
<ClInclude Include="..\Source\Config.h" />
|
| 173 |
+
<ClInclude Include="..\Source\enkiTS\Atomics.h" />
|
| 174 |
+
<ClInclude Include="..\Source\enkiTS\LockLessMultiReadPipe.h" />
|
| 175 |
+
<ClInclude Include="..\Source\enkiTS\TaskScheduler.h" />
|
| 176 |
+
<ClInclude Include="..\Source\enkiTS\TaskScheduler_c.h" />
|
| 177 |
+
<ClInclude Include="..\Source\enkiTS\Threads.h" />
|
| 178 |
+
<ClInclude Include="..\Source\Maths.h" />
|
| 179 |
+
<ClInclude Include="..\Source\MathSimd.h" />
|
| 180 |
+
<ClInclude Include="..\Source\Test.h" />
|
| 181 |
+
<ClInclude Include="..\Source\stb_image.h" />
|
| 182 |
+
</ItemGroup>
|
| 183 |
+
<ItemGroup>
|
| 184 |
+
<None Include="..\.editorconfig" />
|
| 185 |
+
</ItemGroup>
|
| 186 |
+
<ItemGroup>
|
| 187 |
+
<FxCompile Include="ComputeShader.hlsl">
|
| 188 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType>
|
| 189 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">5.0</ShaderModel>
|
| 190 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
|
| 191 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">5.0</ShaderModel>
|
| 192 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType>
|
| 193 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">5.0</ShaderModel>
|
| 194 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compute</ShaderType>
|
| 195 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel>
|
| 196 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">g_CSBytecode</VariableName>
|
| 197 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CompiledComputeShader.h</HeaderFileOutput>
|
| 198 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">g_CSBytecode</VariableName>
|
| 199 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CompiledComputeShader.h</HeaderFileOutput>
|
| 200 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">g_CSBytecode</VariableName>
|
| 201 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CompiledComputeShader.h</HeaderFileOutput>
|
| 202 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">g_CSBytecode</VariableName>
|
| 203 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CompiledComputeShader.h</HeaderFileOutput>
|
| 204 |
+
</FxCompile>
|
| 205 |
+
<FxCompile Include="PixelShader.hlsl">
|
| 206 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
|
| 207 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
|
| 208 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
|
| 209 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
|
| 210 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">5.0</ShaderModel>
|
| 211 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel>
|
| 212 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">5.0</ShaderModel>
|
| 213 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">5.0</ShaderModel>
|
| 214 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CompiledPixelShader.h</HeaderFileOutput>
|
| 215 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CompiledPixelShader.h</HeaderFileOutput>
|
| 216 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CompiledPixelShader.h</HeaderFileOutput>
|
| 217 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CompiledPixelShader.h</HeaderFileOutput>
|
| 218 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">g_PSBytecode</VariableName>
|
| 219 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">g_PSBytecode</VariableName>
|
| 220 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">g_PSBytecode</VariableName>
|
| 221 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">g_PSBytecode</VariableName>
|
| 222 |
+
</FxCompile>
|
| 223 |
+
<FxCompile Include="VertexShader.hlsl">
|
| 224 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType>
|
| 225 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
|
| 226 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType>
|
| 227 |
+
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
|
| 228 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">5.0</ShaderModel>
|
| 229 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">5.0</ShaderModel>
|
| 230 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">5.0</ShaderModel>
|
| 231 |
+
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">5.0</ShaderModel>
|
| 232 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CompiledVertexShader.h</HeaderFileOutput>
|
| 233 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CompiledVertexShader.h</HeaderFileOutput>
|
| 234 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CompiledVertexShader.h</HeaderFileOutput>
|
| 235 |
+
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CompiledVertexShader.h</HeaderFileOutput>
|
| 236 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">g_VSBytecode</VariableName>
|
| 237 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">g_VSBytecode</VariableName>
|
| 238 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">g_VSBytecode</VariableName>
|
| 239 |
+
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">g_VSBytecode</VariableName>
|
| 240 |
+
</FxCompile>
|
| 241 |
+
</ItemGroup>
|
| 242 |
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
| 243 |
+
<ImportGroup Label="ExtensionTargets">
|
| 244 |
+
</ImportGroup>
|
| 245 |
+
</Project>
|
third_party/tracy/examples/ToyPathTracer/Windows/TestCpu.vcxproj.filters
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
| 2 |
+
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
| 3 |
+
<ItemGroup>
|
| 4 |
+
<ClCompile Include="TestWin.cpp" />
|
| 5 |
+
<ClCompile Include="..\Source\Test.cpp">
|
| 6 |
+
<Filter>Source</Filter>
|
| 7 |
+
</ClCompile>
|
| 8 |
+
<ClCompile Include="..\Source\enkiTS\TaskScheduler.cpp">
|
| 9 |
+
<Filter>Source\enkiTS</Filter>
|
| 10 |
+
</ClCompile>
|
| 11 |
+
<ClCompile Include="..\Source\enkiTS\TaskScheduler_c.cpp">
|
| 12 |
+
<Filter>Source\enkiTS</Filter>
|
| 13 |
+
</ClCompile>
|
| 14 |
+
<ClCompile Include="..\Source\Maths.cpp">
|
| 15 |
+
<Filter>Source</Filter>
|
| 16 |
+
</ClCompile>
|
| 17 |
+
<ClCompile Include="..\..\..\public\TracyClient.cpp" />
|
| 18 |
+
</ItemGroup>
|
| 19 |
+
<ItemGroup>
|
| 20 |
+
<Filter Include="Source">
|
| 21 |
+
<UniqueIdentifier>{5f19f217-c1c7-4eeb-be61-8b986fee9375}</UniqueIdentifier>
|
| 22 |
+
</Filter>
|
| 23 |
+
<Filter Include="Source\enkiTS">
|
| 24 |
+
<UniqueIdentifier>{38c448a8-1dcc-4116-9410-a9f8d068caff}</UniqueIdentifier>
|
| 25 |
+
</Filter>
|
| 26 |
+
</ItemGroup>
|
| 27 |
+
<ItemGroup>
|
| 28 |
+
<ClInclude Include="..\Source\Test.h">
|
| 29 |
+
<Filter>Source</Filter>
|
| 30 |
+
</ClInclude>
|
| 31 |
+
<ClInclude Include="..\Source\stb_image.h">
|
| 32 |
+
<Filter>Source</Filter>
|
| 33 |
+
</ClInclude>
|
| 34 |
+
<ClInclude Include="..\Source\enkiTS\Atomics.h">
|
| 35 |
+
<Filter>Source\enkiTS</Filter>
|
| 36 |
+
</ClInclude>
|
| 37 |
+
<ClInclude Include="..\Source\enkiTS\LockLessMultiReadPipe.h">
|
| 38 |
+
<Filter>Source\enkiTS</Filter>
|
| 39 |
+
</ClInclude>
|
| 40 |
+
<ClInclude Include="..\Source\enkiTS\TaskScheduler.h">
|
| 41 |
+
<Filter>Source\enkiTS</Filter>
|
| 42 |
+
</ClInclude>
|
| 43 |
+
<ClInclude Include="..\Source\enkiTS\TaskScheduler_c.h">
|
| 44 |
+
<Filter>Source\enkiTS</Filter>
|
| 45 |
+
</ClInclude>
|
| 46 |
+
<ClInclude Include="..\Source\enkiTS\Threads.h">
|
| 47 |
+
<Filter>Source\enkiTS</Filter>
|
| 48 |
+
</ClInclude>
|
| 49 |
+
<ClInclude Include="..\Source\Maths.h">
|
| 50 |
+
<Filter>Source</Filter>
|
| 51 |
+
</ClInclude>
|
| 52 |
+
<ClInclude Include="..\Source\Config.h">
|
| 53 |
+
<Filter>Source</Filter>
|
| 54 |
+
</ClInclude>
|
| 55 |
+
<ClInclude Include="..\Source\MathSimd.h">
|
| 56 |
+
<Filter>Source</Filter>
|
| 57 |
+
</ClInclude>
|
| 58 |
+
</ItemGroup>
|
| 59 |
+
<ItemGroup>
|
| 60 |
+
<None Include="..\.editorconfig" />
|
| 61 |
+
</ItemGroup>
|
| 62 |
+
<ItemGroup>
|
| 63 |
+
<FxCompile Include="VertexShader.hlsl" />
|
| 64 |
+
<FxCompile Include="PixelShader.hlsl" />
|
| 65 |
+
<FxCompile Include="ComputeShader.hlsl" />
|
| 66 |
+
</ItemGroup>
|
| 67 |
+
</Project>
|
third_party/tracy/examples/ToyPathTracer/Windows/TestWin.cpp
ADDED
|
@@ -0,0 +1,567 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include <stdint.h>
|
| 2 |
+
#define WIN32_LEAN_AND_MEAN
|
| 3 |
+
#define NOMINMAX
|
| 4 |
+
#include <windows.h>
|
| 5 |
+
#include <d3d11_1.h>
|
| 6 |
+
|
| 7 |
+
#include <stdio.h>
|
| 8 |
+
#include <stdlib.h>
|
| 9 |
+
#include <time.h>
|
| 10 |
+
#include <algorithm>
|
| 11 |
+
|
| 12 |
+
#include "../Source/Config.h"
|
| 13 |
+
#include "../Source/Maths.h"
|
| 14 |
+
#include "../Source/Test.h"
|
| 15 |
+
#include "CompiledVertexShader.h"
|
| 16 |
+
#include "CompiledPixelShader.h"
|
| 17 |
+
|
| 18 |
+
#include "../../../public/tracy/Tracy.hpp"
|
| 19 |
+
#include "../../../public/tracy/TracyD3D11.hpp"
|
| 20 |
+
|
| 21 |
+
static HINSTANCE g_HInstance;
|
| 22 |
+
static HWND g_Wnd;
|
| 23 |
+
|
| 24 |
+
ATOM MyRegisterClass(HINSTANCE hInstance);
|
| 25 |
+
BOOL InitInstance(HINSTANCE, int);
|
| 26 |
+
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
| 27 |
+
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
|
| 28 |
+
|
| 29 |
+
static HRESULT InitD3DDevice();
|
| 30 |
+
static void ShutdownD3DDevice();
|
| 31 |
+
static void RenderFrame();
|
| 32 |
+
|
| 33 |
+
static float* g_Backbuffer;
|
| 34 |
+
|
| 35 |
+
static D3D_FEATURE_LEVEL g_D3D11FeatureLevel = D3D_FEATURE_LEVEL_11_0;
|
| 36 |
+
static ID3D11Device* g_D3D11Device = nullptr;
|
| 37 |
+
static ID3D11DeviceContext* g_D3D11Ctx = nullptr;
|
| 38 |
+
static IDXGISwapChain* g_D3D11SwapChain = nullptr;
|
| 39 |
+
static ID3D11RenderTargetView* g_D3D11RenderTarget = nullptr;
|
| 40 |
+
static ID3D11VertexShader* g_VertexShader;
|
| 41 |
+
static ID3D11PixelShader* g_PixelShader;
|
| 42 |
+
static ID3D11Texture2D *g_BackbufferTexture, *g_BackbufferTexture2;
|
| 43 |
+
static ID3D11ShaderResourceView *g_BackbufferSRV, *g_BackbufferSRV2;
|
| 44 |
+
static ID3D11UnorderedAccessView *g_BackbufferUAV, *g_BackbufferUAV2;
|
| 45 |
+
static ID3D11SamplerState* g_SamplerLinear;
|
| 46 |
+
static ID3D11RasterizerState* g_RasterState;
|
| 47 |
+
static int g_BackbufferIndex;
|
| 48 |
+
static tracy::D3D11Ctx *g_tracyCtx;
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
#if DO_COMPUTE_GPU
|
| 52 |
+
#include "CompiledComputeShader.h"
|
| 53 |
+
struct ComputeParams
|
| 54 |
+
{
|
| 55 |
+
Camera cam;
|
| 56 |
+
int sphereCount;
|
| 57 |
+
int screenWidth;
|
| 58 |
+
int screenHeight;
|
| 59 |
+
int frames;
|
| 60 |
+
float invWidth;
|
| 61 |
+
float invHeight;
|
| 62 |
+
float lerpFac;
|
| 63 |
+
int emissiveCount;
|
| 64 |
+
};
|
| 65 |
+
static ID3D11ComputeShader* g_ComputeShader;
|
| 66 |
+
static ID3D11Buffer* g_DataSpheres; static ID3D11ShaderResourceView* g_SRVSpheres;
|
| 67 |
+
static ID3D11Buffer* g_DataMaterials; static ID3D11ShaderResourceView* g_SRVMaterials;
|
| 68 |
+
static ID3D11Buffer* g_DataParams; static ID3D11ShaderResourceView* g_SRVParams;
|
| 69 |
+
static ID3D11Buffer* g_DataEmissives; static ID3D11ShaderResourceView* g_SRVEmissives;
|
| 70 |
+
static ID3D11Buffer* g_DataCounter; static ID3D11UnorderedAccessView* g_UAVCounter;
|
| 71 |
+
static int g_SphereCount, g_ObjSize, g_MatSize;
|
| 72 |
+
static ID3D11Query *g_QueryBegin, *g_QueryEnd, *g_QueryDisjoint;
|
| 73 |
+
#endif // #if DO_COMPUTE_GPU
|
| 74 |
+
|
| 75 |
+
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR, _In_ int nCmdShow)
|
| 76 |
+
{
|
| 77 |
+
g_Backbuffer = new float[kBackbufferWidth * kBackbufferHeight * 4];
|
| 78 |
+
memset(g_Backbuffer, 0, kBackbufferWidth * kBackbufferHeight * 4 * sizeof(g_Backbuffer[0]));
|
| 79 |
+
|
| 80 |
+
InitializeTest();
|
| 81 |
+
|
| 82 |
+
MyRegisterClass(hInstance);
|
| 83 |
+
if (!InitInstance (hInstance, nCmdShow))
|
| 84 |
+
{
|
| 85 |
+
return FALSE;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
if (FAILED(InitD3DDevice()))
|
| 89 |
+
{
|
| 90 |
+
ShutdownD3DDevice();
|
| 91 |
+
return 0;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
g_D3D11Device->CreateVertexShader(g_VSBytecode, ARRAYSIZE(g_VSBytecode), NULL, &g_VertexShader);
|
| 95 |
+
g_D3D11Device->CreatePixelShader(g_PSBytecode, ARRAYSIZE(g_PSBytecode), NULL, &g_PixelShader);
|
| 96 |
+
#if DO_COMPUTE_GPU
|
| 97 |
+
g_D3D11Device->CreateComputeShader(g_CSBytecode, ARRAYSIZE(g_CSBytecode), NULL, &g_ComputeShader);
|
| 98 |
+
#endif
|
| 99 |
+
|
| 100 |
+
D3D11_TEXTURE2D_DESC texDesc = {};
|
| 101 |
+
texDesc.Width = kBackbufferWidth;
|
| 102 |
+
texDesc.Height = kBackbufferHeight;
|
| 103 |
+
texDesc.MipLevels = 1;
|
| 104 |
+
texDesc.ArraySize = 1;
|
| 105 |
+
texDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
| 106 |
+
texDesc.SampleDesc.Count = 1;
|
| 107 |
+
texDesc.SampleDesc.Quality = 0;
|
| 108 |
+
#if DO_COMPUTE_GPU
|
| 109 |
+
texDesc.Usage = D3D11_USAGE_DEFAULT;
|
| 110 |
+
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
|
| 111 |
+
texDesc.CPUAccessFlags = 0;
|
| 112 |
+
#else
|
| 113 |
+
texDesc.Usage = D3D11_USAGE_DYNAMIC;
|
| 114 |
+
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
| 115 |
+
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
| 116 |
+
#endif
|
| 117 |
+
texDesc.MiscFlags = 0;
|
| 118 |
+
g_D3D11Device->CreateTexture2D(&texDesc, NULL, &g_BackbufferTexture);
|
| 119 |
+
g_D3D11Device->CreateTexture2D(&texDesc, NULL, &g_BackbufferTexture2);
|
| 120 |
+
|
| 121 |
+
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
| 122 |
+
srvDesc.Format = texDesc.Format;
|
| 123 |
+
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
| 124 |
+
srvDesc.Texture2D.MipLevels = 1;
|
| 125 |
+
srvDesc.Texture2D.MostDetailedMip = 0;
|
| 126 |
+
g_D3D11Device->CreateShaderResourceView(g_BackbufferTexture, &srvDesc, &g_BackbufferSRV);
|
| 127 |
+
g_D3D11Device->CreateShaderResourceView(g_BackbufferTexture2, &srvDesc, &g_BackbufferSRV2);
|
| 128 |
+
|
| 129 |
+
D3D11_SAMPLER_DESC smpDesc = {};
|
| 130 |
+
smpDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
| 131 |
+
smpDesc.AddressU = smpDesc.AddressV = smpDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
| 132 |
+
g_D3D11Device->CreateSamplerState(&smpDesc, &g_SamplerLinear);
|
| 133 |
+
|
| 134 |
+
D3D11_RASTERIZER_DESC rasterDesc = {};
|
| 135 |
+
rasterDesc.FillMode = D3D11_FILL_SOLID;
|
| 136 |
+
rasterDesc.CullMode = D3D11_CULL_NONE;
|
| 137 |
+
g_D3D11Device->CreateRasterizerState(&rasterDesc, &g_RasterState);
|
| 138 |
+
|
| 139 |
+
#if DO_COMPUTE_GPU
|
| 140 |
+
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
|
| 141 |
+
|
| 142 |
+
int camSize;
|
| 143 |
+
GetObjectCount(g_SphereCount, g_ObjSize, g_MatSize, camSize);
|
| 144 |
+
assert(g_ObjSize == 20);
|
| 145 |
+
assert(g_MatSize == 36);
|
| 146 |
+
assert(camSize == 88);
|
| 147 |
+
D3D11_BUFFER_DESC bdesc = {};
|
| 148 |
+
bdesc.ByteWidth = g_SphereCount * g_ObjSize;
|
| 149 |
+
bdesc.Usage = D3D11_USAGE_DEFAULT;
|
| 150 |
+
bdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
| 151 |
+
bdesc.CPUAccessFlags = 0;
|
| 152 |
+
bdesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
|
| 153 |
+
bdesc.StructureByteStride = g_ObjSize;
|
| 154 |
+
g_D3D11Device->CreateBuffer(&bdesc, NULL, &g_DataSpheres);
|
| 155 |
+
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
| 156 |
+
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
| 157 |
+
srvDesc.Buffer.FirstElement = 0;
|
| 158 |
+
srvDesc.Buffer.NumElements = g_SphereCount;
|
| 159 |
+
g_D3D11Device->CreateShaderResourceView(g_DataSpheres, &srvDesc, &g_SRVSpheres);
|
| 160 |
+
|
| 161 |
+
bdesc.ByteWidth = g_SphereCount * g_MatSize;
|
| 162 |
+
bdesc.StructureByteStride = g_MatSize;
|
| 163 |
+
g_D3D11Device->CreateBuffer(&bdesc, NULL, &g_DataMaterials);
|
| 164 |
+
srvDesc.Buffer.NumElements = g_SphereCount;
|
| 165 |
+
g_D3D11Device->CreateShaderResourceView(g_DataMaterials, &srvDesc, &g_SRVMaterials);
|
| 166 |
+
|
| 167 |
+
bdesc.ByteWidth = sizeof(ComputeParams);
|
| 168 |
+
bdesc.StructureByteStride = sizeof(ComputeParams);
|
| 169 |
+
g_D3D11Device->CreateBuffer(&bdesc, NULL, &g_DataParams);
|
| 170 |
+
srvDesc.Buffer.NumElements = 1;
|
| 171 |
+
g_D3D11Device->CreateShaderResourceView(g_DataParams, &srvDesc, &g_SRVParams);
|
| 172 |
+
|
| 173 |
+
bdesc.ByteWidth = g_SphereCount * 4;
|
| 174 |
+
bdesc.StructureByteStride = 4;
|
| 175 |
+
g_D3D11Device->CreateBuffer(&bdesc, NULL, &g_DataEmissives);
|
| 176 |
+
srvDesc.Buffer.NumElements = g_SphereCount;
|
| 177 |
+
g_D3D11Device->CreateShaderResourceView(g_DataEmissives, &srvDesc, &g_SRVEmissives);
|
| 178 |
+
|
| 179 |
+
bdesc.ByteWidth = 4;
|
| 180 |
+
bdesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
|
| 181 |
+
bdesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
|
| 182 |
+
bdesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
| 183 |
+
g_D3D11Device->CreateBuffer(&bdesc, NULL, &g_DataCounter);
|
| 184 |
+
uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
|
| 185 |
+
uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
| 186 |
+
uavDesc.Buffer.FirstElement = 0;
|
| 187 |
+
uavDesc.Buffer.NumElements = 1;
|
| 188 |
+
uavDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
|
| 189 |
+
g_D3D11Device->CreateUnorderedAccessView(g_DataCounter, &uavDesc, &g_UAVCounter);
|
| 190 |
+
|
| 191 |
+
uavDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
| 192 |
+
uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
|
| 193 |
+
uavDesc.Texture2D.MipSlice = 0;
|
| 194 |
+
g_D3D11Device->CreateUnorderedAccessView(g_BackbufferTexture, &uavDesc, &g_BackbufferUAV);
|
| 195 |
+
g_D3D11Device->CreateUnorderedAccessView(g_BackbufferTexture2, &uavDesc, &g_BackbufferUAV2);
|
| 196 |
+
|
| 197 |
+
D3D11_QUERY_DESC qDesc = {};
|
| 198 |
+
qDesc.Query = D3D11_QUERY_TIMESTAMP;
|
| 199 |
+
g_D3D11Device->CreateQuery(&qDesc, &g_QueryBegin);
|
| 200 |
+
g_D3D11Device->CreateQuery(&qDesc, &g_QueryEnd);
|
| 201 |
+
qDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
| 202 |
+
g_D3D11Device->CreateQuery(&qDesc, &g_QueryDisjoint);
|
| 203 |
+
#endif // #if DO_COMPUTE_GPU
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
static int framesLeft = 10;
|
| 207 |
+
|
| 208 |
+
// Main message loop
|
| 209 |
+
MSG msg = { 0 };
|
| 210 |
+
while (msg.message != WM_QUIT)
|
| 211 |
+
{
|
| 212 |
+
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
| 213 |
+
{
|
| 214 |
+
TranslateMessage(&msg);
|
| 215 |
+
DispatchMessage(&msg);
|
| 216 |
+
}
|
| 217 |
+
else
|
| 218 |
+
{
|
| 219 |
+
RenderFrame();
|
| 220 |
+
TracyD3D11Collect(g_tracyCtx);
|
| 221 |
+
if( --framesLeft == 0 ) break;
|
| 222 |
+
}
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
ShutdownTest();
|
| 226 |
+
ShutdownD3DDevice();
|
| 227 |
+
|
| 228 |
+
return (int) msg.wParam;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
ATOM MyRegisterClass(HINSTANCE hInstance)
|
| 233 |
+
{
|
| 234 |
+
ZoneScoped;
|
| 235 |
+
|
| 236 |
+
WNDCLASSEXW wcex;
|
| 237 |
+
memset(&wcex, 0, sizeof(wcex));
|
| 238 |
+
wcex.cbSize = sizeof(WNDCLASSEX);
|
| 239 |
+
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
| 240 |
+
wcex.lpfnWndProc = WndProc;
|
| 241 |
+
wcex.cbClsExtra = 0;
|
| 242 |
+
wcex.cbWndExtra = 0;
|
| 243 |
+
wcex.hInstance = hInstance;
|
| 244 |
+
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
| 245 |
+
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
| 246 |
+
wcex.lpszClassName = L"TestClass";
|
| 247 |
+
return RegisterClassExW(&wcex);
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
|
| 251 |
+
{
|
| 252 |
+
ZoneScoped;
|
| 253 |
+
|
| 254 |
+
g_HInstance = hInstance;
|
| 255 |
+
RECT rc = { 0, 0, kBackbufferWidth, kBackbufferHeight };
|
| 256 |
+
DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
| 257 |
+
AdjustWindowRect(&rc, style, FALSE);
|
| 258 |
+
HWND hWnd = CreateWindowW(L"TestClass", L"Test", style, CW_USEDEFAULT, CW_USEDEFAULT, rc.right-rc.left, rc.bottom-rc.top, nullptr, nullptr, hInstance, nullptr);
|
| 259 |
+
if (!hWnd)
|
| 260 |
+
return FALSE;
|
| 261 |
+
g_Wnd = hWnd;
|
| 262 |
+
ShowWindow(hWnd, nCmdShow);
|
| 263 |
+
UpdateWindow(hWnd);
|
| 264 |
+
return TRUE;
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
static uint64_t s_Time;
|
| 268 |
+
static int s_Count;
|
| 269 |
+
static char s_Buffer[200];
|
| 270 |
+
static unsigned s_Flags = kFlagProgressive;
|
| 271 |
+
static int s_FrameCount = 0;
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
static void RenderFrame()
|
| 275 |
+
{
|
| 276 |
+
ZoneScoped;
|
| 277 |
+
TracyD3D11Zone(g_tracyCtx, "RenderFrame");
|
| 278 |
+
|
| 279 |
+
LARGE_INTEGER time1;
|
| 280 |
+
|
| 281 |
+
#if DO_COMPUTE_GPU
|
| 282 |
+
QueryPerformanceCounter(&time1);
|
| 283 |
+
float t = float(clock()) / CLOCKS_PER_SEC;
|
| 284 |
+
UpdateTest(t, s_FrameCount, kBackbufferWidth, kBackbufferHeight, s_Flags);
|
| 285 |
+
|
| 286 |
+
g_BackbufferIndex = 1 - g_BackbufferIndex;
|
| 287 |
+
void* dataSpheres = alloca(g_SphereCount * g_ObjSize);
|
| 288 |
+
void* dataMaterials = alloca(g_SphereCount * g_MatSize);
|
| 289 |
+
void* dataEmissives = alloca(g_SphereCount * 4);
|
| 290 |
+
ComputeParams dataParams;
|
| 291 |
+
GetSceneDesc(dataSpheres, dataMaterials, &dataParams.cam, dataEmissives, &dataParams.emissiveCount);
|
| 292 |
+
|
| 293 |
+
dataParams.sphereCount = g_SphereCount;
|
| 294 |
+
dataParams.screenWidth = kBackbufferWidth;
|
| 295 |
+
dataParams.screenHeight = kBackbufferHeight;
|
| 296 |
+
dataParams.frames = s_FrameCount;
|
| 297 |
+
dataParams.invWidth = 1.0f / kBackbufferWidth;
|
| 298 |
+
dataParams.invHeight = 1.0f / kBackbufferHeight;
|
| 299 |
+
float lerpFac = float(s_FrameCount) / float(s_FrameCount + 1);
|
| 300 |
+
if (s_Flags & kFlagAnimate)
|
| 301 |
+
lerpFac *= DO_ANIMATE_SMOOTHING;
|
| 302 |
+
if (!(s_Flags & kFlagProgressive))
|
| 303 |
+
lerpFac = 0;
|
| 304 |
+
dataParams.lerpFac = lerpFac;
|
| 305 |
+
|
| 306 |
+
g_D3D11Ctx->UpdateSubresource(g_DataSpheres, 0, NULL, dataSpheres, 0, 0);
|
| 307 |
+
g_D3D11Ctx->UpdateSubresource(g_DataMaterials, 0, NULL, dataMaterials, 0, 0);
|
| 308 |
+
g_D3D11Ctx->UpdateSubresource(g_DataParams, 0, NULL, &dataParams, 0, 0);
|
| 309 |
+
g_D3D11Ctx->UpdateSubresource(g_DataEmissives, 0, NULL, dataEmissives, 0, 0);
|
| 310 |
+
|
| 311 |
+
ID3D11ShaderResourceView* srvs[] = {
|
| 312 |
+
g_BackbufferIndex == 0 ? g_BackbufferSRV2 : g_BackbufferSRV,
|
| 313 |
+
g_SRVSpheres,
|
| 314 |
+
g_SRVMaterials,
|
| 315 |
+
g_SRVParams,
|
| 316 |
+
g_SRVEmissives
|
| 317 |
+
};
|
| 318 |
+
g_D3D11Ctx->CSSetShaderResources(0, ARRAYSIZE(srvs), srvs);
|
| 319 |
+
ID3D11UnorderedAccessView* uavs[] = {
|
| 320 |
+
g_BackbufferIndex == 0 ? g_BackbufferUAV : g_BackbufferUAV2,
|
| 321 |
+
g_UAVCounter
|
| 322 |
+
};
|
| 323 |
+
g_D3D11Ctx->CSSetUnorderedAccessViews(0, ARRAYSIZE(uavs), uavs, NULL);
|
| 324 |
+
g_D3D11Ctx->CSSetShader(g_ComputeShader, NULL, 0);
|
| 325 |
+
g_D3D11Ctx->Begin(g_QueryDisjoint);
|
| 326 |
+
g_D3D11Ctx->End(g_QueryBegin);
|
| 327 |
+
g_D3D11Ctx->Dispatch(kBackbufferWidth/kCSGroupSizeX, kBackbufferHeight/kCSGroupSizeY, 1);
|
| 328 |
+
g_D3D11Ctx->End(g_QueryEnd);
|
| 329 |
+
uavs[0] = NULL;
|
| 330 |
+
g_D3D11Ctx->CSSetUnorderedAccessViews(0, ARRAYSIZE(uavs), uavs, NULL);
|
| 331 |
+
++s_FrameCount;
|
| 332 |
+
|
| 333 |
+
#else
|
| 334 |
+
QueryPerformanceCounter(&time1);
|
| 335 |
+
float t = float(clock()) / CLOCKS_PER_SEC;
|
| 336 |
+
static size_t s_RayCounter = 0;
|
| 337 |
+
int rayCount;
|
| 338 |
+
UpdateTest(t, s_FrameCount, kBackbufferWidth, kBackbufferHeight, s_Flags);
|
| 339 |
+
DrawTest(t, s_FrameCount, kBackbufferWidth, kBackbufferHeight, g_Backbuffer, rayCount, s_Flags);
|
| 340 |
+
s_FrameCount++;
|
| 341 |
+
s_RayCounter += rayCount;
|
| 342 |
+
LARGE_INTEGER time2;
|
| 343 |
+
QueryPerformanceCounter(&time2);
|
| 344 |
+
uint64_t dt = time2.QuadPart - time1.QuadPart;
|
| 345 |
+
++s_Count;
|
| 346 |
+
s_Time += dt;
|
| 347 |
+
if (s_Count > 10)
|
| 348 |
+
{
|
| 349 |
+
LARGE_INTEGER frequency;
|
| 350 |
+
QueryPerformanceFrequency(&frequency);
|
| 351 |
+
|
| 352 |
+
double s = double(s_Time) / double(frequency.QuadPart) / s_Count;
|
| 353 |
+
sprintf_s(s_Buffer, sizeof(s_Buffer), "%.2fms (%.1f FPS) %.1fMrays/s %.2fMrays/frame frames %i\n", s * 1000.0f, 1.f / s, s_RayCounter / s_Count / s * 1.0e-6f, s_RayCounter / s_Count * 1.0e-6f, s_FrameCount);
|
| 354 |
+
SetWindowTextA(g_Wnd, s_Buffer);
|
| 355 |
+
OutputDebugStringA(s_Buffer);
|
| 356 |
+
s_Count = 0;
|
| 357 |
+
s_Time = 0;
|
| 358 |
+
s_RayCounter = 0;
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
D3D11_MAPPED_SUBRESOURCE mapped;
|
| 362 |
+
g_D3D11Ctx->Map(g_BackbufferTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
| 363 |
+
const uint8_t* src = (const uint8_t*)g_Backbuffer;
|
| 364 |
+
uint8_t* dst = (uint8_t*)mapped.pData;
|
| 365 |
+
for (int y = 0; y < kBackbufferHeight; ++y)
|
| 366 |
+
{
|
| 367 |
+
memcpy(dst, src, kBackbufferWidth * 16);
|
| 368 |
+
src += kBackbufferWidth * 16;
|
| 369 |
+
dst += mapped.RowPitch;
|
| 370 |
+
}
|
| 371 |
+
g_D3D11Ctx->Unmap(g_BackbufferTexture, 0);
|
| 372 |
+
#endif
|
| 373 |
+
|
| 374 |
+
g_D3D11Ctx->VSSetShader(g_VertexShader, NULL, 0);
|
| 375 |
+
g_D3D11Ctx->PSSetShader(g_PixelShader, NULL, 0);
|
| 376 |
+
g_D3D11Ctx->PSSetShaderResources(0, 1, g_BackbufferIndex == 0 ? &g_BackbufferSRV : &g_BackbufferSRV2);
|
| 377 |
+
g_D3D11Ctx->PSSetSamplers(0, 1, &g_SamplerLinear);
|
| 378 |
+
g_D3D11Ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
| 379 |
+
g_D3D11Ctx->RSSetState(g_RasterState);
|
| 380 |
+
g_D3D11Ctx->Draw(3, 0);
|
| 381 |
+
g_D3D11SwapChain->Present(0, 0);
|
| 382 |
+
|
| 383 |
+
FrameMark;
|
| 384 |
+
|
| 385 |
+
#if DO_COMPUTE_GPU
|
| 386 |
+
g_D3D11Ctx->End(g_QueryDisjoint);
|
| 387 |
+
|
| 388 |
+
// get GPU times
|
| 389 |
+
while (g_D3D11Ctx->GetData(g_QueryDisjoint, NULL, 0, 0) == S_FALSE) { Sleep(0); }
|
| 390 |
+
D3D10_QUERY_DATA_TIMESTAMP_DISJOINT tsDisjoint;
|
| 391 |
+
g_D3D11Ctx->GetData(g_QueryDisjoint, &tsDisjoint, sizeof(tsDisjoint), 0);
|
| 392 |
+
if (!tsDisjoint.Disjoint)
|
| 393 |
+
{
|
| 394 |
+
UINT64 tsBegin, tsEnd;
|
| 395 |
+
// Note: on some GPUs/drivers, even when the disjoint query above already said "yeah I have data",
|
| 396 |
+
// might still not return "I have data" for timestamp queries before it.
|
| 397 |
+
while (g_D3D11Ctx->GetData(g_QueryBegin, &tsBegin, sizeof(tsBegin), 0) == S_FALSE) { Sleep(0); }
|
| 398 |
+
while (g_D3D11Ctx->GetData(g_QueryEnd, &tsEnd, sizeof(tsEnd), 0) == S_FALSE) { Sleep(0); }
|
| 399 |
+
|
| 400 |
+
float s = float(tsEnd - tsBegin) / float(tsDisjoint.Frequency);
|
| 401 |
+
|
| 402 |
+
static uint64_t s_RayCounter;
|
| 403 |
+
D3D11_MAPPED_SUBRESOURCE mapped;
|
| 404 |
+
g_D3D11Ctx->Map(g_DataCounter, 0, D3D11_MAP_READ, 0, &mapped);
|
| 405 |
+
s_RayCounter += *(const int*)mapped.pData;
|
| 406 |
+
g_D3D11Ctx->Unmap(g_DataCounter, 0);
|
| 407 |
+
int zeroCount = 0;
|
| 408 |
+
g_D3D11Ctx->UpdateSubresource(g_DataCounter, 0, NULL, &zeroCount, 0, 0);
|
| 409 |
+
|
| 410 |
+
static float s_Time;
|
| 411 |
+
++s_Count;
|
| 412 |
+
s_Time += s;
|
| 413 |
+
if (s_Count > 150)
|
| 414 |
+
{
|
| 415 |
+
s = s_Time / s_Count;
|
| 416 |
+
sprintf_s(s_Buffer, sizeof(s_Buffer), "%.2fms (%.1f FPS) %.1fMrays/s %.2fMrays/frame frames %i\n", s * 1000.0f, 1.f / s, s_RayCounter / s_Count / s * 1.0e-6f, s_RayCounter / s_Count * 1.0e-6f, s_FrameCount);
|
| 417 |
+
SetWindowTextA(g_Wnd, s_Buffer);
|
| 418 |
+
s_Count = 0;
|
| 419 |
+
s_Time = 0;
|
| 420 |
+
s_RayCounter = 0;
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
}
|
| 424 |
+
#endif // #if DO_COMPUTE_GPU
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
|
| 428 |
+
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
| 429 |
+
{
|
| 430 |
+
switch (message)
|
| 431 |
+
{
|
| 432 |
+
case WM_PAINT:
|
| 433 |
+
{
|
| 434 |
+
PAINTSTRUCT ps;
|
| 435 |
+
HDC hdc = BeginPaint(hWnd, &ps);
|
| 436 |
+
EndPaint(hWnd, &ps);
|
| 437 |
+
}
|
| 438 |
+
break;
|
| 439 |
+
case WM_DESTROY:
|
| 440 |
+
PostQuitMessage(0);
|
| 441 |
+
break;
|
| 442 |
+
case WM_CHAR:
|
| 443 |
+
if (wParam == 'a')
|
| 444 |
+
s_Flags = s_Flags ^ kFlagAnimate;
|
| 445 |
+
if (wParam == 'p')
|
| 446 |
+
{
|
| 447 |
+
s_Flags = s_Flags ^ kFlagProgressive;
|
| 448 |
+
s_FrameCount = 0;
|
| 449 |
+
}
|
| 450 |
+
break;
|
| 451 |
+
default:
|
| 452 |
+
return DefWindowProc(hWnd, message, wParam, lParam);
|
| 453 |
+
}
|
| 454 |
+
return 0;
|
| 455 |
+
}
|
| 456 |
+
|
| 457 |
+
|
| 458 |
+
static HRESULT InitD3DDevice()
|
| 459 |
+
{
|
| 460 |
+
ZoneScoped;
|
| 461 |
+
|
| 462 |
+
HRESULT hr = S_OK;
|
| 463 |
+
|
| 464 |
+
RECT rc;
|
| 465 |
+
GetClientRect(g_Wnd, &rc);
|
| 466 |
+
UINT width = rc.right - rc.left;
|
| 467 |
+
UINT height = rc.bottom - rc.top;
|
| 468 |
+
|
| 469 |
+
UINT createDeviceFlags = 0;
|
| 470 |
+
#ifdef _DEBUG
|
| 471 |
+
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
| 472 |
+
#endif
|
| 473 |
+
|
| 474 |
+
D3D_FEATURE_LEVEL featureLevels[] =
|
| 475 |
+
{
|
| 476 |
+
D3D_FEATURE_LEVEL_11_0,
|
| 477 |
+
};
|
| 478 |
+
UINT numFeatureLevels = ARRAYSIZE(featureLevels);
|
| 479 |
+
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &g_D3D11Device, &g_D3D11FeatureLevel, &g_D3D11Ctx);
|
| 480 |
+
if (FAILED(hr))
|
| 481 |
+
return hr;
|
| 482 |
+
|
| 483 |
+
// Get DXGI factory
|
| 484 |
+
IDXGIFactory1* dxgiFactory = nullptr;
|
| 485 |
+
{
|
| 486 |
+
IDXGIDevice* dxgiDevice = nullptr;
|
| 487 |
+
hr = g_D3D11Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
|
| 488 |
+
if (SUCCEEDED(hr))
|
| 489 |
+
{
|
| 490 |
+
IDXGIAdapter* adapter = nullptr;
|
| 491 |
+
hr = dxgiDevice->GetAdapter(&adapter);
|
| 492 |
+
if (SUCCEEDED(hr))
|
| 493 |
+
{
|
| 494 |
+
hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory));
|
| 495 |
+
adapter->Release();
|
| 496 |
+
}
|
| 497 |
+
dxgiDevice->Release();
|
| 498 |
+
}
|
| 499 |
+
}
|
| 500 |
+
if (FAILED(hr))
|
| 501 |
+
return hr;
|
| 502 |
+
|
| 503 |
+
// Create swap chain
|
| 504 |
+
DXGI_SWAP_CHAIN_DESC sd;
|
| 505 |
+
ZeroMemory(&sd, sizeof(sd));
|
| 506 |
+
sd.BufferCount = 1;
|
| 507 |
+
sd.BufferDesc.Width = width;
|
| 508 |
+
sd.BufferDesc.Height = height;
|
| 509 |
+
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
| 510 |
+
sd.BufferDesc.RefreshRate.Numerator = 60;
|
| 511 |
+
sd.BufferDesc.RefreshRate.Denominator = 1;
|
| 512 |
+
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
| 513 |
+
sd.OutputWindow = g_Wnd;
|
| 514 |
+
sd.SampleDesc.Count = 1;
|
| 515 |
+
sd.SampleDesc.Quality = 0;
|
| 516 |
+
sd.Windowed = TRUE;
|
| 517 |
+
hr = dxgiFactory->CreateSwapChain(g_D3D11Device, &sd, &g_D3D11SwapChain);
|
| 518 |
+
|
| 519 |
+
// Prevent Alt-Enter
|
| 520 |
+
dxgiFactory->MakeWindowAssociation(g_Wnd, DXGI_MWA_NO_ALT_ENTER);
|
| 521 |
+
dxgiFactory->Release();
|
| 522 |
+
|
| 523 |
+
if (FAILED(hr))
|
| 524 |
+
return hr;
|
| 525 |
+
|
| 526 |
+
// RTV
|
| 527 |
+
ID3D11Texture2D* pBackBuffer = nullptr;
|
| 528 |
+
hr = g_D3D11SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer));
|
| 529 |
+
if (FAILED(hr))
|
| 530 |
+
return hr;
|
| 531 |
+
hr = g_D3D11Device->CreateRenderTargetView(pBackBuffer, nullptr, &g_D3D11RenderTarget);
|
| 532 |
+
pBackBuffer->Release();
|
| 533 |
+
if (FAILED(hr))
|
| 534 |
+
return hr;
|
| 535 |
+
|
| 536 |
+
g_D3D11Ctx->OMSetRenderTargets(1, &g_D3D11RenderTarget, nullptr);
|
| 537 |
+
|
| 538 |
+
// Viewport
|
| 539 |
+
D3D11_VIEWPORT vp;
|
| 540 |
+
vp.Width = (float)width;
|
| 541 |
+
vp.Height = (float)height;
|
| 542 |
+
vp.MinDepth = 0.0f;
|
| 543 |
+
vp.MaxDepth = 1.0f;
|
| 544 |
+
vp.TopLeftX = 0;
|
| 545 |
+
vp.TopLeftY = 0;
|
| 546 |
+
g_D3D11Ctx->RSSetViewports(1, &vp);
|
| 547 |
+
|
| 548 |
+
g_tracyCtx = TracyD3D11Context(g_D3D11Device, g_D3D11Ctx);
|
| 549 |
+
const char* tracyD3D11CtxName = "D3D11";
|
| 550 |
+
TracyD3D11ContextName(g_tracyCtx, tracyD3D11CtxName, (uint16_t)strlen(tracyD3D11CtxName));
|
| 551 |
+
|
| 552 |
+
return S_OK;
|
| 553 |
+
}
|
| 554 |
+
|
| 555 |
+
static void ShutdownD3DDevice()
|
| 556 |
+
{
|
| 557 |
+
ZoneScoped;
|
| 558 |
+
|
| 559 |
+
if (g_tracyCtx) TracyD3D11Destroy(g_tracyCtx);
|
| 560 |
+
|
| 561 |
+
if (g_D3D11Ctx) g_D3D11Ctx->ClearState();
|
| 562 |
+
|
| 563 |
+
if (g_D3D11RenderTarget) g_D3D11RenderTarget->Release();
|
| 564 |
+
if (g_D3D11SwapChain) g_D3D11SwapChain->Release();
|
| 565 |
+
if (g_D3D11Ctx) g_D3D11Ctx->Release();
|
| 566 |
+
if (g_D3D11Device) g_D3D11Device->Release();
|
| 567 |
+
}
|
third_party/tracy/examples/ToyPathTracer/Windows/VertexShader.hlsl
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
struct vs2ps
|
| 2 |
+
{
|
| 3 |
+
float2 uv : TEXCOORD0;
|
| 4 |
+
float4 pos : SV_Position;
|
| 5 |
+
};
|
| 6 |
+
|
| 7 |
+
vs2ps main(uint vid : SV_VertexID)
|
| 8 |
+
{
|
| 9 |
+
vs2ps o;
|
| 10 |
+
o.uv = float2((vid << 1) & 2, vid & 2);
|
| 11 |
+
o.pos = float4(o.uv * float2(2, 2) + float2(-1, -1), 0, 1);
|
| 12 |
+
return o;
|
| 13 |
+
}
|
third_party/tracy/examples/ToyPathTracer/license.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
This is free and unencumbered software released into the public domain.
|
| 2 |
+
|
| 3 |
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
| 4 |
+
distribute this software, either in source code form or as a compiled
|
| 5 |
+
binary, for any purpose, commercial or non-commercial, and by any
|
| 6 |
+
means.
|
| 7 |
+
|
| 8 |
+
In jurisdictions that recognize copyright laws, the author or authors
|
| 9 |
+
of this software dedicate any and all copyright interest in the
|
| 10 |
+
software to the public domain. We make this dedication for the benefit
|
| 11 |
+
of the public at large and to the detriment of our heirs and
|
| 12 |
+
successors. We intend this dedication to be an overt act of
|
| 13 |
+
relinquishment in perpetuity of all present and future rights to this
|
| 14 |
+
software under copyright law.
|
| 15 |
+
|
| 16 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 17 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| 18 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
| 19 |
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
| 20 |
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
| 21 |
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
| 22 |
+
OTHER DEALINGS IN THE SOFTWARE.
|
| 23 |
+
|
| 24 |
+
For more information, please refer to <http://unlicense.org>
|
third_party/tracy/examples/fibers.cpp
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// g++ fibers.cpp ../public/TracyClient.cpp -I../public/tracy -DTRACY_ENABLE -DTRACY_FIBERS -lpthread -ldl
|
| 2 |
+
|
| 3 |
+
#include <thread>
|
| 4 |
+
#include <unistd.h>
|
| 5 |
+
|
| 6 |
+
#include "Tracy.hpp"
|
| 7 |
+
#include "TracyC.h"
|
| 8 |
+
|
| 9 |
+
const char* fiber = "job1";
|
| 10 |
+
TracyCZoneCtx zone;
|
| 11 |
+
|
| 12 |
+
int main()
|
| 13 |
+
{
|
| 14 |
+
std::thread t1( [] {
|
| 15 |
+
TracyFiberEnter( fiber );
|
| 16 |
+
TracyCZone( ctx, 1 );
|
| 17 |
+
zone = ctx;
|
| 18 |
+
sleep( 1 );
|
| 19 |
+
TracyFiberLeave;
|
| 20 |
+
});
|
| 21 |
+
t1.join();
|
| 22 |
+
|
| 23 |
+
std::thread t2( [] {
|
| 24 |
+
TracyFiberEnter( fiber );
|
| 25 |
+
sleep( 1 );
|
| 26 |
+
TracyCZoneEnd( zone );
|
| 27 |
+
TracyFiberLeave;
|
| 28 |
+
});
|
| 29 |
+
t2.join();
|
| 30 |
+
}
|
third_party/tracy/public/TracyClient.cpp
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
//
|
| 2 |
+
// Tracy profiler
|
| 3 |
+
// ----------------
|
| 4 |
+
//
|
| 5 |
+
// For fast integration, compile and
|
| 6 |
+
// link with this source file (and none
|
| 7 |
+
// other) in your executable (or in the
|
| 8 |
+
// main DLL / shared object on multi-DLL
|
| 9 |
+
// projects).
|
| 10 |
+
//
|
| 11 |
+
|
| 12 |
+
// Define TRACY_ENABLE to enable profiler.
|
| 13 |
+
|
| 14 |
+
#include "common/TracySystem.cpp"
|
| 15 |
+
|
| 16 |
+
#ifdef TRACY_ENABLE
|
| 17 |
+
|
| 18 |
+
#ifdef _MSC_VER
|
| 19 |
+
# pragma warning(push, 0)
|
| 20 |
+
#endif
|
| 21 |
+
|
| 22 |
+
#include "common/tracy_lz4.cpp"
|
| 23 |
+
#include "client/TracyProfiler.cpp"
|
| 24 |
+
#include "client/TracyCallstack.cpp"
|
| 25 |
+
#include "client/TracySysPower.cpp"
|
| 26 |
+
#include "client/TracySysTime.cpp"
|
| 27 |
+
#include "client/TracySysTrace.cpp"
|
| 28 |
+
#include "common/TracySocket.cpp"
|
| 29 |
+
#include "client/tracy_rpmalloc.cpp"
|
| 30 |
+
#include "client/TracyDxt1.cpp"
|
| 31 |
+
#include "client/TracyAlloc.cpp"
|
| 32 |
+
#include "client/TracyOverride.cpp"
|
| 33 |
+
#include "client/TracyKCore.cpp"
|
| 34 |
+
|
| 35 |
+
#if defined(TRACY_HAS_CALLSTACK)
|
| 36 |
+
# if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
|
| 37 |
+
# include "libbacktrace/alloc.cpp"
|
| 38 |
+
# include "libbacktrace/dwarf.cpp"
|
| 39 |
+
# include "libbacktrace/fileline.cpp"
|
| 40 |
+
# include "libbacktrace/mmapio.cpp"
|
| 41 |
+
# include "libbacktrace/posix.cpp"
|
| 42 |
+
# include "libbacktrace/sort.cpp"
|
| 43 |
+
# include "libbacktrace/state.cpp"
|
| 44 |
+
# if TRACY_HAS_CALLSTACK == 4
|
| 45 |
+
# include "libbacktrace/macho.cpp"
|
| 46 |
+
# else
|
| 47 |
+
# include "libbacktrace/elf.cpp"
|
| 48 |
+
# endif
|
| 49 |
+
# include "common/TracyStackFrames.cpp"
|
| 50 |
+
# endif
|
| 51 |
+
#endif
|
| 52 |
+
|
| 53 |
+
#ifdef _MSC_VER
|
| 54 |
+
# pragma comment(lib, "ws2_32.lib")
|
| 55 |
+
# pragma comment(lib, "dbghelp.lib")
|
| 56 |
+
# pragma comment(lib, "advapi32.lib")
|
| 57 |
+
# pragma comment(lib, "user32.lib")
|
| 58 |
+
# pragma warning(pop)
|
| 59 |
+
#endif
|
| 60 |
+
|
| 61 |
+
#endif
|
third_party/tracy/public/libbacktrace/alloc.cpp
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* alloc.c -- Memory allocation without mmap.
|
| 2 |
+
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
| 3 |
+
Written by Ian Lance Taylor, Google.
|
| 4 |
+
|
| 5 |
+
Redistribution and use in source and binary forms, with or without
|
| 6 |
+
modification, are permitted provided that the following conditions are
|
| 7 |
+
met:
|
| 8 |
+
|
| 9 |
+
(1) Redistributions of source code must retain the above copyright
|
| 10 |
+
notice, this list of conditions and the following disclaimer.
|
| 11 |
+
|
| 12 |
+
(2) Redistributions in binary form must reproduce the above copyright
|
| 13 |
+
notice, this list of conditions and the following disclaimer in
|
| 14 |
+
the documentation and/or other materials provided with the
|
| 15 |
+
distribution.
|
| 16 |
+
|
| 17 |
+
(3) The name of the author may not be used to
|
| 18 |
+
endorse or promote products derived from this software without
|
| 19 |
+
specific prior written permission.
|
| 20 |
+
|
| 21 |
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
| 22 |
+
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| 23 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 24 |
+
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
| 25 |
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| 26 |
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
| 27 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
| 28 |
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
| 29 |
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
| 30 |
+
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
| 31 |
+
POSSIBILITY OF SUCH DAMAGE. */
|
| 32 |
+
|
| 33 |
+
#include "config.h"
|
| 34 |
+
|
| 35 |
+
#include <errno.h>
|
| 36 |
+
#include <stdlib.h>
|
| 37 |
+
#include <sys/types.h>
|
| 38 |
+
|
| 39 |
+
#include "backtrace.hpp"
|
| 40 |
+
#include "internal.hpp"
|
| 41 |
+
|
| 42 |
+
#include "../common/TracyAlloc.hpp"
|
| 43 |
+
|
| 44 |
+
namespace tracy
|
| 45 |
+
{
|
| 46 |
+
|
| 47 |
+
/* Allocation routines to use on systems that do not support anonymous
|
| 48 |
+
mmap. This implementation just uses malloc, which means that the
|
| 49 |
+
backtrace functions may not be safely invoked from a signal
|
| 50 |
+
handler. */
|
| 51 |
+
|
| 52 |
+
/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
|
| 53 |
+
report an error. */
|
| 54 |
+
|
| 55 |
+
void *
|
| 56 |
+
backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
| 57 |
+
size_t size, backtrace_error_callback error_callback,
|
| 58 |
+
void *data)
|
| 59 |
+
{
|
| 60 |
+
void *ret;
|
| 61 |
+
|
| 62 |
+
ret = tracy_malloc (size);
|
| 63 |
+
if (ret == NULL)
|
| 64 |
+
{
|
| 65 |
+
if (error_callback)
|
| 66 |
+
error_callback (data, "malloc", errno);
|
| 67 |
+
}
|
| 68 |
+
return ret;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
/* Free memory. */
|
| 72 |
+
|
| 73 |
+
void
|
| 74 |
+
backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
| 75 |
+
void *p, size_t size ATTRIBUTE_UNUSED,
|
| 76 |
+
backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
|
| 77 |
+
void *data ATTRIBUTE_UNUSED)
|
| 78 |
+
{
|
| 79 |
+
tracy_free (p);
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
/* Grow VEC by SIZE bytes. */
|
| 83 |
+
|
| 84 |
+
void *
|
| 85 |
+
backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
| 86 |
+
size_t size, backtrace_error_callback error_callback,
|
| 87 |
+
void *data, struct backtrace_vector *vec)
|
| 88 |
+
{
|
| 89 |
+
void *ret;
|
| 90 |
+
|
| 91 |
+
if (size > vec->alc)
|
| 92 |
+
{
|
| 93 |
+
size_t alc;
|
| 94 |
+
void *base;
|
| 95 |
+
|
| 96 |
+
if (vec->size == 0)
|
| 97 |
+
alc = 32 * size;
|
| 98 |
+
else if (vec->size >= 4096)
|
| 99 |
+
alc = vec->size + 4096;
|
| 100 |
+
else
|
| 101 |
+
alc = 2 * vec->size;
|
| 102 |
+
|
| 103 |
+
if (alc < vec->size + size)
|
| 104 |
+
alc = vec->size + size;
|
| 105 |
+
|
| 106 |
+
base = tracy_realloc (vec->base, alc);
|
| 107 |
+
if (base == NULL)
|
| 108 |
+
{
|
| 109 |
+
error_callback (data, "realloc", errno);
|
| 110 |
+
return NULL;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
vec->base = base;
|
| 114 |
+
vec->alc = alc - vec->size;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
ret = (char *) vec->base + vec->size;
|
| 118 |
+
vec->size += size;
|
| 119 |
+
vec->alc -= size;
|
| 120 |
+
return ret;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
/* Finish the current allocation on VEC. */
|
| 124 |
+
|
| 125 |
+
void *
|
| 126 |
+
backtrace_vector_finish (struct backtrace_state *state,
|
| 127 |
+
struct backtrace_vector *vec,
|
| 128 |
+
backtrace_error_callback error_callback,
|
| 129 |
+
void *data)
|
| 130 |
+
{
|
| 131 |
+
void *ret;
|
| 132 |
+
|
| 133 |
+
/* With this allocator we call realloc in backtrace_vector_grow,
|
| 134 |
+
which means we can't easily reuse the memory here. So just
|
| 135 |
+
release it. */
|
| 136 |
+
if (!backtrace_vector_release (state, vec, error_callback, data))
|
| 137 |
+
return NULL;
|
| 138 |
+
ret = vec->base;
|
| 139 |
+
vec->base = NULL;
|
| 140 |
+
vec->size = 0;
|
| 141 |
+
vec->alc = 0;
|
| 142 |
+
return ret;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
/* Release any extra space allocated for VEC. */
|
| 146 |
+
|
| 147 |
+
int
|
| 148 |
+
backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
| 149 |
+
struct backtrace_vector *vec,
|
| 150 |
+
backtrace_error_callback error_callback,
|
| 151 |
+
void *data)
|
| 152 |
+
{
|
| 153 |
+
vec->alc = 0;
|
| 154 |
+
|
| 155 |
+
if (vec->size == 0)
|
| 156 |
+
{
|
| 157 |
+
/* As of C17, realloc with size 0 is marked as an obsolescent feature, use
|
| 158 |
+
free instead. */
|
| 159 |
+
tracy_free (vec->base);
|
| 160 |
+
vec->base = NULL;
|
| 161 |
+
return 1;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
vec->base = tracy_realloc (vec->base, vec->size);
|
| 165 |
+
if (vec->base == NULL)
|
| 166 |
+
{
|
| 167 |
+
error_callback (data, "realloc", errno);
|
| 168 |
+
return 0;
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
return 1;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
}
|
third_party/tracy/public/libbacktrace/dwarf.cpp
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
third_party/tracy/public/libbacktrace/elf.cpp
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
third_party/tracy/public/libbacktrace/mmapio.cpp
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* mmapio.c -- File views using mmap.
|
| 2 |
+
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
| 3 |
+
Written by Ian Lance Taylor, Google.
|
| 4 |
+
|
| 5 |
+
Redistribution and use in source and binary forms, with or without
|
| 6 |
+
modification, are permitted provided that the following conditions are
|
| 7 |
+
met:
|
| 8 |
+
|
| 9 |
+
(1) Redistributions of source code must retain the above copyright
|
| 10 |
+
notice, this list of conditions and the following disclaimer.
|
| 11 |
+
|
| 12 |
+
(2) Redistributions in binary form must reproduce the above copyright
|
| 13 |
+
notice, this list of conditions and the following disclaimer in
|
| 14 |
+
the documentation and/or other materials provided with the
|
| 15 |
+
distribution.
|
| 16 |
+
|
| 17 |
+
(3) The name of the author may not be used to
|
| 18 |
+
endorse or promote products derived from this software without
|
| 19 |
+
specific prior written permission.
|
| 20 |
+
|
| 21 |
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
| 22 |
+
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| 23 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 24 |
+
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
| 25 |
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| 26 |
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
| 27 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
| 28 |
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
| 29 |
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
| 30 |
+
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
| 31 |
+
POSSIBILITY OF SUCH DAMAGE. */
|
| 32 |
+
|
| 33 |
+
#include "config.h"
|
| 34 |
+
|
| 35 |
+
#include <errno.h>
|
| 36 |
+
#include <sys/types.h>
|
| 37 |
+
#include <sys/mman.h>
|
| 38 |
+
#include <unistd.h>
|
| 39 |
+
|
| 40 |
+
#include "backtrace.hpp"
|
| 41 |
+
#include "internal.hpp"
|
| 42 |
+
|
| 43 |
+
#ifndef HAVE_DECL_GETPAGESIZE
|
| 44 |
+
extern int getpagesize (void);
|
| 45 |
+
#endif
|
| 46 |
+
|
| 47 |
+
#ifndef MAP_FAILED
|
| 48 |
+
#define MAP_FAILED ((void *)-1)
|
| 49 |
+
#endif
|
| 50 |
+
|
| 51 |
+
namespace tracy
|
| 52 |
+
{
|
| 53 |
+
|
| 54 |
+
/* This file implements file views and memory allocation when mmap is
|
| 55 |
+
available. */
|
| 56 |
+
|
| 57 |
+
/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */
|
| 58 |
+
|
| 59 |
+
int
|
| 60 |
+
backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
| 61 |
+
int descriptor, off_t offset, uint64_t size,
|
| 62 |
+
backtrace_error_callback error_callback,
|
| 63 |
+
void *data, struct backtrace_view *view)
|
| 64 |
+
{
|
| 65 |
+
size_t pagesize;
|
| 66 |
+
unsigned int inpage;
|
| 67 |
+
off_t pageoff;
|
| 68 |
+
void *map;
|
| 69 |
+
|
| 70 |
+
if ((uint64_t) (size_t) size != size)
|
| 71 |
+
{
|
| 72 |
+
error_callback (data, "file size too large", 0);
|
| 73 |
+
return 0;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
pagesize = getpagesize ();
|
| 77 |
+
inpage = offset % pagesize;
|
| 78 |
+
pageoff = offset - inpage;
|
| 79 |
+
|
| 80 |
+
size += inpage;
|
| 81 |
+
size = (size + (pagesize - 1)) & ~ (pagesize - 1);
|
| 82 |
+
|
| 83 |
+
map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);
|
| 84 |
+
if (map == MAP_FAILED)
|
| 85 |
+
{
|
| 86 |
+
error_callback (data, "mmap", errno);
|
| 87 |
+
return 0;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
view->data = (char *) map + inpage;
|
| 91 |
+
view->base = map;
|
| 92 |
+
view->len = size;
|
| 93 |
+
|
| 94 |
+
return 1;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
/* Release a view read by backtrace_get_view. */
|
| 98 |
+
|
| 99 |
+
void
|
| 100 |
+
backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
|
| 101 |
+
struct backtrace_view *view,
|
| 102 |
+
backtrace_error_callback error_callback,
|
| 103 |
+
void *data)
|
| 104 |
+
{
|
| 105 |
+
union {
|
| 106 |
+
const void *cv;
|
| 107 |
+
void *v;
|
| 108 |
+
} cc;
|
| 109 |
+
|
| 110 |
+
cc.cv = view->base;
|
| 111 |
+
if (munmap (cc.v, view->len) < 0)
|
| 112 |
+
error_callback (data, "munmap", errno);
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
}
|
third_party/tracy/public/libbacktrace/sort.cpp
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* sort.c -- Sort without allocating memory
|
| 2 |
+
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
| 3 |
+
Written by Ian Lance Taylor, Google.
|
| 4 |
+
|
| 5 |
+
Redistribution and use in source and binary forms, with or without
|
| 6 |
+
modification, are permitted provided that the following conditions are
|
| 7 |
+
met:
|
| 8 |
+
|
| 9 |
+
(1) Redistributions of source code must retain the above copyright
|
| 10 |
+
notice, this list of conditions and the following disclaimer.
|
| 11 |
+
|
| 12 |
+
(2) Redistributions in binary form must reproduce the above copyright
|
| 13 |
+
notice, this list of conditions and the following disclaimer in
|
| 14 |
+
the documentation and/or other materials provided with the
|
| 15 |
+
distribution.
|
| 16 |
+
|
| 17 |
+
(3) The name of the author may not be used to
|
| 18 |
+
endorse or promote products derived from this software without
|
| 19 |
+
specific prior written permission.
|
| 20 |
+
|
| 21 |
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
| 22 |
+
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| 23 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 24 |
+
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
| 25 |
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| 26 |
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
| 27 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
| 28 |
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
| 29 |
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
| 30 |
+
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
| 31 |
+
POSSIBILITY OF SUCH DAMAGE. */
|
| 32 |
+
|
| 33 |
+
#include "config.h"
|
| 34 |
+
|
| 35 |
+
#include <stddef.h>
|
| 36 |
+
#include <sys/types.h>
|
| 37 |
+
|
| 38 |
+
#include "backtrace.hpp"
|
| 39 |
+
#include "internal.hpp"
|
| 40 |
+
|
| 41 |
+
namespace tracy
|
| 42 |
+
{
|
| 43 |
+
|
| 44 |
+
/* The GNU glibc version of qsort allocates memory, which we must not
|
| 45 |
+
do if we are invoked by a signal handler. So provide our own
|
| 46 |
+
sort. */
|
| 47 |
+
|
| 48 |
+
static void
|
| 49 |
+
swap (char *a, char *b, size_t size)
|
| 50 |
+
{
|
| 51 |
+
size_t i;
|
| 52 |
+
|
| 53 |
+
for (i = 0; i < size; i++, a++, b++)
|
| 54 |
+
{
|
| 55 |
+
char t;
|
| 56 |
+
|
| 57 |
+
t = *a;
|
| 58 |
+
*a = *b;
|
| 59 |
+
*b = t;
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
void
|
| 64 |
+
backtrace_qsort (void *basearg, size_t count, size_t size,
|
| 65 |
+
int (*compar) (const void *, const void *))
|
| 66 |
+
{
|
| 67 |
+
char *base = (char *) basearg;
|
| 68 |
+
size_t i;
|
| 69 |
+
size_t mid;
|
| 70 |
+
|
| 71 |
+
tail_recurse:
|
| 72 |
+
if (count < 2)
|
| 73 |
+
return;
|
| 74 |
+
|
| 75 |
+
/* The symbol table and DWARF tables, which is all we use this
|
| 76 |
+
routine for, tend to be roughly sorted. Pick the middle element
|
| 77 |
+
in the array as our pivot point, so that we are more likely to
|
| 78 |
+
cut the array in half for each recursion step. */
|
| 79 |
+
swap (base, base + (count / 2) * size, size);
|
| 80 |
+
|
| 81 |
+
mid = 0;
|
| 82 |
+
for (i = 1; i < count; i++)
|
| 83 |
+
{
|
| 84 |
+
if ((*compar) (base, base + i * size) > 0)
|
| 85 |
+
{
|
| 86 |
+
++mid;
|
| 87 |
+
if (i != mid)
|
| 88 |
+
swap (base + mid * size, base + i * size, size);
|
| 89 |
+
}
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
if (mid > 0)
|
| 93 |
+
swap (base, base + mid * size, size);
|
| 94 |
+
|
| 95 |
+
/* Recurse with the smaller array, loop with the larger one. That
|
| 96 |
+
ensures that our maximum stack depth is log count. */
|
| 97 |
+
if (2 * mid < count)
|
| 98 |
+
{
|
| 99 |
+
backtrace_qsort (base, mid, size, compar);
|
| 100 |
+
base += (mid + 1) * size;
|
| 101 |
+
count -= mid + 1;
|
| 102 |
+
goto tail_recurse;
|
| 103 |
+
}
|
| 104 |
+
else
|
| 105 |
+
{
|
| 106 |
+
backtrace_qsort (base + (mid + 1) * size, count - (mid + 1),
|
| 107 |
+
size, compar);
|
| 108 |
+
count = mid;
|
| 109 |
+
goto tail_recurse;
|
| 110 |
+
}
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
}
|
third_party/tracy/public/libbacktrace/state.cpp
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* state.c -- Create the backtrace state.
|
| 2 |
+
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
| 3 |
+
Written by Ian Lance Taylor, Google.
|
| 4 |
+
|
| 5 |
+
Redistribution and use in source and binary forms, with or without
|
| 6 |
+
modification, are permitted provided that the following conditions are
|
| 7 |
+
met:
|
| 8 |
+
|
| 9 |
+
(1) Redistributions of source code must retain the above copyright
|
| 10 |
+
notice, this list of conditions and the following disclaimer.
|
| 11 |
+
|
| 12 |
+
(2) Redistributions in binary form must reproduce the above copyright
|
| 13 |
+
notice, this list of conditions and the following disclaimer in
|
| 14 |
+
the documentation and/or other materials provided with the
|
| 15 |
+
distribution.
|
| 16 |
+
|
| 17 |
+
(3) The name of the author may not be used to
|
| 18 |
+
endorse or promote products derived from this software without
|
| 19 |
+
specific prior written permission.
|
| 20 |
+
|
| 21 |
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
| 22 |
+
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| 23 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 24 |
+
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
| 25 |
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| 26 |
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
| 27 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
| 28 |
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
| 29 |
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
| 30 |
+
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
| 31 |
+
POSSIBILITY OF SUCH DAMAGE. */
|
| 32 |
+
|
| 33 |
+
#include "config.h"
|
| 34 |
+
|
| 35 |
+
#include <string.h>
|
| 36 |
+
#include <sys/types.h>
|
| 37 |
+
|
| 38 |
+
#include "backtrace.hpp"
|
| 39 |
+
#include "internal.hpp"
|
| 40 |
+
|
| 41 |
+
namespace tracy
|
| 42 |
+
{
|
| 43 |
+
|
| 44 |
+
/* Create the backtrace state. This will then be passed to all the
|
| 45 |
+
other routines. */
|
| 46 |
+
|
| 47 |
+
struct backtrace_state *
|
| 48 |
+
backtrace_create_state (const char *filename, int threaded,
|
| 49 |
+
backtrace_error_callback error_callback,
|
| 50 |
+
void *data)
|
| 51 |
+
{
|
| 52 |
+
struct backtrace_state init_state;
|
| 53 |
+
struct backtrace_state *state;
|
| 54 |
+
|
| 55 |
+
#ifndef HAVE_SYNC_FUNCTIONS
|
| 56 |
+
if (threaded)
|
| 57 |
+
{
|
| 58 |
+
error_callback (data, "backtrace library does not support threads", 0);
|
| 59 |
+
return NULL;
|
| 60 |
+
}
|
| 61 |
+
#endif
|
| 62 |
+
|
| 63 |
+
memset (&init_state, 0, sizeof init_state);
|
| 64 |
+
init_state.filename = filename;
|
| 65 |
+
init_state.threaded = threaded;
|
| 66 |
+
|
| 67 |
+
state = ((struct backtrace_state *)
|
| 68 |
+
backtrace_alloc (&init_state, sizeof *state, error_callback, data));
|
| 69 |
+
if (state == NULL)
|
| 70 |
+
return NULL;
|
| 71 |
+
*state = init_state;
|
| 72 |
+
|
| 73 |
+
return state;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
}
|
third_party/tracy/server/TracyCharUtil.hpp
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#ifndef __TRACY__CHARUTIL_HPP__
|
| 2 |
+
#define __TRACY__CHARUTIL_HPP__
|
| 3 |
+
|
| 4 |
+
#include <stddef.h>
|
| 5 |
+
#include <stdint.h>
|
| 6 |
+
#include <string.h>
|
| 7 |
+
|
| 8 |
+
#define XXH_INLINE_ALL
|
| 9 |
+
#include "tracy_xxhash.h"
|
| 10 |
+
|
| 11 |
+
namespace tracy
|
| 12 |
+
{
|
| 13 |
+
namespace charutil
|
| 14 |
+
{
|
| 15 |
+
|
| 16 |
+
static inline size_t hash( const char* str )
|
| 17 |
+
{
|
| 18 |
+
const auto sz = strlen( str );
|
| 19 |
+
return XXH3_64bits( str, sz );
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
static inline size_t hash( const char* str, size_t sz )
|
| 23 |
+
{
|
| 24 |
+
return XXH3_64bits( str, sz );
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
struct Hasher
|
| 28 |
+
{
|
| 29 |
+
size_t operator()( const char* key ) const
|
| 30 |
+
{
|
| 31 |
+
return hash( key );
|
| 32 |
+
}
|
| 33 |
+
};
|
| 34 |
+
|
| 35 |
+
struct Comparator
|
| 36 |
+
{
|
| 37 |
+
bool operator()( const char* lhs, const char* rhs ) const
|
| 38 |
+
{
|
| 39 |
+
return strcmp( lhs, rhs ) == 0;
|
| 40 |
+
}
|
| 41 |
+
};
|
| 42 |
+
|
| 43 |
+
struct LessComparator
|
| 44 |
+
{
|
| 45 |
+
bool operator()( const char* lhs, const char* rhs ) const
|
| 46 |
+
{
|
| 47 |
+
return strcmp( lhs, rhs ) < 0;
|
| 48 |
+
}
|
| 49 |
+
};
|
| 50 |
+
|
| 51 |
+
struct StringKey
|
| 52 |
+
{
|
| 53 |
+
const char* ptr;
|
| 54 |
+
size_t sz;
|
| 55 |
+
|
| 56 |
+
struct Hasher
|
| 57 |
+
{
|
| 58 |
+
size_t operator()( const StringKey& key ) const
|
| 59 |
+
{
|
| 60 |
+
return hash( key.ptr, key.sz );
|
| 61 |
+
}
|
| 62 |
+
};
|
| 63 |
+
|
| 64 |
+
struct Comparator
|
| 65 |
+
{
|
| 66 |
+
bool operator()( const StringKey& lhs, const StringKey& rhs ) const
|
| 67 |
+
{
|
| 68 |
+
return lhs.sz == rhs.sz && memcmp( lhs.ptr, rhs.ptr, lhs.sz ) == 0;
|
| 69 |
+
}
|
| 70 |
+
};
|
| 71 |
+
};
|
| 72 |
+
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
#endif
|
third_party/tracy/server/TracyEvent.hpp
ADDED
|
@@ -0,0 +1,850 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#ifndef __TRACYEVENT_HPP__
|
| 2 |
+
#define __TRACYEVENT_HPP__
|
| 3 |
+
|
| 4 |
+
#include <assert.h>
|
| 5 |
+
#include <limits>
|
| 6 |
+
#include <stdint.h>
|
| 7 |
+
#include <string>
|
| 8 |
+
#include <string.h>
|
| 9 |
+
|
| 10 |
+
#include "TracyCharUtil.hpp"
|
| 11 |
+
#include "TracyShortPtr.hpp"
|
| 12 |
+
#include "TracySortedVector.hpp"
|
| 13 |
+
#include "TracyVector.hpp"
|
| 14 |
+
#include "tracy_robin_hood.h"
|
| 15 |
+
#include "../public/common/TracyForceInline.hpp"
|
| 16 |
+
#include "../public/common/TracyQueue.hpp"
|
| 17 |
+
|
| 18 |
+
namespace tracy
|
| 19 |
+
{
|
| 20 |
+
|
| 21 |
+
#pragma pack( push, 1 )
|
| 22 |
+
|
| 23 |
+
struct StringRef
|
| 24 |
+
{
|
| 25 |
+
enum Type { Ptr, Idx };
|
| 26 |
+
|
| 27 |
+
tracy_force_inline StringRef() : str( 0 ), __data( 0 ) {}
|
| 28 |
+
tracy_force_inline StringRef( Type t, uint64_t data )
|
| 29 |
+
: str( data )
|
| 30 |
+
, __data( 0 )
|
| 31 |
+
{
|
| 32 |
+
isidx = t == Idx;
|
| 33 |
+
active = 1;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
uint64_t str;
|
| 37 |
+
|
| 38 |
+
union
|
| 39 |
+
{
|
| 40 |
+
struct
|
| 41 |
+
{
|
| 42 |
+
uint8_t isidx : 1;
|
| 43 |
+
uint8_t active : 1;
|
| 44 |
+
};
|
| 45 |
+
uint8_t __data;
|
| 46 |
+
};
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
struct StringRefHasher
|
| 50 |
+
{
|
| 51 |
+
size_t operator()( const StringRef& key ) const
|
| 52 |
+
{
|
| 53 |
+
return charutil::hash( (const char*)&key, sizeof( StringRef ) );
|
| 54 |
+
}
|
| 55 |
+
};
|
| 56 |
+
|
| 57 |
+
struct StringRefComparator
|
| 58 |
+
{
|
| 59 |
+
bool operator()( const StringRef& lhs, const StringRef& rhs ) const
|
| 60 |
+
{
|
| 61 |
+
return memcmp( &lhs, &rhs, sizeof( StringRef ) ) == 0;
|
| 62 |
+
}
|
| 63 |
+
};
|
| 64 |
+
|
| 65 |
+
class StringIdx
|
| 66 |
+
{
|
| 67 |
+
public:
|
| 68 |
+
tracy_force_inline StringIdx() { memset( m_idx, 0, sizeof( m_idx ) ); }
|
| 69 |
+
tracy_force_inline StringIdx( uint32_t idx )
|
| 70 |
+
{
|
| 71 |
+
SetIdx( idx );
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
tracy_force_inline void SetIdx( uint32_t idx )
|
| 75 |
+
{
|
| 76 |
+
idx++;
|
| 77 |
+
memcpy( m_idx, &idx, 3 );
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
tracy_force_inline uint32_t Idx() const
|
| 81 |
+
{
|
| 82 |
+
uint32_t idx = 0;
|
| 83 |
+
memcpy( &idx, m_idx, 3 );
|
| 84 |
+
assert( idx != 0 );
|
| 85 |
+
return idx - 1;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
tracy_force_inline bool Active() const
|
| 89 |
+
{
|
| 90 |
+
uint32_t zero = 0;
|
| 91 |
+
return memcmp( m_idx, &zero, 3 ) != 0;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
private:
|
| 95 |
+
uint8_t m_idx[3];
|
| 96 |
+
};
|
| 97 |
+
|
| 98 |
+
struct StringIdxHasher
|
| 99 |
+
{
|
| 100 |
+
size_t operator()( const StringIdx& key ) const
|
| 101 |
+
{
|
| 102 |
+
return charutil::hash( (const char*)&key, sizeof( StringIdx ) );
|
| 103 |
+
}
|
| 104 |
+
};
|
| 105 |
+
|
| 106 |
+
struct StringIdxComparator
|
| 107 |
+
{
|
| 108 |
+
bool operator()( const StringIdx& lhs, const StringIdx& rhs ) const
|
| 109 |
+
{
|
| 110 |
+
return memcmp( &lhs, &rhs, sizeof( StringIdx ) ) == 0;
|
| 111 |
+
}
|
| 112 |
+
};
|
| 113 |
+
|
| 114 |
+
class Int24
|
| 115 |
+
{
|
| 116 |
+
public:
|
| 117 |
+
tracy_force_inline Int24() { memset( m_val, 0, sizeof( m_val ) ); }
|
| 118 |
+
tracy_force_inline Int24( uint32_t val )
|
| 119 |
+
{
|
| 120 |
+
SetVal( val );
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
tracy_force_inline void SetVal( uint32_t val )
|
| 124 |
+
{
|
| 125 |
+
memcpy( m_val, &val, 2 );
|
| 126 |
+
val >>= 16;
|
| 127 |
+
memcpy( m_val+2, &val, 1 );
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
tracy_force_inline uint32_t Val() const
|
| 131 |
+
{
|
| 132 |
+
uint8_t hi;
|
| 133 |
+
memcpy( &hi, m_val+2, 1 );
|
| 134 |
+
uint16_t lo;
|
| 135 |
+
memcpy( &lo, m_val, 2 );
|
| 136 |
+
return ( uint32_t( hi ) << 16 ) | lo;
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
private:
|
| 140 |
+
uint8_t m_val[3];
|
| 141 |
+
};
|
| 142 |
+
|
| 143 |
+
class Int48
|
| 144 |
+
{
|
| 145 |
+
public:
|
| 146 |
+
tracy_force_inline Int48() {}
|
| 147 |
+
tracy_force_inline Int48( int64_t val )
|
| 148 |
+
{
|
| 149 |
+
SetVal( val );
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
tracy_force_inline void Clear()
|
| 153 |
+
{
|
| 154 |
+
memset( m_val, 0, 6 );
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
tracy_force_inline void SetVal( int64_t val )
|
| 158 |
+
{
|
| 159 |
+
memcpy( m_val, &val, 4 );
|
| 160 |
+
val >>= 32;
|
| 161 |
+
memcpy( m_val+4, &val, 2 );
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
tracy_force_inline int64_t Val() const
|
| 165 |
+
{
|
| 166 |
+
int16_t hi;
|
| 167 |
+
memcpy( &hi, m_val+4, 2 );
|
| 168 |
+
uint32_t lo;
|
| 169 |
+
memcpy( &lo, m_val, 4 );
|
| 170 |
+
return ( int64_t( uint64_t( hi ) << 32 ) ) | lo;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
tracy_force_inline bool IsNonNegative() const
|
| 174 |
+
{
|
| 175 |
+
return ( m_val[5] >> 7 ) == 0;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
private:
|
| 179 |
+
uint8_t m_val[6];
|
| 180 |
+
};
|
| 181 |
+
|
| 182 |
+
struct Int48Sort { bool operator()( const Int48& lhs, const Int48& rhs ) { return lhs.Val() < rhs.Val(); }; };
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
struct SourceLocationBase
|
| 186 |
+
{
|
| 187 |
+
StringRef name;
|
| 188 |
+
StringRef function;
|
| 189 |
+
StringRef file;
|
| 190 |
+
uint32_t line;
|
| 191 |
+
uint32_t color;
|
| 192 |
+
};
|
| 193 |
+
|
| 194 |
+
struct SourceLocation : public SourceLocationBase
|
| 195 |
+
{
|
| 196 |
+
mutable uint32_t namehash;
|
| 197 |
+
};
|
| 198 |
+
|
| 199 |
+
enum { SourceLocationSize = sizeof( SourceLocation ) };
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
struct ZoneEvent
|
| 203 |
+
{
|
| 204 |
+
tracy_force_inline ZoneEvent() {};
|
| 205 |
+
|
| 206 |
+
tracy_force_inline int64_t Start() const { return int64_t( _start_srcloc ) >> 16; }
|
| 207 |
+
tracy_force_inline void SetStart( int64_t start ) { assert( start < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_start_srcloc)+2, &start, 4 ); memcpy( ((char*)&_start_srcloc)+6, ((char*)&start)+4, 2 ); }
|
| 208 |
+
tracy_force_inline int64_t End() const { return int64_t( _end_child1 ) >> 16; }
|
| 209 |
+
tracy_force_inline void SetEnd( int64_t end ) { assert( end < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_end_child1)+2, &end, 4 ); memcpy( ((char*)&_end_child1)+6, ((char*)&end)+4, 2 ); }
|
| 210 |
+
tracy_force_inline bool IsEndValid() const { return ( _end_child1 >> 63 ) == 0; }
|
| 211 |
+
tracy_force_inline int16_t SrcLoc() const { return int16_t( _start_srcloc & 0xFFFF ); }
|
| 212 |
+
tracy_force_inline void SetSrcLoc( int16_t srcloc ) { memcpy( &_start_srcloc, &srcloc, 2 ); }
|
| 213 |
+
tracy_force_inline int32_t Child() const { int32_t child; memcpy( &child, &_child2, 4 ); return child; }
|
| 214 |
+
tracy_force_inline void SetChild( int32_t child ) { memcpy( &_child2, &child, 4 ); }
|
| 215 |
+
tracy_force_inline bool HasChildren() const { uint8_t tmp; memcpy( &tmp, ((char*)&_end_child1)+1, 1 ); return ( tmp >> 7 ) == 0; }
|
| 216 |
+
|
| 217 |
+
tracy_force_inline void SetStartSrcLoc( int64_t start, int16_t srcloc ) { assert( start < (int64_t)( 1ull << 47 ) ); start <<= 16; start |= uint16_t( srcloc ); memcpy( &_start_srcloc, &start, 8 ); }
|
| 218 |
+
|
| 219 |
+
uint64_t _start_srcloc;
|
| 220 |
+
uint16_t _child2;
|
| 221 |
+
uint64_t _end_child1;
|
| 222 |
+
uint32_t extra;
|
| 223 |
+
};
|
| 224 |
+
|
| 225 |
+
enum { ZoneEventSize = sizeof( ZoneEvent ) };
|
| 226 |
+
static_assert( std::is_standard_layout<ZoneEvent>::value, "ZoneEvent is not standard layout" );
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
struct ZoneExtra
|
| 230 |
+
{
|
| 231 |
+
Int24 callstack;
|
| 232 |
+
StringIdx text;
|
| 233 |
+
StringIdx name;
|
| 234 |
+
Int24 color;
|
| 235 |
+
};
|
| 236 |
+
|
| 237 |
+
enum { ZoneExtraSize = sizeof( ZoneExtra ) };
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
// This union exploits the fact that the current implementations of x64 and arm64 do not provide
|
| 241 |
+
// full 64 bit address space. The high bits must be bit-extended, so 0x80... is an invalid pointer.
|
| 242 |
+
// This allows using the highest bit as a selector between a native pointer and a table index here.
|
| 243 |
+
union CallstackFrameId
|
| 244 |
+
{
|
| 245 |
+
struct
|
| 246 |
+
{
|
| 247 |
+
uint64_t idx : 62;
|
| 248 |
+
uint64_t sel : 1;
|
| 249 |
+
uint64_t custom : 1;
|
| 250 |
+
};
|
| 251 |
+
uint64_t data;
|
| 252 |
+
};
|
| 253 |
+
|
| 254 |
+
enum { CallstackFrameIdSize = sizeof( CallstackFrameId ) };
|
| 255 |
+
|
| 256 |
+
static tracy_force_inline bool operator==( const CallstackFrameId& lhs, const CallstackFrameId& rhs ) { return lhs.data == rhs.data; }
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
struct SampleData
|
| 260 |
+
{
|
| 261 |
+
Int48 time;
|
| 262 |
+
Int24 callstack;
|
| 263 |
+
};
|
| 264 |
+
|
| 265 |
+
enum { SampleDataSize = sizeof( SampleData ) };
|
| 266 |
+
|
| 267 |
+
struct SampleDataSort { bool operator()( const SampleData& lhs, const SampleData& rhs ) { return lhs.time.Val() < rhs.time.Val(); }; };
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
struct SampleDataRange
|
| 271 |
+
{
|
| 272 |
+
Int48 time;
|
| 273 |
+
uint16_t thread;
|
| 274 |
+
CallstackFrameId ip;
|
| 275 |
+
};
|
| 276 |
+
|
| 277 |
+
enum { SampleDataRangeSize = sizeof( SampleDataRange ) };
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
struct HwSampleData
|
| 281 |
+
{
|
| 282 |
+
SortedVector<Int48, Int48Sort> cycles;
|
| 283 |
+
SortedVector<Int48, Int48Sort> retired;
|
| 284 |
+
SortedVector<Int48, Int48Sort> cacheRef;
|
| 285 |
+
SortedVector<Int48, Int48Sort> cacheMiss;
|
| 286 |
+
SortedVector<Int48, Int48Sort> branchRetired;
|
| 287 |
+
SortedVector<Int48, Int48Sort> branchMiss;
|
| 288 |
+
|
| 289 |
+
bool is_sorted() const
|
| 290 |
+
{
|
| 291 |
+
return
|
| 292 |
+
cycles.is_sorted() &&
|
| 293 |
+
retired.is_sorted() &&
|
| 294 |
+
cacheRef.is_sorted() &&
|
| 295 |
+
cacheMiss.is_sorted() &&
|
| 296 |
+
branchRetired.is_sorted() &&
|
| 297 |
+
branchMiss.is_sorted();
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
+
void sort()
|
| 301 |
+
{
|
| 302 |
+
if( !cycles.is_sorted() ) cycles.sort();
|
| 303 |
+
if( !retired.is_sorted() ) retired.sort();
|
| 304 |
+
if( !cacheRef.is_sorted() ) cacheRef.sort();
|
| 305 |
+
if( !cacheMiss.is_sorted() ) cacheMiss.sort();
|
| 306 |
+
if( !branchRetired.is_sorted() ) branchRetired.sort();
|
| 307 |
+
if( !branchMiss.is_sorted() ) branchMiss.sort();
|
| 308 |
+
}
|
| 309 |
+
};
|
| 310 |
+
|
| 311 |
+
enum { HwSampleDataSize = sizeof( HwSampleData ) };
|
| 312 |
+
|
| 313 |
+
|
| 314 |
+
struct LockEvent
|
| 315 |
+
{
|
| 316 |
+
enum class Type : uint8_t
|
| 317 |
+
{
|
| 318 |
+
Wait,
|
| 319 |
+
Obtain,
|
| 320 |
+
Release,
|
| 321 |
+
WaitShared,
|
| 322 |
+
ObtainShared,
|
| 323 |
+
ReleaseShared
|
| 324 |
+
};
|
| 325 |
+
|
| 326 |
+
tracy_force_inline int64_t Time() const { return int64_t( _time_srcloc ) >> 16; }
|
| 327 |
+
tracy_force_inline void SetTime( int64_t time ) { assert( time < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_time_srcloc)+2, &time, 4 ); memcpy( ((char*)&_time_srcloc)+6, ((char*)&time)+4, 2 ); }
|
| 328 |
+
tracy_force_inline int16_t SrcLoc() const { return int16_t( _time_srcloc & 0xFFFF ); }
|
| 329 |
+
tracy_force_inline void SetSrcLoc( int16_t srcloc ) { memcpy( &_time_srcloc, &srcloc, 2 ); }
|
| 330 |
+
|
| 331 |
+
uint64_t _time_srcloc;
|
| 332 |
+
uint8_t thread;
|
| 333 |
+
Type type;
|
| 334 |
+
};
|
| 335 |
+
|
| 336 |
+
struct LockEventShared : public LockEvent
|
| 337 |
+
{
|
| 338 |
+
uint64_t waitShared;
|
| 339 |
+
uint64_t sharedList;
|
| 340 |
+
};
|
| 341 |
+
|
| 342 |
+
struct LockEventPtr
|
| 343 |
+
{
|
| 344 |
+
short_ptr<LockEvent> ptr;
|
| 345 |
+
uint8_t lockingThread;
|
| 346 |
+
uint8_t lockCount;
|
| 347 |
+
uint64_t waitList;
|
| 348 |
+
};
|
| 349 |
+
|
| 350 |
+
enum { LockEventSize = sizeof( LockEvent ) };
|
| 351 |
+
enum { LockEventSharedSize = sizeof( LockEventShared ) };
|
| 352 |
+
enum { LockEventPtrSize = sizeof( LockEventPtr ) };
|
| 353 |
+
|
| 354 |
+
enum { MaxLockThreads = sizeof( LockEventPtr::waitList ) * 8 };
|
| 355 |
+
static_assert( std::numeric_limits<decltype(LockEventPtr::lockCount)>::max() >= MaxLockThreads, "Not enough space for lock count." );
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
enum class LockType : uint8_t;
|
| 359 |
+
|
| 360 |
+
struct LockMap
|
| 361 |
+
{
|
| 362 |
+
struct TimeRange
|
| 363 |
+
{
|
| 364 |
+
int64_t start = std::numeric_limits<int64_t>::max();
|
| 365 |
+
int64_t end = std::numeric_limits<int64_t>::min();
|
| 366 |
+
};
|
| 367 |
+
|
| 368 |
+
StringIdx customName;
|
| 369 |
+
int16_t srcloc;
|
| 370 |
+
Vector<LockEventPtr> timeline;
|
| 371 |
+
unordered_flat_map<uint64_t, uint8_t> threadMap;
|
| 372 |
+
std::vector<uint64_t> threadList;
|
| 373 |
+
LockType type;
|
| 374 |
+
int64_t timeAnnounce;
|
| 375 |
+
int64_t timeTerminate;
|
| 376 |
+
bool valid;
|
| 377 |
+
bool isContended;
|
| 378 |
+
uint64_t lockingThread;
|
| 379 |
+
|
| 380 |
+
TimeRange range[64];
|
| 381 |
+
};
|
| 382 |
+
|
| 383 |
+
struct LockHighlight
|
| 384 |
+
{
|
| 385 |
+
int64_t id;
|
| 386 |
+
int64_t begin;
|
| 387 |
+
int64_t end;
|
| 388 |
+
uint8_t thread;
|
| 389 |
+
bool blocked;
|
| 390 |
+
};
|
| 391 |
+
|
| 392 |
+
|
| 393 |
+
struct GpuEvent
|
| 394 |
+
{
|
| 395 |
+
tracy_force_inline int64_t CpuStart() const { return int64_t( _cpuStart_srcloc ) >> 16; }
|
| 396 |
+
tracy_force_inline void SetCpuStart( int64_t cpuStart ) { assert( cpuStart < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_cpuStart_srcloc)+2, &cpuStart, 4 ); memcpy( ((char*)&_cpuStart_srcloc)+6, ((char*)&cpuStart)+4, 2 ); }
|
| 397 |
+
tracy_force_inline int64_t CpuEnd() const { return int64_t( _cpuEnd_thread ) >> 16; }
|
| 398 |
+
tracy_force_inline void SetCpuEnd( int64_t cpuEnd ) { assert( cpuEnd < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_cpuEnd_thread)+2, &cpuEnd, 4 ); memcpy( ((char*)&_cpuEnd_thread)+6, ((char*)&cpuEnd)+4, 2 ); }
|
| 399 |
+
tracy_force_inline int64_t GpuStart() const { return int64_t( _gpuStart_child1 ) >> 16; }
|
| 400 |
+
tracy_force_inline void SetGpuStart( int64_t gpuStart ) { /*assert( gpuStart < (int64_t)( 1ull << 47 ) );*/ memcpy( ((char*)&_gpuStart_child1)+2, &gpuStart, 4 ); memcpy( ((char*)&_gpuStart_child1)+6, ((char*)&gpuStart)+4, 2 ); }
|
| 401 |
+
tracy_force_inline int64_t GpuEnd() const { return int64_t( _gpuEnd_child2 ) >> 16; }
|
| 402 |
+
tracy_force_inline void SetGpuEnd( int64_t gpuEnd ) { assert( gpuEnd < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_gpuEnd_child2)+2, &gpuEnd, 4 ); memcpy( ((char*)&_gpuEnd_child2)+6, ((char*)&gpuEnd)+4, 2 ); }
|
| 403 |
+
tracy_force_inline int16_t SrcLoc() const { return int16_t( _cpuStart_srcloc & 0xFFFF ); }
|
| 404 |
+
tracy_force_inline void SetSrcLoc( int16_t srcloc ) { memcpy( &_cpuStart_srcloc, &srcloc, 2 ); }
|
| 405 |
+
tracy_force_inline uint16_t Thread() const { return uint16_t( _cpuEnd_thread & 0xFFFF ); }
|
| 406 |
+
tracy_force_inline void SetThread( uint16_t thread ) { memcpy( &_cpuEnd_thread, &thread, 2 ); }
|
| 407 |
+
tracy_force_inline int32_t Child() const { return int32_t( uint32_t( _gpuStart_child1 & 0xFFFF ) | ( uint32_t( _gpuEnd_child2 & 0xFFFF ) << 16 ) ); }
|
| 408 |
+
tracy_force_inline void SetChild( int32_t child ) { memcpy( &_gpuStart_child1, &child, 2 ); memcpy( &_gpuEnd_child2, ((char*)&child)+2, 2 ); }
|
| 409 |
+
|
| 410 |
+
uint64_t _cpuStart_srcloc;
|
| 411 |
+
uint64_t _cpuEnd_thread;
|
| 412 |
+
uint64_t _gpuStart_child1;
|
| 413 |
+
uint64_t _gpuEnd_child2;
|
| 414 |
+
Int24 callstack;
|
| 415 |
+
};
|
| 416 |
+
|
| 417 |
+
enum { GpuEventSize = sizeof( GpuEvent ) };
|
| 418 |
+
static_assert( std::is_standard_layout<GpuEvent>::value, "GpuEvent is not standard layout" );
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
struct MemEvent
|
| 422 |
+
{
|
| 423 |
+
tracy_force_inline uint64_t Ptr() const { return uint64_t( int64_t( _ptr_csalloc1 ) >> 8 ); }
|
| 424 |
+
tracy_force_inline void SetPtr( uint64_t ptr ) { memcpy( ((char*)&_ptr_csalloc1)+1, &ptr, 4 ); memcpy( ((char*)&_ptr_csalloc1)+5, ((char*)&ptr)+4, 2 ); memcpy( ((char*)&_ptr_csalloc1)+7, ((char*)&ptr)+6, 1 ); }
|
| 425 |
+
tracy_force_inline uint64_t Size() const { return _size_csalloc2 >> 16; }
|
| 426 |
+
tracy_force_inline void SetSize( uint64_t size ) { assert( size < ( 1ull << 47 ) ); memcpy( ((char*)&_size_csalloc2)+2, &size, 4 ); memcpy( ((char*)&_size_csalloc2)+6, ((char*)&size)+4, 2 ); }
|
| 427 |
+
tracy_force_inline uint32_t CsAlloc() const { return uint8_t( _ptr_csalloc1 ) | ( uint16_t( _size_csalloc2 ) << 8 ); }
|
| 428 |
+
tracy_force_inline void SetCsAlloc( uint32_t csAlloc ) { memcpy( &_ptr_csalloc1, &csAlloc, 1 ); memcpy( &_size_csalloc2, ((char*)&csAlloc)+1, 2 ); }
|
| 429 |
+
tracy_force_inline int64_t TimeAlloc() const { return int64_t( _time_thread_alloc ) >> 16; }
|
| 430 |
+
tracy_force_inline void SetTimeAlloc( int64_t time ) { assert( time < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_time_thread_alloc)+2, &time, 4 ); memcpy( ((char*)&_time_thread_alloc)+6, ((char*)&time)+4, 2 ); }
|
| 431 |
+
tracy_force_inline int64_t TimeFree() const { return int64_t( _time_thread_free ) >> 16; }
|
| 432 |
+
tracy_force_inline void SetTimeFree( int64_t time ) { assert( time < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_time_thread_free)+2, &time, 4 ); memcpy( ((char*)&_time_thread_free)+6, ((char*)&time)+4, 2 ); }
|
| 433 |
+
tracy_force_inline uint16_t ThreadAlloc() const { return uint16_t( _time_thread_alloc ); }
|
| 434 |
+
tracy_force_inline void SetThreadAlloc( uint16_t thread ) { memcpy( &_time_thread_alloc, &thread, 2 ); }
|
| 435 |
+
tracy_force_inline uint16_t ThreadFree() const { return uint16_t( _time_thread_free ); }
|
| 436 |
+
tracy_force_inline void SetThreadFree( uint16_t thread ) { memcpy( &_time_thread_free, &thread, 2 ); }
|
| 437 |
+
|
| 438 |
+
tracy_force_inline void SetTimeThreadAlloc( int64_t time, uint16_t thread ) { time <<= 16; time |= thread; memcpy( &_time_thread_alloc, &time, 8 ); }
|
| 439 |
+
tracy_force_inline void SetTimeThreadFree( int64_t time, uint16_t thread ) { uint64_t t; memcpy( &t, &time, 8 ); t <<= 16; t |= thread; memcpy( &_time_thread_free, &t, 8 ); }
|
| 440 |
+
|
| 441 |
+
uint64_t _ptr_csalloc1;
|
| 442 |
+
uint64_t _size_csalloc2;
|
| 443 |
+
Int24 csFree;
|
| 444 |
+
uint64_t _time_thread_alloc;
|
| 445 |
+
uint64_t _time_thread_free;
|
| 446 |
+
};
|
| 447 |
+
|
| 448 |
+
enum { MemEventSize = sizeof( MemEvent ) };
|
| 449 |
+
static_assert( std::is_standard_layout<MemEvent>::value, "MemEvent is not standard layout" );
|
| 450 |
+
|
| 451 |
+
|
| 452 |
+
struct CallstackFrameBasic
|
| 453 |
+
{
|
| 454 |
+
StringIdx name;
|
| 455 |
+
StringIdx file;
|
| 456 |
+
uint32_t line;
|
| 457 |
+
};
|
| 458 |
+
|
| 459 |
+
struct CallstackFrame : public CallstackFrameBasic
|
| 460 |
+
{
|
| 461 |
+
uint64_t symAddr;
|
| 462 |
+
};
|
| 463 |
+
|
| 464 |
+
struct SymbolData : public CallstackFrameBasic
|
| 465 |
+
{
|
| 466 |
+
StringIdx imageName;
|
| 467 |
+
StringIdx callFile;
|
| 468 |
+
uint32_t callLine;
|
| 469 |
+
uint8_t isInline;
|
| 470 |
+
Int24 size;
|
| 471 |
+
};
|
| 472 |
+
|
| 473 |
+
enum { CallstackFrameBasicSize = sizeof( CallstackFrameBasic ) };
|
| 474 |
+
enum { CallstackFrameSize = sizeof( CallstackFrame ) };
|
| 475 |
+
enum { SymbolDataSize = sizeof( SymbolData ) };
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
struct SymbolLocation
|
| 479 |
+
{
|
| 480 |
+
uint64_t addr;
|
| 481 |
+
uint32_t len;
|
| 482 |
+
};
|
| 483 |
+
|
| 484 |
+
enum { SymbolLocationSize = sizeof( SymbolLocation ) };
|
| 485 |
+
|
| 486 |
+
|
| 487 |
+
struct CallstackFrameData
|
| 488 |
+
{
|
| 489 |
+
short_ptr<CallstackFrame> data;
|
| 490 |
+
uint8_t size;
|
| 491 |
+
StringIdx imageName;
|
| 492 |
+
};
|
| 493 |
+
|
| 494 |
+
enum { CallstackFrameDataSize = sizeof( CallstackFrameData ) };
|
| 495 |
+
|
| 496 |
+
|
| 497 |
+
struct MemCallstackFrameTree
|
| 498 |
+
{
|
| 499 |
+
MemCallstackFrameTree( CallstackFrameId id ) : frame( id ), alloc( 0 ), count( 0 ) {}
|
| 500 |
+
|
| 501 |
+
CallstackFrameId frame;
|
| 502 |
+
uint64_t alloc;
|
| 503 |
+
uint32_t count;
|
| 504 |
+
unordered_flat_map<uint64_t, MemCallstackFrameTree> children;
|
| 505 |
+
unordered_flat_set<uint32_t> callstacks;
|
| 506 |
+
};
|
| 507 |
+
|
| 508 |
+
enum { MemCallstackFrameTreeSize = sizeof( MemCallstackFrameTree ) };
|
| 509 |
+
|
| 510 |
+
|
| 511 |
+
struct CallstackFrameTree
|
| 512 |
+
{
|
| 513 |
+
CallstackFrameTree( CallstackFrameId id ) : frame( id ), count( 0 ) {}
|
| 514 |
+
|
| 515 |
+
CallstackFrameId frame;
|
| 516 |
+
uint32_t count;
|
| 517 |
+
unordered_flat_map<uint64_t, CallstackFrameTree> children;
|
| 518 |
+
};
|
| 519 |
+
|
| 520 |
+
enum { CallstackFrameTreeSize = sizeof( CallstackFrameTree ) };
|
| 521 |
+
|
| 522 |
+
|
| 523 |
+
struct CrashEvent
|
| 524 |
+
{
|
| 525 |
+
uint64_t thread = 0;
|
| 526 |
+
int64_t time = 0;
|
| 527 |
+
uint64_t message = 0;
|
| 528 |
+
uint32_t callstack = 0;
|
| 529 |
+
};
|
| 530 |
+
|
| 531 |
+
enum { CrashEventSize = sizeof( CrashEvent ) };
|
| 532 |
+
|
| 533 |
+
|
| 534 |
+
struct ContextSwitchData
|
| 535 |
+
{
|
| 536 |
+
enum : int8_t { Fiber = 99 };
|
| 537 |
+
enum : int8_t { NoState = 100 };
|
| 538 |
+
enum : int8_t { Wakeup = -2 };
|
| 539 |
+
|
| 540 |
+
tracy_force_inline int64_t Start() const { return int64_t( _start_cpu ) >> 16; }
|
| 541 |
+
tracy_force_inline void SetStart( int64_t start ) { assert( start < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_start_cpu)+2, &start, 4 ); memcpy( ((char*)&_start_cpu)+6, ((char*)&start)+4, 2 ); }
|
| 542 |
+
tracy_force_inline int64_t End() const { return int64_t( _end_reason_state ) >> 16; }
|
| 543 |
+
tracy_force_inline void SetEnd( int64_t end ) { assert( end < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_end_reason_state)+2, &end, 4 ); memcpy( ((char*)&_end_reason_state)+6, ((char*)&end)+4, 2 ); }
|
| 544 |
+
tracy_force_inline bool IsEndValid() const { return ( _end_reason_state >> 63 ) == 0; }
|
| 545 |
+
tracy_force_inline uint8_t Cpu() const { return uint8_t( _start_cpu & 0xFF ); }
|
| 546 |
+
tracy_force_inline void SetCpu( uint8_t cpu ) { memcpy( &_start_cpu, &cpu, 1 ); }
|
| 547 |
+
tracy_force_inline int8_t Reason() const { return int8_t( (_end_reason_state >> 8) & 0xFF ); }
|
| 548 |
+
tracy_force_inline void SetReason( int8_t reason ) { memcpy( ((char*)&_end_reason_state)+1, &reason, 1 ); }
|
| 549 |
+
tracy_force_inline int8_t State() const { return int8_t( _end_reason_state & 0xFF ); }
|
| 550 |
+
tracy_force_inline void SetState( int8_t state ) { memcpy( &_end_reason_state, &state, 1 ); }
|
| 551 |
+
tracy_force_inline int64_t WakeupVal() const { return _wakeup.Val(); }
|
| 552 |
+
tracy_force_inline void SetWakeup( int64_t wakeup ) { assert( wakeup < (int64_t)( 1ull << 47 ) ); _wakeup.SetVal( wakeup ); }
|
| 553 |
+
tracy_force_inline uint16_t Thread() const { return _thread; }
|
| 554 |
+
tracy_force_inline void SetThread( uint16_t thread ) { _thread = thread; }
|
| 555 |
+
|
| 556 |
+
tracy_force_inline void SetStartCpu( int64_t start, uint8_t cpu ) { assert( start < (int64_t)( 1ull << 47 ) ); _start_cpu = ( uint64_t( start ) << 16 ) | cpu; }
|
| 557 |
+
tracy_force_inline void SetEndReasonState( int64_t end, int8_t reason, int8_t state ) { assert( end < (int64_t)( 1ull << 47 ) ); _end_reason_state = ( uint64_t( end ) << 16 ) | ( uint64_t( reason ) << 8 ) | uint8_t( state ); }
|
| 558 |
+
|
| 559 |
+
uint64_t _start_cpu;
|
| 560 |
+
uint64_t _end_reason_state;
|
| 561 |
+
Int48 _wakeup;
|
| 562 |
+
uint16_t _thread;
|
| 563 |
+
};
|
| 564 |
+
|
| 565 |
+
enum { ContextSwitchDataSize = sizeof( ContextSwitchData ) };
|
| 566 |
+
|
| 567 |
+
|
| 568 |
+
struct ContextSwitchCpu
|
| 569 |
+
{
|
| 570 |
+
tracy_force_inline int64_t Start() const { return int64_t( _start_thread ) >> 16; }
|
| 571 |
+
tracy_force_inline void SetStart( int64_t start ) { assert( start < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_start_thread)+2, &start, 4 ); memcpy( ((char*)&_start_thread)+6, ((char*)&start)+4, 2 ); }
|
| 572 |
+
tracy_force_inline int64_t End() const { int64_t v; memcpy( &v, ((char*)&_end)-2, 8 ); return v >> 16; }
|
| 573 |
+
tracy_force_inline void SetEnd( int64_t end ) { assert( end < (int64_t)( 1ull << 47 ) ); _end.SetVal( end ); }
|
| 574 |
+
tracy_force_inline bool IsEndValid() const { return _end.IsNonNegative(); }
|
| 575 |
+
tracy_force_inline uint16_t Thread() const { return uint16_t( _start_thread ); }
|
| 576 |
+
tracy_force_inline void SetThread( uint16_t thread ) { memcpy( &_start_thread, &thread, 2 ); }
|
| 577 |
+
|
| 578 |
+
tracy_force_inline void SetStartThread( int64_t start, uint16_t thread ) { assert( start < (int64_t)( 1ull << 47 ) ); _start_thread = ( uint64_t( start ) << 16 ) | thread; }
|
| 579 |
+
|
| 580 |
+
uint64_t _start_thread;
|
| 581 |
+
Int48 _end;
|
| 582 |
+
};
|
| 583 |
+
|
| 584 |
+
enum { ContextSwitchCpuSize = sizeof( ContextSwitchCpu ) };
|
| 585 |
+
|
| 586 |
+
|
| 587 |
+
struct ContextSwitchUsage
|
| 588 |
+
{
|
| 589 |
+
ContextSwitchUsage() {}
|
| 590 |
+
ContextSwitchUsage( int64_t time, uint8_t other, uint8_t own ) { SetTime( time ); SetOther( other ); SetOwn( own ); }
|
| 591 |
+
|
| 592 |
+
tracy_force_inline int64_t Time() const { return int64_t( _time_other_own ) >> 16; }
|
| 593 |
+
tracy_force_inline void SetTime( int64_t time ) { assert( time < (int64_t)( 1ull << 47 ) ); memcpy( ((char*)&_time_other_own)+2, &time, 4 ); memcpy( ((char*)&_time_other_own)+6, ((char*)&time)+4, 2 ); }
|
| 594 |
+
tracy_force_inline uint8_t Other() const { return uint8_t( _time_other_own ); }
|
| 595 |
+
tracy_force_inline void SetOther( uint8_t other ) { memcpy( &_time_other_own, &other, 1 ); }
|
| 596 |
+
tracy_force_inline uint8_t Own() const { uint8_t v; memcpy( &v, ((char*)&_time_other_own)+1, 1 );return v; }
|
| 597 |
+
tracy_force_inline void SetOwn( uint8_t own ) { memcpy( ((char*)&_time_other_own)+1, &own, 1 ); }
|
| 598 |
+
|
| 599 |
+
uint64_t _time_other_own;
|
| 600 |
+
};
|
| 601 |
+
|
| 602 |
+
enum { ContextSwitchUsageSize = sizeof( ContextSwitchUsage ) };
|
| 603 |
+
|
| 604 |
+
|
| 605 |
+
struct MessageData
|
| 606 |
+
{
|
| 607 |
+
int64_t time;
|
| 608 |
+
StringRef ref;
|
| 609 |
+
uint16_t thread;
|
| 610 |
+
uint32_t color;
|
| 611 |
+
Int24 callstack;
|
| 612 |
+
};
|
| 613 |
+
|
| 614 |
+
enum { MessageDataSize = sizeof( MessageData ) };
|
| 615 |
+
|
| 616 |
+
|
| 617 |
+
struct PlotItem
|
| 618 |
+
{
|
| 619 |
+
Int48 time;
|
| 620 |
+
double val;
|
| 621 |
+
};
|
| 622 |
+
|
| 623 |
+
enum { PlotItemSize = sizeof( PlotItem ) };
|
| 624 |
+
|
| 625 |
+
|
| 626 |
+
struct FrameEvent
|
| 627 |
+
{
|
| 628 |
+
int64_t start;
|
| 629 |
+
int64_t end;
|
| 630 |
+
int32_t frameImage;
|
| 631 |
+
};
|
| 632 |
+
|
| 633 |
+
enum { FrameEventSize = sizeof( FrameEvent ) };
|
| 634 |
+
|
| 635 |
+
|
| 636 |
+
struct FrameImage
|
| 637 |
+
{
|
| 638 |
+
short_ptr<const char> ptr;
|
| 639 |
+
uint32_t csz;
|
| 640 |
+
uint16_t w, h;
|
| 641 |
+
uint32_t frameRef;
|
| 642 |
+
uint8_t flip;
|
| 643 |
+
};
|
| 644 |
+
|
| 645 |
+
enum { FrameImageSize = sizeof( FrameImage ) };
|
| 646 |
+
|
| 647 |
+
|
| 648 |
+
struct GhostZone
|
| 649 |
+
{
|
| 650 |
+
Int48 start, end;
|
| 651 |
+
Int24 frame;
|
| 652 |
+
int32_t child;
|
| 653 |
+
};
|
| 654 |
+
|
| 655 |
+
enum { GhostZoneSize = sizeof( GhostZone ) };
|
| 656 |
+
|
| 657 |
+
|
| 658 |
+
struct ChildSample
|
| 659 |
+
{
|
| 660 |
+
Int48 time;
|
| 661 |
+
uint64_t addr;
|
| 662 |
+
};
|
| 663 |
+
|
| 664 |
+
enum { ChildSampleSize = sizeof( ChildSample ) };
|
| 665 |
+
|
| 666 |
+
#pragma pack( pop )
|
| 667 |
+
|
| 668 |
+
|
| 669 |
+
struct ThreadData
|
| 670 |
+
{
|
| 671 |
+
uint64_t id;
|
| 672 |
+
uint64_t count;
|
| 673 |
+
Vector<short_ptr<ZoneEvent>> timeline;
|
| 674 |
+
Vector<short_ptr<ZoneEvent>> stack;
|
| 675 |
+
Vector<short_ptr<MessageData>> messages;
|
| 676 |
+
uint32_t nextZoneId;
|
| 677 |
+
Vector<uint32_t> zoneIdStack;
|
| 678 |
+
#ifndef TRACY_NO_STATISTICS
|
| 679 |
+
Vector<int64_t> childTimeStack;
|
| 680 |
+
Vector<GhostZone> ghostZones;
|
| 681 |
+
uint64_t ghostIdx;
|
| 682 |
+
SortedVector<SampleData, SampleDataSort> postponedSamples;
|
| 683 |
+
#endif
|
| 684 |
+
Vector<SampleData> samples;
|
| 685 |
+
SampleData pendingSample;
|
| 686 |
+
Vector<SampleData> ctxSwitchSamples;
|
| 687 |
+
uint64_t kernelSampleCnt;
|
| 688 |
+
uint8_t isFiber;
|
| 689 |
+
ThreadData* fiber;
|
| 690 |
+
uint8_t* stackCount;
|
| 691 |
+
int32_t groupHint;
|
| 692 |
+
|
| 693 |
+
tracy_force_inline void IncStackCount( int16_t srcloc ) { stackCount[uint16_t(srcloc)]++; }
|
| 694 |
+
tracy_force_inline bool DecStackCount( int16_t srcloc ) { return --stackCount[uint16_t(srcloc)] != 0; }
|
| 695 |
+
};
|
| 696 |
+
|
| 697 |
+
struct GpuCtxThreadData
|
| 698 |
+
{
|
| 699 |
+
Vector<short_ptr<GpuEvent>> timeline;
|
| 700 |
+
Vector<short_ptr<GpuEvent>> stack;
|
| 701 |
+
};
|
| 702 |
+
|
| 703 |
+
struct GpuCtxData
|
| 704 |
+
{
|
| 705 |
+
int64_t timeDiff;
|
| 706 |
+
uint64_t thread;
|
| 707 |
+
uint64_t count;
|
| 708 |
+
float period;
|
| 709 |
+
GpuContextType type;
|
| 710 |
+
bool hasPeriod;
|
| 711 |
+
bool hasCalibration;
|
| 712 |
+
int64_t calibratedGpuTime;
|
| 713 |
+
int64_t calibratedCpuTime;
|
| 714 |
+
double calibrationMod;
|
| 715 |
+
int64_t lastGpuTime;
|
| 716 |
+
uint64_t overflow;
|
| 717 |
+
uint32_t overflowMul;
|
| 718 |
+
StringIdx name;
|
| 719 |
+
unordered_flat_map<uint64_t, GpuCtxThreadData> threadData;
|
| 720 |
+
short_ptr<GpuEvent> query[64*1024];
|
| 721 |
+
};
|
| 722 |
+
|
| 723 |
+
enum { GpuCtxDataSize = sizeof( GpuCtxData ) };
|
| 724 |
+
|
| 725 |
+
|
| 726 |
+
enum class PlotType : uint8_t
|
| 727 |
+
{
|
| 728 |
+
User,
|
| 729 |
+
Memory,
|
| 730 |
+
SysTime,
|
| 731 |
+
Power
|
| 732 |
+
};
|
| 733 |
+
|
| 734 |
+
// Keep this in sync with enum in TracyC.h
|
| 735 |
+
enum class PlotValueFormatting : uint8_t
|
| 736 |
+
{
|
| 737 |
+
Number,
|
| 738 |
+
Memory,
|
| 739 |
+
Percentage,
|
| 740 |
+
Watt
|
| 741 |
+
};
|
| 742 |
+
|
| 743 |
+
struct PlotData
|
| 744 |
+
{
|
| 745 |
+
struct PlotItemSort { bool operator()( const PlotItem& lhs, const PlotItem& rhs ) { return lhs.time.Val() < rhs.time.Val(); }; };
|
| 746 |
+
|
| 747 |
+
uint64_t name;
|
| 748 |
+
double min;
|
| 749 |
+
double max;
|
| 750 |
+
double sum;
|
| 751 |
+
SortedVector<PlotItem, PlotItemSort> data;
|
| 752 |
+
PlotType type;
|
| 753 |
+
PlotValueFormatting format;
|
| 754 |
+
uint8_t showSteps;
|
| 755 |
+
uint8_t fill;
|
| 756 |
+
uint32_t color;
|
| 757 |
+
|
| 758 |
+
double rMin, rMax, num;
|
| 759 |
+
};
|
| 760 |
+
|
| 761 |
+
struct MemData
|
| 762 |
+
{
|
| 763 |
+
Vector<MemEvent> data;
|
| 764 |
+
Vector<uint32_t> frees;
|
| 765 |
+
unordered_flat_map<uint64_t, size_t> active;
|
| 766 |
+
uint64_t high = std::numeric_limits<uint64_t>::min();
|
| 767 |
+
uint64_t low = std::numeric_limits<uint64_t>::max();
|
| 768 |
+
uint64_t usage = 0;
|
| 769 |
+
PlotData* plot = nullptr;
|
| 770 |
+
bool reconstruct = false;
|
| 771 |
+
uint64_t name = 0;
|
| 772 |
+
};
|
| 773 |
+
|
| 774 |
+
struct FrameData
|
| 775 |
+
{
|
| 776 |
+
uint64_t name;
|
| 777 |
+
Vector<FrameEvent> frames;
|
| 778 |
+
uint8_t continuous;
|
| 779 |
+
|
| 780 |
+
int64_t min = std::numeric_limits<int64_t>::max();
|
| 781 |
+
int64_t max = std::numeric_limits<int64_t>::min();
|
| 782 |
+
int64_t total = 0;
|
| 783 |
+
double sumSq = 0;
|
| 784 |
+
};
|
| 785 |
+
|
| 786 |
+
struct StringLocation
|
| 787 |
+
{
|
| 788 |
+
const char* ptr;
|
| 789 |
+
uint32_t idx;
|
| 790 |
+
};
|
| 791 |
+
|
| 792 |
+
struct SourceLocationHasher
|
| 793 |
+
{
|
| 794 |
+
size_t operator()( const SourceLocation* ptr ) const
|
| 795 |
+
{
|
| 796 |
+
return charutil::hash( (const char*)ptr, sizeof( SourceLocationBase ) );
|
| 797 |
+
}
|
| 798 |
+
};
|
| 799 |
+
|
| 800 |
+
struct SourceLocationComparator
|
| 801 |
+
{
|
| 802 |
+
bool operator()( const SourceLocation* lhs, const SourceLocation* rhs ) const
|
| 803 |
+
{
|
| 804 |
+
return memcmp( lhs, rhs, sizeof( SourceLocationBase ) ) == 0;
|
| 805 |
+
}
|
| 806 |
+
};
|
| 807 |
+
|
| 808 |
+
|
| 809 |
+
struct ContextSwitch
|
| 810 |
+
{
|
| 811 |
+
Vector<ContextSwitchData> v;
|
| 812 |
+
int64_t runningTime = 0;
|
| 813 |
+
};
|
| 814 |
+
|
| 815 |
+
struct CpuData
|
| 816 |
+
{
|
| 817 |
+
Vector<ContextSwitchCpu> cs;
|
| 818 |
+
};
|
| 819 |
+
|
| 820 |
+
struct CpuThreadData
|
| 821 |
+
{
|
| 822 |
+
int64_t runningTime = 0;
|
| 823 |
+
uint32_t runningRegions = 0;
|
| 824 |
+
uint32_t migrations = 0;
|
| 825 |
+
};
|
| 826 |
+
|
| 827 |
+
enum { CpuThreadDataSize = sizeof( CpuThreadData ) };
|
| 828 |
+
|
| 829 |
+
|
| 830 |
+
struct Parameter
|
| 831 |
+
{
|
| 832 |
+
uint32_t idx;
|
| 833 |
+
StringRef name;
|
| 834 |
+
bool isBool;
|
| 835 |
+
int32_t val;
|
| 836 |
+
};
|
| 837 |
+
|
| 838 |
+
|
| 839 |
+
struct SymbolStats
|
| 840 |
+
{
|
| 841 |
+
uint32_t incl, excl;
|
| 842 |
+
unordered_flat_map<uint32_t, uint32_t> parents;
|
| 843 |
+
unordered_flat_map<uint32_t, uint32_t> baseParents;
|
| 844 |
+
};
|
| 845 |
+
|
| 846 |
+
enum { SymbolStatsSize = sizeof( SymbolStats ) };
|
| 847 |
+
|
| 848 |
+
}
|
| 849 |
+
|
| 850 |
+
#endif
|
third_party/tracy/server/TracyFileHeader.hpp
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#ifndef __TRACYFILEHEADER_HPP__
|
| 2 |
+
#define __TRACYFILEHEADER_HPP__
|
| 3 |
+
|
| 4 |
+
#include <stdint.h>
|
| 5 |
+
|
| 6 |
+
#include "../public/common/TracyForceInline.hpp"
|
| 7 |
+
|
| 8 |
+
namespace tracy
|
| 9 |
+
{
|
| 10 |
+
|
| 11 |
+
static const uint8_t TracyHeader[4] = { 't', 'r', 253, 'P' };
|
| 12 |
+
static const uint8_t Lz4Header[4] = { 't', 'l', 'Z', 4 };
|
| 13 |
+
static const uint8_t ZstdHeader[4] = { 't', 'Z', 's', 't' };
|
| 14 |
+
|
| 15 |
+
static constexpr tracy_force_inline int FileVersion( uint8_t h5, uint8_t h6, uint8_t h7 )
|
| 16 |
+
{
|
| 17 |
+
return ( h5 << 16 ) | ( h6 << 8 ) | h7;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
#endif
|