Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 134 additions & 4 deletions .github/workflows/ci-steps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,62 @@ jobs:
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libxmu-dev libxi-dev libgl-dev libxrandr-dev libxinerama-dev libxcursor-dev mono-complete

- name: Setup Virtual GPU for Testing (Linux only)
if: runner.os == 'Linux'
run: |
echo "=== Setting up Linux Software Rendering ==="

# Set up Xvfb (virtual display) and Vulkan software rendering
sudo apt-get update
sudo apt-get install -y xvfb mesa-utils libgl1-mesa-dri mesa-vulkan-drivers vulkan-tools

# Start Xvfb and wait for it to be ready
Xvfb :99 -screen 0 1024x768x24 &
sleep 2 # Give Xvfb time to start
export DISPLAY=:99
echo "DISPLAY=:99" >> $GITHUB_ENV

# Verify Xvfb is running
echo "=== Verifying Xvfb startup ==="
ps aux | grep Xvfb | grep -v grep || echo "Xvfb not found in process list"
echo "DISPLAY variable: $DISPLAY"

# Try both approaches: OpenGL software + Vulkan software
echo "LIBGL_ALWAYS_SOFTWARE=1" >> $GITHUB_ENV # OpenGL software fallback
echo "GALLIUM_DRIVER=llvmpipe" >> $GITHUB_ENV # LLVMpipe for OpenGL
echo "VK_ICD_FILENAMES=$LAVAPIPE_ICD" >> $GITHUB_ENV # Lavapipe for Vulkan

# Find the correct Lavapipe ICD file (for Vulkan fallback testing)
echo "=== Available Vulkan ICD files ==="
ls -la /usr/share/vulkan/icd.d/ || echo "No ICD directory found"

LAVAPIPE_ICD=$(find /usr/share/vulkan/icd.d/ -name "*lvp*" -o -name "*lavapipe*" 2>/dev/null | head -1)
if [ -z "$LAVAPIPE_ICD" ]; then
LAVAPIPE_ICD="/usr/share/vulkan/icd.d/lvp_icd.x86_64.json" # Fallback
fi
echo "VK_ICD_FILENAMES=$LAVAPIPE_ICD" >> $GITHUB_ENV
echo "Found Lavapipe ICD: $LAVAPIPE_ICD"

# Mesa tuning for better accuracy (potentially closer to hardware)
echo "MESA_GL_VERSION_OVERRIDE=4.6" >> $GITHUB_ENV
echo "MESA_GLSL_VERSION_OVERRIDE=460" >> $GITHUB_ENV
echo "GALLIUM_LLVM_DISABLE_UNSAFE_FP_MATH=1" >> $GITHUB_ENV # More precise floating point math
echo "MESA_NO_DITHER=1" >> $GITHUB_ENV # Disable dithering
echo "LP_NUM_THREADS=1" >> $GITHUB_ENV # Single-threaded for determinism

# Test all available software renderers for comparison
echo "=== Testing LLVMpipe (Original) ==="
DISPLAY=:99 LIBGL_ALWAYS_SOFTWARE=1 GALLIUM_DRIVER=llvmpipe glxinfo | grep -E "(OpenGL version|OpenGL renderer)" || echo "LLVMpipe test failed"

echo "=== Testing Tuned LLVMpipe ==="
DISPLAY=:99 LIBGL_ALWAYS_SOFTWARE=1 GALLIUM_DRIVER=llvmpipe MESA_GL_VERSION_OVERRIDE=4.6 MESA_GLSL_VERSION_OVERRIDE=460 GALLIUM_LLVM_DISABLE_UNSAFE_FP_MATH=1 glxinfo | grep -E "(OpenGL version|OpenGL renderer)" || echo "Tuned LLVMpipe test failed"

echo "=== Testing Vulkan/Lavapipe availability ==="
DISPLAY=:99 VK_ICD_FILENAMES="$LAVAPIPE_ICD" vulkaninfo --summary 2>/dev/null | grep -E "(deviceName|driverName)" || echo "Vulkan Lavapipe test failed"

echo "=== Testing Zink + Lavapipe (OpenGL-on-Vulkan fallback) ==="
DISPLAY=:99 LIBGL_ALWAYS_SOFTWARE=1 GALLIUM_DRIVER=zink VK_ICD_FILENAMES="$LAVAPIPE_ICD" glxinfo | grep -E "(OpenGL version|OpenGL renderer)" || echo "Zink+Lavapipe test failed"

- name: Install required dependencies (MacOS only)
if: runner.os == 'macOS'
run: brew install mono
Expand All @@ -50,13 +106,87 @@ jobs:
- name: Build
run: cmake --build --preset ${{ inputs.build_type }}

