diff --git a/CMakeLists.txt b/CMakeLists.txt index 24f3192654..e7869c4d27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ include(CMakeDependentOption) include(FeatureSummary) include(Dependencies) include(VcpkgToolchain) +include(MetalShaderSupport) project(Plasma) @@ -161,6 +162,7 @@ endif(PLASMA_PIPELINE_GL) if(PLASMA_PIPELINE_METAL) add_definitions(-DPLASMA_PIPELINE_METAL) + enable_language(Metal) endif(PLASMA_PIPELINE_METAL) # Allow us to disable certain parts of the build diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index d8a882c400..0faa4b33e0 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -116,10 +116,6 @@ elseif(APPLE) Mac-Cocoa/PLSLoginWindowController.xib Mac-Cocoa/PLSPatcherWindowController.xib ) - list(APPEND plClient_SHADERTARGETS - pfMetalPipelineShadersMSL21 - pfMetalPipelineShadersMSL23 - ) else() list(APPEND plClient_SOURCES main.cpp @@ -158,17 +154,12 @@ if(APPLE) XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES" XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER org.Huru.UruExplorer - XCODE_EMBED_RESOURCES "${plClient_SHADERTARGETS}" ) target_compile_options(plClient PRIVATE -fobjc-arc) target_sources(plClient PRIVATE Mac-Cocoa/Assets.xcassets) set_source_files_properties(Mac-Cocoa/Assets.xcassets ${RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) - - if(${CMAKE_VERSION} VERSION_LESS 3.28) - message(FATAL_ERROR "Cannot build Mac client without CMake 3.28") - endif() if(PLASMA_APPLE_DEVELOPMENT_TEAM_ID) set_target_properties(plClient PROPERTIES @@ -178,6 +169,13 @@ if(APPLE) endif() endif() +if(PLASMA_PIPELINE_METAL) + target_embed_metal_shader_libraries(plClient + pfMetalPipelineShadersMSL21 + pfMetalPipelineShadersMSL23 + ) +endif() + if(PLASMA_BUILD_RESOURCE_DAT) target_sources(plClient PRIVATE ${external_SCRIPTS} ${external_SOURCES} ${external_DAT}) endif() diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfMetalPipeline/CMakeLists.txt index 7a583ee2ef..2a0cbf4b91 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/CMakeLists.txt @@ -44,6 +44,22 @@ set(pfMetalPipeline_HEADERS pfMetalPipelineCreatable.h ) +set(pfMetalPipeline_SHADERS + ShaderSrc/FixedPipelineShaders.metal + ShaderSrc/PlateShaders.metal + ShaderSrc/BiasNormals.metal + ShaderSrc/CompCosines.metal + ShaderSrc/WaveSet7.metal + ShaderSrc/Grass.metal + ShaderSrc/WaveDecEnv.metal + ShaderSrc/Avatar.metal + ShaderSrc/WaveDec1Lay_7.metal + ShaderSrc/WaveRip.metal + ShaderSrc/Clear.metal + ShaderSrc/GammaCorrection.metal + ShaderSrc/TextFontShader.metal +) + plasma_library(pfMetalPipeline SOURCES ${pfMetalPipeline_SOURCES} ${pfMetalPipeline_HEADERS}) target_link_libraries(pfMetalPipeline PUBLIC @@ -70,47 +86,21 @@ source_group("Source Files" FILES ${pfMetalPipeline_SOURCES}) source_group("Header Files" FILES ${pfMetalPipeline_HEADERS}) # All supported Macs for Plasma/Metal support MSL 2.1 -add_library(pfMetalPipelineShadersMSL21 MODULE) -# Build a 2.3 varient for macOS 11 and/or Apple Silicon specific features -add_library(pfMetalPipelineShadersMSL23 MODULE) - -set(pfMetalPipeline_SHADERS - ShaderSrc/FixedPipelineShaders.metal - ShaderSrc/PlateShaders.metal - ShaderSrc/BiasNormals.metal - ShaderSrc/CompCosines.metal - ShaderSrc/WaveSet7.metal - ShaderSrc/Grass.metal - ShaderSrc/WaveDecEnv.metal - ShaderSrc/Avatar.metal - ShaderSrc/WaveDec1Lay_7.metal - ShaderSrc/WaveRip.metal - ShaderSrc/Clear.metal - ShaderSrc/GammaCorrection.metal - ShaderSrc/TextFontShader.metal +add_metal_shader_library(pfMetalPipelineShadersMSL21 + STANDARD macos-metal2.1 + ${pfMetalPipeline_SHADERS} ) -set_target_properties(pfMetalPipelineShadersMSL21 PROPERTIES - XCODE_PRODUCT_TYPE com.apple.product-type.metal-library - XCODE_ATTRIBUTE_MTL_LANGUAGE_REVISION Metal21 - XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "${Plasma_SOURCE_DIR}/Sources/Plasma/NucleusLib/inc/" - SUFFIX ".metallib" - PREFIX "" - XCODE_ATTRIBUTE_MTL_FAST_MATH "YES" - XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=Debug] "INCLUDE_SOURCE" - XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=RelWithDebInfo] "INCLUDE_SOURCE" -) -set_target_properties(pfMetalPipelineShadersMSL23 PROPERTIES - XCODE_PRODUCT_TYPE com.apple.product-type.metal-library - XCODE_ATTRIBUTE_MTL_LANGUAGE_REVISION Metal23 - XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "${Plasma_SOURCE_DIR}/Sources/Plasma/NucleusLib/inc/" - SUFFIX ".metallib" - PREFIX "" - XCODE_ATTRIBUTE_MTL_FAST_MATH "YES" - XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=Debug] "INCLUDE_SOURCE" - XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=RelWithDebInfo] "INCLUDE_SOURCE" +target_include_directories(pfMetalPipelineShadersMSL21 + PRIVATE + $ ) -set_source_files_properties(${pfMetalPipeline_SHADERS} TARGET_DIRECTORY pfMetalPipelineShadersMSL21 PROPERTIES LANGUAGE METAL) -set_source_files_properties(${pfMetalPipeline_SHADERS} TARGET_DIRECTORY pfMetalPipelineShadersMSL23 PROPERTIES LANGUAGE METAL) -target_sources(pfMetalPipelineShadersMSL21 PRIVATE ${pfMetalPipeline_SHADERS}) -target_sources(pfMetalPipelineShadersMSL23 PRIVATE ${pfMetalPipeline_SHADERS}) +# Build a 2.3 varient for macOS 11 and/or Apple Silicon specific features +add_metal_shader_library(pfMetalPipelineShadersMSL23 + STANDARD macos-metal2.3 + ${pfMetalPipeline_SHADERS} +) +target_include_directories(pfMetalPipelineShadersMSL23 + PRIVATE + $ +) diff --git a/cmake/CMakeDetermineMetalCompiler.cmake b/cmake/CMakeDetermineMetalCompiler.cmake new file mode 100644 index 0000000000..bcf07e0f1c --- /dev/null +++ b/cmake/CMakeDetermineMetalCompiler.cmake @@ -0,0 +1,83 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file LICENCE.txt or https://cmake.org/licensing for details. + +# CMakeDetermine(LANG)Compiler.cmake -> this should find the compiler for LANG and configure CMake(LANG)Compiler.cmake.in + +include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) + +if(NOT CMAKE_Metal_COMPILER_NAMES) + set(CMAKE_Metal_COMPILER_NAMES metal) +endif() + +if("${CMAKE_GENERATOR}" STREQUAL "Xcode") + set(CMAKE_Metal_COMPILER_XCODE_TYPE sourcecode.metal) + + execute_process(COMMAND xcrun --find metal + OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _xcrun_err RESULT_VARIABLE _xcrun_result) + if(_xcrun_result EQUAL 0 AND EXISTS "${_xcrun_out}") + set(CMAKE_Metal_COMPILER "${_xcrun_out}") + else() + _cmake_find_compiler_path(Metal) + endif() +else() + if(CMAKE_Metal_COMPILER) + _cmake_find_compiler_path(Metal) + else() + set(CMAKE_Metal_COMPILER_INIT NOTFOUND) + + if(NOT $ENV{METALC} STREQUAL "") + get_filename_component(CMAKE_Metal_COMPILER_INIT $ENV{METALC} PROGRAM PROGRAM_ARGS CMAKE_Metal_FLAGS_ENV_INIT) + if(CMAKE_Metal_FLAGS_ENV_INIT) + set(CMAKE_Metal_COMPILER_ARG1 "${CMAKE_Metal_FLAGS_ENV_INIT}" CACHE STRING "Arguments to the Metal compiler") + endif() + if(NOT EXISTS ${CMAKE_Metal_COMPILER_INIT}) + message(FATAL_ERROR "Could not find compiler set in environment variable METALC\n$ENV{METALC}.\n${CMAKE_Metal_COMPILER_INIT}") + endif() + endif() + + if(NOT CMAKE_Metal_COMPILER_INIT) + set(CMAKE_Metal_COMPILER_LIST metal ${_CMAKE_TOOLCHAIN_PREFIX}metal) + endif() + + _cmake_find_compiler(Metal) + endif() + + mark_as_advanced(CMAKE_Metal_COMPILER) +endif() + +# For Metal we need to explicitly query the version. +if(CMAKE_Metal_COMPILER AND NOT CMAKE_Metal_COMPILER_VERSION) + execute_process( + COMMAND "${CMAKE_Metal_COMPILER}" --version + OUTPUT_VARIABLE output ERROR_VARIABLE output + RESULT_VARIABLE result + TIMEOUT 10 + ) + message(CONFIGURE_LOG + "Running the Metal compiler: \"${CMAKE_Metal_COMPILER}\" --version\n" + "${output}\n" + ) + + if(output MATCHES [[metal version ([0-9]+\.[0-9]+(\.[0-9]+)?)]]) + set(CMAKE_Metal_COMPILER_VERSION "${CMAKE_MATCH_1}") + if(NOT CMAKE_Metal_COMPILER_ID) + set(CMAKE_Metal_COMPILER_ID "Apple") + endif() + endif() +endif() + +if (NOT _CMAKE_TOOLCHAIN_LOCATION) + get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_Metal_COMPILER}" PATH) +endif () + +set(_CMAKE_PROCESSING_LANGUAGE "Metal") +include(CMakeFindBinUtils) +unset(_CMAKE_PROCESSING_LANGUAGE) + +configure_file( + ${CMAKE_CURRENT_LIST_DIR}/CMakeMetalCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeMetalCompiler.cmake +) + +set(CMAKE_Metal_COMPILER_ENV_VAR "METALC") diff --git a/cmake/CMakeMetalCompiler.cmake.in b/cmake/CMakeMetalCompiler.cmake.in new file mode 100644 index 0000000000..d636af4b7d --- /dev/null +++ b/cmake/CMakeMetalCompiler.cmake.in @@ -0,0 +1,27 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file LICENCE.txt or https://cmake.org/licensing for details. + +# CMake(LANG)Compiler.cmake.in -> used by CMakeDetermine(LANG)Compiler.cmake +# This file is used to store compiler information and is copied down into try +# compile directories so that try compiles do not need to re-determine and test +# the LANG + +set(CMAKE_Metal_COMPILER "@CMAKE_Metal_COMPILER@") +set(CMAKE_Metal_COMPILER_ID "@CMAKE_Metal_COMPILER_ID@") +set(CMAKE_Metal_COMPILER_VERSION "@CMAKE_Metal_COMPILER_VERSION@") + +set(CMAKE_Metal_COMPILER_LOADED 1) +set(CMAKE_Metal_COMPILER_WORKS "@CMAKE_Metal_COMPILER_WORKS@") + +set(CMAKE_Metal_COMPILER_ENV_VAR "METALC") + +set(CMAKE_Metal_COMPILER_ID_RUN "@CMAKE_Metal_COMPILER_ID_RUN@") +set(CMAKE_Metal_SOURCE_FILE_EXTENSIONS metal) +set(CMAKE_Metal_OUTPUT_EXTENSION ".air") +set(CMAKE_STATIC_LIBRARY_PREFIX_Metal "") +set(CMAKE_STATIC_LIBRARY_SUFFIX_Metal ".metal-ar") +set(CMAKE_SHARED_LIBRARY_PREFIX_Metal "") +set(CMAKE_SHARED_LIBRARY_SUFFIX_Metal ".metallib") +set(CMAKE_SHARED_MODULE_PREFIX_Metal "") +set(CMAKE_SHARED_MODULE_SUFFIX_Metal ".metallib") +set(CMAKE_EXECUTABLE_SUFFIX_Metal ".metallib") diff --git a/cmake/CMakeMetalInformation.cmake b/cmake/CMakeMetalInformation.cmake new file mode 100644 index 0000000000..7b0c0011be --- /dev/null +++ b/cmake/CMakeMetalInformation.cmake @@ -0,0 +1,78 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file LICENCE.txt or https://cmake.org/licensing for details. + +# CMake(LANG)Information.cmake -> set up rule variables for LANG : +# CMAKE_(LANG)_CREATE_SHARED_LIBRARY +# CMAKE_(LANG)_CREATE_SHARED_MODULE +# CMAKE_(LANG)_CREATE_STATIC_LIBRARY +# CMAKE_(LANG)_COMPILE_OBJECT +# CMAKE_(LANG)_LINK_EXECUTABLE + +include (CMakeCommonLanguageInclude) + +set(CMAKE_Metal_FLAGS_INIT "-ffast-math") +set(CMAKE_Metal_FLAGS_DEBUG_INIT "-gline-tables-only -frecord-sources") +set(CMAKE_Metal_FLAGS_RELWITHDEBINFO_INIT "-gline-tables-only -frecord-sources") + +cmake_initialize_per_config_variable(CMAKE_Metal_FLAGS "Flags used by the Metal compiler") + +set(CMAKE_INCLUDE_FLAG_Metal "-I ") +set(CMAKE_Metal_COMPILER_ARG1 "") +set(CMAKE_Metal_DEFINE_FLAG -D) +set(CMAKE_Metal_FRAMEWORK_SEARCH_FLAG "-F ") +set(CMAKE_Metal_LIBRARY_PATH_FLAG "-L ") +set(CMAKE_Metal_SYSROOT_FLAG "-isysroot") +set(CMAKE_Metal_COMPILE_OPTIONS_TARGET "-target ") +set(CMAKE_DEPFILE_FLAGS_Metal "-MMD -MT dependencies -MF ") + +if(CMAKE_GENERATOR MATCHES "Makefiles") + set(CMAKE_Metal_DEPFILE_FORMAT gcc) + set(CMAKE_Metal_DEPENDS_USE_COMPILER TRUE) +endif() + +set(CMAKE_Metal_COMPILER_PREDEFINES_COMMAND "${CMAKE_Metal_COMPILER}") +if(CMAKE_Metal_COMPILER_TARGET) + list(APPEND CMAKE_Metal_COMPILER_PREDEFINES_COMMAND "-target" "${CMAKE_Metal_COMPILER_TARGET}") +endif() + +# now define the following rule variables + +# CMAKE_Metal_CREATE_SHARED_LIBRARY +# CMAKE_Metal_CREATE_SHARED_MODULE +# CMAKE_Metal_COMPILE_OBJECT +# CMAKE_Metal_LINK_EXECUTABLE + +# variables supplied by the generator at use time +# +# the target without the suffix +# +# +# +# +# + +# Metal compiler information +# +# +# +# + +if(NOT CMAKE_Metal_COMPILE_OBJECT) + set(CMAKE_Metal_COMPILE_OBJECT + " -c -o ") +endif() + +if(NOT CMAKE_Metal_CREATE_SHARED_LIBRARY) + set(CMAKE_Metal_CREATE_SHARED_LIBRARY " -o ") +endif() + +if(NOT CMAKE_Metal_CREATE_SHARED_MODULE) + set(CMAKE_Metal_CREATE_SHARED_MODULE "${CMAKE_Metal_CREATE_SHARED_LIBRARY}") +endif() + +if(NOT CMAKE_Metal_LINK_EXECUTABLE) + # Metal shaders don't really have "executables", but we need this for the try_compile to work properly, so we'll just have it output a metallib file + set(CMAKE_Metal_LINK_EXECUTABLE " -o ") +endif() + +set(CMAKE_Metal_INFORMATION_LOADED 1) diff --git a/cmake/CMakeTestMetalCompiler.cmake b/cmake/CMakeTestMetalCompiler.cmake new file mode 100644 index 0000000000..29a8db8b11 --- /dev/null +++ b/cmake/CMakeTestMetalCompiler.cmake @@ -0,0 +1,75 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file LICENCE.txt or https://cmake.org/licensing for details. + +# CMakeTest(LANG)Compiler.cmake -> test the compiler and set: +# SET(CMAKE_(LANG)_COMPILER_WORKS 1 CACHE INTERNAL "") + +if(CMAKE_Metal_COMPILER_FORCED) + # The compiler configuration was forced by the user. + # Assume the user has configured all compiler information. + set(CMAKE_Metal_COMPILER_WORKS TRUE) + return() +endif() + +include (CMakeTestCompilerCommon) + +if("${CMAKE_GENERATOR}" STREQUAL "Xcode") + if(XCODE_VERSION VERSION_GREATER 7.0) + set(CMAKE_Metal_COMPILER_WORKS 1) + endif() +endif() + +# This file is used by EnableLanguage in cmGlobalGenerator to +# determine that that selected Metal compiler can actually compile +# and link the most basic of programs. If not, a fatal error +# is set and cmake stops processing commands and will not generate +# any makefiles or projects. +if(NOT CMAKE_Metal_COMPILER_WORKS) + PrintTestCompilerStatus("Metal") + __TestCompiler_setTryCompileTargetType() + + string(CONCAT __TestCompiler_testMetalCompilerSource + "#ifndef __METAL_VERSION__\n" + "# error \"The CMAKE_Metal_COMPILER is not a Metal compiler\"\n" + "#endif\n" + "#import \n" + "using namespace metal;\n") + + # Clear result from normal variable. + unset(CMAKE_Metal_COMPILER_WORKS) + + # Puts test result in cache variable. + try_compile(CMAKE_Metal_COMPILER_WORKS + SOURCE_FROM_VAR testMetalCompiler.metal __TestCompiler_testMetalCompilerSource + OUTPUT_VARIABLE __CMAKE_Metal_COMPILER_OUTPUT) + unset(__TestCompiler_testMetalCompilerSource) + + # Move result from cache to normal variable. + set(CMAKE_Metal_COMPILER_WORKS ${CMAKE_Metal_COMPILER_WORKS}) + unset(CMAKE_Metal_COMPILER_WORKS CACHE) + __TestCompiler_restoreTryCompileTargetType() + set(METAL_TEST_WAS_RUN 1) +endif() + +if(NOT CMAKE_Metal_COMPILER_WORKS) + PrintTestCompilerResult(CHECK_FAIL "broken") + string(REPLACE "\n" "\n " _output "${__CMAKE_Metal_COMPILER_OUTPUT}") + message(FATAL_ERROR "The Metal compiler\n \"${CMAKE_Metal_COMPILER}\"\n" + "is not able to compile a simple test program.\nIt fails " + "with the following output:\n ${_output}\n\n" + "CMake will not be able to correctly generate this project.") +else() + if(METAL_TEST_WAS_RUN) + PrintTestCompilerResult(CHECK_PASS "works") + endif() + + # Re-configure to save learned information. + configure_file( + ${CMAKE_CURRENT_LIST_DIR}/CMakeMetalCompiler.cmake.in + ${CMAKE_PLATFORM_INFO_DIR}/CMakeMetalCompiler.cmake + @ONLY + ) + include(${CMAKE_PLATFORM_INFO_DIR}/CMakeMetalCompiler.cmake) +endif() + +unset(__CMAKE_Metal_COMPILER_OUTPUT) diff --git a/cmake/CheckLanguage.cmake b/cmake/CheckLanguage.cmake new file mode 100644 index 0000000000..e212e3aab2 --- /dev/null +++ b/cmake/CheckLanguage.cmake @@ -0,0 +1,169 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file LICENCE.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +CheckLanguage +------------- + +Check whether a language can be enabled by the :command:`enable_language` +or :command:`project` commands: + +.. command:: check_language + + .. code-block:: cmake + + check_language() + + Try enabling language ```` in a test project and record results + in the cache: + + :variable:`CMAKE__COMPILER` + If the language can be enabled, this variable is set to the compiler + that was found. If the language cannot be enabled, this variable is + set to ``NOTFOUND``. + + If this variable is already set, either explicitly or cached by + a previous call, the check is skipped. + + :variable:`CMAKE__HOST_COMPILER` + This variable is set when ```` is ``CUDA`` or ``HIP``. + + If the check detects an explicit host compiler that is required for + compilation, this variable will be set to that compiler. + If the check detects that no explicit host compiler is needed, + this variable will be cleared. + + If this variable is already set, its value is preserved only if + :variable:`CMAKE__COMPILER` is also set. + Otherwise, the check runs and overwrites + :variable:`CMAKE__HOST_COMPILER` with a new result. + Note that :variable:`CMAKE__HOST_COMPILER` documents it should + not be set without also setting + :variable:`CMAKE__COMPILER` to a NVCC compiler. + + :variable:`CMAKE__PLATFORM ` + This variable is set to the detected GPU platform when ```` is ``HIP``. + + If the variable is already set its value is always preserved. Only compatible values + will be considered for :variable:`CMAKE__COMPILER`. + +For example: + +.. code-block:: cmake + + check_language(Fortran) + if(CMAKE_Fortran_COMPILER) + enable_language(Fortran) + else() + message(STATUS "No Fortran support") + endif() +#]=======================================================================] + +# This file has been modified to take into account the CMAKE_MODULES path when trying to build the test project +# Ref https://gitlab.kitware.com/cmake/cmake/-/issues/26020 +# This was merged in to CMake 3.30.0, so we only need this for older versions + +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.30) + include(${CMAKE_ROOT}/Modules/CheckLanguage.cmake) +else() + include_guard(GLOBAL) + + block(SCOPE_FOR POLICIES) + cmake_policy(SET CMP0126 NEW) + + macro(check_language lang) + if(NOT DEFINED CMAKE_${lang}_COMPILER) + set(_desc "Looking for a ${lang} compiler") + message(CHECK_START "${_desc}") + file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}) + + set(extra_compiler_variables) + if("${lang}" MATCHES "^(CUDA|HIP)$" AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") + set(extra_compiler_variables "set(CMAKE_${lang}_HOST_COMPILER \\\"\${CMAKE_${lang}_HOST_COMPILER}\\\")") + endif() + + if("${lang}" STREQUAL "HIP") + list(APPEND extra_compiler_variables "set(CMAKE_${lang}_PLATFORM \\\"\${CMAKE_${lang}_PLATFORM}\\\")") + endif() + + list(TRANSFORM extra_compiler_variables PREPEND "\"") + list(TRANSFORM extra_compiler_variables APPEND "\\n\"") + list(JOIN extra_compiler_variables "\n " extra_compiler_variables) + + set(_cl_content + "cmake_minimum_required(VERSION ${CMAKE_VERSION}) + set(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\") + project(Check${lang} ${lang}) + file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" + \"set(CMAKE_${lang}_COMPILER \\\"\${CMAKE_${lang}_COMPILER}\\\")\\n\" + ${extra_compiler_variables} + )" + ) + + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}/CMakeLists.txt" + "${_cl_content}") + if(CMAKE_GENERATOR_INSTANCE) + set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}") + else() + set(_D_CMAKE_GENERATOR_INSTANCE "") + endif() + if(CMAKE_GENERATOR MATCHES "^(Xcode$|Green Hills MULTI$|Visual Studio)") + set(_D_CMAKE_MAKE_PROGRAM "") + else() + set(_D_CMAKE_MAKE_PROGRAM "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}") + endif() + if(CMAKE_TOOLCHAIN_FILE) + set(_D_CMAKE_TOOLCHAIN_FILE "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_TOOLCHAIN_FILE}") + else() + set(_D_CMAKE_TOOLCHAIN_FILE "") + endif() + if(CMAKE_${lang}_PLATFORM) + set(_D_CMAKE_LANG_PLATFORM "-DCMAKE_${lang}_PLATFORM:STRING=${CMAKE_${lang}_PLATFORM}") + else() + set(_D_CMAKE_LANG_PLATFORM "") + endif() + execute_process( + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang} + COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR} + -A "${CMAKE_GENERATOR_PLATFORM}" + -T "${CMAKE_GENERATOR_TOOLSET}" + ${_D_CMAKE_GENERATOR_INSTANCE} + ${_D_CMAKE_MAKE_PROGRAM} + ${_D_CMAKE_TOOLCHAIN_FILE} + ${_D_CMAKE_LANG_PLATFORM} + OUTPUT_VARIABLE _cl_output + ERROR_VARIABLE _cl_output + RESULT_VARIABLE _cl_result + ) + include(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}/result.cmake OPTIONAL) + if(CMAKE_${lang}_COMPILER AND "${_cl_result}" STREQUAL "0") + message(CONFIGURE_LOG + "${_desc} passed with the following output:\n" + "${_cl_output}\n") + set(_CHECK_COMPILER_STATUS CHECK_PASS) + else() + set(CMAKE_${lang}_COMPILER NOTFOUND) + set(_CHECK_COMPILER_STATUS CHECK_FAIL) + message(CONFIGURE_LOG + "${_desc} failed with the following output:\n" + "${_cl_output}\n") + endif() + message(${_CHECK_COMPILER_STATUS} "${CMAKE_${lang}_COMPILER}") + set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER}" CACHE FILEPATH "${lang} compiler") + mark_as_advanced(CMAKE_${lang}_COMPILER) + + if(CMAKE_${lang}_HOST_COMPILER) + message(STATUS "Looking for a ${lang} host compiler - ${CMAKE_${lang}_HOST_COMPILER}") + set(CMAKE_${lang}_HOST_COMPILER "${CMAKE_${lang}_HOST_COMPILER}" CACHE FILEPATH "${lang} host compiler") + mark_as_advanced(CMAKE_${lang}_HOST_COMPILER) + endif() + + if(CMAKE_${lang}_PLATFORM) + set(CMAKE_${lang}_PLATFORM "${CMAKE_${lang}_PLATFORM}" CACHE STRING "${lang} platform") + mark_as_advanced(CMAKE_${lang}_PLATFORM) + endif() + endif() + endmacro() + + endblock() +endif() diff --git a/cmake/MetalShaderSupport.cmake b/cmake/MetalShaderSupport.cmake new file mode 100644 index 0000000000..bb214c1c0d --- /dev/null +++ b/cmake/MetalShaderSupport.cmake @@ -0,0 +1,52 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file LICENCE.txt or https://cmake.org/licensing for details. + +function(add_metal_shader_library TARGET) + cmake_parse_arguments(PARSE_ARGV 1 _amsl + "" + "STANDARD" + "" + ) + + add_library(${TARGET} MODULE ${_amsl_UNPARSED_ARGUMENTS}) + + set_target_properties(${TARGET} PROPERTIES + XCODE_PRODUCT_TYPE com.apple.product-type.metal-library + XCODE_ATTRIBUTE_MTL_FAST_MATH "YES" + XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=Debug] "INCLUDE_SOURCE" + XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=RelWithDebInfo] "INCLUDE_SOURCE" + XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "$(HEADER_SEARCH_PATHS)" + ) + + if(_amsl_STANDARD AND _amsl_STANDARD MATCHES "metal([0-9]+)\.([0-9]+)") + target_compile_options(${TARGET} + PRIVATE "-std=${_amsl_STANDARD}" + ) + + set_target_properties(${TARGET} PROPERTIES + XCODE_ATTRIBUTE_MTL_LANGUAGE_REVISION "Metal${CMAKE_MATCH_1}${CMAKE_MATCH_2}" + ) + endif() +endfunction() + +function(target_embed_metal_shader_libraries TARGET) + cmake_parse_arguments(PARSE_ARGV 1 _temsl + "" + "" + "" + ) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.28 AND ${CMAKE_GENERATOR} STREQUAL "Xcode") + set_target_properties(${TARGET} PROPERTIES + XCODE_EMBED_RESOURCES "${_temsl_UNPARSED_ARGUMENTS}" + ) + else() + foreach(SHADERLIB IN LISTS _temsl_UNPARSED_ARGUMENTS) + add_custom_command(TARGET ${TARGET} POST_BUILD + DEPENDS ${SHADERLIB} + COMMAND ${CMAKE_COMMAND} -E copy "$" "$/Resources/$" + VERBATIM + ) + endforeach() + endif() +endfunction()