From c2653ba1ec8f06453f0653d141bcd348eff5d4a5 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Tue, 2 Mar 2021 17:03:16 -0500 Subject: Fix issue with long identifier names in GLSL output (#1731) * #include an absolute path didn't work - because paths were taken to always be relative. * First pass at handling 'names' that are too long in GLSL output. * Test to check functionality with very long func name. * Add access a long names buffer. * Fix typo in assert. Fix issue with coercion error for 1.0f / 0x7fffffff Co-authored-by: Tim Foley --- source/core/slang-string.cpp | 45 ++++++++++++++++++++++++++++++++++++++ source/core/slang-string.h | 4 +++- source/slang/slang-emit-c-like.cpp | 31 ++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/core/slang-string.cpp b/source/core/slang-string.cpp index a7374d8ba..62bc19754 100644 --- a/source/core/slang-string.cpp +++ b/source/core/slang-string.cpp @@ -340,6 +340,51 @@ namespace Slang } } + void String::reduceLength(Index newLength) + { + Index oldLength = getLength(); + SLANG_ASSERT(newLength <= oldLength); + if (oldLength == newLength) + { + return; + } + + // It must have a buffer, because only 0 length allows for nullptr + // and being 0 sized is already covered + SLANG_ASSERT(m_buffer); + + if (m_buffer->isUniquelyReferenced()) + { + m_buffer->length = newLength; + m_buffer->getData()[newLength] = 0; + } + else + { + // If 0 length is wanted we can just free + if (newLength == 0) + { + m_buffer.setNull(); + } + else + { + // We need to make a new copy, that we will shrink + + // We'll just go with capacity enough for the new length + const Index newCapacity = newLength; + StringRepresentation* newRepresentation = StringRepresentation::createWithCapacityAndLength(newCapacity, newLength); + + // Copy + char* dst = newRepresentation->getData(); + memcpy(dst, m_buffer->getData(), sizeof(char) * newLength); + // Zero terminate + dst[newLength] = 0; + + // Set the new rep + m_buffer = newRepresentation; + } + } + } + void String::append(const char* textBegin, char const* textEnd) { auto oldLength = getLength(); diff --git a/source/core/slang-string.h b/source/core/slang-string.h index 2312c0439..f42e78ac4 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -559,7 +559,9 @@ namespace Slang { return m_buffer ? m_buffer->getLength() : 0; } - + /// Make the length of the string the amount specified. Must be less than current size + void reduceLength(Index length); + friend String operator+(const char*op1, const String & op2); friend String operator+(const String & op1, const char * op2); friend String operator+(const String & op1, const String & op2); diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index d099af255..8e106fe55 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -620,6 +620,37 @@ void CLikeSourceEmitter::appendScrubbedName(const UnownedStringSlice& name, Stri out.appendChar(c); prevChar = c; } + + if (getSourceLanguage() == SourceLanguage::GLSL) + { + // It looks like the default glslang name limit is 1024, but let's go a little less so there is some wiggle room + const Index maxTokenLength = 1024 - 8; + + const Index length = out.getLength(); + + if (length > maxTokenLength) + { + // We are going to output with a prefix and a hash of the full name + const HashCode64 hash = getStableHashCode64(out.getBuffer(), length); + // Two hex chars per byte + const Index hashSize = sizeof(hash) * 2; + + // Work out a size that is within range taking into account the hash size and extra chars + Index reducedBaseLength = maxTokenLength - hashSize - 1; + // If it has a trailing _ remove it. + // We know because of scrubbing there can only be single _ + reducedBaseLength -= Index(out[reducedBaseLength - 1] == '_'); + + // Reduce the length + out.reduceLength(reducedBaseLength); + // Let's add a _ to separate from the rest of the name + out.appendChar('_'); + // Append the hash in hex + out.append(uint64_t(hash), 16); + + SLANG_ASSERT(out.getLength() <= maxTokenLength); + } + } } String CLikeSourceEmitter::generateEntryPointNameImpl(IREntryPointDecoration* entryPointDecor) -- cgit v1.2.3