# Unit tests still failing using pixar USD.
# - name: Test
# run: ctest --preset ${{ inputs.build_type }}
- name: Test
if: runner.os == 'Linux'
run: |
echo "=== Debug: Environment variables before test ==="
echo "DISPLAY: $DISPLAY"
echo "LIBGL_ALWAYS_SOFTWARE: $LIBGL_ALWAYS_SOFTWARE"
echo "GALLIUM_DRIVER: $GALLIUM_DRIVER"
echo "MESA_GL_VERSION_OVERRIDE: $MESA_GL_VERSION_OVERRIDE"

echo "=== Verifying Xvfb is still running ==="
ps aux | grep Xvfb | grep -v grep || echo "Xvfb not running!"
netstat -ln | grep :6099 || echo "X11 port not listening"

echo "=== Testing GLX setup before running actual tests ==="
glxinfo | head -10 || echo "glxinfo failed"

echo "=== Detailed GLX configuration ==="
glxinfo -B || echo "glxinfo -B failed"

echo "=== Testing Vulkan + Lavapipe directly ==="
vulkaninfo --summary | head -10 || echo "Vulkan test failed"

echo "=== Note: HVT Vulkan tests disabled by default (would require rebuild) ==="
echo "Current test will use OpenGL + LLVMpipe software rendering"

echo "=== Running ctest with explicit environment ==="
ctest --preset ${{ inputs.build_type }} --output-on-failure
env:
DISPLAY: :99
LIBGL_ALWAYS_SOFTWARE: 1
GALLIUM_DRIVER: llvmpipe

MESA_GL_VERSION_OVERRIDE: 4.6
MESA_GLSL_VERSION_OVERRIDE: 460
GALLIUM_LLVM_DISABLE_UNSAFE_FP_MATH: 1
MESA_NO_DITHER: 1
LP_NUM_THREADS: 1

- name: Debug Test Output Files
if: runner.os == 'Linux' && always()
run: |
echo "=== Test output directory structure ==="
find build/${{ inputs.build_type }}/ -name "*.png" -type f 2>/dev/null | head -20 || echo "No PNG files found in build dir"
echo "=== Test source baseline structure ==="
find test/ -name "*.png" -type f 2>/dev/null | head -20 || echo "No PNG files found in test dir"
echo "=== Current environment ==="
echo "GALLIUM_DRIVER: $GALLIUM_DRIVER" # Should show "llvmpipe"
echo "VK_ICD_FILENAMES: $VK_ICD_FILENAMES" # Should show lavapipe path (for fallback)
echo "LIBGL_ALWAYS_SOFTWARE: $LIBGL_ALWAYS_SOFTWARE"
echo "MESA_GL_VERSION_OVERRIDE: $MESA_GL_VERSION_OVERRIDE"
echo "MESA_GLSL_VERSION_OVERRIDE: $MESA_GLSL_VERSION_OVERRIDE"
echo "GALLIUM_LLVM_DISABLE_UNSAFE_FP_MATH: $GALLIUM_LLVM_DISABLE_UNSAFE_FP_MATH"
echo "MESA_NO_DITHER: $MESA_NO_DITHER"
echo "LP_NUM_THREADS: $LP_NUM_THREADS"

- name: Upload Generated Test Images
if: runner.os == 'Linux' && always()
uses: actions/upload-artifact@v4
with:
name: test-images-llvmpipe-tuned-${{ inputs.build_type }}
path: |
build/${{ inputs.build_type }}/test/**/generated_*.png
build/${{ inputs.build_type }}/test/**/*_computed.png
build/${{ inputs.build_type }}/test/**/*_output.png
if-no-files-found: warn

- name: Upload Baseline Images for Comparison
if: runner.os == 'Linux' && always()
uses: actions/upload-artifact@v4
with:
name: baseline-images-${{ inputs.build_type }}
path: |
test/**/baseline_*.png
test/**/*_linux.png
test/**/*_osx.png
test/**/baselines/**/*.png
if-no-files-found: warn

- name: Upload vcpkg failure logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: vcpkg-build-logs
name: vcpkg-build-logs-${{ runner.os }}-${{ inputs.build_type }}
path: externals/vcpkg/buildtrees
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,15 @@ string(COMPARE EQUAL "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}" _HVT_PR
if (_HVT_PROJECT_IS_TOP_LEVEL AND UNIX)
set_if_not_defined(CMAKE_SKIP_BUILD_RPATH TRUE "")
set_if_not_defined(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE "")
set_if_not_defined(CMAKE_INSTALL_RPATH "@loader_path/" "")
if(APPLE)
set_if_not_defined(CMAKE_INSTALL_RPATH "@loader_path/" "")
else()
# Linux and other Unix systems use $ORIGIN instead of @loader_path
set_if_not_defined(CMAKE_INSTALL_RPATH "$ORIGIN/" "")
# Force RPATH instead of RUNPATH on Linux for better library discovery
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--disable-new-dtags")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--disable-new-dtags")
endif()
set_if_not_defined(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE "")

