From e1b2e29d51c1ea9a4f5ba6a726ebdc7be45e662b Mon Sep 17 00:00:00 2001
From: Antonio Orefice <kokoko3k@gmail.com>
Date: Mon, 21 Oct 2024 23:45:44 +0200
Subject: [PATCH] slang shaders: add support for __has_include like C++17
 macro. (#17109)

* slang shaders: add support for __has_include like C++17 macro.
This adds a new #pragma include_if_exist "filename" directive that acts like #include statements,
but does not return error if the file does not exists.

* removed unuseful define
---
 gfx/drivers_shader/glslang_util.c       | 21 ++++++++++++++-------
 gfx/drivers_shader/glslang_util.h       |  2 +-
 gfx/drivers_shader/glslang_util_cxx.cpp |  2 +-
 gfx/drivers_shader/slang_process.cpp    |  2 +-
 4 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/gfx/drivers_shader/glslang_util.c b/gfx/drivers_shader/glslang_util.c
index c18a776125..728b05dea9 100644
--- a/gfx/drivers_shader/glslang_util.c
+++ b/gfx/drivers_shader/glslang_util.c
@@ -98,7 +98,7 @@ enum slang_texture_semantic slang_name_to_texture_semantic_array(
 }
 
 bool glslang_read_shader_file(const char *path,
-      struct string_list *output, bool root_file)
+      struct string_list *output, bool root_file, bool is_optional)
 {
    size_t i;
    char tmp[PATH_MAX_LENGTH];
@@ -124,7 +124,8 @@ bool glslang_read_shader_file(const char *path,
    /* Read file contents */
    if (!filestream_read_file(path, (void**)&buf, &buf_len))
    {
-      RARCH_ERR("[slang]: Failed to open shader file: \"%s\".\n", path);
+      if (!is_optional)
+         RARCH_ERR("[slang]: Failed to open shader file: \"%s\".\n", path);
       return false;
    }
 
@@ -181,15 +182,17 @@ bool glslang_read_shader_file(const char *path,
    snprintf(tmp, sizeof(tmp), "#line %u \"%s\"", root_file ? 2 : 1, basename);
    if (!string_list_append(output, tmp, attr))
       goto error;
-
+   
    /* Loop through lines of file */
    for (i = root_file ? 1 : 0; i < lines.size; i++)
    {
       const char *line   = lines.elems[i].data;
-
+   
       /* Check for 'include' statements */
-      if (!strncmp("#include ", line, STRLEN_CONST("#include ")))
+      bool include_optional = !strncmp("#pragma include_optional ", line, STRLEN_CONST("#pragma include_optional "));
+      if ( !strncmp("#include ", line, STRLEN_CONST("#include ")) || include_optional )
       {
+
          char include_file[PATH_MAX_LENGTH];
          char include_path[PATH_MAX_LENGTH];
 
@@ -209,8 +212,12 @@ bool glslang_read_shader_file(const char *path,
                include_path, path, include_file, sizeof(include_path));
 
          /* Parse include file */
-         if (!glslang_read_shader_file(include_path, output, false))
-            goto error;
+         if (!glslang_read_shader_file(include_path, output, false, include_optional)) {
+            if (include_optional)
+               RARCH_LOG("[slang]: Optional include not found \"%s\".\n", include_path);
+            else
+               goto error;
+         }
 
          /* After including a file, use line directive
           * to pull it back to current file. */
diff --git a/gfx/drivers_shader/glslang_util.h b/gfx/drivers_shader/glslang_util.h
index 53d421fad8..c34944c1cf 100644
--- a/gfx/drivers_shader/glslang_util.h
+++ b/gfx/drivers_shader/glslang_util.h
@@ -129,7 +129,7 @@ enum glslang_format glslang_find_format(const char *fmt);
    Returns a Bool indicating if parsing was successful.
  */
 bool glslang_read_shader_file(const char *path,
-      struct string_list *output, bool root_file);
+      struct string_list *output, bool root_file, bool is_optional);
 
 bool slang_texture_semantic_is_array(enum slang_texture_semantic sem);
 
diff --git a/gfx/drivers_shader/glslang_util_cxx.cpp b/gfx/drivers_shader/glslang_util_cxx.cpp
index 4f1fa0095d..b6115f5256 100644
--- a/gfx/drivers_shader/glslang_util_cxx.cpp
+++ b/gfx/drivers_shader/glslang_util_cxx.cpp
@@ -220,7 +220,7 @@ bool glslang_compile_shader(const char *shader_path, glslang_output *output)
 
    RARCH_LOG("[slang]: Compiling shader: \"%s\".\n", shader_path);
 
-   if (!glslang_read_shader_file(shader_path, &lines, true))
+   if (!glslang_read_shader_file(shader_path, &lines, true, false))
       goto error;
    output->meta = glslang_meta{};
    if (!glslang_parse_meta(&lines, &output->meta))
diff --git a/gfx/drivers_shader/slang_process.cpp b/gfx/drivers_shader/slang_process.cpp
index f06536697d..9318cd9003 100644
--- a/gfx/drivers_shader/slang_process.cpp
+++ b/gfx/drivers_shader/slang_process.cpp
@@ -397,7 +397,7 @@ bool slang_preprocess_parse_parameters(const char *shader_path,
    if (!string_list_initialize(&lines))
       goto error;
 
-   if (!glslang_read_shader_file(shader_path, &lines, true))
+   if (!glslang_read_shader_file(shader_path, &lines, true, false))
       goto error;
    meta = glslang_meta{};
    if (!glslang_parse_meta(&lines, &meta))