Cmake为什么不构建我的vulkan / spirv着色器?

时间:2019-08-13 13:16:35

标签: cmake vulkan spir-v

我目前正在按照this website学习Vulkan。目前,我需要将GLSL着色器编译为SPIR-V。与网站仅为着色器(例如,使用bash)创建单独的编译脚本的网站不同,我想完全使用Cmake编写代码。

由于该网站推荐的SPIR-V / GLSL编译器glslc已安装在我系统的路径上(稍后我会担心可移植性。),我决定在cmake函数中使用Cmake的add_custom_command充当包装以添加要编译的着色器。

但是,当我尝试执行此操作时,好像完全没有对Cmake代码进行任何更改。我的树外生成文件夹或源文件夹中没有生成.spv文件。当我使用C ++源代码在真实项目上运行VERBOSE=1 make时,我会看到C ++编译器的命令,但看不到任何glslc命令。

我认为,罪魁祸首可能是使用Cmake函数进行范围界定的,我通过复制和粘贴函数的源代码,然后手动替换其参数的值,将其中一个着色器调用移至任何函数调用之外。两种样式都显示在下面的MCVE中。

add_custom_command之外,Cmake还具有add_custom_target功能,但是Cmake's documentation表示以下内容:

  

[add_custom_target]添加具有给定名称的目标,该目标将执行给定命令。目标没有输出文件,即使命令尝试使用目标名称创建文件,也始终将其视为已过期。使用add_custom_command()命令生成具有依赖性的文件。默认情况下,任何内容都不取决于自定义目标。   这不是我想要的,因为我不想每次运行Cmake时都构建我的着色器,而是仅当自上次构建以来已更改glsl文件时,才作为链接C ++应用程序的依赖项他们是,我希望Clion能够认识到这一点。

这是MCVE:

目录结构:

$ tree
.
├── CMakeLists.txt
├── CMakeLists.txt~
├── fragmentshader.glsl
└── vertexshader.glsl

在Linux上重现该问题的命令:

cd /path/to/folder/with/these/files
mkdir cmake-build-test
cd cmake-build-test
cmake ..
make

CMakeLists.txt:

    cmake_minimum_required(VERSION 3.14)
    project(vulkan_cmake)

    function(add_spirv_shader SHADER_STAGE INPUT_FILE OUTPUT_FILE)
        add_custom_command(
                OUTPUT ${OUTPUT_FILE}
                COMMAND "glslc -fshader-stage=${SHADER_STAGE} ${INPUT_FILE} -o ${OUTPUT_FILE}" #glslc is on the system path on my computer, so I am not currently worried about `find_package`ing it.
                MAIN_DEPENDENCY ${INPUT_FILE}
                WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
        )
    endfunction()

    add_spirv_shader(vector vertexshader.glsl vertexshader.hpv)

    add_custom_command(
            OUTPUT fragment.spv
            COMMAND "glslc -fshader-stage=fragment fragmentshader.glsl -o fragment.spv" #glslc is on the system path on my computer, so I am not currently worried about `find_package`ing it.
            MAIN_DEPENDENCY fragmentshader.glsl
            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    )

fragmentshader.glsl:

    #version 450
    #extension GL_ARB_separate_shader_objects : enable

    layout (location = 0) out vec4 outColor;

    void main(){
        outColor = vec4(1.0, 0.0, 0.0, 1.0);
    }

vertexshader.glsl:

    #version 450
    #extension GL_ARB_separate_shader_objects : enable

    vec2 positions[3] = vec2[](
        vec2(0.0, -0.5),
        vec2(-0.5, 0.5),
        vec2(0.5, 0.5)
    );

    void main(){
        gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
    }

1 个答案:

答案 0 :(得分:0)

我是这样做的:

[...]

find_package(Vulkan REQUIRED COMPONENTS glslc)
find_program(glslc_executable NAMES glslc HINTS Vulkan::glslc)

#==============================================================================
# COMPILE SHADERS
#

set(SHADER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/shaders)
set(SHADER_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/shaders)

file(GLOB SHADERS
  ${SHADER_SOURCE_DIR}/*.vert
  ${SHADER_SOURCE_DIR}/*.frag
  ${SHADER_SOURCE_DIR}/*.comp
  ${SHADER_SOURCE_DIR}/*.geom
  ${SHADER_SOURCE_DIR}/*.tesc
  ${SHADER_SOURCE_DIR}/*.tese
  ${SHADER_SOURCE_DIR}/*.mesh
  ${SHADER_SOURCE_DIR}/*.task
  ${SHADER_SOURCE_DIR}/*.rgen
  ${SHADER_SOURCE_DIR}/*.rchit
  ${SHADER_SOURCE_DIR}/*.rmiss)

add_custom_command(
  COMMAND
    ${CMAKE_COMMAND} -E make_directory ${SHADER_BINARY_DIR}
  OUTPUT ${SHADER_BINARY_DIR}
  COMMENT "Creating ${SHADER_BINARY_DIR}"
)

foreach(source IN LISTS SHADERS)
  get_filename_component(FILENAME ${source} NAME)
  add_custom_command(
    COMMAND
      ${glslc_executable}
      #      -MD -MF ${SHADER_BINARY_DIR}/${FILENAME}.d
      -o ${SHADER_BINARY_DIR}/${FILENAME}.spv
      ${source}
    OUTPUT ${SHADER_BINARY_DIR}/${FILENAME}.spv
    DEPENDS ${source} ${SHADER_BINARY_DIR}
    COMMENT "Compiling ${FILENAME}"
  )
  list(APPEND SPV_SHADERS ${SHADER_BINARY_DIR}/${FILENAME}.spv)
endforeach()

add_custom_target(shaders ALL DEPENDS ${SPV_SHADERS})

请注意,我注释掉了 -MD -MF,因为它似乎不需要(在我的 linux 机器上)。

有关完整(和最新)版本,请参阅 my project on github