fb1ae9d3a6
Hydra's HdxColorCorrectionTask rendered prims black in OCIO mode and could corrupt the GlfDrawTarget bind stack on failure (skipping Unbind), blacking out every later frame including sRGB. Replace it with our own GL post-process: the scene renders linear (RGBA16F) and is corrected by a fullscreen shader -- linear->sRGB encode, or OCIO via the OCIO 2.1 GPU API (GpuShaderDesc plus uploaded 1D/3D LUT textures). OCIO build failures fall back to sRGB (never black) and USD diagnostics are routed to the app log. - core: ViewportColorCorrector + ApplyViewportColorCorrection in UsdSceneRenderer - utils: OcioConfigParser enumerates displays/views/colorspaces/looks from $OCIO - ui: gear-menu OCIO controls (ViewportTile) + per-viewport persistence (ViewportPanel) - Application: point $OCIO at the bundled ACES 1.2 config - CMake: link/copy OpenColorIO, download ACES 1.2 config; plus hdCycles build config (disable OpenVDB/Embree, fix TBB/OpenSubdiv/Imath dirs, exclude CRT DLLs) - main: pre-flight plugin DLL load check to skip plugins with missing deps Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
762 lines
31 KiB
CMake
762 lines
31 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
project(UsdLayerManager VERSION 1.0.0 LANGUAGES C CXX)
|
|
|
|
# Set C++ standard
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
# Add cmake modules path
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")
|
|
|
|
# Find dependencies
|
|
find_package(OpenGL REQUIRED)
|
|
find_package(OpenUSD REQUIRED)
|
|
find_package(Imgui REQUIRED)
|
|
find_package(Glad REQUIRED)
|
|
find_package(FFmpeg REQUIRED)
|
|
|
|
# OpenColorIO — provided by the OpenUSD distribution (USD built with OCIO support)
|
|
set(OpenColorIO_DIR
|
|
"${OpenUSD_ROOT_DIR}/lib/cmake/OpenColorIO"
|
|
CACHE PATH "OpenColorIO CMake config dir" FORCE)
|
|
find_package(OpenColorIO CONFIG REQUIRED)
|
|
|
|
# USD build that includes hdEmbree (built with PXR_ENABLE_EMBREE_PLUGIN=ON).
|
|
# Can be a separate install from OpenUSD_ROOT_DIR; leave empty to search there instead.
|
|
set(HDEMBREE_USD_ROOT "" CACHE PATH "USD build containing hdEmbree plugin (separate from OpenUSD_ROOT_DIR)")
|
|
# Only needed if embree*.dll are not inside HDEMBREE_USD_ROOT/bin.
|
|
set(EMBREE_LOCATION "" CACHE PATH "Embree SDK bin/ directory (leave empty if bundled in HDEMBREE_USD_ROOT/bin)")
|
|
|
|
# ── hdEmbree detection ───────────────────────────────────────────────────────
|
|
if(HDEMBREE_USD_ROOT AND EXISTS "${HDEMBREE_USD_ROOT}")
|
|
set(_hdembree_root "${HDEMBREE_USD_ROOT}")
|
|
else()
|
|
set(_hdembree_root "${OpenUSD_ROOT_DIR}")
|
|
endif()
|
|
|
|
# hdEmbree.dll lives at plugin/usd/hdEmbree.dll; the subdir holds only plugin metadata.
|
|
set(HDEMBREE_PLUGIN_DIR "${_hdembree_root}/plugin/usd/hdEmbree")
|
|
set(HDEMBREE_DLL "${_hdembree_root}/plugin/usd/hdEmbree.dll")
|
|
|
|
if(EXISTS "${HDEMBREE_PLUGIN_DIR}")
|
|
set(OPENUSD_HAS_EMBREE TRUE)
|
|
if(EMBREE_LOCATION AND EXISTS "${EMBREE_LOCATION}")
|
|
set(_embree_dll_dir "${EMBREE_LOCATION}")
|
|
else()
|
|
set(_embree_dll_dir "${_hdembree_root}/bin")
|
|
endif()
|
|
# Skip tbb*.dll — already supplied by the main USD install to avoid conflicts.
|
|
file(GLOB EMBREE_DLLS "${_embree_dll_dir}/embree*.dll")
|
|
else()
|
|
set(OPENUSD_HAS_EMBREE FALSE)
|
|
message(STATUS "hdEmbree: NOT found — set HDEMBREE_USD_ROOT to a USD build with PXR_ENABLE_EMBREE_PLUGIN=ON")
|
|
endif()
|
|
|
|
# ── hdArnold detection ───────────────────────────────────────────────────────
|
|
# HDARNOLD_ROOT: CMAKE_INSTALL_PREFIX used when building arnold-usd
|
|
set(HDARNOLD_ROOT "" CACHE PATH "arnold-usd install directory (the one containing plugin/hdArnold.dll)")
|
|
# ARNOLD_LOCATION: Arnold SDK root (MtoA dir) — needed to deploy ai.dll
|
|
set(ARNOLD_LOCATION "" CACHE PATH "Arnold SDK root (e.g. C:/Autodesk/mtoa/5.5.0/2026) for ai.dll deployment")
|
|
|
|
if(HDARNOLD_ROOT AND EXISTS "${HDARNOLD_ROOT}/plugin/hdArnold.dll")
|
|
set(OPENUSD_HAS_ARNOLD TRUE)
|
|
set(HDARNOLD_DLL "${HDARNOLD_ROOT}/plugin/hdArnold.dll")
|
|
set(NDRARNOLD_DLL "${HDARNOLD_ROOT}/plugin/ndrArnold.dll")
|
|
set(HDARNOLD_PLUGIN_DIR "${HDARNOLD_ROOT}/plugin/hdArnold")
|
|
set(NDRARNOLD_PLUGIN_DIR "${HDARNOLD_ROOT}/plugin/ndrArnold")
|
|
if(ARNOLD_LOCATION AND EXISTS "${ARNOLD_LOCATION}/bin/ai.dll")
|
|
set(ARNOLD_AI_DLL "${ARNOLD_LOCATION}/bin/ai.dll")
|
|
# ai.dll also requires companion runtime DLLs (OIDN denoiser, Adsk licensing, cer)
|
|
file(GLOB ARNOLD_RUNTIME_DLLS
|
|
"${ARNOLD_LOCATION}/bin/ai*.dll"
|
|
"${ARNOLD_LOCATION}/bin/AdClm*.dll"
|
|
"${ARNOLD_LOCATION}/bin/AdskLicensing*.dll"
|
|
"${ARNOLD_LOCATION}/bin/cer.dll"
|
|
)
|
|
else()
|
|
set(ARNOLD_AI_DLL "")
|
|
set(ARNOLD_RUNTIME_DLLS "")
|
|
endif()
|
|
else()
|
|
set(OPENUSD_HAS_ARNOLD FALSE)
|
|
message(STATUS "hdArnold: NOT found — set HDARNOLD_ROOT to the arnold-usd install dir and ARNOLD_LOCATION to the MtoA root")
|
|
endif()
|
|
|
|
# ── Cycles hdCycles Hydra render delegate ────────────────────────────────────
|
|
# Build Blender Cycles from third_party/cycles using ExternalProject.
|
|
# Set WITH_CYCLES=ON to enable; requires MSVC, and uses the precompiled libs
|
|
# bundled in third_party/cycles/lib/windows_x64/.
|
|
# hdCycles.dll is deployed to usd/ alongside hdEmbree and hdArnold.
|
|
option(WITH_CYCLES "Build Cycles Hydra render delegate from third_party/cycles" OFF)
|
|
|
|
set(CYCLES_BINARY_DIR "${CMAKE_BINARY_DIR}/cycles_build")
|
|
set(CYCLES_INSTALL_DIR "${CMAKE_BINARY_DIR}/cycles_install")
|
|
set(HDCYCLES_DLL "${CYCLES_INSTALL_DIR}/hydra/hdCycles.dll")
|
|
set(HDCYCLES_PLUGIN_DIR "${CYCLES_INSTALL_DIR}/hydra/hdCycles")
|
|
# tbb12.dll is required by openvdb/embree4 but lives in the precompiled lib tree,
|
|
# not in the install output — deploy it explicitly.
|
|
set(CYCLES_TBB12_DLL "${CMAKE_SOURCE_DIR}/third_party/cycles/lib/windows_x64/tbb/bin/tbb12.dll")
|
|
|
|
if(WITH_CYCLES)
|
|
include(ExternalProject)
|
|
|
|
# Resolve absolute USD root so we can forward it to the sub-build.
|
|
# FindOpenUSD.cmake stores the path in OpenUSD_ROOT_DIR.
|
|
if(NOT OpenUSD_ROOT_DIR)
|
|
message(FATAL_ERROR "WITH_CYCLES requires OpenUSD_ROOT_DIR to be set (run find_package(OpenUSD) first).")
|
|
endif()
|
|
|
|
ExternalProject_Add(CyclesBuild
|
|
SOURCE_DIR "${CMAKE_SOURCE_DIR}/third_party/cycles"
|
|
BINARY_DIR "${CYCLES_BINARY_DIR}"
|
|
INSTALL_DIR "${CYCLES_INSTALL_DIR}"
|
|
CMAKE_ARGS
|
|
# Always Release — Cycles' Debug build is slow and rarely needed here.
|
|
-DCMAKE_BUILD_TYPE=Release
|
|
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
|
|
# Point Cycles at our app's USD so hdCycles is ABI-compatible.
|
|
-DPXR_ROOT=${OpenUSD_ROOT_DIR}
|
|
# Hydra delegate is the only deliverable we need.
|
|
-DWITH_CYCLES_HYDRA_RENDER_DELEGATE=ON
|
|
-DWITH_CYCLES_USD=ON
|
|
# Use bundled precompiled libs from lib/windows_x64/.
|
|
-DWITH_LIBS_PRECOMPILED=ON
|
|
# Turn off heavy optional features that aren't needed for the delegate.
|
|
-DWITH_CYCLES_STANDALONE_GUI=OFF
|
|
-DWITH_CYCLES_DEVICE_CUDA=OFF
|
|
-DWITH_CYCLES_DEVICE_OPTIX=OFF
|
|
-DWITH_CYCLES_DEVICE_HIP=OFF
|
|
-DWITH_CYCLES_DEVICE_ONEAPI=OFF
|
|
-DWITH_CYCLES_LOGGING=OFF
|
|
# USD ships OpenVDB v9; Cycles prebuilt is v13 — ABI mismatch, both named
|
|
# openvdb.dll. Disable openvdb in Cycles to avoid the version conflict.
|
|
-DWITH_CYCLES_OPENVDB=OFF
|
|
# Embree4 links tbb12.dll; USD already loads tbb.dll at process startup.
|
|
# oneTBB detects the older tbb.dll and aborts initialization (DLL_INIT_FAILED).
|
|
# Disable Embree so Cycles uses its own BVH traversal instead.
|
|
-DWITH_CYCLES_EMBREE=OFF
|
|
# ---- pxrConfig.cmake dependency overrides ----
|
|
# pxrConfig.cmake runs find_dependency() for these before Cycles'
|
|
# precompiled lib paths are on CMAKE_PREFIX_PATH, so we must supply
|
|
# them explicitly. The Python3 vars also override the hardcoded
|
|
# CI build-machine path embedded in pxrConfig.cmake.
|
|
-DPython3_EXECUTABLE=$ENV{LOCALAPPDATA}/Programs/Python/Python312/python.exe
|
|
-DPython3_LIBRARY=$ENV{LOCALAPPDATA}/Programs/Python/Python312/libs/python312.lib
|
|
-DPython3_INCLUDE_DIR=$ENV{LOCALAPPDATA}/Programs/Python/Python312/include
|
|
-DTBB_DIR=${CMAKE_SOURCE_DIR}/third_party/cycles/lib/windows_x64/tbb/lib/cmake/TBB
|
|
-DMaterialX_DIR=${OpenUSD_ROOT_DIR}/lib/cmake/MaterialX
|
|
# OpenSubdiv and Imath cmake configs are bundled in the USD install.
|
|
# We must supply their dirs so pxrTargets.cmake can resolve the imported targets.
|
|
-DOpenSubdiv_DIR=${OpenUSD_ROOT_DIR}/lib/cmake/OpenSubdiv
|
|
-DImath_DIR=${OpenUSD_ROOT_DIR}/lib/cmake/Imath
|
|
# Force Cycles to use its own prebuilt OCIO 2.5, not the OCIO 2.1
|
|
# bundled in the new USD include dir. Without this, the new USD's
|
|
# include/OpenColorIO/ (OCIO 2.1) shadows Cycles' prebuilt OCIO 2.5
|
|
# headers and the colorspace.cpp API calls fail to compile.
|
|
-DOpenColorIO_DIR=${CMAKE_SOURCE_DIR}/third_party/cycles/lib/windows_x64/opencolorio/lib/cmake/OpenColorIO
|
|
BUILD_COMMAND
|
|
${CMAKE_COMMAND} --build <BINARY_DIR> --config Release
|
|
INSTALL_COMMAND
|
|
${CMAKE_COMMAND} --install <BINARY_DIR> --config Release
|
|
BUILD_BYPRODUCTS
|
|
"${HDCYCLES_DLL}"
|
|
)
|
|
|
|
set(OPENUSD_HAS_CYCLES TRUE)
|
|
else()
|
|
set(OPENUSD_HAS_CYCLES FALSE)
|
|
message(STATUS "hdCycles: disabled — set WITH_CYCLES=ON to build from third_party/cycles")
|
|
endif()
|
|
|
|
# Collect source files
|
|
file(GLOB_RECURSE CORE_SOURCES "src/core/*.cpp")
|
|
file(GLOB_RECURSE UI_SOURCES "src/ui/*.cpp")
|
|
file(GLOB_RECURSE UTILS_SOURCES "src/utils/*.cpp")
|
|
set(MAIN_SOURCE "src/main.cpp")
|
|
|
|
# Create executable
|
|
add_executable(UsdLayerManager
|
|
${MAIN_SOURCE}
|
|
${CORE_SOURCES}
|
|
${UI_SOURCES}
|
|
${UTILS_SOURCES}
|
|
)
|
|
|
|
# Include directories
|
|
target_include_directories(UsdLayerManager PRIVATE
|
|
${CMAKE_SOURCE_DIR}/src
|
|
${CMAKE_SOURCE_DIR}/include
|
|
${CMAKE_SOURCE_DIR}/third_party/fontawesome
|
|
${CMAKE_SOURCE_DIR}/third_party/nanosvg
|
|
)
|
|
|
|
# Link libraries
|
|
target_link_libraries(UsdLayerManager PRIVATE
|
|
OpenUSD::OpenUSD
|
|
Imgui::Imgui
|
|
Glad::Glad
|
|
FFmpeg::FFmpeg
|
|
OpenColorIO::OpenColorIO
|
|
ole32
|
|
shell32
|
|
)
|
|
|
|
target_include_directories(UsdLayerManager PRIVATE
|
|
"${CMAKE_SOURCE_DIR}/third_party/ffmpeg/include"
|
|
)
|
|
|
|
# Cycles is an ExternalProject; UsdLayerManager must wait for it to finish
|
|
# before POST_BUILD copies hdCycles.dll to the output directory.
|
|
if(WITH_CYCLES)
|
|
add_dependencies(UsdLayerManager CyclesBuild)
|
|
endif()
|
|
|
|
# Platform-specific settings
|
|
if(WIN32)
|
|
# Windows-specific settings
|
|
target_compile_definitions(UsdLayerManager PRIVATE
|
|
WIN32_LEAN_AND_MEAN
|
|
NOMINMAX
|
|
_CRT_SECURE_NO_WARNINGS
|
|
)
|
|
|
|
# OpenColorIO DLL — copy from USD bin/ (which already ships OpenColorIO_2_1.dll)
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"${OpenUSD_ROOT_DIR}/bin/OpenColorIO_2_1.dll"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
COMMENT "Copying OpenColorIO runtime DLL..."
|
|
)
|
|
|
|
# FFmpeg DLLs — copy all .dll files from third_party/ffmpeg/bin
|
|
file(GLOB FFMPEG_RUNTIME_DLLS "${CMAKE_SOURCE_DIR}/third_party/ffmpeg/bin/*.dll")
|
|
if(FFMPEG_RUNTIME_DLLS)
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
${FFMPEG_RUNTIME_DLLS}
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
COMMENT "Copying FFmpeg runtime DLLs..."
|
|
)
|
|
endif()
|
|
|
|
# cmake -P script to copy USD bin/ DLLs excluding CRT DLLs (msvcp, vcruntime, etc.).
|
|
# The USD distribution bundles older CRT DLLs (14.34) that conflict with Cycles
|
|
# binaries built against the newer system CRT (14.42+). The system CRT is
|
|
# always present on Windows 10+ — no need to bundle our own copy.
|
|
file(WRITE "${CMAKE_BINARY_DIR}/copy_usd_bin_dlls.cmake"
|
|
"file(GLOB _all_dlls \"${OpenUSD_ROOT_DIR}/bin/*.dll\")\n"
|
|
"set(_dlls)\n"
|
|
"foreach(_dll \${_all_dlls})\n"
|
|
" get_filename_component(_name \"\${_dll}\" NAME)\n"
|
|
" string(TOLOWER \"\${_name}\" _lname)\n"
|
|
" if(_lname MATCHES \"^(msvcp|vcruntime|ucrtbase|concrt|api-ms-win-)\")\n"
|
|
" continue()\n"
|
|
" endif()\n"
|
|
" list(APPEND _dlls \"\${_dll}\")\n"
|
|
"endforeach()\n"
|
|
"if(_dlls)\n"
|
|
" file(COPY \${_dlls} DESTINATION \"\${DEST_DIR}\")\n"
|
|
"endif()\n"
|
|
)
|
|
|
|
# Copy runtime DLLs to output directory for each configuration
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
# OpenUSD lib/ — usd_*.dll, boost_*.dll, Alembic.dll, etc.
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${OpenUSD_BIN_DIR}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
# OpenUSD bin/ — tbb.dll, MaterialX, OpenEXR, OpenImageIO, etc. (CRT DLLs excluded)
|
|
COMMAND ${CMAKE_COMMAND}
|
|
"-DDEST_DIR=$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
-P "${CMAKE_BINARY_DIR}/copy_usd_bin_dlls.cmake"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${OpenUSD_ROOT_DIR}/lib/usd"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${OpenUSD_ROOT_DIR}/plugin/usd"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"$ENV{LOCALAPPDATA}/Programs/Python/Python312/python312.dll"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"$ENV{LOCALAPPDATA}/Programs/Python/Python312/python3.dll"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
COMMENT "Copying runtime DLLs and USD plugins..."
|
|
)
|
|
|
|
if(OPENUSD_HAS_EMBREE)
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
# plugInfo.json has LibraryPath "../hdEmbree.dll" relative to usd/hdEmbree/,
|
|
# which resolves to usd/hdEmbree.dll — so the DLL must live in usd/, not exe root.
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"${HDEMBREE_DLL}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd/hdEmbree.dll"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${HDEMBREE_PLUGIN_DIR}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd/hdEmbree"
|
|
COMMENT "Copying hdEmbree plugin..."
|
|
)
|
|
if(EMBREE_DLLS)
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
${EMBREE_DLLS}
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
COMMENT "Copying Embree runtime DLLs..."
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
if(OPENUSD_HAS_ARNOLD)
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
# DLLs go in usd/ alongside their metadata dirs (LibraryPath "../hdArnold.dll")
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"${HDARNOLD_DLL}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd/hdArnold.dll"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"${NDRARNOLD_DLL}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd/ndrArnold.dll"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${HDARNOLD_PLUGIN_DIR}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd/hdArnold"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${NDRARNOLD_PLUGIN_DIR}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd/ndrArnold"
|
|
COMMENT "Copying hdArnold plugin..."
|
|
)
|
|
if(ARNOLD_RUNTIME_DLLS)
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
${ARNOLD_RUNTIME_DLLS}
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
COMMENT "Copying Arnold runtime DLLs (ai, OIDN, licensing)..."
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
if(OPENUSD_HAS_CYCLES)
|
|
# hdCycles uses the same usd/ layout as hdEmbree:
|
|
# usd/hdCycles.dll + usd/hdCycles/resources/plugInfo.json
|
|
# The bundled plugInfo.json has Root=".." and LibraryPath="../hdCycles.dll"
|
|
# which resolves correctly once the plugin dir lives in usd/.
|
|
#
|
|
# Runtime deps (embree4, epoxy, imath, openvdb, OIDN, sycl, vulkan, etc.)
|
|
# live in CYCLES_INSTALL_DIR root and must be next to the exe. We can't
|
|
# file(GLOB) them at configure time (ExternalProject hasn't run yet), so we
|
|
# write a small cmake -P script that globs them at build time instead.
|
|
# The script runs at build time (after ExternalProject finishes) so it can glob
|
|
# the actual install output. CRT/Windows DLLs are excluded — they must come
|
|
# from the system or the main exe's toolchain, not from Cycles' bundled copy.
|
|
file(WRITE "${CMAKE_BINARY_DIR}/copy_cycles_runtime_dlls.cmake"
|
|
"file(GLOB _all_dlls \"${CYCLES_INSTALL_DIR}/*.dll\")\n"
|
|
"set(_dlls)\n"
|
|
"foreach(_dll \${_all_dlls})\n"
|
|
" get_filename_component(_name \"\${_dll}\" NAME)\n"
|
|
" string(TOLOWER \"\${_name}\" _lname)\n"
|
|
# Exclude CRT DLLs (system must supply these; Cycles bundles an older version).
|
|
" if(_lname MATCHES \"^(msvcp|vcruntime|ucrtbase|concrt|api-ms-win-)\")\n"
|
|
" continue()\n"
|
|
" endif()\n"
|
|
# Exclude debug-variant DLLs (not needed in release, just wasted space).
|
|
# Pattern: OpenColorIO_d_2_5.dll → contains "_d_"
|
|
# openjph.0.25d.dll → ends with "d.dll"
|
|
" if(_lname MATCHES \"_d_\" OR _lname MATCHES \"d[.]dll$\")\n"
|
|
" continue()\n"
|
|
" endif()\n"
|
|
" list(APPEND _dlls \"\${_dll}\")\n"
|
|
"endforeach()\n"
|
|
"if(_dlls)\n"
|
|
" file(COPY \${_dlls} DESTINATION \"\${DEST_DIR}\")\n"
|
|
"endif()\n"
|
|
)
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"${HDCYCLES_DLL}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd/hdCycles.dll"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${HDCYCLES_PLUGIN_DIR}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/usd/hdCycles"
|
|
COMMAND ${CMAKE_COMMAND}
|
|
"-DDEST_DIR=$<TARGET_FILE_DIR:UsdLayerManager>"
|
|
-P "${CMAKE_BINARY_DIR}/copy_cycles_runtime_dlls.cmake"
|
|
# tbb12.dll is required by openvdb/embree4 but is not in the install output
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"${CYCLES_TBB12_DLL}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/tbb12.dll"
|
|
COMMENT "Copying hdCycles plugin and runtime DLLs..."
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
# Compiler warnings
|
|
if(MSVC)
|
|
target_compile_options(UsdLayerManager PRIVATE /W4)
|
|
else()
|
|
target_compile_options(UsdLayerManager PRIVATE -Wall -Wextra -Wpedantic)
|
|
endif()
|
|
|
|
# Install rules
|
|
install(TARGETS UsdLayerManager
|
|
RUNTIME DESTINATION bin
|
|
)
|
|
|
|
# Install all OpenUSD runtime DLLs (same set that POST_BUILD copies to build/Release).
|
|
# Without these the exe cannot start from install/bin.
|
|
install(DIRECTORY ${OpenUSD_BIN_DIR}/
|
|
DESTINATION bin
|
|
FILES_MATCHING PATTERN "*.dll"
|
|
)
|
|
|
|
# Install OpenUSD bin/ DLLs — tbb.dll, tbbmalloc.dll, MaterialX, OpenEXR,
|
|
# OpenImageIO, zlib, etc. Exclude CRT DLLs: the system VC++ Redistributable supplies
|
|
# these at runtime; bundling an older copy (14.34) causes crashes on machines with
|
|
# Cycles or other DLLs compiled against the newer CRT (14.42+).
|
|
install(DIRECTORY ${OpenUSD_ROOT_DIR}/bin/
|
|
DESTINATION bin
|
|
FILES_MATCHING PATTERN "*.dll"
|
|
PATTERN "msvcp*" EXCLUDE
|
|
PATTERN "vcruntime*" EXCLUDE
|
|
PATTERN "ucrtbase*" EXCLUDE
|
|
PATTERN "concrt*" EXCLUDE
|
|
PATTERN "api-ms-win-*" EXCLUDE
|
|
)
|
|
|
|
install(DIRECTORY ${OpenUSD_ROOT_DIR}/lib/usd
|
|
DESTINATION bin
|
|
)
|
|
|
|
install(DIRECTORY ${OpenUSD_ROOT_DIR}/plugin/usd/
|
|
DESTINATION bin/usd
|
|
)
|
|
|
|
if(OPENUSD_HAS_EMBREE)
|
|
# Install to bin/usd/ so plugInfo.json's LibraryPath "../hdEmbree.dll" resolves correctly.
|
|
install(FILES "${HDEMBREE_DLL}"
|
|
DESTINATION bin/usd
|
|
OPTIONAL
|
|
)
|
|
install(DIRECTORY "${HDEMBREE_PLUGIN_DIR}"
|
|
DESTINATION bin/usd
|
|
OPTIONAL
|
|
)
|
|
if(EMBREE_DLLS)
|
|
install(FILES ${EMBREE_DLLS}
|
|
DESTINATION bin
|
|
OPTIONAL
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
if(OPENUSD_HAS_ARNOLD)
|
|
install(FILES "${HDARNOLD_DLL}" "${NDRARNOLD_DLL}"
|
|
DESTINATION bin/usd
|
|
OPTIONAL
|
|
)
|
|
install(DIRECTORY "${HDARNOLD_PLUGIN_DIR}"
|
|
DESTINATION bin/usd
|
|
OPTIONAL
|
|
)
|
|
install(DIRECTORY "${NDRARNOLD_PLUGIN_DIR}"
|
|
DESTINATION bin/usd
|
|
OPTIONAL
|
|
)
|
|
if(ARNOLD_RUNTIME_DLLS)
|
|
install(FILES ${ARNOLD_RUNTIME_DLLS}
|
|
DESTINATION bin
|
|
OPTIONAL
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
if(OPENUSD_HAS_CYCLES)
|
|
install(FILES "${HDCYCLES_DLL}"
|
|
DESTINATION bin/usd
|
|
OPTIONAL
|
|
)
|
|
install(DIRECTORY "${HDCYCLES_PLUGIN_DIR}"
|
|
DESTINATION bin/usd
|
|
OPTIONAL
|
|
)
|
|
# Cycles runtime deps (embree4, epoxy, imath, openvdb, OIDN, sycl, etc.).
|
|
# No OPTIONAL: install(DIRECTORY) disallows it with FILES_MATCHING, and the
|
|
# dir always exists here since it is produced by the CyclesBuild step.
|
|
#
|
|
# EXCLUDE the MSVC CRT and api-ms-win DLLs that Cycles bundles: they are
|
|
# older than what the system ships (v14.34 vs system v14.42+), and placing
|
|
# an older MSVCP140.dll/VCRUNTIME140.dll ahead of System32 on the DLL
|
|
# search path causes sycl8.dll (built with newer CRT) to fail DllMain with
|
|
# ERROR_DLL_INIT_FAILED (1114) when hdCycles.dll is loaded.
|
|
# The system VC++ Redistributable always satisfies these deps at runtime.
|
|
install(DIRECTORY "${CYCLES_INSTALL_DIR}/"
|
|
DESTINATION bin
|
|
FILES_MATCHING
|
|
PATTERN "*.dll"
|
|
PATTERN "MSVCP140*.dll" EXCLUDE
|
|
PATTERN "VCRUNTIME140*.dll" EXCLUDE
|
|
PATTERN "ucrtbase*.dll" EXCLUDE
|
|
PATTERN "api-ms-win-*.dll" EXCLUDE
|
|
PATTERN "OpenColorIO_d_*.dll" EXCLUDE # debug OCIO build
|
|
PATTERN "openjph.*d.dll" EXCLUDE # debug OpenJPH
|
|
)
|
|
# tbb12.dll (used by openvdb/embree4) lives in the precompiled lib tree, not install output
|
|
install(FILES "${CYCLES_TBB12_DLL}"
|
|
DESTINATION bin
|
|
OPTIONAL
|
|
)
|
|
endif()
|
|
|
|
# Install Python runtime DLLs required by OpenUSD and Cycles.
|
|
# python312.dll : linked by Cycles (hdCycles.dll → python312.dll)
|
|
# python311.dll : linked by usd_python.dll (the OpenUSD Python bindings were
|
|
# built against Python 3.11, regardless of what we compile with)
|
|
# Detect python311.dll from common install paths.
|
|
foreach(_pyroot
|
|
"$ENV{LOCALAPPDATA}/Programs/Python/Python311"
|
|
"C:/Python311"
|
|
"C:/Program Files/Python311"
|
|
)
|
|
if(EXISTS "${_pyroot}/python311.dll")
|
|
set(PYTHON311_DLL "${_pyroot}/python311.dll")
|
|
message(STATUS "Found python311.dll (required by usd_python.dll): ${PYTHON311_DLL}")
|
|
break()
|
|
endif()
|
|
endforeach()
|
|
|
|
set(_python_runtime_dlls
|
|
"$ENV{LOCALAPPDATA}/Programs/Python/Python312/python312.dll"
|
|
"$ENV{LOCALAPPDATA}/Programs/Python/Python312/python3.dll"
|
|
)
|
|
if(PYTHON311_DLL)
|
|
list(APPEND _python_runtime_dlls "${PYTHON311_DLL}")
|
|
endif()
|
|
|
|
install(FILES ${_python_runtime_dlls}
|
|
DESTINATION bin
|
|
OPTIONAL # OPTIONAL so the install doesn't fail on machines with a
|
|
# system-wide Python; in that case the DLL is on PATH already.
|
|
)
|
|
|
|
# Also copy python311.dll to the build output directory so debug runs work
|
|
# without requiring C:\Python311 to be on PATH.
|
|
if(PYTHON311_DLL)
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"${PYTHON311_DLL}"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/python311.dll"
|
|
COMMENT "Copying python311.dll (for usd_python.dll)..."
|
|
)
|
|
endif()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# OCIO: download ACES 1.2 config at configure time if not present
|
|
# ---------------------------------------------------------------------------
|
|
set(_ocio_config_dir "${CMAKE_SOURCE_DIR}/resources/OpenColorIO-Configs/aces_1.2")
|
|
if(NOT EXISTS "${_ocio_config_dir}/config.ocio")
|
|
message(STATUS "Downloading ACES 1.2 OCIO config (~124 MB) ...")
|
|
set(_ocio_zip "${CMAKE_BINARY_DIR}/aces_1.2.zip")
|
|
file(DOWNLOAD
|
|
"https://github.com/colour-science/OpenColorIO-Configs/releases/download/v1.2/OpenColorIO-Config-ACES-1.2.zip"
|
|
"${_ocio_zip}"
|
|
SHOW_PROGRESS
|
|
STATUS _ocio_dl_status
|
|
)
|
|
list(GET _ocio_dl_status 0 _ocio_dl_code)
|
|
if(_ocio_dl_code EQUAL 0)
|
|
execute_process(
|
|
COMMAND ${CMAKE_COMMAND} -E tar xf "${_ocio_zip}"
|
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
|
)
|
|
file(COPY "${CMAKE_BINARY_DIR}/OpenColorIO-Config-ACES-1.2/aces_1.2/"
|
|
DESTINATION "${_ocio_config_dir}")
|
|
file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/OpenColorIO-Config-ACES-1.2")
|
|
file(REMOVE "${_ocio_zip}")
|
|
message(STATUS "ACES 1.2 OCIO config installed to ${_ocio_config_dir}")
|
|
else()
|
|
message(WARNING "ACES 1.2 OCIO download failed (${_ocio_dl_status}) — OCIO will not be bundled.")
|
|
endif()
|
|
endif()
|
|
|
|
# Copy resources to build directory
|
|
file(COPY ${CMAKE_SOURCE_DIR}/resources
|
|
DESTINATION ${CMAKE_BINARY_DIR}
|
|
)
|
|
|
|
# Copy font and SVG icons to build directory
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:UsdLayerManager>/../resources/font"
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:UsdLayerManager>/resources/icons"
|
|
COMMAND ${CMAKE_COMMAND} -E copy
|
|
"${CMAKE_SOURCE_DIR}/third_party/Inter/Inter.ttc"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/resources/font/Inter.ttc"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${CMAKE_SOURCE_DIR}/resources/icons"
|
|
"$<TARGET_FILE_DIR:UsdLayerManager>/resources/icons"
|
|
COMMENT "Copying fonts and SVG icons to build output"
|
|
)
|
|
|
|
# Copy ACES OCIO config to build output — only on first build (skipped if already present).
|
|
if(EXISTS "${_ocio_config_dir}/config.ocio")
|
|
add_custom_command(TARGET UsdLayerManager POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND}
|
|
"-DSRC=${_ocio_config_dir}"
|
|
"-DDST=$<TARGET_FILE_DIR:UsdLayerManager>/resources/OpenColorIO-Configs/aces_1.2"
|
|
-P "${CMAKE_SOURCE_DIR}/cmake/CopyDirIfMissing.cmake"
|
|
COMMENT "Copying ACES OCIO config to build output (first time only)"
|
|
)
|
|
endif()
|
|
|
|
# Install OpenColorIO DLL (from the OpenUSD distribution's bin/)
|
|
install(FILES
|
|
"${OpenUSD_ROOT_DIR}/bin/OpenColorIO_2_1.dll"
|
|
DESTINATION bin
|
|
OPTIONAL
|
|
)
|
|
|
|
# Install resources (icons, fonts placeholder) next to the exe so the
|
|
# exe-relative path "resources/..." resolves correctly from install/bin/.
|
|
install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources
|
|
DESTINATION bin
|
|
)
|
|
|
|
# Install Inter font next to the exe under resources/font/
|
|
# ImGuiContext tries "resources/font/Inter.ttf" then "resources/font/Inter.ttc".
|
|
install(FILES ${CMAKE_SOURCE_DIR}/third_party/Inter/Inter.ttc
|
|
DESTINATION bin/resources/font
|
|
)
|
|
|
|
# Print configuration summary
|
|
message(STATUS "")
|
|
message(STATUS "=== USD Layer Manager Configuration ===")
|
|
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
|
message(STATUS "C++ standard: ${CMAKE_CXX_STANDARD}")
|
|
message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")
|
|
message(STATUS "OpenUSD found: ${OpenUSD_FOUND}")
|
|
message(STATUS "ImGui found: ${Imgui_FOUND}")
|
|
message(STATUS "OpenGL found: ${OPENGL_FOUND}")
|
|
message(STATUS "Glad found: ${Glad_FOUND}")
|
|
message(STATUS "Build tests: ${BUILD_TESTS}")
|
|
message(STATUS "hdEmbree support: ${OPENUSD_HAS_EMBREE}")
|
|
if(OPENUSD_HAS_EMBREE AND EMBREE_DLLS)
|
|
message(STATUS "Embree DLLs: ${EMBREE_DLLS}")
|
|
elseif(OPENUSD_HAS_EMBREE)
|
|
message(WARNING "hdEmbree found but no Embree DLLs detected — set EMBREE_LOCATION to the Embree SDK bin/ dir or check HDEMBREE_USD_ROOT/bin")
|
|
endif()
|
|
message(STATUS "hdArnold support: ${OPENUSD_HAS_ARNOLD}")
|
|
if(OPENUSD_HAS_ARNOLD)
|
|
message(STATUS "hdArnold DLL: ${HDARNOLD_DLL}")
|
|
message(STATUS "Arnold runtime DLLs: ${ARNOLD_RUNTIME_DLLS}")
|
|
if(NOT ARNOLD_AI_DLL)
|
|
message(WARNING "hdArnold found but ai.dll not located — set ARNOLD_LOCATION to the MtoA root (e.g. C:/Autodesk/mtoa/5.5.0/2026)")
|
|
endif()
|
|
endif()
|
|
message(STATUS "hdCycles support: ${OPENUSD_HAS_CYCLES}")
|
|
if(OPENUSD_HAS_CYCLES)
|
|
message(STATUS "Cycles source: ${CMAKE_SOURCE_DIR}/third_party/cycles")
|
|
message(STATUS "Cycles build: ${CYCLES_BINARY_DIR}")
|
|
message(STATUS "Cycles install: ${CYCLES_INSTALL_DIR}")
|
|
endif()
|
|
message(STATUS "=======================================")
|
|
message(STATUS "")
|
|
|
|
# === Test build option ===
|
|
option(BUILD_TESTS "Build test executables" OFF)
|
|
|
|
if(BUILD_TESTS)
|
|
|
|
# === Viewport Display Test ===
|
|
add_executable(ViewportDisplayTest
|
|
tests/viewport_display_test.cpp
|
|
${CORE_SOURCES}
|
|
${UTILS_SOURCES}
|
|
)
|
|
|
|
target_include_directories(ViewportDisplayTest PRIVATE
|
|
${CMAKE_SOURCE_DIR}/src
|
|
${CMAKE_SOURCE_DIR}/include
|
|
"${CMAKE_SOURCE_DIR}/third_party/ffmpeg/include"
|
|
)
|
|
|
|
target_link_libraries(ViewportDisplayTest PRIVATE
|
|
OpenUSD::OpenUSD
|
|
Glad::Glad
|
|
FFmpeg::FFmpeg
|
|
)
|
|
|
|
if(WIN32)
|
|
target_compile_definitions(ViewportDisplayTest PRIVATE
|
|
WIN32_LEAN_AND_MEAN
|
|
NOMINMAX
|
|
_CRT_SECURE_NO_WARNINGS
|
|
)
|
|
|
|
add_custom_command(TARGET ViewportDisplayTest POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${OpenUSD_BIN_DIR}"
|
|
"$<TARGET_FILE_DIR:ViewportDisplayTest>"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${OpenUSD_ROOT_DIR}/lib/usd"
|
|
"$<TARGET_FILE_DIR:ViewportDisplayTest>/usd"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${OpenUSD_ROOT_DIR}/plugin/usd"
|
|
"$<TARGET_FILE_DIR:ViewportDisplayTest>/usd"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"$ENV{LOCALAPPDATA}/Programs/Python/Python312/python312.dll"
|
|
"$<TARGET_FILE_DIR:ViewportDisplayTest>"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"$ENV{LOCALAPPDATA}/Programs/Python/Python312/python3.dll"
|
|
"$<TARGET_FILE_DIR:ViewportDisplayTest>"
|
|
COMMENT "Copying runtime DLLs and USD plugins for test..."
|
|
)
|
|
endif()
|
|
|
|
enable_testing()
|
|
add_test(NAME ViewportDisplayTest COMMAND ViewportDisplayTest)
|
|
|
|
add_executable(RendererDiagnosticTest
|
|
tests/renderer_diagnostic_test.cpp
|
|
${CORE_SOURCES}
|
|
${UTILS_SOURCES}
|
|
)
|
|
|
|
target_include_directories(RendererDiagnosticTest PRIVATE
|
|
${CMAKE_SOURCE_DIR}/src
|
|
${CMAKE_SOURCE_DIR}/include
|
|
"${CMAKE_SOURCE_DIR}/third_party/ffmpeg/include"
|
|
)
|
|
|
|
target_link_libraries(RendererDiagnosticTest PRIVATE
|
|
OpenUSD::OpenUSD
|
|
Glad::Glad
|
|
FFmpeg::FFmpeg
|
|
)
|
|
|
|
if(WIN32)
|
|
target_compile_definitions(RendererDiagnosticTest PRIVATE
|
|
WIN32_LEAN_AND_MEAN
|
|
NOMINMAX
|
|
_CRT_SECURE_NO_WARNINGS
|
|
)
|
|
|
|
add_custom_command(TARGET RendererDiagnosticTest POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${OpenUSD_BIN_DIR}"
|
|
"$<TARGET_FILE_DIR:RendererDiagnosticTest>"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${OpenUSD_ROOT_DIR}/lib/usd"
|
|
"$<TARGET_FILE_DIR:RendererDiagnosticTest>/usd"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${OpenUSD_ROOT_DIR}/plugin/usd"
|
|
"$<TARGET_FILE_DIR:RendererDiagnosticTest>/usd"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"$ENV{LOCALAPPDATA}/Programs/Python/Python312/python312.dll"
|
|
"$<TARGET_FILE_DIR:RendererDiagnosticTest>"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"$ENV{LOCALAPPDATA}/Programs/Python/Python312/python3.dll"
|
|
"$<TARGET_FILE_DIR:RendererDiagnosticTest>"
|
|
COMMENT "Copying runtime DLLs and USD plugins for diagnostic test..."
|
|
)
|
|
endif()
|
|
|
|
endif() # BUILD_TESTS
|