diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 4702e6c5fa32..c9c28c53344f 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -56,7 +56,7 @@ add_app(iir_blur) add_app(interpolate) add_app(lens_blur) add_app(linear_algebra) -# add_app(linear_blur) # TODO(#5374): missing CMake build +add_app(linear_blur) add_app(local_laplacian) add_app(max_filter) add_app(nl_means) diff --git a/apps/linear_blur/CMakeLists.txt b/apps/linear_blur/CMakeLists.txt new file mode 100644 index 000000000000..a092d6e56fee --- /dev/null +++ b/apps/linear_blur/CMakeLists.txt @@ -0,0 +1,66 @@ +cmake_minimum_required(VERSION 3.28) +project(linear_blur) + +enable_testing() + +# Set up language settings +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED YES) +set(CMAKE_CXX_EXTENSIONS NO) + +# Find Halide +find_package(Halide REQUIRED) + +# Component generators (standalone executables that also produce stubs) +add_halide_generator(srgb_to_linear.generator SOURCES srgb_to_linear_generator.cpp) +add_halide_generator(simple_blur.generator SOURCES simple_blur_generator.cpp) +add_halide_generator(linear_to_srgb.generator SOURCES linear_to_srgb_generator.cpp) + +# Generate stub headers for pipeline composition +add_halide_stub(srgb_to_linear.stub FROM srgb_to_linear.generator GENERATOR srgb_to_linear) +add_halide_stub(simple_blur.stub FROM simple_blur.generator GENERATOR simple_blur) +add_halide_stub(linear_to_srgb.stub FROM linear_to_srgb.generator GENERATOR linear_to_srgb) + +# Composite generator: includes all component sources (for HALIDE_REGISTER_GENERATOR +# factory functions) and links stub headers (for compile-time composition). +add_halide_generator( + linear_blur.generator + SOURCES + linear_blur_generator.cpp + srgb_to_linear_generator.cpp + simple_blur_generator.cpp + linear_to_srgb_generator.cpp + + LINK_LIBRARIES + srgb_to_linear.stub + simple_blur.stub + linear_to_srgb.stub +) + +# AOT-compiled filter libraries +add_halide_library(simple_blur FROM simple_blur.generator + PARAMS + input.type=float32 input.dim=3 + output.type=float32 output.dim=3) +add_halide_library(linear_blur FROM linear_blur.generator + AUTOSCHEDULER Halide::Mullapudi2016) + +# Main executable +add_executable(linear_blur_process run_linear_blur.cpp) +target_link_libraries(linear_blur_process + PRIVATE + Halide::ImageIO + linear_blur + simple_blur) + +# Test that the app actually works! +set(IMAGE ${CMAKE_CURRENT_LIST_DIR}/../images/rgb.png) +if (EXISTS ${IMAGE}) + configure_file(${IMAGE} rgb.png COPYONLY) + add_test(NAME linear_blur_test + COMMAND linear_blur_process 1 rgb.png out.png) + set_tests_properties(linear_blur_test PROPERTIES + LABELS linear_blur + PASS_REGULAR_EXPRESSION "Using linear blur" + SKIP_REGULAR_EXPRESSION "\\[SKIP\\]") +endif () diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index ef7e32d87b47..01042fc2c281 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -208,7 +208,7 @@ function(_Halide_library_from_generator TARGET) set(compiler_log_extension ".halide_compiler_log") set(conceptual_stmt_extension ".conceptual.stmt") set(conceptual_stmt_html_extension ".conceptual.stmt.html") - # set(cpp_stub_extension ".stub.h") # not implemented + # set(cpp_stub_extension ".stub.h") # handled by add_halide_stub() set(device_code_extension ".device_code") set(featurization_extension ".featurization") set(function_info_header_extension ".function_info.h") @@ -465,6 +465,83 @@ function(_Halide_set_osx_arch TARGET TRIPLE) endif () endfunction() +## +# Function to generate a C++ stub header from a Halide generator. +# +# Stubs allow one Generator to compose another at Halide compile time by +# inlining the sub-generator's pipeline definition. The stub header provides +# a type-safe C++ interface (Inputs, Outputs, GeneratorParams structs and a +# static generate() method) for the sub-generator. +# +# The generated .stub.h must be available when compiling the composite +# generator, and the composite generator executable must link the component +# generators' sources so that their HALIDE_REGISTER_GENERATOR factory +# functions are present at link time. +# +# Usage: +# add_halide_stub( FROM +# [GENERATOR ] +# [OUTPUT_DIR ]) +# +# The GENERATOR name defaults to TARGET and controls both the -g flag and the +# output filename (.stub.h). +## + +function(add_halide_stub TARGET) + set(options "") + set(oneValueArgs FROM GENERATOR OUTPUT_DIR) + set(multiValueArgs "") + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if (NOT ARG_FROM) + message(FATAL_ERROR "add_halide_stub requires FROM specifying a generator target") + endif () + + if (NOT ARG_GENERATOR) + set(ARG_GENERATOR "${TARGET}") + endif () + + if (NOT ARG_OUTPUT_DIR) + set(ARG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") + endif () + + cmake_path(SET ARG_OUTPUT_DIR "${ARG_OUTPUT_DIR}") + cmake_path(ABSOLUTE_PATH ARG_OUTPUT_DIR BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" NORMALIZE) + + _Halide_compute_generator_cmd( + FROM "${ARG_FROM}" + OUT_COMMAND generator_cmd + OUT_DEPENDS generator_cmd_deps + ) + + # Absolute path to the generated stub header. + cmake_path(SET stub_file NORMALIZE "${ARG_OUTPUT_DIR}/${ARG_GENERATOR}.stub.h") + + # Relative path for add_custom_command OUTPUT (avoids Xcode .rule file collisions). + cmake_path(RELATIVE_PATH stub_file BASE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + OUTPUT_VARIABLE stub_file_rel) + + add_custom_command( + OUTPUT "${stub_file_rel}" + COMMAND ${generator_cmd} + -g "${ARG_GENERATOR}" + -n "${ARG_GENERATOR}" + -o "${ARG_OUTPUT_DIR}" + -e cpp_stub + DEPENDS ${generator_cmd_deps} + VERBATIM + ) + + add_library("${TARGET}" INTERFACE) + add_custom_target("${TARGET}.update" DEPENDS "${stub_file}") + set_property(TARGET "${TARGET}.update" PROPERTY FOLDER "Halide Internal") + add_dependencies("${TARGET}" "${TARGET}.update") + target_sources("${TARGET}" INTERFACE + FILE_SET HEADERS + BASE_DIRS "${ARG_OUTPUT_DIR}" + FILES "${stub_file}") +endfunction() + ## # Function to simplify writing the CMake rules for invoking a generator executable # and getting a usable CMake library out of it. @@ -477,7 +554,7 @@ function(add_halide_library TARGET) # See Module.cpp for list of extra outputs. The following outputs intentionally do not appear: # - `c_header` is always generated - # - `cpp_stub` is not available + # - `cpp_stub` is handled by add_halide_stub() # - `object` is selected for CMake-target-compile # - `static_library` is selected for cross-compile set(extra_output_names