# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later set(FIDELITYFX_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/externals/FidelityFX-FSR/ffx-fsr) set(FIDELITYFX_FILES ${FIDELITYFX_INCLUDE_DIR}/ffx_a.h ${FIDELITYFX_INCLUDE_DIR}/ffx_fsr1.h ) set(GLSL_INCLUDES fidelityfx_fsr.frag ${FIDELITYFX_FILES} ) set(SHADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_vertex_repack.comp ${CMAKE_CURRENT_SOURCE_DIR}/astc_decoder.comp ${CMAKE_CURRENT_SOURCE_DIR}/bc_encoder.comp ${CMAKE_CURRENT_SOURCE_DIR}/blit_color_float.frag ${CMAKE_CURRENT_SOURCE_DIR}/blit_color_srgb_to_linear.frag ${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_2d.comp ${CMAKE_CURRENT_SOURCE_DIR}/blit_color_msaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/blit_depth.frag ${CMAKE_CURRENT_SOURCE_DIR}/blit_depth_msaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/blit_depth_stencil_msaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_3d.comp ${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_3d_bcn.comp ${CMAKE_CURRENT_SOURCE_DIR}/convert_abgr8_to_d24s8.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_abgr8_to_d32f.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_d32f_to_abgr8.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_d24s8_to_abgr8.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_depth_to_float.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_float_to_depth.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.comp ${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_depth.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_depth_stencil.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.comp ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_depth.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_depth_stencil.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_s8d24_to_abgr8.frag ${CMAKE_CURRENT_SOURCE_DIR}/full_screen_triangle.vert ${CMAKE_CURRENT_SOURCE_DIR}/fxaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/fxaa.vert ${CMAKE_CURRENT_SOURCE_DIR}/opengl_convert_s8d24.comp ${CMAKE_CURRENT_SOURCE_DIR}/opengl_copy_bc4.comp ${CMAKE_CURRENT_SOURCE_DIR}/opengl_fidelityfx_fsr.frag ${CMAKE_CURRENT_SOURCE_DIR}/opengl_fidelityfx_fsr_easu.frag ${CMAKE_CURRENT_SOURCE_DIR}/opengl_fidelityfx_fsr_rcas.frag ${CMAKE_CURRENT_SOURCE_DIR}/opengl_lmem_warmup.comp ${CMAKE_CURRENT_SOURCE_DIR}/opengl_present.frag ${CMAKE_CURRENT_SOURCE_DIR}/opengl_present.vert ${CMAKE_CURRENT_SOURCE_DIR}/opengl_present_scaleforce.frag ${CMAKE_CURRENT_SOURCE_DIR}/opengl_smaa.glsl ${CMAKE_CURRENT_SOURCE_DIR}/pitch_unswizzle.comp ${CMAKE_CURRENT_SOURCE_DIR}/present_area.frag ${CMAKE_CURRENT_SOURCE_DIR}/present_bicubic.frag ${CMAKE_CURRENT_SOURCE_DIR}/present_zero_tangent.frag ${CMAKE_CURRENT_SOURCE_DIR}/present_bspline.frag ${CMAKE_CURRENT_SOURCE_DIR}/present_mitchell.frag ${CMAKE_CURRENT_SOURCE_DIR}/present_gaussian.frag ${CMAKE_CURRENT_SOURCE_DIR}/present_lanczos.frag ${CMAKE_CURRENT_SOURCE_DIR}/present_spline1.frag ${CMAKE_CURRENT_SOURCE_DIR}/present_mmpx.frag ${CMAKE_CURRENT_SOURCE_DIR}/queries_prefix_scan_sum.comp ${CMAKE_CURRENT_SOURCE_DIR}/queries_prefix_scan_sum_nosubgroups.comp ${CMAKE_CURRENT_SOURCE_DIR}/resolve_conditional_render.comp ${CMAKE_CURRENT_SOURCE_DIR}/smaa_edge_detection.vert ${CMAKE_CURRENT_SOURCE_DIR}/smaa_edge_detection.frag ${CMAKE_CURRENT_SOURCE_DIR}/smaa_blending_weight_calculation.vert ${CMAKE_CURRENT_SOURCE_DIR}/smaa_blending_weight_calculation.frag ${CMAKE_CURRENT_SOURCE_DIR}/smaa_neighborhood_blending.vert ${CMAKE_CURRENT_SOURCE_DIR}/smaa_neighborhood_blending.frag ${CMAKE_CURRENT_SOURCE_DIR}/temporal_sharpen.frag ${CMAKE_CURRENT_SOURCE_DIR}/temporal_upscale.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_blit_depth_stencil.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_color_clear.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_color_clear.vert ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_depthstencil_clear.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_fidelityfx_fsr.vert ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_fidelityfx_fsr_easu_fp16.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_fidelityfx_fsr_easu_fp32.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_fidelityfx_fsr_rcas_fp16.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_fidelityfx_fsr_rcas_fp32.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_present.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_present.vert ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_present_scaleforce_fp16.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_present_scaleforce_fp32.frag ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_quad_indexed.comp ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_turbo_mode.comp ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_uint8.comp # Snapdragon Game Super Resolution ${CMAKE_CURRENT_SOURCE_DIR}/sgsr1_shader.vert ${CMAKE_CURRENT_SOURCE_DIR}/sgsr1_shader_mobile.frag ${CMAKE_CURRENT_SOURCE_DIR}/sgsr1_shader_mobile_edge_direction.frag ${CMAKE_CURRENT_SOURCE_DIR}/fsr3_optical_flow.comp ${CMAKE_CURRENT_SOURCE_DIR}/fsr3_frame_interpolation.comp ) if (HAIKUOS) # glslangValidator WILL crash, glslang will not set(GLSLANGVALIDATOR "glslang") else() # Normal sane platform who doesn't have a CRASHING glslangValidator find_program(GLSLANGVALIDATOR "glslangValidator") endif() if ("${GLSLANGVALIDATOR}" STREQUAL "GLSLANGVALIDATOR-NOTFOUND") message(FATAL_ERROR "Required program `glslangValidator` not found.") endif() set(GLSL_FLAGS "-DUseUniformBlock=1") set(SPIR_V_VERSION "spirv1.3") set(QUIET_FLAG "--quiet") set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include) set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders) set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE) set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in) set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) # Check if `--quiet` is available on host's glslangValidator version # glslangValidator prints to STDERR iff an unrecognized flag is passed to it execute_process( COMMAND ${GLSLANGVALIDATOR} ${QUIET_FLAG} ERROR_VARIABLE GLSLANG_ERROR # STDOUT variable defined to silence unnecessary output during CMake configuration OUTPUT_VARIABLE GLSLANG_OUTPUT ) if (NOT GLSLANG_ERROR STREQUAL "") message(WARNING "Refusing to use unavailable flag `${QUIET_FLAG}` on `${GLSLANGVALIDATOR}`") set(QUIET_FLAG "") endif() foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES}) get_filename_component(FILENAME ${SOURCE_FILE} NAME) string(REPLACE "." "_" SHADER_NAME ${FILENAME}) # Skip generating source headers on Vulkan exclusive files if (NOT ${FILENAME} MATCHES "vulkan.*") set(SOURCE_HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}.h) add_custom_command( OUTPUT ${SOURCE_HEADER_FILE} COMMAND ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${SOURCE_HEADER_FILE} ${INPUT_FILE} MAIN_DEPENDENCY ${SOURCE_FILE} DEPENDS ${INPUT_FILE} # HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified ) set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE}) endif() # Skip compiling to SPIR-V OpenGL exclusive files if (NOT ${FILENAME} MATCHES "opengl.*") string(TOUPPER ${SHADER_NAME}_SPV SPIRV_VARIABLE_NAME) set(SPIRV_HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}_spv.h) add_custom_command( OUTPUT ${SPIRV_HEADER_FILE} COMMAND ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION} MAIN_DEPENDENCY ${SOURCE_FILE} ) set(SHADER_HEADERS ${SHADER_HEADERS} ${SPIRV_HEADER_FILE}) endif() endforeach() # Integer variants of the MSAA conversion shaders. They only differ from the float # source in the sampler and output types, so they are generated from it via defines. set(SHADER_TYPE_VARIANTS "convert_msaa_to_non_msaa.frag|sint|isampler2DMS|ivec4" "convert_msaa_to_non_msaa.frag|uint|usampler2DMS|uvec4" "convert_non_msaa_to_msaa.frag|sint|isampler2D|ivec4" "convert_non_msaa_to_msaa.frag|uint|usampler2D|uvec4" ) foreach(VARIANT IN ITEMS ${SHADER_TYPE_VARIANTS}) string(REPLACE "|" ";" VARIANT_PARTS ${VARIANT}) list(GET VARIANT_PARTS 0 VARIANT_FILENAME) list(GET VARIANT_PARTS 1 VARIANT_SUFFIX) list(GET VARIANT_PARTS 2 VARIANT_SAMPLER) list(GET VARIANT_PARTS 3 VARIANT_TEXEL) set(VARIANT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/${VARIANT_FILENAME}) get_filename_component(VARIANT_STEM ${VARIANT_FILENAME} NAME_WE) get_filename_component(VARIANT_EXT ${VARIANT_FILENAME} EXT) string(REPLACE "." "" VARIANT_EXT ${VARIANT_EXT}) set(VARIANT_NAME ${VARIANT_STEM}_${VARIANT_SUFFIX}_${VARIANT_EXT}) string(TOUPPER ${VARIANT_NAME}_SPV VARIANT_VARIABLE_NAME) set(VARIANT_HEADER_FILE ${SHADER_DIR}/${VARIANT_NAME}_spv.h) add_custom_command( OUTPUT ${VARIANT_HEADER_FILE} COMMAND ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} -DSAMPLER_TYPE=${VARIANT_SAMPLER} -DTEXEL_TYPE=${VARIANT_TEXEL} --variable-name ${VARIANT_VARIABLE_NAME} -o ${VARIANT_HEADER_FILE} ${VARIANT_SOURCE} --target-env ${SPIR_V_VERSION} MAIN_DEPENDENCY ${VARIANT_SOURCE} ) set(SHADER_HEADERS ${SHADER_HEADERS} ${VARIANT_HEADER_FILE}) endforeach() # AMD FidelityFX Super Resolution 3.1 upscaler (externals/FidelityFX-SDK, unmodified): the SDK's # Vulkan pass files, compiled with one set of options (render-size motion vectors, reversed depth, # HDR colour, reference Lanczos), plus the sharpening and the no-wave-operation SPD variants. set(FSR3_GPU_DIR ${CMAKE_SOURCE_DIR}/externals/FidelityFX-SDK/include/FidelityFX/gpu) set(FSR3_PASS_DIR ${CMAKE_SOURCE_DIR}/externals/FidelityFX-SDK/shaders/fsr3upscaler) file(GLOB FSR3_GPU_FILES ${FSR3_GPU_DIR}/*.h ${FSR3_GPU_DIR}/fsr1/*.h ${FSR3_GPU_DIR}/spd/*.h ${FSR3_GPU_DIR}/fsr3upscaler/*.h) set(FSR3_FLAGS -DFFX_GPU=1 -DFFX_GLSL=1 -DFFX_FSR3UPSCALER_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF=0 -DFFX_FSR3UPSCALER_OPTION_ACCUMULATE_SAMPLERS_USE_DATA_HALF=0 -DFFX_FSR3UPSCALER_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF=1 -DFFX_FSR3UPSCALER_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF=0 -DFFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE=2 -DFFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE=0 -DFFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT=1 -DFFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS=1 -DFFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS=0 -DFFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH=1 ) set(FSR3_VARIANTS "prepare_inputs|prepare_inputs|none" "luma_pyramid|luma_pyramid|none" "luma_pyramid_nowave|luma_pyramid|-DFFX_SPD_NO_WAVE_OPERATIONS=1" "shading_change_pyramid|shading_change_pyramid|none" "shading_change_pyramid_nowave|shading_change_pyramid|-DFFX_SPD_NO_WAVE_OPERATIONS=1" "shading_change|shading_change|none" "prepare_reactivity|prepare_reactivity|none" "luma_instability|luma_instability|none" "accumulate|accumulate|none" "accumulate_sharpen|accumulate|-DFFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING=1" "rcas|rcas|none" ) foreach(VARIANT IN ITEMS ${FSR3_VARIANTS}) string(REPLACE "|" ";" VARIANT_PARTS "${VARIANT}") list(GET VARIANT_PARTS 0 FSR3_NAME) list(GET VARIANT_PARTS 1 FSR3_PASS) list(GET VARIANT_PARTS 2 FSR3_DEFINE) if (FSR3_DEFINE STREQUAL "none") set(FSR3_DEFINE "") endif() if (NOT FSR3_DEFINE MATCHES "APPLY_SHARPENING") list(APPEND FSR3_DEFINE -DFFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING=0) endif() set(FSR3_SOURCE ${FSR3_PASS_DIR}/ffx_fsr3upscaler_${FSR3_PASS}_pass.glsl) string(TOUPPER fsr3_upscaler_${FSR3_NAME}_comp_spv FSR3_VARIABLE_NAME) set(FSR3_HEADER_FILE ${SHADER_DIR}/fsr3_upscaler_${FSR3_NAME}_comp_spv.h) add_custom_command( OUTPUT ${FSR3_HEADER_FILE} COMMAND ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -S comp -I"${FSR3_GPU_DIR}" -I"${FSR3_GPU_DIR}/fsr3upscaler" ${FSR3_FLAGS} ${FSR3_DEFINE} --variable-name ${FSR3_VARIABLE_NAME} -o ${FSR3_HEADER_FILE} ${FSR3_SOURCE} --target-env ${SPIR_V_VERSION} MAIN_DEPENDENCY ${FSR3_SOURCE} DEPENDS ${FSR3_GPU_FILES} ) set(SHADER_HEADERS ${SHADER_HEADERS} ${FSR3_HEADER_FILE}) endforeach() foreach(FILEPATH IN ITEMS ${FIDELITYFX_FILES}) get_filename_component(FILENAME ${FILEPATH} NAME) string(REPLACE "." "_" HEADER_NAME ${FILENAME}) set(SOURCE_FILE ${FILEPATH}) set(SOURCE_HEADER_FILE ${SHADER_DIR}/${HEADER_NAME}.h) add_custom_command( OUTPUT ${SOURCE_HEADER_FILE} COMMAND ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${SOURCE_HEADER_FILE} ${INPUT_FILE} MAIN_DEPENDENCY ${SOURCE_FILE} DEPENDS ${INPUT_FILE} # HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified ) set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE}) endforeach() set(SHADER_SOURCES ${SHADER_FILES}) list(APPEND SHADER_SOURCES ${GLSL_INCLUDES}) add_custom_target(host_shaders DEPENDS ${SHADER_HEADERS} SOURCES ${SHADER_SOURCES} )