# macOS specific (ignored on other platforms)
Expand Down
26 changes: 26 additions & 0 deletions test/RenderingFramework/TestHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#include <RenderingFramework/TestHelpers.h>

#include <cstdlib> // For getenv

#if TARGET_OS_IPHONE
#include <RenderingFramework/MetalTestContext.h>
#else
Expand Down Expand Up @@ -102,11 +104,28 @@
return camelCaseFilename;
}

bool isSoftwareRenderingEnabled()
{
// Check if software rendering is enabled via environment variable
// Note: In test environment, this is safe - worst case is wrong baseline selection
// NOLINTNEXTLINE(concurrency-mt-unsafe) - Test code, single-threaded usage
const char* softwareRendering = getenv("LIBGL_ALWAYS_SOFTWARE");

Check warning on line 112 in test/RenderingFramework/TestHelpers.cpp

View check run for this annotation

Autodesk Chorus / security/flawfinder

getenv

Environment variables are untrustable input if they can be set by an attacker. They can have any content and length, and the same variable can be set more than once (CWE-807, CWE-20).
if (softwareRendering != nullptr) {
// Validate the environment variable value for safety
std::string envValue(softwareRendering);
return (envValue == "1" || envValue == "true");
Comment on lines +112 to +116
Copy link

Copilot AI Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using getenv() can be unsafe in multi-threaded environments. Consider using a thread-safe alternative or ensuring this function is only called during single-threaded initialization phases.

Suggested change
const char* softwareRendering = getenv("LIBGL_ALWAYS_SOFTWARE");
if (softwareRendering != nullptr) {
// Validate the environment variable value for safety
std::string envValue(softwareRendering);
return (envValue == "1" || envValue == "true");
const std::string softwareRendering = getEnvVar("LIBGL_ALWAYS_SOFTWARE");
if (!softwareRendering.empty()) {
// Validate the environment variable value for safety
return (softwareRendering == "1" || softwareRendering == "true");

Copilot uses AI. Check for mistakes.

}
return false;
}

std::string HydraRendererContext::getFilename(
const std::filesystem::path& filePath, const std::string& filename)
{
std::string fullFilepath = filePath.string() + "/" + filename;

// Use helper function to detect software rendering
bool isSoftwareRendering = isSoftwareRenderingEnabled();

#ifdef __ANDROID__
fullFilepath += "_android";
#elif defined(__APPLE__)
Expand All @@ -120,8 +139,15 @@
}
fullFilepath += "_ios";
#else
// macOS hardware GPU uses _osx baselines
Copy link

Copilot AI Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an extra trailing space after 'baselines' in the comment.

Suggested change
// macOS hardware GPU uses _osx baselines
// macOS hardware GPU uses _osx baselines

Copilot uses AI. Check for mistakes.

fullFilepath += "_osx";
#endif // TARGET_OS_IPHONE
#elif defined(__linux__)
if (isSoftwareRendering) {
// Linux software rendering (CI environment)
fullFilepath += "_linux";
}
// Linux hardware GPU uses main baselines
#endif // __ANDROID__
fullFilepath += ".png";

Expand Down
4 changes: 4 additions & 0 deletions test/RenderingFramework/TestHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ std::filesystem::path const& getAssetsDataFolder();
/// Gets the path to the data directory where to find baseline images.
std::filesystem::path const& getBaselineFolder();

/// Detects if software rendering is enabled via environment variable.
/// Returns true if LIBGL_ALWAYS_SOFTWARE is set to "1" or "true".
bool isSoftwareRenderingEnabled();

/// Base class for the OpenGL and Metal context renderers.
class HydraRendererContext
{
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/TestFramePasses_MainOnly_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/TestFramePasses_MainWithBlur_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/TestFramePasses_MainWithFxaa_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/TestFramePasses_MultiViewports_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/TestFramePasses_SceneIndex_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/TestSearchFaces_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/TestSearchPrims_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/TestTaskManager_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/compose_ComposeTask2_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/compose_ComposeTask3_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/compose_ComposeTask_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/compose_ShareTextures4_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/compose_ShareTextures_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/howTo/createACustomRenderTask_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/howTo/createMinimalListOfTasks_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/howTo/createOneFramePass_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/howTo/useCollectionToExclude_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/howTo/useCollectionToInclude_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/howTo/useFXAARenderTask_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/howTo/useSSAORenderTask_linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/data/baselines/howTo/useSkyDomeTask_linux.png
3 changes: 3 additions & 0 deletions test/data/baselines/howTo/useWireFrameSceneIndex_linux.png
3 changes: 3 additions & 0 deletions test/data/baselines/testDynamicCameraAndLights_linux.png
3 changes: 3 additions & 0 deletions test/data/baselines/testDynamicResolution_linux.png
Loading
Loading