30#define SHADER_SOURCE(datatoc, filename, filepath) extern char datatoc[];
31#include "glsl_compositor_source_list.h"
32#include "glsl_draw_source_list.h"
33#include "glsl_gpu_source_list.h"
35# include "glsl_ocio_source_list.h"
66 builtins |= shader::BuiltinBits::FRAG_COORD;
69 builtins |= shader::BuiltinBits::FRONT_FACING;
72 builtins |= shader::BuiltinBits::GLOBAL_INVOCATION_ID;
75 builtins |= shader::BuiltinBits::INSTANCE_ID;
78 builtins |= shader::BuiltinBits::LOCAL_INVOCATION_ID;
81 builtins |= shader::BuiltinBits::LOCAL_INVOCATION_INDEX;
84 builtins |= shader::BuiltinBits::NUM_WORK_GROUP;
87 builtins |= shader::BuiltinBits::POINT_COORD;
90 builtins |= shader::BuiltinBits::POINT_SIZE;
93 builtins |= shader::BuiltinBits::PRIMITIVE_ID;
96 builtins |= shader::BuiltinBits::VERTEX_ID;
99 builtins |= shader::BuiltinBits::WORK_GROUP_ID;
102 builtins |= shader::BuiltinBits::WORK_GROUP_SIZE;
112 if (source.find(
"'") != StringRef::not_found) {
113 char_literals_preprocess();
121 filename !=
"draw_debug_print_display_vert.glsl" &&
123 !
ELEM(
filename,
"common_debug_draw_lib.glsl",
"draw_debug_draw_display_vert.glsl"))
128#if GPU_SHADER_PRINTF_ENABLE
130 printf_preprocess(g_formats);
131 builtins |= shader::BuiltinBits::USE_PRINTF;
146 return (input.
rfind(
"/*", offset) > input.
rfind(
"*/", offset)) ||
147 (input.
rfind(
"//", offset) > input.
rfind(
"\n", offset));
150 template<
bool check_whole_word = true,
bool reversed = false,
typename T>
155 offset = input.
rfind(keyword, offset);
158 offset = input.
find(keyword, offset);
161 if constexpr (check_whole_word) {
163 char previous_char = input[offset - 1];
164 if (!
ELEM(previous_char,
'\n',
'\t',
' ',
':',
'(',
',')) {
179#define find_keyword find_str<true, false>
180#define rfind_keyword find_str<true, true>
181#define find_token find_str<false, false>
182#define rfind_token find_str<false, true>
190 int64_t char_number = offset - line_start + 1;
194 std::cerr <<
fullpath <<
":" << line_number <<
":" << char_number;
196 std::cerr <<
" error: " << message <<
"\n";
197 std::cerr << std::setw(5) << line_number <<
" | "
198 << input.
substr(line_start, line_end - line_start) <<
"\n";
200 for (
int64_t i = 0; i < char_number - 1; i++) {
206#define CHECK(test_value, str, ofs, msg) \
207 if ((test_value) == -1) { \
208 print_error(str, ofs, msg); \
240 if (
source.find_first_of(
'"') == -1) {
267 check_type(
"char2 ");
268 check_type(
"char3 ");
269 check_type(
"char4 ");
270 check_type(
"uchar ");
271 check_type(
"uchar2 ");
272 check_type(
"uchar3 ");
273 check_type(
"uchar4 ");
274 check_type(
"short ");
275 check_type(
"short2 ");
276 check_type(
"short3 ");
277 check_type(
"short4 ");
278 check_type(
"ushort ");
279 check_type(
"ushort2 ");
280 check_type(
"ushort3 ");
281 check_type(
"ushort4 ");
283 check_type(
"half2 ");
284 check_type(
"half3 ");
285 check_type(
"half4 ");
328 const bool is_cpp =
filename.endswith(
".hh");
342 if (cursor >= 8 && input.
substr(cursor - 8, 8) ==
"typedef ") {
352 CHECK(values_start, input, cursor,
"Malformed enum class. Expected \'{\' after typename.");
354 StringRef enum_name = input.
substr(name_start, values_start - name_start);
357 CHECK(name_end, input, name_start,
"Expected \':\' after C++ enum name.");
360 CHECK(underlying_type, input, name_start,
"C++ enums needs uint32_t underlying type.");
362 enum_name = input.
substr(name_start, name_end);
365 output +=
"#define " + enum_name +
" uint\n";
369 CHECK(values_end, input, cursor,
"Malformed enum class. Expected \'}\' after values.");
374 StringRef enum_values = input.
substr(values_start, values_end - values_start);
378 int64_t not_found = (token == -1) ? 0 : -1;
379 CHECK(not_found, input, values_start + token,
"Unexpected \'{\' token inside enum values.");
384 if (last_comma > last_equal) {
385 enum_values = input.
substr(values_start, last_comma);
388 output +=
"const uint " + enum_values;
390 int64_t semicolon_found = (input[values_end + 1] ==
';') ? 0 : -1;
391 CHECK(semicolon_found, input, values_end + 1,
"Expected \';\' after enum type declaration.");
394 cursor = last_pos = values_end + 1;
413 const char whitespace_chars[] =
" \r\n\t";
415 auto function_parse = [&](
const StringRef input,
425 if (arg_start == -1) {
434 if (body_start != -1 && next_semicolon != -1 && body_start > next_semicolon) {
436 BLI_assert_msg(
false,
"No prototypes allowed in node GLSL libraries.");
439 if (name_start == -1) {
443 if (name_end == -1) {
447 out_return_type =
"void";
448 out_name = input.
substr(name_start, name_end - name_start);
449 out_args = input.
substr(arg_start + 1, arg_end - (arg_start + 1));
454 int64_t keyword_start =
str.find_first_not_of(whitespace_chars, cursor);
455 if (keyword_start == -1) {
457 return str.substr(0, 0);
459 int64_t keyword_end =
str.find_first_of(whitespace_chars, keyword_start);
460 if (keyword_end == -1) {
462 keyword_end =
str.size();
464 cursor = keyword_end + 1;
465 return str.substr(keyword_start, keyword_end - keyword_start);
473 int64_t arg_start = cursor + 1;
474 if (arg_start >=
str.size()) {
482 const StringRef arg =
str.substr(arg_start, cursor - arg_start);
485 out_qualifier = keyword_parse(arg, keyword_cursor);
486 out_type = keyword_parse(arg, keyword_cursor);
487 out_name = keyword_parse(arg, keyword_cursor);
488 if (out_name.is_empty()) {
491 out_type = out_qualifier;
492 out_qualifier = arg.
substr(0, 0);
498 StringRef func_return_type, func_name, func_args;
499 while (function_parse(input, cursor, func_return_type, func_name, func_args)) {
501 if (func_name ==
"main") {
505 GPUFunction *func = MEM_new<GPUFunction>(__func__);
507 func->
source =
reinterpret_cast<void *
>(
this);
516 if (other_source !=
this) {
519 "Function redefinition or overload in two different files ...");
521 input, other_source->
source.
find(func_name),
"... previous definition was here");
530 if (func_return_type !=
"void") {
536 StringRef arg_qualifier, arg_type, arg_name;
537 while (arg_parse(func_args, args_cursor, arg_qualifier, arg_type, arg_name)) {
545 if (qualifier ==
"out") {
548 if (qualifier ==
"inout") {
555 if (type ==
"float") {
558 if (type ==
"vec2") {
561 if (type ==
"vec3") {
564 if (type ==
"vec4") {
567 if (type ==
"mat3") {
570 if (type ==
"mat4") {
573 if (type ==
"sampler1DArray") {
576 if (type ==
"sampler2DArray") {
579 if (type ==
"sampler2D") {
582 if (type ==
"sampler3D") {
585 if (type ==
"Closure") {
595 std::string err =
"Unknown parameter type \"" + arg_type +
"\"";
623 int64_t char_start = cursor + 1;
625 CHECK(char_end, input, cursor,
"Malformed char literal. Missing ending `'`.");
627 StringRef input_char = input.
substr(char_start, char_end - char_start);
629 CHECK(-1, input, cursor,
"Malformed char literal. Empty character constant");
632 uint8_t char_value = input_char[0];
634 if (input_char[0] ==
'\\') {
635 if (input_char[1] ==
'n') {
639 CHECK(-1, input, cursor,
"Unsupported escaped character");
643 if (input_char.
size() > 1) {
644 CHECK(-1, input, cursor,
"Malformed char literal. Multi-character character constant");
652 cursor = last_pos = char_end + 1;
680 bool do_endl =
false;
685 else if (func.
startswith(
"drw_print_no_endl(")) {
698 CHECK(semicolon, input, cursor,
"Malformed print(). Missing `;` .");
700 if (str_end < str_start) {
701 CHECK(-1, input, cursor,
"Malformed print(). Missing closing `)` .");
704 std::stringstream sub_output;
707 auto print_string = [&](std::string
str) ->
int {
708 size_t len_before_pad =
str.length();
710 while (
str.length() % 4 != 0) {
714 sub_output <<
"/* " <<
str <<
"*/";
715 sub_output <<
"drw_print_string_start(" << len_before_pad <<
");";
716 for (
size_t i = 0; i < len_before_pad; i += 4) {
718 *(
reinterpret_cast<const uint8_t *
>(
str.c_str()) + i + 1),
719 *(
reinterpret_cast<const uint8_t *
>(
str.c_str()) + i + 2),
720 *(
reinterpret_cast<const uint8_t *
>(
str.c_str()) + i + 3)};
721 if (i + 4 > len_before_pad) {
722 chars[len_before_pad - i] =
'\0';
725 SNPRINTF(uint_hex,
"0x%.2X%.2X%.2X%.2Xu", chars[3], chars[2], chars[1], chars[0]);
726 sub_output <<
"drw_print_char4(" <<
StringRefNull(uint_hex) <<
");";
731 std::string func_args = input_args;
734 bool string_scope =
false;
736 for (
char &c : func_args) {
738 string_scope = !string_scope;
740 else if (!string_scope) {
747 else if (c ==
',' && func_scope != 0) {
753 const bool print_as_variable = (input_args[0] !=
'"') &&
find_token(input_args,
',') == -1;
754 if (print_as_variable) {
756 std::string arg = input_args;
758 while (arg.length() % 4 != 0) {
763 sub_output <<
"drw_print_value(" << input_args <<
");";
766 const std::regex arg_regex(
768 "[\\s]*\"([^\r\n\t\f\v\"]*)\""
773 std::smatch args_match;
774 std::string::const_iterator args_search_start(func_args.cbegin());
775 while (std::regex_search(args_search_start, func_args.cend(), args_match, arg_regex)) {
776 args_search_start = args_match.suffix().first;
777 std::string arg_string = args_match[1].str();
778 std::string arg_val = args_match[2].str();
780 if (arg_string.empty()) {
781 for (
char &c : arg_val) {
786 sub_output <<
"drw_print_value(" << arg_val <<
");";
789 print_string(arg_string);
795 sub_output <<
"drw_print_newline();";
798 output << sub_output.str();
800 cursor = last_pos = str_end + 1;
807 if (
filename !=
"common_debug_print_lib.glsl") {
843 CHECK(semicolon, input, cursor,
"Malformed printf(). Missing `;` .");
845 if (str_end < str_start) {
846 CHECK(-1, input, cursor,
"Malformed printf(). Missing closing `)` .");
851 std::string func_args = input_args;
855 bool string_scope =
false;
857 for (
char &c : func_args) {
859 string_scope = !string_scope;
861 else if (!string_scope) {
868 else if (c ==
',' && func_scope != 0) {
877 const std::regex arg_regex(
879 "[\\s]*\"([^\r\n\t\f\v\"]*)\""
884 std::smatch args_match;
885 std::string::const_iterator args_search_start(func_args.cbegin());
886 while (std::regex_search(args_search_start, func_args.cend(), args_match, arg_regex)) {
887 args_search_start = args_match.suffix().first;
888 std::string arg_string = args_match[1].str();
889 std::string arg_val = args_match[2].str();
891 if (!arg_string.empty()) {
893 CHECK(-1, input, cursor,
"Format string is not the only string arg.");
896 CHECK(-1, input, cursor,
"Format string is not first argument.");
901 for (
char &c : arg_val) {
907 arguments.
append(arg_val);
913 CHECK(-1, input, cursor,
"No format string found.");
916 int format_arg_count = std::count(
format.begin(),
format.end(),
'%');
917 if (format_arg_count > arguments.
size()) {
918 CHECK(-1, input, cursor,
"printf call has not enough arguments.");
921 if (format_arg_count < arguments.
size()) {
922 CHECK(-1, input, cursor,
"printf call has too many arguments.");
929 if (format_map->
contains(format_hash)) {
931 CHECK(-1, input, cursor,
"printf format hash collision.");
943 format = std::regex_replace(
format, std::regex(R
"(\\n)"), "\n");
944 format = std::regex_replace(
format, std::regex(R
"(\\v)"), "\v");
945 format = std::regex_replace(
format, std::regex(R
"(\\t)"), "\t");
946 format = std::regex_replace(
format, std::regex(R
"(\\')"), "\'");
947 format = std::regex_replace(
format, std::regex(R
"(\\")"), "\"");
948 format = std::regex_replace(
format, std::regex(R
"(\\\\)"), "\\");
953 while ((end =
format.find_first_of(
'%', start + 1)) != -1) {
958 switch (
format[end + 1]) {
978 format_map->
add(format_hash, fmt);
981 std::string sub_output =
"print_header(" + std::to_string(format_hash) +
"u, " +
982 std::to_string(format_arg_count) +
"u)";
983 for (std::string &arg : arguments) {
984 sub_output =
"print_data(" + sub_output +
", " + arg +
")";
987 output << sub_output <<
";\n";
989 cursor = last_pos = str_end + 1;
1012 if (this->dependencies_init) {
1015 this->dependencies_init =
true;
1020 if ((
builtins & BuiltinBits::USE_PRINTF) == BuiltinBits::USE_PRINTF) {
1023 if ((
builtins & BuiltinBits::USE_DEBUG_DRAW) == BuiltinBits::USE_DEBUG_DRAW) {
1026 if ((
builtins & BuiltinBits::USE_DEBUG_PRINT) == BuiltinBits::USE_DEBUG_PRINT) {
1045 dependency_source = dict.
lookup_default(dependency_name,
nullptr);
1046 if (dependency_source ==
nullptr) {
1072 result.append(dep->source.c_str());
1081 out_builtins |= dep->builtins;
1083 return out_builtins;
1088 return (
filename.startswith(
"gpu_shader_material_") ||
1089 filename.startswith(
"gpu_shader_common_") ||
1090 filename.startswith(
"gpu_shader_compositor_")) &&
1110#define SHADER_SOURCE(datatoc, filename, filepath) \
1111 g_sources->add_new(filename, new GPUSource(filepath, filename, datatoc, g_functions, g_formats));
1112#include "glsl_compositor_source_list.h"
1113#include "glsl_draw_source_list.h"
1114#include "glsl_gpu_source_list.h"
1116# include "glsl_ocio_source_list.h"
1121 for (
auto *value :
g_sources->values()) {
1124 BLI_assert_msg(errors == 0,
"Dependency errors detected: Aborting");
1127#if GPU_SHADER_PRINTF_ENABLE
1131 for (
auto *value :
g_sources->values()) {
1133 if (value->filename.startswith(
"gpu_shader_material_")) {
1145 for (
auto *value :
g_sources->values()) {
1162 BLI_assert_msg(function !=
nullptr,
"Requested function not in the function library");
1189 if (shader_source_name.
is_empty()) {
1192 if (
g_sources->contains(shader_source_name) ==
false) {
1193 std::cerr <<
"Error: Could not find \"" << shader_source_name
1194 <<
"\" in the list of registered source.\n";
1207 if (src ==
nullptr) {
1208 std::cerr <<
"Error source not found : " << shader_source_name << std::endl;
1217 if (src ==
nullptr) {
1218 std::cerr <<
"Error source not found : " << shader_source_name << std::endl;
1226 for (
auto &source :
g_sources->values()) {
1227 if (source->source.c_str() == source_string.
c_str()) {
1228 return source->filename;
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
bool BLI_gset_add(GSet *gs, void *key)
void BLI_kdtree_nd_ insert(KDTree *tree, int index, const float co[KD_DIMS]) ATTR_NONNULL(1
#define SNPRINTF(dst, format,...)
#define UNUSED_VARS_NDEBUG(...)
eGPUBackendType GPU_backend_get_type()
bool add(const Key &key, const Value &value)
const Value & lookup(const Key &key) const
Value lookup_default(const Key &key, const Value &default_value) const
bool contains(const Key &key) const
static constexpr int64_t not_found
constexpr int64_t rfind(char c, int64_t pos=INT64_MAX) const
void copy(char *dst, int64_t dst_size) const
constexpr int64_t find(char c, int64_t pos=0) const
constexpr const char * begin() const
constexpr const char * end() const
constexpr int64_t find_last_not_of(StringRef chars, int64_t pos=INT64_MAX) const
constexpr int64_t find_first_not_of(StringRef chars, int64_t pos=0) const
constexpr bool is_empty() const
constexpr StringRef substr(int64_t start, int64_t size) const
constexpr bool startswith(StringRef prefix) const
constexpr int64_t size() const
constexpr const char * c_str() const
void append(const T &value)
GPUFunction * gpu_material_library_use_function(GSet *used_libraries, const char *name)
static bool force_printf_injection
void gpu_shader_dependency_init()
void gpu_shader_dependency_exit()
static GPUFunctionDictionnary * g_functions
#define CHECK(test_value, str, ofs, msg)
static GPUSourceDictionnary * g_sources
static void print_error(const char *message, va_list str_format_args)
Vector< const char * > gpu_shader_dependency_get_resolved_source(const StringRefNull shader_source_name)
StringRefNull gpu_shader_dependency_get_filename_from_source_string(const StringRefNull source_string)
Find the name of the file from which the given string was generated.
const PrintfFormat & gpu_shader_dependency_get_printf_format(uint32_t format_hash)
BuiltinBits gpu_shader_dependency_get_builtins(const StringRefNull shader_source_name)
bool gpu_shader_dependency_has_printf()
bool gpu_shader_dependency_force_gpu_print_injection()
StringRefNull gpu_shader_dependency_get_source(const StringRefNull shader_source_name)
static ConversionType reversed(ConversionType type)
Map< StringRef, GPUFunction * > GPUFunctionDictionnary
Map< uint32_t, shader::PrintfFormat > GPUPrintFormatMap
Map< StringRef, struct GPUSource * > GPUSourceDictionnary
uint64_t hash_string(StringRef str)
static OVERLAY_InstanceFormats g_formats
unsigned __int64 uint64_t
eGPUType paramtype[MAX_PARAMETER]
char name[MAX_FUNCTION_NAME]
GPUFunctionQual paramqual[MAX_PARAMETER]
Vector< GPUSource * > dependencies
bool is_from_material_library() const
int init_dependencies(const GPUSourceDictionnary &dict, const GPUFunctionDictionnary &g_functions)
void material_functions_parse(GPUFunctionDictionnary *g_functions)
void build(Vector< const char * > &result) const
shader::BuiltinBits builtins_get() const
static int64_t find_str(const StringRef &input, const T keyword, int64_t offset=0)
std::string processed_source
GPUSource(const char *path, const char *file, const char *datatoc, GPUFunctionDictionnary *g_functions, GPUPrintFormatMap *g_formats)
shader::BuiltinBits builtins
void char_literals_preprocess()
static bool is_in_comment(const StringRef &input, int64_t offset)
void printf_preprocess(GPUPrintFormatMap *format_map)
void print_error(const StringRef &input, int64_t offset, const StringRef message)
static const char hex[17]