diff --git a/filament/src/driver/opengl/OpenGLProgram.cpp b/filament/src/driver/opengl/OpenGLProgram.cpp index 4b824ecedf..6201b73a86 100644 --- a/filament/src/driver/opengl/OpenGLProgram.cpp +++ b/filament/src/driver/opengl/OpenGLProgram.cpp @@ -30,6 +30,17 @@ namespace filament { using namespace math; using namespace utils; +// we just want a small, tight loop for our purpose here, so we avoid std::copy_n +UTILS_NOINLINE +static char* copy_n(char const* s, size_t n, char* d) noexcept { + char* const e = d + n; +#pragma nounroll + while (d != e) { + *d++ = *s++; + } + return d; +} + OpenGLProgram::OpenGLProgram(OpenGLDriver* gl, const Program& programBuilder) noexcept : HwProgram(programBuilder.getName()), mIsValid(false) { @@ -117,6 +128,9 @@ OpenGLProgram::OpenGLProgram(OpenGLDriver* gl, const Program& programBuilder) no auto& indicesRun = mIndicesRuns; uint8_t numUsedBindings = 0; uint8_t tmu = 0; + + char uniformName[256]; + #pragma nounroll for (size_t i = 0, c = samplerInterfaceBlocks.size(); i < c; i++) { auto const& sib = samplerInterfaceBlocks[i]; @@ -128,19 +142,27 @@ OpenGLProgram::OpenGLProgram(OpenGLDriver* gl, const Program& programBuilder) no info.binding = uint8_t(i); // sampler interface block name - std::string sib_name(sib->getName().c_str()); - sib_name.front() = char(std::tolower(sib_name.front())); + CString const& sibName = sib->getName(); + char* const prefix = copy_n(sibName.begin(), + std::min(sizeof(uniformName) / 2, (size_t)sibName.size()), + uniformName); + if (uniformName[0] >= 'A' && uniformName[0] <= 'Z') { + uniformName[0] |= 0x20; // poor man's tolower() + } + *prefix = '_'; uint8_t count = 0; for (uint8_t j = 0, m = uint8_t(infos.size()); j < m; ++j) { // build unique name for this uniform (sampler) auto const& e = infos[j]; - std::string e_name(e.name.c_str()); - std::string uniformSamplerName(sib_name); - uniformSamplerName.append("_").append(e_name); + char* last = copy_n(e.name.begin(), + std::min(sizeof(uniformName) / 2 - 2, (size_t)e.name.size()), + prefix + 1); + *last++ = 0; // null terminator + assert(last <= std::end(uniformName)); // find its location and associate a TMU to it - GLint loc = glGetUniformLocation(program, uniformSamplerName.c_str()); + GLint loc = glGetUniformLocation(program, uniformName); if (loc >= 0) { glUniform1i(loc, tmu); indicesRun[tmu] = j; diff --git a/libs/filaflat/src/Unflattener.cpp b/libs/filaflat/src/Unflattener.cpp index b7f7dcc2e3..e072b19bf9 100644 --- a/libs/filaflat/src/Unflattener.cpp +++ b/libs/filaflat/src/Unflattener.cpp @@ -25,8 +25,8 @@ bool Unflattener::read(utils::CString* s) noexcept { } bool overflowed = mCursor >= mEnd; if (!overflowed) { - mCursor++; *s = utils::CString{ (const char*)start, (utils::CString::size_type)(mCursor - start) }; + mCursor++; } return !overflowed; } diff --git a/libs/utils/src/CString.cpp b/libs/utils/src/CString.cpp index d39e6e86d1..a6023becd8 100644 --- a/libs/utils/src/CString.cpp +++ b/libs/utils/src/CString.cpp @@ -35,6 +35,9 @@ int StaticString::compare(const StaticString& rhs) const noexcept { UTILS_NOINLINE CString::CString(const char* cstr, size_type length) { if (length && cstr) { + // I think we can't use this assert with vulkan, because shaders are returned as CString + // (see ShaderBuilder). + // assert(length == strlen(cstr)); Data* p = (Data*)malloc(sizeof(Data) + length + 1); p->length = length; mCStr = (value_type*)(p + 1);