Files
test/source/blender/gpu/glsl_preprocess/glsl_preprocess.cc
Clément Foucault fe213f80a4 GPU: Shader: Make info files generated
This is the first step of moving the create infos
back inside shader sources.

All info files are now treated as source files.
However, they are not considered in the include tree
yet. This will come in another following PR.

Each shader source file now generate a `.info` file
containing only the create info declarations.

This renames all info files so that they do not
conflict with their previous versions that were
copied (non-generated).

Pull Request: https://projects.blender.org/blender/blender/pulls/146676
2025-09-25 10:57:02 +02:00

140 lines
4.7 KiB
C++

/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup glsl_preprocess
*/
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <string>
#include "glsl_preprocess.hh"
int main(int argc, char **argv)
{
if (argc != 5) {
std::cerr << "Usage: glsl_preprocess <data_file_from> <data_file_to> <metadata_file_to> "
"<infos_file_to>"
<< std::endl;
exit(1);
}
const char *input_file_name = argv[1];
const char *output_file_name = argv[2];
const char *metadata_file_name = argv[3];
const char *infos_file_name = argv[4];
/* Open the input file for reading */
std::ifstream input_file(input_file_name);
if (!input_file) {
std::cerr << "Error: Could not open input file " << input_file_name << std::endl;
exit(1);
}
/* We make the required directories here rather than having the build system
* do the work for us, as having cmake do it leads to several thousand cmake
* instances being launched, leading to significant overhead, see pr #141404
* for details. */
std::filesystem::path parent_dir = std::filesystem::path(output_file_name).parent_path();
std::error_code ec;
if (!std::filesystem::create_directories(parent_dir, ec)) {
if (ec) {
std::cerr << "Unable to create " << parent_dir << " : " << ec.message() << std::endl;
exit(1);
}
}
/* Open the output file for writing */
std::ofstream output_file(output_file_name, std::ofstream::out | std::ofstream::binary);
if (!output_file) {
std::cerr << "Error: Could not open output file " << output_file_name << std::endl;
input_file.close();
exit(1);
}
/* Open the output file for writing */
std::ofstream metadata_file(metadata_file_name, std::ofstream::out | std::ofstream::binary);
if (!output_file) {
std::cerr << "Error: Could not open output file " << metadata_file_name << std::endl;
input_file.close();
exit(1);
}
/* Open the output file for writing */
std::ofstream infos_file(infos_file_name, std::ofstream::out | std::ofstream::binary);
if (!output_file) {
std::cerr << "Error: Could not open output file " << infos_file_name << std::endl;
input_file.close();
exit(1);
}
std::stringstream buffer;
buffer << input_file.rdbuf();
int error = 0;
auto report_error =
[&](int err_line, int err_char, const std::string &line, const char *err_msg) {
std::cerr << input_file_name;
std::cerr << ':' << std::to_string(err_line) << ':' << std::to_string(err_char + 1);
std::cerr << ": error: " << err_msg << std::endl;
std::cerr << line << std::endl;
std::cerr << std::string(err_char, ' ') << '^' << std::endl;
error++;
};
std::string filename(output_file_name);
const bool is_info = filename.find("infos.hh") != std::string::npos;
const bool is_glsl = filename.find(".glsl") != std::string::npos;
const bool is_shared = filename.find("shared.h") != std::string::npos;
const bool is_library = is_glsl &&
(filename.find("gpu_shader_material_") != std::string::npos ||
filename.find("gpu_shader_common_") != std::string::npos ||
filename.find("gpu_shader_compositor_") != std::string::npos);
using Preprocessor = blender::gpu::shader::Preprocessor;
Preprocessor processor;
Preprocessor::SourceLanguage language = Preprocessor::language_from_filename(filename);
if (language == Preprocessor::SourceLanguage::GLSL) {
/* All build-time GLSL files should be considered blender-GLSL. */
language = Preprocessor::SourceLanguage::BLENDER_GLSL;
}
blender::gpu::shader::metadata::Source metadata;
if (is_info) {
/* Until they are parsed properly. Nullify them. */
output_file << "";
}
else {
output_file << processor.process(
language, buffer.str(), input_file_name, is_library, is_shared, report_error, metadata);
}
/* TODO(fclem): Don't use regex for that. */
std::string metadata_function_name = "metadata_" +
std::regex_replace(
filename, std::regex(R"((?:.*)\/(.*))"), "$1");
std::replace(metadata_function_name.begin(), metadata_function_name.end(), '.', '_');
metadata_file << metadata.serialize(metadata_function_name);
if (is_info) {
/* Simple copy for now. But we need to rename all includes. */
std::string str = std::regex_replace(
buffer.str(), std::regex(R"(_infos.hh")"), "_infos.hh.info\"");
infos_file << str;
}
input_file.close();
output_file.close();
metadata_file.close();
infos_file.close();
return error;
}