GPU: Add GLSL preprocessor

This splits the GLSL processing into its own file
as it will grow in complexity.

Removes the complexity from `datatoc` and chain them
during the build process.

Rel #128076

Pull Request: https://projects.blender.org/blender/blender/pulls/128261
This commit is contained in:
Clément Foucault
2024-10-04 11:33:21 +02:00
committed by Clément Foucault
parent af19a48e80
commit 0bfd5e3536
10 changed files with 128 additions and 161 deletions

View File

@@ -974,7 +974,6 @@ function(delayed_do_install
endfunction()
# Same as above but generates the var name and output automatic.
# Takes optional: `STRIP_LEADING_C_COMMENTS` argument.
function(data_to_c
file_from file_to
list_to_add
@@ -985,19 +984,10 @@ function(data_to_c
get_filename_component(_file_to_path ${file_to} PATH)
set(optional_args "")
foreach(f ${ARGN})
if(f STREQUAL "STRIP_LEADING_C_COMMENTS")
set(optional_args "--options=strip_leading_c_comments")
else()
message(FATAL_ERROR "Unknown optional argument ${f} to \"data_to_c\"")
endif()
endforeach()
add_custom_command(
OUTPUT ${file_to}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path}
COMMAND "$<TARGET_FILE:datatoc>" ${file_from} ${file_to} ${optional_args}
COMMAND "$<TARGET_FILE:datatoc>" ${file_from} ${file_to}
DEPENDS ${file_from} datatoc)
set_source_files_properties(${file_to} PROPERTIES GENERATED TRUE)
@@ -1005,7 +995,6 @@ endfunction()
# Same as above but generates the var name and output automatic.
# Takes optional: `STRIP_LEADING_C_COMMENTS` argument.
function(data_to_c_simple
file_from
list_to_add
@@ -1022,24 +1011,45 @@ function(data_to_c_simple
get_filename_component(_file_to_path ${_file_to} PATH)
set(optional_args "")
foreach(f ${ARGN})
if(f STREQUAL "STRIP_LEADING_C_COMMENTS")
set(optional_args "--options=strip_leading_c_comments")
else()
message(FATAL_ERROR "Unknown optional argument ${f} to \"data_to_c_simple\"")
endif()
endforeach()
add_custom_command(
OUTPUT ${_file_to}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path}
COMMAND "$<TARGET_FILE:datatoc>" ${_file_from} ${_file_to} ${optional_args}
COMMAND "$<TARGET_FILE:datatoc>" ${_file_from} ${_file_to}
DEPENDS ${_file_from} datatoc)
set_source_files_properties(${_file_to} PROPERTIES GENERATED TRUE)
endfunction()
# Process glsl file and convert it to c
function(glsl_to_c
file_from
list_to_add
)
# remove ../'s
get_filename_component(_file_from ${CMAKE_CURRENT_SOURCE_DIR}/${file_from} REALPATH)
get_filename_component(_file_tmp ${CMAKE_CURRENT_BINARY_DIR}/${file_from} REALPATH)
get_filename_component(_file_to ${CMAKE_CURRENT_BINARY_DIR}/${file_from}.c REALPATH)
list(APPEND ${list_to_add} ${_file_to})
source_group(Generated FILES ${_file_to})
list(APPEND ${list_to_add} ${file_from})
set(${list_to_add} ${${list_to_add}} PARENT_SCOPE)
get_filename_component(_file_to_path ${_file_to} PATH)
add_custom_command(
OUTPUT ${_file_to}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path}
COMMAND "$<TARGET_FILE:glsl_preprocess>" ${_file_from} ${_file_tmp}
COMMAND "$<TARGET_FILE:datatoc>" ${_file_tmp} ${_file_to}
DEPENDS ${_file_from} datatoc glsl_preprocess)
set_source_files_properties(${_file_to} PROPERTIES GENERATED TRUE)
endfunction()
function(msgfmt_simple
file_from
list_to_add

View File

@@ -66,7 +66,7 @@ if(WITH_OPENCOLORIO)
set(GLSL_C)
foreach(GLSL_FILE ${GLSL_SRC})
data_to_c_simple(${GLSL_FILE} GLSL_C STRIP_LEADING_C_COMMENTS)
glsl_to_c(${GLSL_FILE} GLSL_C)
endforeach()
blender_add_lib(bf_ocio_shaders "${GLSL_C}" "" "" "")

View File

@@ -85,10 +85,9 @@ if(WITH_OPENSUBDIV)
add_definitions(-D_USE_MATH_DEFINES)
endif()
data_to_c_simple(
glsl_to_c(
internal/evaluator/shaders/glsl_compute_kernel.glsl
SRC
STRIP_LEADING_C_COMMENTS
)
else()
list(APPEND SRC

View File

@@ -137,6 +137,7 @@ set(SRC_DNA_OTHER_INC
)
add_subdirectory(datatoc)
add_subdirectory(gpu/glsl_preprocess)
add_subdirectory(editors)
add_subdirectory(windowmanager)
add_subdirectory(animrig)

View File

@@ -280,7 +280,7 @@ set(GLSL_SRC
set(GLSL_C)
foreach(GLSL_FILE ${GLSL_SRC})
data_to_c_simple(${GLSL_FILE} GLSL_C STRIP_LEADING_C_COMMENTS)
glsl_to_c(${GLSL_FILE} GLSL_C)
endforeach()
blender_add_lib(bf_compositor_shaders "${GLSL_C}" "" "" "")

View File

@@ -31,95 +31,6 @@ static char *arg_basename(char *string)
return std::max({string, lfslash, lbslash});
}
/**
* Detect leading C-style comments and seek the file to it's end,
* returning the number of bytes skipped and setting `r_newlines`
* or return zero and seek to the file start.
*
* The number of newlines is used so the number of lines matches
* the generated data, so any errors provide useful line numbers
* (this could be made optional, as there may be cases where it's not helpful).
*/
static int strip_leading_c_comment(FILE *fpin, int size, int *r_newlines)
{
*r_newlines = 0;
if (size < 4) {
return 0;
}
enum {
IS_SPACE = 1,
IS_COMMENT = 2,
IS_COMMENT_MAYBE_BEG = 3,
IS_COMMENT_MAYBE_END = 4,
} context = IS_SPACE;
/* Last known valid offset. */
int offset_checkpoint = 0;
int newlines_checkpoint = 0;
int offset = 0;
int newlines = 0;
while (offset < size) {
const char c_curr = getc(fpin);
offset += 1;
if (context == IS_SPACE) {
if (c_curr == ' ' || c_curr == '\t' || c_curr == '\n') {
/* Pass. */
}
else if (c_curr == '/') {
context = IS_COMMENT_MAYBE_BEG;
}
else {
/* Non-space and non-comment, exit. */
break;
}
}
else if (context == IS_COMMENT) {
if (c_curr == '*') {
context = IS_COMMENT_MAYBE_END;
}
}
else if (context == IS_COMMENT_MAYBE_BEG) {
if (c_curr == '*') {
context = IS_COMMENT;
}
else {
/* Non-comment text, exit. */
break;
}
}
else if (context == IS_COMMENT_MAYBE_END) {
if (c_curr == '/') {
context = IS_SPACE;
}
else if (c_curr == '*') {
/* Pass. */
}
else {
context = IS_COMMENT;
}
}
if (c_curr == '\n') {
newlines += 1;
}
if (context == IS_SPACE) {
offset_checkpoint = offset;
newlines_checkpoint = newlines;
}
}
if (offset != offset_checkpoint) {
fseek(fpin, offset_checkpoint, SEEK_SET);
}
*r_newlines = newlines_checkpoint;
return offset_checkpoint;
}
int main(int argc, char **argv)
{
FILE *fpin, *fpout;
@@ -127,36 +38,11 @@ int main(int argc, char **argv)
int i;
int argv_len;
bool strip_leading_c_comments_test = false;
int leading_newlines = 0;
if (argc < 2) {
printf(
"Usage: "
"datatoc <data_file_from> <data_file_to> [--options=strip_leading_c_comments]\n");
if (argc != 3) {
printf("Usage: datatoc <data_file_from> <data_file_to>\n");
exit(1);
}
if (argc > 3) {
const char *arg_extra = argv[3];
const char *arg_transform = "--options=";
if (STRPREFIX(arg_extra, arg_transform)) {
/* We may want to have other options in the future. */
const char *options = arg_extra + strlen(arg_transform);
if (strcmp(options, "strip_leading_c_comments") == 0) {
strip_leading_c_comments_test = true;
}
else {
printf("Unknown --options=<%s>\n", options);
exit(1);
}
}
else {
printf("Unknown argument <%s>, expected --options=[...] or none.\n", arg_extra);
exit(1);
}
}
fpin = fopen(argv[1], "rb");
if (!fpin) {
printf("Unable to open input <%s>\n", argv[1]);
@@ -169,11 +55,6 @@ int main(int argc, char **argv)
size = ftell(fpin);
fseek(fpin, 0L, SEEK_SET);
if (strip_leading_c_comments_test) {
const int size_offset = strip_leading_c_comment(fpin, size, &leading_newlines);
size -= size_offset; /* The comment is skipped, */
}
if (argv[1][0] == '.') {
argv[1]++;
}
@@ -201,19 +82,9 @@ int main(int argc, char **argv)
fprintf(fpout, "extern const int datatoc_%s_size;\n", argv[1]);
fprintf(fpout, "extern const char datatoc_%s[];\n\n", argv[1]);
fprintf(fpout, "const int datatoc_%s_size = %d;\n", argv[1], int(leading_newlines + size));
fprintf(fpout, "const int datatoc_%s_size = %d;\n", argv[1], int(size));
fprintf(fpout, "const char datatoc_%s[] = {\n", argv[1]);
if (leading_newlines) {
while (leading_newlines--) {
if (leading_newlines % 32 == 31) {
fprintf(fpout, "\n");
}
fprintf(fpout, "%3d,", '\n');
}
fprintf(fpout, "\n");
}
while (size--) {
/* Even though this file is generated and doesn't need new-lines,
* these files may be loaded by developers when looking up symbols.

View File

@@ -800,7 +800,7 @@ set(GLSL_SRC
set(GLSL_C)
foreach(GLSL_FILE ${GLSL_SRC})
data_to_c_simple(${GLSL_FILE} GLSL_C STRIP_LEADING_C_COMMENTS)
glsl_to_c(${GLSL_FILE} GLSL_C)
endforeach()
blender_add_lib(bf_draw_shaders "${GLSL_C}" "" "" "")

View File

@@ -698,13 +698,13 @@ if(WITH_METAL_BACKEND)
set(MSL_C)
foreach(MSL_FILE ${MSL_SRC})
data_to_c_simple(${MSL_FILE} MSL_C STRIP_LEADING_C_COMMENTS)
glsl_to_c(${MSL_FILE} MSL_C)
endforeach()
endif()
set(GLSL_C)
foreach(GLSL_FILE ${GLSL_SRC})
data_to_c_simple(${GLSL_FILE} GLSL_C STRIP_LEADING_C_COMMENTS)
glsl_to_c(${GLSL_FILE} GLSL_C)
endforeach()
set(SHADER_C)

View File

@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: 2023 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
# -----------------------------------------------------------------------------
# Build `glsl_preprocess` executable.
set(SRC
glsl_preprocess.cc
)
# `SRC_DNA_INC` is defined in the parent directory.
add_executable(glsl_preprocess ${SRC})

View File

@@ -0,0 +1,73 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup glsl_preprocess
*/
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char **argv)
{
if (argc != 3) {
std::cerr << "Usage: glsl_preprocess <data_file_from> <data_file_to>" << std::endl;
exit(1);
}
const char *input_file_name = argv[1];
const char *output_file_name = argv[2];
/* 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);
}
/* Open the output file for writing */
std::ofstream output_file(output_file_name);
if (!output_file) {
std::cerr << "Error: Could not open output file " << output_file_name << std::endl;
input_file.close();
exit(1);
}
bool first_comment = true;
bool inside_comment = false;
std::string line;
while (std::getline(input_file, line)) {
/* Remove licence headers (first comment). */
if (line.rfind("/*", 0) == 0 && first_comment) {
first_comment = false;
inside_comment = true;
}
const bool skip_line = inside_comment;
if (inside_comment && (line.find("*/") != std::string::npos)) {
inside_comment = false;
}
if (skip_line) {
line = "";
}
#if 0 /* Wait until we support this new syntax. */
else if (line.rfind("#include ", 0) == 0 || line.rfind("#pragma once", 0) == 0) {
line[0] = line[1] = '/';
}
#endif
output_file << line << "\n";
}
input_file.close();
output_file.close();
return 0;
}