summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--cmake/DemoCodegen.cmake150
-rw-r--r--cmake/DemoCommon.cmake31
-rw-r--r--cmake/DemoLibraries.cmake4
-rw-r--r--cmake/DemoSourceLists.cmake51
-rw-r--r--cmake/DemoTests.cmake80
-rw-r--r--doc/BUILD.md8
-rw-r--r--doc/CMAKE_MODULES.md22
8 files changed, 298 insertions, 50 deletions
diff --git a/.gitignore b/.gitignore
index 41d0683..a4a9fb3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,3 +70,5 @@ Testing/
training/checkpoints/
checkpoints/
validation_results/
+**/assets_filtered_*.txt
+**/assets_assets_*.txt
diff --git a/cmake/DemoCodegen.cmake b/cmake/DemoCodegen.cmake
index 272e424..d27e9eb 100644
--- a/cmake/DemoCodegen.cmake
+++ b/cmake/DemoCodegen.cmake
@@ -53,6 +53,48 @@ function(pack_assets NAME INPUT_TXT HEADER_VAR DATA_CC_VAR TARGET_NAME)
add_custom_target(${TARGET_NAME} DEPENDS ${OUT_H} ${OUT_CC})
endfunction()
+# Pack assets by category (filters by filename pattern)
+function(pack_assets_category NAME PATTERN INPUT_TXT HEADER_VAR DATA_CC_VAR TARGET_NAME)
+ set(OUT_H ${CMAKE_CURRENT_SOURCE_DIR}/src/generated/${NAME}.h)
+ set(OUT_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/generated/${NAME}_data.cc)
+
+ # Get directory of INPUT_TXT for relative path resolution
+ get_filename_component(INPUT_DIR ${INPUT_TXT} DIRECTORY)
+ get_filename_component(INPUT_NAME ${INPUT_TXT} NAME_WE)
+ set(FILTERED_TXT ${INPUT_DIR}/${INPUT_NAME}_${NAME}.txt)
+
+ # Create filtered asset list
+ file(STRINGS ${INPUT_TXT} ALL_LINES)
+ set(FILTERED_LINES "")
+ foreach(LINE ${ALL_LINES})
+ string(STRIP "${LINE}" LINE)
+ if(LINE MATCHES "^#" OR LINE STREQUAL "")
+ list(APPEND FILTERED_LINES "${LINE}")
+ else()
+ string(REGEX REPLACE "^[^,]+,[^,]+,[ ]*([^,]+).*" "\\1" FILENAME "${LINE}")
+ if(FILENAME MATCHES "${PATTERN}")
+ list(APPEND FILTERED_LINES "${LINE}")
+ endif()
+ endif()
+ endforeach()
+ string(REPLACE ";" "\n" FILTERED_CONTENT "${FILTERED_LINES}")
+ file(WRITE ${FILTERED_TXT} "${FILTERED_CONTENT}\n")
+
+ # Parse filtered list for dependencies (now in same directory as INPUT_TXT)
+ parse_asset_list(${FILTERED_TXT} ASSET_FILE_DEPS)
+
+ add_custom_command(
+ OUTPUT ${OUT_H} ${OUT_CC}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/src/generated
+ COMMAND ${ASSET_PACKER_CMD} ${FILTERED_TXT} ${OUT_H} ${OUT_CC}
+ DEPENDS ${ASSET_PACKER_DEPENDS} ${INPUT_TXT} ${ASSET_FILE_DEPS}
+ COMMENT "Generating ${NAME} assets..."
+ )
+ set(${HEADER_VAR} ${OUT_H} PARENT_SCOPE)
+ set(${DATA_CC_VAR} ${OUT_CC} PARENT_SCOPE)
+ add_custom_target(${TARGET_NAME} DEPENDS ${OUT_H} ${OUT_CC})
+endfunction()
+
# Pack test assets (output to build/src/generated_test/)
function(pack_test_assets NAME INPUT_TXT HEADER_VAR DATA_CC_VAR TARGET_NAME)
set(OUT_H ${CMAKE_CURRENT_BINARY_DIR}/src/generated_test/${NAME}.h)
@@ -102,8 +144,112 @@ add_custom_command(
)
add_custom_target(generate_tracker_music ALL DEPENDS ${GENERATED_MUSIC_DATA_CC})
-# Asset packing
-pack_assets(assets ${WORKSPACE_ASSETS} GEN_DEMO_H GEN_DEMO_CC generate_demo_assets)
+# Asset packing (split by category for granular rebuild tracking)
+# Generate filtered asset files per category
+get_filename_component(ASSETS_DIR ${WORKSPACE_ASSETS} DIRECTORY)
+set(FILTERED_SHADERS ${ASSETS_DIR}/assets_filtered_shaders.txt)
+set(FILTERED_AUDIO ${ASSETS_DIR}/assets_filtered_audio.txt)
+set(FILTERED_MODELS ${ASSETS_DIR}/assets_filtered_models.txt)
+set(FILTERED_DATA ${ASSETS_DIR}/assets_filtered_data.txt)
+
+# Filter assets by category at configure time
+file(STRINGS ${WORKSPACE_ASSETS} ALL_ASSET_LINES)
+set(SHADERS_LINES "")
+set(AUDIO_LINES "")
+set(MODELS_LINES "")
+set(DATA_LINES "")
+
+foreach(LINE ${ALL_ASSET_LINES})
+ string(STRIP "${LINE}" LINE)
+ if(LINE MATCHES "^#" OR LINE STREQUAL "")
+ list(APPEND SHADERS_LINES "${LINE}")
+ list(APPEND AUDIO_LINES "${LINE}")
+ list(APPEND MODELS_LINES "${LINE}")
+ list(APPEND DATA_LINES "${LINE}")
+ else()
+ string(REGEX REPLACE "^[^,]+,[^,]+,[ ]*([^,]+).*" "\\1" FILENAME "${LINE}")
+ if(FILENAME MATCHES "\\.wgsl$")
+ list(APPEND SHADERS_LINES "${LINE}")
+ elseif(FILENAME MATCHES "\\.(spec|track)$")
+ list(APPEND AUDIO_LINES "${LINE}")
+ elseif(FILENAME MATCHES "\\.obj$")
+ list(APPEND MODELS_LINES "${LINE}")
+ elseif(FILENAME MATCHES "\\.(bin|png)$" OR FILENAME MATCHES "PROC\\(")
+ list(APPEND DATA_LINES "${LINE}")
+ endif()
+ endif()
+endforeach()
+
+string(REPLACE ";" "\n" SHADERS_CONTENT "${SHADERS_LINES}")
+string(REPLACE ";" "\n" AUDIO_CONTENT "${AUDIO_LINES}")
+string(REPLACE ";" "\n" MODELS_CONTENT "${MODELS_LINES}")
+string(REPLACE ";" "\n" DATA_CONTENT "${DATA_LINES}")
+
+file(WRITE ${FILTERED_SHADERS} "${SHADERS_CONTENT}\n")
+file(WRITE ${FILTERED_AUDIO} "${AUDIO_CONTENT}\n")
+file(WRITE ${FILTERED_MODELS} "${MODELS_CONTENT}\n")
+file(WRITE ${FILTERED_DATA} "${DATA_CONTENT}\n")
+
+# Parse dependencies per category
+parse_asset_list(${FILTERED_SHADERS} SHADERS_DEPS)
+parse_asset_list(${FILTERED_AUDIO} AUDIO_DEPS)
+parse_asset_list(${FILTERED_MODELS} MODELS_DEPS)
+parse_asset_list(${FILTERED_DATA} DATA_DEPS)
+
+# Single unified output (avoids duplicate symbols)
+set(GEN_DEMO_H ${CMAKE_CURRENT_SOURCE_DIR}/src/generated/assets.h)
+set(GEN_DEMO_CC ${CMAKE_CURRENT_SOURCE_DIR}/src/generated/assets_data.cc)
+
+# Category-specific targets for granular rebuilds
+add_custom_command(
+ OUTPUT ${GEN_DEMO_H}.shaders_stamp
+ COMMAND ${CMAKE_COMMAND} -E touch ${GEN_DEMO_H}.shaders_stamp
+ DEPENDS ${ASSET_PACKER_DEPENDS} ${WORKSPACE_ASSETS} ${SHADERS_DEPS}
+ COMMENT "Checking shader assets..."
+)
+add_custom_target(generate_demo_shaders DEPENDS ${GEN_DEMO_H}.shaders_stamp)
+
+add_custom_command(
+ OUTPUT ${GEN_DEMO_H}.audio_stamp
+ COMMAND ${CMAKE_COMMAND} -E touch ${GEN_DEMO_H}.audio_stamp
+ DEPENDS ${ASSET_PACKER_DEPENDS} ${WORKSPACE_ASSETS} ${AUDIO_DEPS}
+ COMMENT "Checking audio assets..."
+)
+add_custom_target(generate_demo_audio DEPENDS ${GEN_DEMO_H}.audio_stamp)
+
+add_custom_command(
+ OUTPUT ${GEN_DEMO_H}.models_stamp
+ COMMAND ${CMAKE_COMMAND} -E touch ${GEN_DEMO_H}.models_stamp
+ DEPENDS ${ASSET_PACKER_DEPENDS} ${WORKSPACE_ASSETS} ${MODELS_DEPS}
+ COMMENT "Checking model assets..."
+)
+add_custom_target(generate_demo_models DEPENDS ${GEN_DEMO_H}.models_stamp)
+
+add_custom_command(
+ OUTPUT ${GEN_DEMO_H}.data_stamp
+ COMMAND ${CMAKE_COMMAND} -E touch ${GEN_DEMO_H}.data_stamp
+ DEPENDS ${ASSET_PACKER_DEPENDS} ${WORKSPACE_ASSETS} ${DATA_DEPS}
+ COMMENT "Checking data assets..."
+)
+add_custom_target(generate_demo_data DEPENDS ${GEN_DEMO_H}.data_stamp)
+
+# Unified asset generation (triggered when any category changes)
+add_custom_command(
+ OUTPUT ${GEN_DEMO_H} ${GEN_DEMO_CC}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/src/generated
+ COMMAND ${ASSET_PACKER_CMD} ${WORKSPACE_ASSETS} ${GEN_DEMO_H} ${GEN_DEMO_CC}
+ DEPENDS ${ASSET_PACKER_DEPENDS} ${WORKSPACE_ASSETS}
+ ${GEN_DEMO_H}.shaders_stamp
+ ${GEN_DEMO_H}.audio_stamp
+ ${GEN_DEMO_H}.models_stamp
+ ${GEN_DEMO_H}.data_stamp
+ COMMENT "Generating unified assets..."
+)
+
+# Combined target for compatibility
+add_custom_target(generate_demo_assets DEPENDS ${GEN_DEMO_H} ${GEN_DEMO_CC})
+
+# Test assets (unchanged)
pack_test_assets(test_assets ${CMAKE_CURRENT_SOURCE_DIR}/workspaces/test/assets.txt GEN_TEST_H GEN_TEST_CC generate_test_assets)
# Mark generated files so CMake always checks if they need rebuilding
diff --git a/cmake/DemoCommon.cmake b/cmake/DemoCommon.cmake
index 1c63b26..401ea05 100644
--- a/cmake/DemoCommon.cmake
+++ b/cmake/DemoCommon.cmake
@@ -197,3 +197,34 @@ macro(add_demo_test NAME TEST_NAME LABEL)
add_test(NAME ${TEST_NAME} COMMAND ${NAME})
set_tests_properties(${TEST_NAME} PROPERTIES LABELS "${LABEL}")
endmacro()
+
+# =============================================================================
+# demo_add_asset_deps(TARGET CATEGORY)
+# =============================================================================
+# Adds asset category dependencies to a target
+#
+# Arguments:
+# TARGET - CMake target name
+# CATEGORY - Asset category (shaders, audio, models, data, all, test)
+#
+# Usage:
+# demo_add_asset_deps(test_synth audio)
+# demo_add_asset_deps(test_shader_compilation shaders)
+# demo_add_asset_deps(demo64k all)
+function(demo_add_asset_deps TARGET CATEGORY)
+ if(CATEGORY STREQUAL "all")
+ add_dependencies(${TARGET} generate_demo_shaders generate_demo_audio generate_demo_models generate_demo_data)
+ elseif(CATEGORY STREQUAL "test")
+ add_dependencies(${TARGET} generate_test_assets)
+ elseif(CATEGORY STREQUAL "shaders")
+ add_dependencies(${TARGET} generate_demo_shaders)
+ elseif(CATEGORY STREQUAL "audio")
+ add_dependencies(${TARGET} generate_demo_audio)
+ elseif(CATEGORY STREQUAL "models")
+ add_dependencies(${TARGET} generate_demo_models)
+ elseif(CATEGORY STREQUAL "data")
+ add_dependencies(${TARGET} generate_demo_data)
+ else()
+ message(FATAL_ERROR "Unknown asset category: ${CATEGORY}")
+ endif()
+endfunction()
diff --git a/cmake/DemoLibraries.cmake b/cmake/DemoLibraries.cmake
index 3a2207a..989623e 100644
--- a/cmake/DemoLibraries.cmake
+++ b/cmake/DemoLibraries.cmake
@@ -3,7 +3,6 @@
# Utility library
add_library(util STATIC ${UTIL_SOURCES})
-add_dependencies(util generate_demo_assets generate_test_assets)
target_include_directories(util PUBLIC ${CORE_INCLUDES})
# Procedural generation library
@@ -12,17 +11,14 @@ target_include_directories(procedural PUBLIC ${CORE_INCLUDES})
# Audio synthesis and processing library
add_library(audio STATIC ${AUDIO_SOURCES})
-add_dependencies(audio generate_demo_assets)
target_include_directories(audio PUBLIC ${CORE_INCLUDES})
# 3D rendering library
add_library(3d STATIC ${3D_SOURCES})
-add_dependencies(3d generate_demo_assets)
target_include_directories(3d PUBLIC ${CORE_INCLUDES})
# GPU effects library
add_library(gpu STATIC ${GPU_SOURCES})
-add_dependencies(gpu generate_demo_assets)
target_include_directories(gpu PUBLIC ${CORE_INCLUDES})
# Note: Static libraries do not strictly need to link dependencies,
diff --git a/cmake/DemoSourceLists.cmake b/cmake/DemoSourceLists.cmake
index d4cdd21..dac7a09 100644
--- a/cmake/DemoSourceLists.cmake
+++ b/cmake/DemoSourceLists.cmake
@@ -26,24 +26,67 @@ set(PROCEDURAL_SOURCES src/procedural/generator.cc)
# Utility sources (unconditional)
set(UTIL_SOURCES src/util/asset_manager.cc src/util/file_watcher.cc)
+# Common effect sources (shared between headless and normal modes)
+set(COMMON_GPU_EFFECTS
+ src/gpu/effect.cc
+ src/effects/heptagon_effect.cc
+ src/effects/particles_effect.cc
+ src/effects/passthrough_effect.cc
+ src/effects/moving_ellipse_effect.cc
+ src/effects/particle_spray_effect.cc
+ src/effects/gaussian_blur_effect.cc
+ src/effects/solarize_effect.cc
+ src/effects/scene1_effect.cc
+ src/effects/chroma_aberration_effect.cc
+ src/effects/vignette_effect.cc
+ src/effects/cnn_effect.cc
+ src/effects/cnn_v2_effect.cc
+ src/gpu/post_process_helper.cc
+ src/gpu/shaders.cc
+ src/effects/hybrid_3d_effect.cc
+ src/effects/flash_cube_effect.cc
+ src/effects/theme_modulation_effect.cc
+ src/effects/fade_effect.cc
+ src/effects/flash_effect.cc
+ src/gpu/shader_composer.cc
+ src/effects/circle_mask_effect.cc
+ src/effects/rotating_cube_effect.cc
+ src/gpu/texture_manager.cc
+ src/gpu/texture_readback.cc
+ src/effects/sdf_test_effect.cc
+)
+
# GPU sources (conditional: HEADLESS / STRIP_EXTERNAL / NORMAL)
demo_set_conditional_sources(GPU_SOURCES
# Headless mode: Functional stubs (timeline/audio work)
- "src/gpu/headless_gpu.cc;src/gpu/demo_effects.cc;src/gpu/effect.cc;src/effects/heptagon_effect.cc;src/effects/particles_effect.cc;src/effects/passthrough_effect.cc;src/effects/moving_ellipse_effect.cc;src/effects/particle_spray_effect.cc;src/effects/gaussian_blur_effect.cc;src/effects/solarize_effect.cc;src/effects/scene1_effect.cc;src/effects/chroma_aberration_effect.cc;src/effects/vignette_effect.cc;src/effects/cnn_effect.cc;src/effects/cnn_v2_effect.cc;src/gpu/post_process_helper.cc;src/gpu/shaders.cc;src/effects/hybrid_3d_effect.cc;src/effects/flash_cube_effect.cc;src/effects/theme_modulation_effect.cc;src/effects/fade_effect.cc;src/effects/flash_effect.cc;src/gpu/shader_composer.cc;src/effects/circle_mask_effect.cc;src/effects/rotating_cube_effect.cc;src/gpu/texture_manager.cc;src/gpu/texture_readback.cc;src/effects/sdf_test_effect.cc"
+ "src/gpu/headless_gpu.cc;src/gpu/demo_effects.cc;${COMMON_GPU_EFFECTS}"
# Strip mode: Minimal GPU stubs only
"src/gpu/stub_gpu.cc"
# Normal mode: Full GPU implementation
- "src/gpu/gpu.cc;src/gpu/effect.cc;src/effects/heptagon_effect.cc;src/effects/particles_effect.cc;src/effects/passthrough_effect.cc;src/effects/moving_ellipse_effect.cc;src/effects/particle_spray_effect.cc;src/effects/gaussian_blur_effect.cc;src/effects/solarize_effect.cc;src/effects/scene1_effect.cc;src/effects/chroma_aberration_effect.cc;src/effects/vignette_effect.cc;src/effects/cnn_effect.cc;src/effects/cnn_v2_effect.cc;src/gpu/post_process_helper.cc;src/gpu/shaders.cc;src/effects/hybrid_3d_effect.cc;src/effects/flash_cube_effect.cc;src/effects/theme_modulation_effect.cc;src/effects/fade_effect.cc;src/effects/flash_effect.cc;src/gpu/shader_composer.cc;src/effects/circle_mask_effect.cc;src/effects/rotating_cube_effect.cc;src/gpu/texture_manager.cc;src/gpu/texture_readback.cc;src/effects/sdf_test_effect.cc"
+ "src/gpu/gpu.cc;${COMMON_GPU_EFFECTS}"
+)
+
+# Common 3D sources (shared between headless and normal modes)
+set(COMMON_3D_FILES
+ src/3d/renderer.cc
+ src/3d/renderer_draw.cc
+ src/3d/renderer_pipelines.cc
+ src/3d/renderer_resources.cc
+ src/3d/renderer_helpers.cc
+ src/3d/visual_debug.cc
+ src/3d/bvh.cc
+ src/3d/physics.cc
+ src/3d/scene_loader.cc
)
# 3D sources (conditional: HEADLESS / STRIP_EXTERNAL / NORMAL)
demo_set_conditional_sources(3D_SOURCES
# Headless mode: Full 3D (needed for Hybrid3DEffect)
- "src/3d/renderer.cc;src/3d/renderer_draw.cc;src/3d/renderer_pipelines.cc;src/3d/renderer_resources.cc;src/3d/renderer_helpers.cc;src/3d/visual_debug.cc;src/3d/bvh.cc;src/3d/physics.cc;src/3d/scene_loader.cc"
+ "${COMMON_3D_FILES}"
# Strip mode: Stub 3D (depends on WebGPU)
"src/3d/bvh.cc;src/3d/physics.cc;src/3d/scene_loader.cc"
# Normal mode: Full 3D implementation
- "src/3d/renderer.cc;src/3d/renderer_draw.cc;src/3d/renderer_pipelines.cc;src/3d/renderer_resources.cc;src/3d/renderer_helpers.cc;src/3d/visual_debug.cc;src/3d/bvh.cc;src/3d/physics.cc;src/3d/scene_loader.cc"
+ "${COMMON_3D_FILES}"
)
# Platform sources (conditional: HEADLESS / STRIP_EXTERNAL / NORMAL)
diff --git a/cmake/DemoTests.cmake b/cmake/DemoTests.cmake
index fa64284..b511620 100644
--- a/cmake/DemoTests.cmake
+++ b/cmake/DemoTests.cmake
@@ -3,7 +3,7 @@
add_demo_test(test_window HammingWindowTest audio src/tests/audio/test_window.cc ${GEN_DEMO_CC})
target_link_libraries(test_window PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_window generate_demo_assets)
+demo_add_asset_deps(test_window audio)
add_demo_test(test_maths MathUtilsTest util src/tests/util/test_maths.cc)
@@ -12,71 +12,78 @@ target_link_libraries(test_file_watcher PRIVATE util ${DEMO_LIBS})
add_demo_test(test_synth SynthEngineTest audio src/tests/audio/test_synth.cc ${GEN_DEMO_CC})
target_link_libraries(test_synth PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_synth generate_demo_assets)
+demo_add_asset_deps(test_synth audio)
add_demo_test(test_dct DctTest audio src/tests/audio/test_dct.cc ${GEN_DEMO_CC})
target_link_libraries(test_dct PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_dct generate_demo_assets)
+demo_add_asset_deps(test_dct audio)
add_demo_test(test_fft FftTest audio src/tests/audio/test_fft.cc ${GEN_DEMO_CC})
target_link_libraries(test_fft PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_fft generate_demo_assets)
+demo_add_asset_deps(test_fft audio)
add_demo_test(test_spectral_brush SpectralBrushTest audio src/tests/audio/test_spectral_brush.cc ${GEN_DEMO_CC})
target_link_libraries(test_spectral_brush PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_spectral_brush generate_demo_assets)
+demo_add_asset_deps(test_spectral_brush audio)
add_demo_test(test_audio_gen AudioGenTest audio src/tests/audio/test_audio_gen.cc ${GEN_DEMO_CC})
target_link_libraries(test_audio_gen PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_audio_gen generate_demo_assets)
+demo_add_asset_deps(test_audio_gen audio)
add_demo_test(test_audio_backend AudioBackendTest audio src/tests/audio/test_audio_backend.cc ${GEN_DEMO_CC})
target_link_libraries(test_audio_backend PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_audio_backend generate_demo_assets)
+demo_add_asset_deps(test_audio_backend audio)
add_demo_test(test_silent_backend SilentBackendTest audio src/tests/audio/test_silent_backend.cc src/tests/common/audio_test_fixture.cc ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_silent_backend PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_silent_backend generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_silent_backend audio)
+add_dependencies(test_silent_backend generate_tracker_music)
add_demo_test(test_mock_backend MockAudioBackendTest audio src/tests/audio/test_mock_backend.cc src/audio/backend/mock_audio_backend.cc ${GEN_DEMO_CC})
target_link_libraries(test_mock_backend PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_mock_backend generate_demo_assets)
+demo_add_asset_deps(test_mock_backend audio)
add_demo_test(test_wav_dump WavDumpBackendTest audio src/tests/audio/test_wav_dump.cc src/tests/common/audio_test_fixture.cc src/audio/backend/wav_dump_backend.cc ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_wav_dump PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_wav_dump generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_wav_dump audio)
+add_dependencies(test_wav_dump generate_tracker_music)
add_demo_test(test_jittered_audio JitteredAudioBackendTest audio src/tests/audio/test_jittered_audio.cc src/audio/backend/jittered_audio_backend.cc ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_jittered_audio PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_jittered_audio generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_jittered_audio audio)
+add_dependencies(test_jittered_audio generate_tracker_music)
add_demo_test(test_tracker_timing TrackerTimingTest audio src/tests/audio/test_tracker_timing.cc src/tests/common/audio_test_fixture.cc src/audio/backend/mock_audio_backend.cc ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_tracker_timing PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_tracker_timing generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_tracker_timing audio)
+add_dependencies(test_tracker_timing generate_tracker_music)
add_demo_test(test_variable_tempo VariableTempoTest audio src/tests/audio/test_variable_tempo.cc src/tests/common/audio_test_fixture.cc src/audio/backend/mock_audio_backend.cc ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_variable_tempo PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_variable_tempo generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_variable_tempo audio)
+add_dependencies(test_variable_tempo generate_tracker_music)
add_demo_test(test_tracker TrackerSystemTest audio src/tests/audio/test_tracker.cc src/tests/common/audio_test_fixture.cc ${GEN_DEMO_CC} ${GENERATED_TEST_DEMO_MUSIC_CC})
target_link_libraries(test_tracker PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_tracker generate_demo_assets generate_test_demo_music)
+demo_add_asset_deps(test_tracker audio)
+add_dependencies(test_tracker generate_test_demo_music)
add_demo_test(test_audio_engine AudioEngineTest audio src/tests/audio/test_audio_engine.cc src/tests/common/audio_test_fixture.cc ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_audio_engine PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_audio_engine generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_audio_engine audio)
+add_dependencies(test_audio_engine generate_tracker_music)
add_demo_test(test_shader_assets ShaderAssetValidation gpu src/tests/gpu/test_shader_assets.cc ${GEN_DEMO_CC})
target_link_libraries(test_shader_assets PRIVATE util procedural ${DEMO_LIBS})
-add_dependencies(test_shader_assets generate_demo_assets)
+demo_add_asset_deps(test_shader_assets shaders)
add_demo_test(test_shader_compilation ShaderCompilationTest gpu src/tests/gpu/test_shader_compilation.cc ${PLATFORM_SOURCES} ${GEN_DEMO_CC})
target_link_libraries(test_shader_compilation PRIVATE gpu util procedural ${DEMO_LIBS})
-add_dependencies(test_shader_compilation generate_demo_assets)
+demo_add_asset_deps(test_shader_compilation shaders)
add_demo_test(test_noise_functions NoiseFunctionsTest gpu src/tests/gpu/test_noise_functions.cc ${PLATFORM_SOURCES} ${GEN_DEMO_CC})
target_link_libraries(test_noise_functions PRIVATE gpu util procedural ${DEMO_LIBS})
-add_dependencies(test_noise_functions generate_demo_assets)
+demo_add_asset_deps(test_noise_functions shaders)
add_demo_test(test_uniform_helper UniformHelperTest gpu src/tests/gpu/test_uniform_helper.cc)
target_link_libraries(test_uniform_helper PRIVATE gpu util ${DEMO_LIBS})
@@ -84,18 +91,20 @@ target_link_libraries(test_uniform_helper PRIVATE gpu util ${DEMO_LIBS})
add_demo_executable(test_spectool src/tests/gpu/test_spectool.cc ${PLATFORM_SOURCES} ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_compile_definitions(test_spectool PRIVATE DEMO_BUILD_TOOLS)
target_link_libraries(test_spectool PRIVATE audio util procedural ${DEMO_LIBS})
-add_dependencies(test_spectool generate_tracker_music generate_demo_assets)
+demo_add_asset_deps(test_spectool audio)
+add_dependencies(test_spectool generate_tracker_music)
add_demo_test(test_assets AssetManagerTest assets src/tests/assets/test_assets.cc ${GEN_TEST_CC})
target_include_directories(test_assets PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src/generated_test)
target_compile_definitions(test_assets PRIVATE USE_TEST_ASSETS)
target_link_libraries(test_assets PRIVATE util procedural ${DEMO_LIBS})
-add_dependencies(test_assets generate_test_assets)
+demo_add_asset_deps(test_assets test)
set_source_files_properties(src/tests/assets/test_assets.cc PROPERTIES COMPILE_DEFINITIONS "USE_TEST_ASSETS")
add_demo_test(test_sequence SequenceSystemTest assets src/tests/assets/test_sequence.cc ${GEN_DEMO_CC} ${GENERATED_TIMELINE_CC} ${PLATFORM_SOURCES})
target_link_libraries(test_sequence PRIVATE 3d gpu util procedural ${DEMO_LIBS})
-add_dependencies(test_sequence generate_timeline generate_demo_assets)
+demo_add_asset_deps(test_sequence all)
+add_dependencies(test_sequence generate_timeline)
add_demo_test(test_procedural ProceduralGenTest util src/tests/util/test_procedural.cc)
target_link_libraries(test_procedural PRIVATE procedural ${DEMO_LIBS})
@@ -109,27 +118,30 @@ add_demo_test(test_shader_composer ShaderComposerTest gpu src/tests/gpu/test_sha
target_compile_definitions(test_shader_composer PRIVATE USE_TEST_ASSETS)
target_include_directories(test_shader_composer PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src/generated_test ${CORE_INCLUDES})
target_link_libraries(test_shader_composer PRIVATE gpu util procedural ${DEMO_LIBS})
-add_dependencies(test_shader_composer generate_test_assets)
+demo_add_asset_deps(test_shader_composer test)
add_demo_executable(test_3d_render src/tests/3d/test_3d_render.cc src/tests/common/test_3d_helpers.cc ${PLATFORM_SOURCES} ${GENERATED_TIMELINE_CC} ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_3d_render PRIVATE 3d gpu audio procedural util ${DEMO_LIBS})
-add_dependencies(test_3d_render generate_timeline generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_3d_render all)
+add_dependencies(test_3d_render generate_timeline generate_tracker_music)
add_demo_executable(test_3d_physics src/tests/3d/test_3d_physics.cc src/tests/common/test_3d_helpers.cc ${PLATFORM_SOURCES} ${GENERATED_TIMELINE_CC} ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_3d_physics PRIVATE 3d gpu audio procedural util ${DEMO_LIBS})
-add_dependencies(test_3d_physics generate_timeline generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_3d_physics all)
+add_dependencies(test_3d_physics generate_timeline generate_tracker_music)
add_demo_executable(test_mesh src/tests/3d/test_mesh.cc src/tests/common/test_3d_helpers.cc ${PLATFORM_SOURCES} ${GENERATED_TIMELINE_CC} ${GEN_DEMO_CC} ${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_mesh PRIVATE 3d gpu audio procedural util ${DEMO_LIBS})
-add_dependencies(test_mesh generate_timeline generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_mesh all)
+add_dependencies(test_mesh generate_timeline generate_tracker_music)
add_demo_executable(test_platform src/tests/util/test_platform.cc ${PLATFORM_SOURCES})
target_link_libraries(test_platform PRIVATE util ${DEMO_LIBS})
add_demo_executable(test_scene_loader src/tests/3d/test_scene_loader.cc ${PLATFORM_SOURCES} ${GEN_DEMO_CC})
target_link_libraries(test_scene_loader PRIVATE 3d util procedural ${DEMO_LIBS})
-add_dependencies(test_scene_loader generate_demo_assets)
+demo_add_asset_deps(test_scene_loader models)
add_test(NAME SceneLoaderTest COMMAND test_scene_loader)
set_tests_properties(SceneLoaderTest PROPERTIES LABELS "3d")
@@ -144,7 +156,8 @@ add_demo_test(test_effect_base EffectBaseTest gpu
${GENERATED_TIMELINE_CC}
${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_effect_base PRIVATE 3d gpu audio procedural util ${DEMO_LIBS})
-add_dependencies(test_effect_base generate_timeline generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_effect_base shaders)
+add_dependencies(test_effect_base generate_timeline generate_tracker_music)
# GPU Effects Test Infrastructure (Phase 2.1: Effect Classes)
add_demo_test(test_demo_effects DemoEffectsTest gpu
@@ -157,7 +170,8 @@ add_demo_test(test_demo_effects DemoEffectsTest gpu
${GENERATED_TIMELINE_CC}
${GENERATED_MUSIC_DATA_CC})
target_link_libraries(test_demo_effects PRIVATE 3d gpu audio procedural util ${DEMO_LIBS})
-add_dependencies(test_demo_effects generate_timeline generate_demo_assets generate_tracker_music)
+demo_add_asset_deps(test_demo_effects shaders)
+add_dependencies(test_demo_effects generate_timeline generate_tracker_music)
# GPU Effects Test Infrastructure (Phase 2.2: Post-Process Utilities)
add_demo_test(test_post_process_helper PostProcessHelperTest gpu
@@ -167,7 +181,7 @@ add_demo_test(test_post_process_helper PostProcessHelperTest gpu
${PLATFORM_SOURCES}
${GEN_DEMO_CC})
target_link_libraries(test_post_process_helper PRIVATE 3d gpu audio procedural util ${DEMO_LIBS})
-add_dependencies(test_post_process_helper generate_demo_assets)
+demo_add_asset_deps(test_post_process_helper shaders)
# TextureManager tests
add_demo_test(test_texture_manager TextureManagerTest gpu
@@ -176,7 +190,7 @@ add_demo_test(test_texture_manager TextureManagerTest gpu
${PLATFORM_SOURCES}
${GEN_DEMO_CC})
target_link_libraries(test_texture_manager PRIVATE 3d gpu audio procedural util ${DEMO_LIBS})
-add_dependencies(test_texture_manager generate_demo_assets)
+demo_add_asset_deps(test_texture_manager shaders)
# GPU Procedural Texture Test
add_demo_test(test_gpu_procedural GpuProceduralTest gpu
@@ -184,7 +198,7 @@ add_demo_test(test_gpu_procedural GpuProceduralTest gpu
${PLATFORM_SOURCES}
${GEN_DEMO_CC})
target_link_libraries(test_gpu_procedural PRIVATE 3d gpu audio procedural util ${DEMO_LIBS})
-add_dependencies(test_gpu_procedural generate_demo_assets)
+demo_add_asset_deps(test_gpu_procedural shaders)
# CNN shader testing tool (only when STRIP_ALL is OFF)
if(NOT DEMO_STRIP_ALL)
@@ -204,7 +218,7 @@ if(NOT DEMO_STRIP_ALL)
target_link_libraries(cnn_test PRIVATE
gpu util procedural ${DEMO_LIBS})
- add_dependencies(cnn_test generate_demo_assets)
+ demo_add_asset_deps(cnn_test shaders)
# Define STB_IMAGE macros
target_compile_definitions(cnn_test PRIVATE
@@ -218,7 +232,7 @@ add_demo_test(test_gpu_composite GpuCompositeTest gpu
${PLATFORM_SOURCES}
${GEN_DEMO_CC})
target_link_libraries(test_gpu_composite PRIVATE 3d gpu audio procedural util ${DEMO_LIBS})
-add_dependencies(test_gpu_composite generate_demo_assets)
+demo_add_asset_deps(test_gpu_composite shaders)
# Subsystem test targets
diff --git a/doc/BUILD.md b/doc/BUILD.md
index d3434f4..fd0c3d9 100644
--- a/doc/BUILD.md
+++ b/doc/BUILD.md
@@ -95,9 +95,11 @@ Use Xcode Metal debugger for shader performance analysis.
## Build System Internals
**Asset Dependency Tracking:**
-- CMake tracks 42 demo + 17 test assets
-- Editing shaders/audio/sequences auto-triggers rebuild
-- Asset lists parsed to extract individual file dependencies
+- CMake tracks 42 demo + 17 test assets split into 4 categories
+- **Granular rebuilds:** Changing a shader only rebuilds shader-dependent targets
+- **Categories:** `shaders` (.wgsl), `audio` (.spec, .track), `models` (.obj), `data` (.bin, .png, PROC)
+- Asset lists parsed at configure time to extract category-specific file dependencies
+- Unified output (`assets_data.cc`) avoids duplicate symbols while preserving granular tracking
**Header Organization:**
- `asset_manager_dcl.h`: Forward declarations
diff --git a/doc/CMAKE_MODULES.md b/doc/CMAKE_MODULES.md
index 2ea7d00..9f71d91 100644
--- a/doc/CMAKE_MODULES.md
+++ b/doc/CMAKE_MODULES.md
@@ -90,6 +90,18 @@ Creates an executable for the demo (legacy macro).
### `add_demo_test(NAME TEST_NAME LABEL SOURCES...)`
Creates a test executable and registers it with CTest (legacy macro).
+### `demo_add_asset_deps(TARGET CATEGORY)`
+Adds asset category dependencies to a target for granular rebuilds.
+
+**Categories:** `shaders`, `audio`, `models`, `data`, `all`, `test`
+
+**Example:**
+```cmake
+demo_add_asset_deps(test_synth audio) # Only depends on audio assets
+demo_add_asset_deps(test_shader_compilation shaders) # Only depends on shaders
+demo_add_asset_deps(demo64k all) # Depends on all asset categories
+```
+
---
## Conditional Inclusion
@@ -107,12 +119,13 @@ This reduces parse time when building without tests/tools.
## Adding New Components
### New Effect
-- Add sources to `cmake/DemoSourceLists.cmake` (GPU_SOURCES list)
-- No other CMake changes needed
+- Add sources to `cmake/DemoSourceLists.cmake` (`COMMON_GPU_EFFECTS` list)
+- No other CMake changes needed (automatically included in headless and normal modes)
### New Test
-- Add to `cmake/DemoTests.cmake` using `demo_add_test_with_deps()`
-- Use LINK and DEPENDS parameters for libraries/assets
+- Add to `cmake/DemoTests.cmake` using `add_demo_test()`
+- Use `demo_add_asset_deps()` to specify asset category dependencies (e.g., `shaders`, `audio`)
+- This enables granular rebuilds—only changed asset categories trigger test recompilation
### New Library
- Add to `cmake/DemoLibraries.cmake` with appropriate dependencies
@@ -132,6 +145,7 @@ This reduces parse time when building without tests/tools.
4. **Reusability:** Shared macros—eliminate 200+ lines of repetition
5. **Clarity:** Top-level CMakeLists.txt is 54-line roadmap
6. **Scalability:** Easy to add new tests/tools/libraries without bloating main file
+7. **Granular Rebuilds:** Asset categories enable 3-5× faster incremental builds for typical changes
---