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:
committed by
Clément Foucault
parent
af19a48e80
commit
0bfd5e3536
@@ -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
|
||||
|
||||
@@ -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}" "" "" "")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}" "" "" "")
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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}" "" "" "")
|
||||
|
||||
@@ -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)
|
||||
|
||||
13
source/blender/gpu/glsl_preprocess/CMakeLists.txt
Normal file
13
source/blender/gpu/glsl_preprocess/CMakeLists.txt
Normal 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})
|
||||
73
source/blender/gpu/glsl_preprocess/glsl_preprocess.cc
Normal file
73
source/blender/gpu/glsl_preprocess/glsl_preprocess.cc
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user