diff --git a/src/main/cpp/gl/glsl/glsl_for_es.cpp b/src/main/cpp/gl/glsl/glsl_for_es.cpp index 3b8bf17..ad912cb 100644 --- a/src/main/cpp/gl/glsl/glsl_for_es.cpp +++ b/src/main/cpp/gl/glsl/glsl_for_es.cpp @@ -13,6 +13,7 @@ #include #include #include "cache.h" +#include "../../version.h" //#define FEATURE_PRE_CONVERTED_GLSL @@ -556,10 +557,18 @@ char* process_uniform_declarations(char* glslCode) { return modifiedGlslCode; } +std::string processOutColorLocations(const std::string& glslCode) { + const std::regex pattern(R"(\n(out highp vec4 outColor)(\d+);)"); + const std::string replacement = "\nlayout(location=$2) $1$2;"; + return std::regex_replace(glslCode, pattern, replacement); +} + static Cache glslCache; static bool isGlslConvertedSuccessfully; char* GLSLtoGLSLES(char* glsl_code, GLenum glsl_type, uint essl_version, uint glsl_version) { - const char* cachedESSL = glslCache.get(glsl_code); + std::string sha256_string(glsl_code); + sha256_string += "\n" + std::to_string(MAJOR) + "." + std::to_string(MINOR) + "." + std::to_string(REVISION) + "|" + std::to_string(essl_version); + const char* cachedESSL = glslCache.get(sha256_string.c_str()); if (cachedESSL) { LOG_D("GLSL Hit Cache:\n%s\n-->\n%s", glsl_code, cachedESSL) return (char*)cachedESSL; @@ -569,7 +578,7 @@ char* GLSLtoGLSLES(char* glsl_code, GLenum glsl_type, uint essl_version, uint gl char* converted = glsl_version<140?GLSLtoGLSLES_1(glsl_code, glsl_type, essl_version):GLSLtoGLSLES_2(glsl_code, glsl_type, essl_version); if (converted && isGlslConvertedSuccessfully) { converted = process_uniform_declarations(converted); - glslCache.put(glsl_code, converted); + glslCache.put(sha256_string.c_str(), converted); } return converted ? converted : glsl_code; } @@ -685,13 +694,14 @@ char* GLSLtoGLSLES_2(char* glsl_code, GLenum glsl_type, uint essl_version) { spvc_compiler_compile(compiler_glsl, &result); if (!result) { - LOG_D("Error: unexpected error in spirv-cross.") + LOG_E("Error: unexpected error in spirv-cross.") return glsl_code; } essl=result; spvc_context_destroy(context); essl = removeLayoutBinding(essl); + essl = processOutColorLocations(essl); essl = forceSupporterOutput(essl); //essl = makeRGBWriteonly(essl); diff --git a/src/main/cpp/gl/program.cpp b/src/main/cpp/gl/program.cpp index 8f57c0a..6c028bb 100644 --- a/src/main/cpp/gl/program.cpp +++ b/src/main/cpp/gl/program.cpp @@ -6,10 +6,22 @@ #include "log.h" #include "shader.h" #include "program.h" +#include +#include +#include #include "../config/settings.h" #define DEBUG 0 +char* removeLayoutLocations(const char* input) { + std::string code(input); + std::regex pattern(R"(layout\s*\(\s*location\s*=\s*\d+\s*\))"); + std::string result = std::regex_replace(code, pattern, ""); + char* output = new char[result.length() + 1]; + strcpy(output, result.c_str()); + return output; +} + void glBindFragDataLocation(GLuint program, GLuint color, const GLchar *name) { LOG() LOG_D("glBindFragDataLocation(%d, %d, %s)", program, color, name) @@ -19,8 +31,28 @@ void glBindFragDataLocation(GLuint program, GLuint color, const GLchar *name) { // } else { // LOG_W("Warning: No GL_EXT_blend_func_extended, skipping glBindFragDataLocation..."); // } - char* origin_glsl = nullptr; + + if (strlen(name) > 8 && strncmp(name, "outColor", 8) == 0) { + const char* numberStr = name + 8; + bool isNumber = true; + for (int i = 0; numberStr[i] != '\0'; ++i) { + if (!isdigit(numberStr[i])) { + isNumber = false; + break; + } + } + if (isNumber) { + unsigned int extractedColor = static_cast(std::stoul(numberStr)); + if (extractedColor == color) { + // outColor was bound in glsl process. exit now + LOG_D("Find outColor* with color *, skipping") + return; + } + } + } + + char* origin_glsl = nullptr; if (shaderInfo.frag_data_changed) { size_t glslLen = strlen(shaderInfo.frag_data_changed_converted) + 1; origin_glsl = (char *)malloc(glslLen); @@ -39,8 +71,8 @@ void glBindFragDataLocation(GLuint program, GLuint color, const GLchar *name) { strcpy(origin_glsl, shaderInfo.converted); } - size_t len = strlen(name); - size_t tlen = len + 32; + int len = strlen(name); + int tlen = len + 32; char *targetPattern = (char*)malloc(sizeof(char) * tlen); if (!targetPattern) { LOG_E("Memory allocation failed for targetPattern") @@ -67,13 +99,16 @@ void glBindFragDataLocation(GLuint program, GLuint color, const GLchar *name) { origin[matchLen] = '\0'; size_t resultLen = - strlen(origin) + 30; // "layout (location = )" + colorNumber + nullptr terminator + strlen(origin) + 30; // "layout (location = )" + colorNumber + null terminator result = (char *) malloc(resultLen); if (!result) { LOG_E("Memory allocation failed\n") free(origin); break; } + + origin = removeLayoutLocations(origin); + snprintf(result, resultLen, "layout (location = %d) %s", color, origin); char *temp = strstr(searchStart, origin); @@ -103,7 +138,6 @@ void glBindFragDataLocation(GLuint program, GLuint color, const GLchar *name) { return; } strcpy(shaderInfo.frag_data_changed_converted, newConverted); - free(newConverted); }