# This directory is independently configurable: it does not include the game,
# PPC generation, or private assets.
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
    cmake_minimum_required(VERSION 3.28)
    project(LoNativeDlssFixtures LANGUAGES CXX)
    set(CMAKE_CXX_STANDARD 20)
    if(MSVC)
        set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
    endif()
    set(LO_NATIVE_DLSS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../..")
    set(LO_NATIVE_DLSS_STANDALONE ON)
else()
    set(LO_NATIVE_DLSS_ROOT "${CMAKE_SOURCE_DIR}")
    set(LO_NATIVE_DLSS_STANDALONE OFF)
endif()
# config.h and other sources embed CJK UI strings as UTF-8 without BOM.
# MSVC cl defaults to the system code page and misparses them (C4819
# followed by cascading errors); force UTF-8 source encoding instead.
if(MSVC)
    add_compile_options(/utf-8)
endif()
# The P1/P2 planner contracts are CPU-only. Keep this lane usable on CI and
# development machines without a Vulkan loader, the SDK, or game assets.
# FSR ownership fixtures need patched Plume interface headers, not its GPU
# library. The default still builds the existing native GPU fixtures.
option(LO_NATIVE_DLSS_CPU_ONLY "Configure only GPU-free native DLSS contract tests" OFF)

add_executable(LoP1FramePlanTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/frame_plan_test.cpp
    ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp/gpu/upscaling_plan.cpp)
target_include_directories(LoP1FramePlanTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
target_compile_features(LoP1FramePlanTest PRIVATE cxx_std_20)

add_executable(LoNativeDlssP2RoutingTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/native_dlss_p2_routing_test.cpp
    ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp/gpu/upscaling_plan.cpp)
target_include_directories(LoNativeDlssP2RoutingTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
target_compile_features(LoNativeDlssP2RoutingTest PRIVATE cxx_std_20)

# Keep the alpha/mask lifetime coverage: it executes on CPU but uses real
# Plume resource interfaces, so a plain checkout must initialize these headers.
if(NOT EXISTS "${LO_NATIVE_DLSS_ROOT}/thirdparty/plume/plume_render_interface.h")
    message(FATAL_ERROR "CPU ownership fixtures need patched Plume headers; see tools/patches/README.md (initialize thirdparty/plume and apply plume-lostodyssey.patch)")
endif()
file(READ "${LO_NATIVE_DLSS_ROOT}/thirdparty/plume/plume_render_interface_types.h" _lo_plume_types)
string(REGEX MATCH "struct RenderDeviceCapabilities[^}]*shaderFormat"
    _lo_plume_shader_format "${_lo_plume_types}")
if(NOT _lo_plume_shader_format)
    message(FATAL_ERROR "Apply the pinned Plume patch before CPU ownership tests: git -C thirdparty/plume apply ../../tools/patches/plume-lostodyssey.patch")
endif()

add_executable(LoFsrVulkanMemoryPolicyTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/fsr/vulkan_memory_policy_test.cpp)
target_compile_features(LoFsrVulkanMemoryPolicyTest PRIVATE cxx_std_20)

add_executable(LoFsrDispatchPolicyTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/fsr/dispatch_policy_test.cpp)
target_include_directories(LoFsrDispatchPolicyTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
target_compile_definitions(LoFsrDispatchPolicyTest PRIVATE LO_GPU_PLUME=1)
target_compile_features(LoFsrDispatchPolicyTest PRIVATE cxx_std_20)

# The full runtime build already registers this target before this directory.
if(NOT TARGET LoFsrProjectionTest)
    add_executable(LoFsrProjectionTest EXCLUDE_FROM_ALL
        ${LO_NATIVE_DLSS_ROOT}/tools/tests/fsr_projection_test.cpp)
    target_include_directories(LoFsrProjectionTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
    target_compile_features(LoFsrProjectionTest PRIVATE cxx_std_20)
endif()

add_executable(LoFsrAlphaPropagationPolicyTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/fsr/alpha_propagation_policy_test.cpp)
target_include_directories(LoFsrAlphaPropagationPolicyTest PRIVATE
    ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp
    ${LO_NATIVE_DLSS_ROOT}/thirdparty/plume)
target_compile_definitions(LoFsrAlphaPropagationPolicyTest PRIVATE LO_GPU_PLUME=1)
target_compile_features(LoFsrAlphaPropagationPolicyTest PRIVATE cxx_std_20)

add_executable(LoNativeDlssPromotionPolicyTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/native_dlss_promotion_policy_test.cpp)
target_include_directories(LoNativeDlssPromotionPolicyTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
target_compile_features(LoNativeDlssPromotionPolicyTest PRIVATE cxx_std_20)

add_executable(LoNativeDlssSubmissionLifetimeTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/native_dlss_submission_lifetime_test.cpp)
target_include_directories(LoNativeDlssSubmissionLifetimeTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
target_compile_features(LoNativeDlssSubmissionLifetimeTest PRIVATE cxx_std_20)

add_executable(LoNativeDlssFrameInputsTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/temporal_frame_inputs_test.cpp)
target_include_directories(LoNativeDlssFrameInputsTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
target_compile_features(LoNativeDlssFrameInputsTest PRIVATE cxx_std_20)

add_executable(LoTemporalUpscalerContractTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/temporal_upscaler_contract_test.cpp)
target_include_directories(LoTemporalUpscalerContractTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
target_compile_features(LoTemporalUpscalerContractTest PRIVATE cxx_std_20)

add_executable(LoNativeDlssSubmissionFailureTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/native_dlss_submission_failure_test.cpp)
target_include_directories(LoNativeDlssSubmissionFailureTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
target_compile_features(LoNativeDlssSubmissionFailureTest PRIVATE cxx_std_20)

add_executable(LoNativeDlaaTest EXCLUDE_FROM_ALL
    ${LO_NATIVE_DLSS_ROOT}/tools/tests/native_dlaa_test.cpp)
target_include_directories(LoNativeDlaaTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp)
target_compile_features(LoNativeDlaaTest PRIVATE cxx_std_20)

# None of these translation units uses C++ modules. Do not require a separate
# clang-scan-deps binary just to build ordinary C++20 contract fixtures.
set_target_properties(LoFsrVulkanMemoryPolicyTest LoFsrDispatchPolicyTest LoFsrProjectionTest LoTemporalUpscalerContractTest LoNativeDlaaTest LoNativeDlssSubmissionFailureTest LoNativeDlssFrameInputsTest LoP1FramePlanTest LoNativeDlssP2RoutingTest LoFsrAlphaPropagationPolicyTest LoNativeDlssPromotionPolicyTest LoNativeDlssSubmissionLifetimeTest
    PROPERTIES CXX_SCAN_FOR_MODULES OFF)

add_custom_target(LoNativeDlssCpuTests
    DEPENDS LoFsrVulkanMemoryPolicyTest LoFsrDispatchPolicyTest LoFsrProjectionTest LoTemporalUpscalerContractTest LoNativeDlaaTest LoNativeDlssSubmissionFailureTest LoNativeDlssFrameInputsTest LoP1FramePlanTest LoNativeDlssP2RoutingTest LoFsrAlphaPropagationPolicyTest LoNativeDlssPromotionPolicyTest LoNativeDlssSubmissionLifetimeTest)
include(CTest)
if(BUILD_TESTING)
    add_test(NAME LoFsrVulkanMemoryPolicyTest COMMAND LoFsrVulkanMemoryPolicyTest)
    add_test(NAME LoFsrDispatchPolicyTest COMMAND LoFsrDispatchPolicyTest)
    add_test(NAME LoFsrProjectionTest COMMAND LoFsrProjectionTest)
    add_test(NAME LoNativeDlaaTest COMMAND LoNativeDlaaTest)
    add_test(NAME LoP1FramePlanTest COMMAND LoP1FramePlanTest)
    add_test(NAME LoNativeDlssP2RoutingTest COMMAND LoNativeDlssP2RoutingTest)
    add_test(NAME LoFsrAlphaPropagationPolicyTest COMMAND LoFsrAlphaPropagationPolicyTest)
    add_test(NAME LoNativeDlssPromotionPolicyTest COMMAND LoNativeDlssPromotionPolicyTest)
    add_test(NAME LoNativeDlssSubmissionLifetimeTest COMMAND LoNativeDlssSubmissionLifetimeTest)
    add_test(NAME LoNativeDlssFrameInputsTest COMMAND LoNativeDlssFrameInputsTest)
    add_test(NAME LoTemporalUpscalerContractTest COMMAND LoTemporalUpscalerContractTest)
    add_test(NAME LoNativeDlssSubmissionFailureTest COMMAND LoNativeDlssSubmissionFailureTest)
    set_tests_properties(LoFsrVulkanMemoryPolicyTest LoFsrDispatchPolicyTest LoFsrProjectionTest LoTemporalUpscalerContractTest LoNativeDlaaTest LoNativeDlssSubmissionFailureTest LoNativeDlssFrameInputsTest LoP1FramePlanTest LoNativeDlssP2RoutingTest LoFsrAlphaPropagationPolicyTest LoNativeDlssPromotionPolicyTest LoNativeDlssSubmissionLifetimeTest PROPERTIES LABELS "native-dlss;cpu")
endif()
if(LO_NATIVE_DLSS_CPU_ONLY)
    return()
endif()
if(LO_NATIVE_DLSS_STANDALONE)
    include("${LO_NATIVE_DLSS_ROOT}/cmake/LoDlss.cmake")
    add_subdirectory("${LO_NATIVE_DLSS_ROOT}/thirdparty/plume" plume)
endif()

option(LO_NATIVE_DLSS_ENABLE_VALIDATION_LAYER "Enable Vulkan validation for native-DLSS fixture and Plume builds" ${LO_NATIVE_DLSS_STANDALONE})

# Deliberately excluded from the normal build: these fixtures do not touch game
# assets and are run only by the focused native-DLSS validation lane.
add_executable(LoPlumeBridgeTest EXCLUDE_FROM_ALL plume_bridge_test.cpp)
target_include_directories(LoPlumeBridgeTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/thirdparty/plume)
target_compile_features(LoPlumeBridgeTest PRIVATE cxx_std_20)
target_link_libraries(LoPlumeBridgeTest PRIVATE plume)
if(WIN32)
    target_link_libraries(LoPlumeBridgeTest PRIVATE d3d12 dxgi)
endif()

add_executable(LoNativeDlssProbe EXCLUDE_FROM_ALL
    native_dlss_probe.cpp
    ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp/gpu/dlss_ngx.cpp)
target_include_directories(LoNativeDlssProbe PRIVATE
    ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp
    ${LO_NATIVE_DLSS_ROOT}/thirdparty/plume)
target_compile_features(LoNativeDlssProbe PRIVATE cxx_std_20)
target_compile_definitions(LoNativeDlssProbe PRIVATE LO_GPU_PLUME=1)
target_link_libraries(LoNativeDlssProbe PRIVATE plume)
if(WIN32)
    target_link_libraries(LoNativeDlssProbe PRIVATE d3d12 dxgi)
endif()
lo_enable_dlss(LoNativeDlssProbe)

add_executable(LoNativeDlssReportTest EXCLUDE_FROM_ALL
    native_dlss_report_test.cpp
    ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp/gpu/dlss_ngx.cpp)
target_include_directories(LoNativeDlssReportTest PRIVATE
    ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp
    ${LO_NATIVE_DLSS_ROOT}/thirdparty/plume)
target_compile_features(LoNativeDlssReportTest PRIVATE cxx_std_20)
target_compile_definitions(LoNativeDlssReportTest PRIVATE LO_GPU_PLUME=1)
target_link_libraries(LoNativeDlssReportTest PRIVATE plume)
lo_enable_dlss(LoNativeDlssReportTest)

add_executable(LoNativeDlssExecutionTest EXCLUDE_FROM_ALL
    native_dlss_execution_test.cpp
    ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp/gpu/dlss_ngx.cpp)
target_include_directories(LoNativeDlssExecutionTest PRIVATE
    ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp
    ${LO_NATIVE_DLSS_ROOT}/thirdparty/plume)
target_compile_features(LoNativeDlssExecutionTest PRIVATE cxx_std_20)
target_compile_definitions(LoNativeDlssExecutionTest PRIVATE LO_GPU_PLUME=1 NOMINMAX LO_NATIVE_DLSS_TEST_INJECT_EVALUATE_FAILURE=1)
if(LO_NATIVE_DLSS_ENABLE_VALIDATION_LAYER)
    target_compile_definitions(LoNativeDlssExecutionTest PRIVATE VULKAN_VALIDATION_LAYER_ENABLED=1)
    target_compile_definitions(plume PRIVATE VULKAN_VALIDATION_LAYER_ENABLED=1)
endif()
target_link_libraries(LoNativeDlssExecutionTest PRIVATE plume)
if(WIN32)
    target_link_libraries(LoNativeDlssExecutionTest PRIVATE d3d12 dxgi)
endif()
lo_enable_dlss(LoNativeDlssExecutionTest)

if(WIN32)
    add_executable(LoD3D12RootBindingTest EXCLUDE_FROM_ALL d3d12_root_binding_test.cpp)
    target_include_directories(LoD3D12RootBindingTest PRIVATE ${LO_NATIVE_DLSS_ROOT}/thirdparty/plume)
    target_compile_features(LoD3D12RootBindingTest PRIVATE cxx_std_20)
    target_link_libraries(LoD3D12RootBindingTest PRIVATE plume d3d12 dxgi)

    add_executable(LoNativeDlssD3D12ExecutionTest EXCLUDE_FROM_ALL
        native_dlss_d3d12_execution_test.cpp
        ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp/gpu/dlss_ngx.cpp
        ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp/gpu/dlss_ngx_d3d12.cpp)
    target_include_directories(LoNativeDlssD3D12ExecutionTest PRIVATE
        ${LO_NATIVE_DLSS_ROOT}/LostOdysseyRecomp
        ${LO_NATIVE_DLSS_ROOT}/thirdparty/plume)
    target_compile_features(LoNativeDlssD3D12ExecutionTest PRIVATE cxx_std_20)
    target_compile_definitions(LoNativeDlssD3D12ExecutionTest PRIVATE LO_GPU_PLUME=1 NOMINMAX)
    target_link_libraries(LoNativeDlssD3D12ExecutionTest PRIVATE plume d3d12 dxgi)
    lo_enable_dlss(LoNativeDlssD3D12ExecutionTest)
endif()


if(UNIX)
    if(PLUME_SDL_VULKAN_ENABLED)
        if(TARGET SDL3::SDL3-static)
            target_link_libraries(LoPlumeBridgeTest PRIVATE SDL3::SDL3-static)
            target_link_libraries(LoNativeDlssProbe PRIVATE SDL3::SDL3-static)
            target_link_libraries(LoNativeDlssReportTest PRIVATE SDL3::SDL3-static)
            target_link_libraries(LoNativeDlssExecutionTest PRIVATE SDL3::SDL3-static)
        else()
            target_link_libraries(LoPlumeBridgeTest PRIVATE SDL3::SDL3)
            target_link_libraries(LoNativeDlssProbe PRIVATE SDL3::SDL3)
            target_link_libraries(LoNativeDlssReportTest PRIVATE SDL3::SDL3)
            target_link_libraries(LoNativeDlssExecutionTest PRIVATE SDL3::SDL3)
        endif()
    else()
        find_package(X11 REQUIRED)
        foreach(target LoPlumeBridgeTest LoNativeDlssProbe LoNativeDlssReportTest LoNativeDlssExecutionTest)
            target_include_directories(${target} PRIVATE ${X11_INCLUDE_DIR})
            target_link_libraries(${target} PRIVATE ${X11_LIBRARIES})
        endforeach()
    endif()
    target_link_libraries(LoPlumeBridgeTest PRIVATE ${CMAKE_DL_LIBS})
    target_link_libraries(LoNativeDlssProbe PRIVATE ${CMAKE_DL_LIBS})
    target_link_libraries(LoNativeDlssReportTest PRIVATE ${CMAKE_DL_LIBS})
    target_link_libraries(LoNativeDlssExecutionTest PRIVATE ${CMAKE_DL_LIBS})
endif()

include(CTest)
if(BUILD_TESTING)
    add_test(NAME LoNativeDlssProbe COMMAND LoNativeDlssProbe)
    set_tests_properties(LoNativeDlssProbe PROPERTIES SKIP_RETURN_CODE 77)
    add_test(NAME LoNativeDlssReportTest COMMAND LoNativeDlssReportTest)
    add_test(NAME LoNativeDlssExecutionTest COMMAND LoNativeDlssExecutionTest)
    set_tests_properties(LoNativeDlssExecutionTest PROPERTIES SKIP_RETURN_CODE 77)
    if(WIN32)
        add_test(NAME LoD3D12RootBindingTest COMMAND LoD3D12RootBindingTest)
        set_tests_properties(LoD3D12RootBindingTest PROPERTIES SKIP_RETURN_CODE 77)
        add_test(NAME LoNativeDlssD3D12ExecutionTest COMMAND LoNativeDlssD3D12ExecutionTest)
        set_tests_properties(LoNativeDlssD3D12ExecutionTest PROPERTIES SKIP_RETURN_CODE 77)
    endif()
endif()
