我目前正在通过关注这个网站来学习 Vulkan 。我目前正处于需要将我的 GLSL 着色器编译为 SPIR-V 的地步。与仅为着色器创建单独的编译脚本(例如使用 bash)的网站不同,我想在我的代码中完全使用 Cmake。
因为网站推荐的 SPIR-V/GLSL 编译器 glslc 安装在我的系统路径上(稍后我会担心可移植性。),我决定add_custom_command
在一个 cmake 函数中使用 Cmake,它充当包装器以添加着色器要编译。
但是,当我尝试这样做时,就好像我根本没有对 Cmake 代码进行任何更改。.spv
在我的树外构建文件夹或我的源文件夹中都没有生成文件。当我VERBOSE=1 make
使用 C++ 源代码在我的真实项目上运行时,我会看到 C++ 编译器的命令,但看不到任何glslc
命令。
我认为罪魁祸首可能是 Cmake 函数的某种作用域,我通过复制和粘贴函数的源代码然后手动替换其参数的值,将其中一个着色器调用移到任何函数调用之外。两种样式都显示在下面的 MCVE 中。
除了add_custom_command
Cmake 有一个add_custom_target
功能,但Cmake 的文档说如下:
[add_custom_target] 添加具有给定名称的目标以执行给定命令。目标没有输出文件,即使命令尝试使用目标的名称创建文件,它也始终被认为是过时的。使用 add_custom_command() 命令生成具有依赖关系的文件。默认情况下,没有任何东西取决于自定义目标。这不是我想要的,因为我不希望每次运行 Cmake 时都构建我的着色器,而是仅当自上次构建以来已更改 glsl 文件时,作为链接的 C++ 应用程序的依赖项,因为这就是他们是,我希望克莱恩认识到这一点。
这是一个 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}
)
碎片着色器.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);
}
顶点着色器.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);
}