cmake_minimum_required(VERSION 3.24) project(video_shader LANGUAGES C CXX) include(CTest) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") set(TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests") set(LEGACY_THIRD_PARTY_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/3rdParty") set(DEFAULT_THIRD_PARTY_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/video-io-3rdParty") if(NOT EXISTS "${DEFAULT_THIRD_PARTY_ROOT}") set(DEFAULT_THIRD_PARTY_ROOT "${LEGACY_THIRD_PARTY_ROOT}") endif() set(THIRD_PARTY_ROOT "${DEFAULT_THIRD_PARTY_ROOT}" CACHE PATH "Path to the third-party SDK bundle") if(EXISTS "${DEFAULT_THIRD_PARTY_ROOT}" AND THIRD_PARTY_ROOT STREQUAL LEGACY_THIRD_PARTY_ROOT AND NOT EXISTS "${THIRD_PARTY_ROOT}") set(THIRD_PARTY_ROOT "${DEFAULT_THIRD_PARTY_ROOT}" CACHE PATH "Path to the third-party SDK bundle" FORCE) endif() set(SLANG_ROOT "${THIRD_PARTY_ROOT}/slang-2026.8-windows-x86_64" CACHE PATH "Path to a Slang binary release containing bin/slangc.exe") set(MSDF_ATLAS_GEN_ROOT "${THIRD_PARTY_ROOT}/msdf-atlas-gen" CACHE PATH "Path to msdf-atlas-gen binary release") set(NDI_SDK_ROOT "${THIRD_PARTY_ROOT}/NDI 6 SDK" CACHE PATH "Path to the NDI SDK") set(DECKLINK_SDK_ROOT "${THIRD_PARTY_ROOT}/Blackmagic DeckLink SDK 16.0" CACHE PATH "Path to the Blackmagic DeckLink SDK") set(LEGACY_SLANG_ROOT "${LEGACY_THIRD_PARTY_ROOT}/slang-2026.8-windows-x86_64") set(LEGACY_MSDF_ATLAS_GEN_ROOT "${LEGACY_THIRD_PARTY_ROOT}/msdf-atlas-gen") set(LEGACY_NDI_SDK_ROOT "${LEGACY_THIRD_PARTY_ROOT}/NDI 6 SDK") set(LEGACY_DECKLINK_SDK_ROOT "${LEGACY_THIRD_PARTY_ROOT}/Blackmagic DeckLink SDK 16.0") if(EXISTS "${DEFAULT_THIRD_PARTY_ROOT}") if(SLANG_ROOT STREQUAL LEGACY_SLANG_ROOT AND NOT EXISTS "${SLANG_ROOT}") set(SLANG_ROOT "${THIRD_PARTY_ROOT}/slang-2026.8-windows-x86_64" CACHE PATH "Path to a Slang binary release containing bin/slangc.exe" FORCE) endif() if(MSDF_ATLAS_GEN_ROOT STREQUAL LEGACY_MSDF_ATLAS_GEN_ROOT AND NOT EXISTS "${MSDF_ATLAS_GEN_ROOT}") set(MSDF_ATLAS_GEN_ROOT "${THIRD_PARTY_ROOT}/msdf-atlas-gen" CACHE PATH "Path to msdf-atlas-gen binary release" FORCE) endif() if(NDI_SDK_ROOT STREQUAL LEGACY_NDI_SDK_ROOT AND NOT EXISTS "${NDI_SDK_ROOT}") set(NDI_SDK_ROOT "${THIRD_PARTY_ROOT}/NDI 6 SDK" CACHE PATH "Path to the NDI SDK" FORCE) endif() if(DECKLINK_SDK_ROOT STREQUAL LEGACY_DECKLINK_SDK_ROOT AND NOT EXISTS "${DECKLINK_SDK_ROOT}") set(DECKLINK_SDK_ROOT "${THIRD_PARTY_ROOT}/Blackmagic DeckLink SDK 16.0" CACHE PATH "Path to the Blackmagic DeckLink SDK" FORCE) endif() endif() set(VIDEO_SHADER_INCLUDE_DIRS "${SRC_DIR}" "${SRC_DIR}/app" "${SRC_DIR}/control" "${SRC_DIR}/control/http" "${SRC_DIR}/frames" "${SRC_DIR}/json" "${SRC_DIR}/logging" "${SRC_DIR}/platform" "${SRC_DIR}/preview" "${SRC_DIR}/render" "${SRC_DIR}/render/readback" "${SRC_DIR}/render/thread" "${SRC_DIR}/render/runtime" "${SRC_DIR}/runtime" "${SRC_DIR}/runtime/catalog" "${SRC_DIR}/runtime/layers" "${SRC_DIR}/runtime/shader" "${SRC_DIR}/runtime/state" "${SRC_DIR}/runtime/text" "${SRC_DIR}/shader" "${SRC_DIR}/telemetry" "${SRC_DIR}/video" "${SRC_DIR}/video/core" "${SRC_DIR}/video/decklink" "${SRC_DIR}/video/ndi" "${SRC_DIR}/video/playout" ) function(video_shader_target_defaults target) target_include_directories(${target} PRIVATE ${VIDEO_SHADER_INCLUDE_DIRS}) target_compile_definitions(${target} PRIVATE _UNICODE UNICODE) if(MSVC) target_compile_options(${target} PRIVATE /W3) endif() endfunction() function(video_shader_files_exist out_var) set(missing_files) foreach(file IN LISTS ARGN) if(NOT EXISTS "${file}") list(APPEND missing_files "${file}") endif() endforeach() set(${out_var} "${missing_files}" PARENT_SCOPE) endfunction() function(add_video_shader_test name) add_executable(${name} ${ARGN}) video_shader_target_defaults(${name}) add_test(NAME ${name} COMMAND ${name}) endfunction() set(RUNTIME_JSON_SOURCES "${SRC_DIR}/runtime/state/RuntimeJson.cpp" ) set(RUNTIME_PARAMETER_SOURCES ${RUNTIME_JSON_SOURCES} "${SRC_DIR}/runtime/state/RuntimeParameterUtils.cpp" ) set(RUNTIME_STATE_SOURCES ${RUNTIME_JSON_SOURCES} "${SRC_DIR}/runtime/state/RuntimeStatePersistence.cpp" ) set(RUNTIME_LAYER_SOURCES "${SRC_DIR}/runtime/layers/RuntimeLayerModel.cpp" "${SRC_DIR}/runtime/layers/RuntimeLayerReload.cpp" "${SRC_DIR}/runtime/layers/RuntimeLayerSnapshot.cpp" "${SRC_DIR}/runtime/layers/RuntimeLayerStateRestore.cpp" ) set(RUNTIME_TEXT_SOURCES "${SRC_DIR}/runtime/text/FontAtlasBuilder.cpp" "${SRC_DIR}/runtime/text/FontAtlasImageLoader.cpp" "${SRC_DIR}/runtime/text/FontAtlasMetadata.cpp" "${SRC_DIR}/runtime/text/FontAtlasProcess.cpp" "${SRC_DIR}/runtime/text/RuntimeTextTextureComposer.cpp" ) set(RUNTIME_CATALOG_SOURCES "${SRC_DIR}/runtime/catalog/SupportedShaderCatalog.cpp" ) set(SHADER_MANIFEST_SOURCES "${SRC_DIR}/shader/ShaderManifestAssets.cpp" "${SRC_DIR}/shader/ShaderManifestParameters.cpp" "${SRC_DIR}/shader/ShaderManifestParser.cpp" "${SRC_DIR}/shader/ShaderPackageRegistry.cpp" ) set(VIDEO_MODE_SOURCES "${SRC_DIR}/video/core/VideoMode.cpp" ) set(VIDEO_FORMAT_SOURCES "${SRC_DIR}/video/core/VideoIOFormat.cpp" ) set(SLANG_RUNTIME_FILES "${SLANG_ROOT}/bin/slangc.exe" "${SLANG_ROOT}/bin/slang-compiler.dll" "${SLANG_ROOT}/bin/slang-glslang.dll" ) set(SLANG_LICENSE_FILE "${SLANG_ROOT}/LICENSE") set(MSDF_ATLAS_GEN_EXE_FILE "${MSDF_ATLAS_GEN_ROOT}/msdf-atlas-gen.exe") file(GLOB MSDF_ATLAS_GEN_DLL_FILES CONFIGURE_DEPENDS "${MSDF_ATLAS_GEN_ROOT}/*.dll" ) set(MSDF_ATLAS_GEN_RUNTIME_FILES "${MSDF_ATLAS_GEN_EXE_FILE}" ${MSDF_ATLAS_GEN_DLL_FILES} ) set(MSDF_ATLAS_GEN_LICENSE_FILE "${MSDF_ATLAS_GEN_ROOT}/LICENSE.txt") set(MSDF_ATLAS_GEN_README_FILE "${MSDF_ATLAS_GEN_ROOT}/README.md") set(NDI_INCLUDE_DIR "${NDI_SDK_ROOT}/Include") set(NDI_RUNTIME_DLL "${NDI_SDK_ROOT}/Bin/x64/Processing.NDI.Lib.x64.dll") set(NDI_IMPORT_LIB "${NDI_SDK_ROOT}/Lib/x64/Processing.NDI.Lib.x64.lib") set(NDI_LICENSE_FILE "${NDI_SDK_ROOT}/NDI SDK License Agreement.pdf") set(NDI_NOTICES_FILE "${NDI_SDK_ROOT}/Bin/x64/Processing.NDI.Lib.Licenses.txt") set(DECKLINK_SDK_IDL_FILE "${DECKLINK_SDK_ROOT}/Win/include/DeckLinkAPI.idl") set(DECKLINK_SDK_LICENSE_FILE "${DECKLINK_SDK_ROOT}/End User License Agreement.pdf") set(RENDER_CADENCE_APP_REQUIRED_FILES "${SRC_DIR}/RenderCadenceCompositor.cpp" "${SRC_DIR}/video/decklink/DeckLinkAPI_i.c" "${SRC_DIR}/video/decklink/DeckLinkAPI_h.h" ) video_shader_files_exist(RENDER_CADENCE_APP_MISSING_FILES ${RENDER_CADENCE_APP_REQUIRED_FILES}) if(EXISTS "${DECKLINK_SDK_IDL_FILE}") message(STATUS "Blackmagic DeckLink SDK found: ${DECKLINK_SDK_ROOT}") else() message(STATUS "Blackmagic DeckLink SDK not found at ${DECKLINK_SDK_ROOT}; using checked-in DeckLink API shim files only") endif() if(RENDER_CADENCE_APP_MISSING_FILES) message(STATUS "RenderCadenceCompositor target skipped; required app entry or external DeckLink SDK shim files are missing:") foreach(missing_file IN LISTS RENDER_CADENCE_APP_MISSING_FILES) message(STATUS " ${missing_file}") endforeach() else() file(GLOB_RECURSE RENDER_CADENCE_APP_SOURCES CONFIGURE_DEPENDS "${SRC_DIR}/*.c" "${SRC_DIR}/*.cpp" "${SRC_DIR}/*.h" ) add_executable(RenderCadenceCompositor ${RENDER_CADENCE_APP_SOURCES}) video_shader_target_defaults(RenderCadenceCompositor) if(EXISTS "${NDI_INCLUDE_DIR}" AND EXISTS "${NDI_IMPORT_LIB}") target_include_directories(RenderCadenceCompositor PRIVATE "${NDI_INCLUDE_DIR}") target_link_libraries(RenderCadenceCompositor PRIVATE "${NDI_IMPORT_LIB}") if(EXISTS "${NDI_RUNTIME_DLL}") add_custom_command(TARGET RenderCadenceCompositor POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${NDI_RUNTIME_DLL}" "$/Processing.NDI.Lib.x64.dll" ) endif() else() message(STATUS "NDI SDK headers/import library not found; NDI backends will not build correctly: ${NDI_SDK_ROOT}") endif() target_link_libraries(RenderCadenceCompositor PRIVATE opengl32 Ole32 Windowscodecs Ws2_32 ) source_group(TREE "${SRC_DIR}" FILES ${RENDER_CADENCE_APP_SOURCES}) endif() if(BUILD_TESTING) add_subdirectory(tests) endif() if(TARGET RenderCadenceCompositor) install(TARGETS RenderCadenceCompositor RUNTIME DESTINATION "." ) endif() foreach(slang_runtime_file IN LISTS SLANG_RUNTIME_FILES) if(EXISTS "${slang_runtime_file}") install(FILES "${slang_runtime_file}" DESTINATION "3rdParty/slang/bin" ) else() message(STATUS "Slang runtime file not found and will not be installed: ${slang_runtime_file}") endif() endforeach() foreach(msdf_runtime_file IN LISTS MSDF_ATLAS_GEN_RUNTIME_FILES) if(EXISTS "${msdf_runtime_file}") install(FILES "${msdf_runtime_file}" DESTINATION "3rdParty/msdf-atlas-gen" ) else() message(STATUS "msdf-atlas-gen runtime file not found and will not be installed: ${msdf_runtime_file}") endif() endforeach() if(EXISTS "${MSDF_ATLAS_GEN_LICENSE_FILE}") install(FILES "${MSDF_ATLAS_GEN_LICENSE_FILE}" DESTINATION "third_party_notices" RENAME "MSDF_ATLAS_GEN_LICENSE.txt" ) else() message(STATUS "msdf-atlas-gen license file not found: ${MSDF_ATLAS_GEN_LICENSE_FILE}") endif() if(EXISTS "${MSDF_ATLAS_GEN_README_FILE}") install(FILES "${MSDF_ATLAS_GEN_README_FILE}" DESTINATION "third_party_notices" RENAME "MSDF_ATLAS_GEN_README.md" ) else() message(STATUS "msdf-atlas-gen readme file not found: ${MSDF_ATLAS_GEN_README_FILE}") endif() if(EXISTS "${SLANG_LICENSE_FILE}") install(FILES "${SLANG_LICENSE_FILE}" DESTINATION "third_party_notices" RENAME "SLANG_LICENSE.txt" ) else() message(STATUS "Slang license file not found and will not be installed: ${SLANG_LICENSE_FILE}") endif() if(EXISTS "${NDI_RUNTIME_DLL}") install(FILES "${NDI_RUNTIME_DLL}" DESTINATION "." ) else() message(STATUS "NDI runtime DLL not found and will not be installed: ${NDI_RUNTIME_DLL}") endif() if(EXISTS "${NDI_LICENSE_FILE}") install(FILES "${NDI_LICENSE_FILE}" DESTINATION "third_party_notices" RENAME "NDI_SDK_LICENSE_AGREEMENT.pdf" ) else() message(STATUS "NDI license file not found: ${NDI_LICENSE_FILE}") endif() if(EXISTS "${NDI_NOTICES_FILE}") install(FILES "${NDI_NOTICES_FILE}" DESTINATION "third_party_notices" RENAME "NDI_RUNTIME_LICENSES.txt" ) else() message(STATUS "NDI runtime notices file not found: ${NDI_NOTICES_FILE}") endif() if(EXISTS "${DECKLINK_SDK_LICENSE_FILE}") install(FILES "${DECKLINK_SDK_LICENSE_FILE}" DESTINATION "third_party_notices" RENAME "BLACKMAGIC_DECKLINK_SDK_EULA.pdf" ) else() message(STATUS "Blackmagic DeckLink SDK license file not found: ${DECKLINK_SDK_LICENSE_FILE}") endif() install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/shaders/SHADER_CONTRACT.md" DESTINATION "." ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/config/" DESTINATION "config" ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/" DESTINATION "shaders" ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/runtime/templates/" DESTINATION "runtime/templates" ) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/runtime/README.md" DESTINATION "runtime" ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ui/dist/" DESTINATION "ui/dist" OPTIONAL ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/docs/" DESTINATION "docs" OPTIONAL )