Browse Source

Added build to validate determinism between Windows, Linux and MacOS (#189)

PerformanceTest now supports -validate_hash=... to check the hash.
Jorrit Rouwe 3 năm trước cách đây
mục cha
commit
564526ad3d

+ 76 - 0
.github/workflows/determinism_check.yml

@@ -0,0 +1,76 @@
+name: Determinism Check
+
+env:
+    CONVEX_VS_MESH_HASH: '0x4245064f2c076b63'
+    RAGDOLL_HASH: '0xffa62c540d58c892'
+
+on:
+  push:
+    branches: [ master ]
+    paths-ignore:
+      - 'Docs/**'
+      - '**.md'
+      - '**.txt'
+  pull_request:
+    branches: [ master ]
+    paths-ignore:
+      - 'Docs/**'
+      - '**.md'
+      - '**.txt'
+
+jobs:
+  linux:
+    runs-on: ubuntu-latest
+    name: Linux Determinism Check
+
+    steps:
+    - name: Checkout Code
+      uses: actions/checkout@v2
+    - name: Configure CMake
+      run: cmake -B ${{github.workspace}}/Build/Linux_Distribution -DCMAKE_BUILD_TYPE=Distribution Build -DCROSS_PLATFORM_DETERMINISTIC=ON -DTARGET_VIEWER=OFF -DTARGET_SAMPLES=OFF -DTARGET_HELLO_WORLD=OFF -DTARGET_UNIT_TESTS=OFF
+    - name: Build
+      run: cmake --build ${{github.workspace}}/Build/Linux_Distribution --config Distribution
+    - name: Test ConvexVsMesh
+      working-directory: ${{github.workspace}}/Build/Linux_Distribution
+      run: ./PerformanceTest -q=Discrete -t=2 -s=ConvexVsMesh -validate_hash=${CONVEX_VS_MESH_HASH}
+    - name: Test Ragdoll
+      working-directory: ${{github.workspace}}/Build/Linux_Distribution
+      run: ./PerformanceTest -q=Discrete -t=2 -s=Ragdoll -validate_hash=${RAGDOLL_HASH}
+
+  msvc_cl:
+    runs-on: windows-latest
+    name: Visual Studio CL Determinism Check
+
+    steps:
+    - name: Checkout Code
+      uses: actions/checkout@v2
+    - name: Add msbuild to PATH
+      uses: microsoft/[email protected]
+    - name: Configure CMake
+      run: cmake -B ${{github.workspace}}/Build/VS2022_CL -G "Visual Studio 17 2022" -A x64 Build -DCROSS_PLATFORM_DETERMINISTIC=ON -DTARGET_VIEWER=OFF -DTARGET_SAMPLES=OFF -DTARGET_HELLO_WORLD=OFF -DTARGET_UNIT_TESTS=OFF
+    - name: Build
+      run: msbuild Build\VS2022_CL\JoltPhysics.sln /property:Configuration=Distribution
+    - name: Test ConvexVsMesh
+      working-directory: ${{github.workspace}}/Build/VS2022_CL/Distribution
+      run: ./PerformanceTest -q=Discrete -t=2 -s=ConvexVsMesh "-validate_hash=$env:CONVEX_VS_MESH_HASH"
+    - name: Test Ragdoll
+      working-directory: ${{github.workspace}}/Build/VS2022_CL/Distribution
+      run: ./PerformanceTest -q=Discrete -t=2 -s=Ragdoll "-validate_hash=$env:RAGDOLL_HASH"
+
+  macos:
+    runs-on: macos-latest
+    name: MacOS Determinism Check
+
+    steps:
+    - name: Checkout Code
+      uses: actions/checkout@v2
+    - name: Configure CMake
+      run: cmake -B ${{github.workspace}}/Build/Linux_Distribution -DCMAKE_BUILD_TYPE=Distribution Build -DCROSS_PLATFORM_DETERMINISTIC=ON -DTARGET_VIEWER=OFF -DTARGET_SAMPLES=OFF -DTARGET_HELLO_WORLD=OFF -DTARGET_UNIT_TESTS=OFF -DUSE_AVX2=OFF -DUSE_AVX512=OFF -DUSE_LZCNT=OFF -DUSE_TZCNT=OFF
+    - name: Build
+      run: cmake --build ${{github.workspace}}/Build/Linux_Distribution --config Distribution
+    - name: Test ConvexVsMesh
+      working-directory: ${{github.workspace}}/Build/Linux_Distribution
+      run: ./PerformanceTest -q=Discrete -t=2 -s=ConvexVsMesh -validate_hash=${CONVEX_VS_MESH_HASH}
+    - name: Test Ragdoll
+      working-directory: ${{github.workspace}}/Build/Linux_Distribution
+      run: ./PerformanceTest -q=Discrete -t=2 -s=Ragdoll -validate_hash=${RAGDOLL_HASH}

+ 4 - 1
Build/CMakeLists.txt

@@ -246,7 +246,10 @@ if (NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore")
 			target_link_options(PerformanceTest PUBLIC "/SUBSYSTEM:CONSOLE")
 		endif()
 		set_property(TARGET PerformanceTest PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${PHYSICS_REPO_ROOT}")
-	endif()
+		
+		# Copy the assets folder
+		add_custom_command(TARGET PerformanceTest PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${PHYSICS_REPO_ROOT}/Assets/ $<TARGET_FILE_DIR:PerformanceTest>/Assets/)
+	   endif()
 endif()
 
 if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")

+ 5 - 3
Build/cmake_linux_clang_gcc.sh

@@ -5,13 +5,15 @@ then
 	BUILD_TYPE=Debug
 else
 	BUILD_TYPE=$1
+	shift
 fi
 
-if [ -z $2 ] 
+if [ -z $1 ] 
 then
 	COMPILER=clang++
 else
-	COMPILER=$2
+	COMPILER=$1
+	shift
 fi
 
 BUILD_DIR=Linux_$BUILD_TYPE
@@ -21,6 +23,6 @@ echo "Possible configurations: Debug (default), Release, Distribution, ReleaseUB
 echo "Possible compilers: clang++, clang++-XX, g++, g++-XX where XX is the version"
 echo Generating Makefile for build type \"$BUILD_TYPE\" and compiler \"$COMPILER\" in folder \"$BUILD_DIR\"
 
-cmake -S . -B $BUILD_DIR -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=$COMPILER
+cmake -S . -B $BUILD_DIR -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=$COMPILER "${@}"
 
 echo Compile by running \"make -j 8 \&\& ./UnitTests\" in folder \"$BUILD_DIR\"

+ 1 - 1
Build/cmake_vs2022_cl.bat

@@ -1,3 +1,3 @@
 @echo off
-cmake -S . -B VS2022_CL -G "Visual Studio 17 2022" -A x64
+cmake -S . -B VS2022_CL -G "Visual Studio 17 2022" -A x64 %*
 echo Open VS2022_CL\JoltPhysics.sln to build the project.

+ 1 - 0
Docs/PerformanceTest.md

@@ -17,6 +17,7 @@ The performance test application contains a couple of simple scenes to test perf
 - -h: Displays a help text
 - -rs: Record the simulation state in state_[tag].bin.
 - -vs: Validate the recorded simulation state from state_[tag].bin. This will after every simulation step check that the state is the same as the recorded state and trigger a breakpoint if this is not the case. This is used to validate cross platform determinism.
+- -validate_hash=[hash]: Will validate that the hash of the simulation matches the supplied hash. Program terminates with return code 1 if it doesn't. Can be used to automatically validate determinism.
 
 ## Output
 

+ 20 - 2
PerformanceTest/PerformanceTest.cpp

@@ -67,6 +67,7 @@ int main(int argc, char** argv)
 	bool record_state = false;
 	bool validate_state = false;
 	unique_ptr<PerformanceTestScene> scene;
+	const char *validate_hash = nullptr;
 	for (int argidx = 1; argidx < argc; ++argidx)
 	{
 		const char *arg = argv[argidx];
@@ -133,6 +134,10 @@ int main(int argc, char** argv)
 		{
 			validate_state = true;
 		}
+		else if (strncmp(arg, "-validate_hash=", 15) == 0)
+		{
+			validate_hash = arg + 15;
+		}
 		else if (strcmp(arg, "-h") == 0)
 		{
 			// Print usage
@@ -146,7 +151,8 @@ int main(int argc, char** argv)
 				 << "-f: Record per frame timings" << endl
 				 << "-no_sleep: Disable sleeping" << endl
 				 << "-rs: Record state" << endl
-				 << "-vs: Validate state" << endl;
+				 << "-vs: Validate state" << endl
+				 << "-validate_hash=<hash>: Validate hash (return 0 if successful, 1 if failed)" << endl;
 			return 0;
 		}
 	}
@@ -345,11 +351,23 @@ int main(int argc, char** argv)
 				hash = HashBytes(&rot, sizeof(Quat), hash);
 			}
 
+			// Convert hash to string
+			stringstream hash_stream;
+			hash_stream << "0x" << hex << hash << dec;
+			string hash_str = hash_stream.str();
+
 			// Stop test scene
 			scene->StopTest(physics_system);
 
 			// Trace stat line
-			cout << motion_quality_str << ", " << num_threads + 1 << ", " << double(max_iterations) / (1.0e-9 * total_duration.count()) << ", 0x" << hex << hash << dec << endl;
+			cout << motion_quality_str << ", " << num_threads + 1 << ", " << double(max_iterations) / (1.0e-9 * total_duration.count()) << ", " << hash_str << endl;
+
+			// Check hash code
+			if (validate_hash != nullptr && hash_str != validate_hash)
+			{
+				cout << "Fail hash validation. Was: " << hash_str << ", expected: " << validate_hash << endl;
+				return 1;
+			}
 		}
 	}