载入着色器

我们已经得到了SPIR-V格式的着色器字节码文件,现在需要在应用程序中载入字节码文件。为了完成这项工作,我们首先编写一个用于载入二进制文件的辅助函数。

#include <fstream>

        ...

static std::vector<char> readFile(const std::string& filename) {
    std::ifstream file(filename, std::ios::ate | std::ios::binary);

    if (!file.is_open()) {
        throw std::runtime_error("failed to open file!");
    }
}

readFile函数会读取指定文件的所有字节,然后将数据保存在std::vector数组返回给调用者。上面代码中我们使用了下面两个模式打开文件:

  • ate:从文件尾部开始读取

  • binary:以二进制的形式读取文件(避免进行诸如行末格式是\n还是\r\n的转换)

使用ate模式,从文件尾部开始读取的原因是,我们可以根据读取位置确定文件的大小,然后分配足够的数组空间来容纳数据:

size_t fileSize = (size_t) file.tellg();
std::vector<char> buffer(fileSize);

分配好足够的数组空间后,我们可以跳到文件头部,读取整个文件:

file.seekg(0);
file.read(buffer.data(), fileSize);

最后,关闭文件,返回数据数组:

file.close();

return buffer;

现在,我们可以在createGraphicsPipeline函数中调用readFile函数来完成着色器字节码的读取:

void createGraphicsPipeline() {
    auto vertShaderCode = readFile("shaders/vert.spv");
    auto fragShaderCode = readFile("shaders/frag.spv");
}

我们可以通过比较打印出的分配的数组大小和实际的文件大小,确保着色器字节码被正确载入。