Title: [156352] trunk/Source/WebCore
Revision
156352
Author
[email protected]
Date
2013-09-24 12:43:25 -0700 (Tue, 24 Sep 2013)

Log Message

Implement symbol name hashing for WebGL shaders
https://bugs.webkit.org/show_bug.cgi?id=121849

Reviewed by Anders Carlsson.

Turn on ANGLE's symbol name mapping for shader programs.
This avoids compilation failures (or worse, crashers)
on some hardware that doesn't like it when shaders redefine
symbols like "sin", even though that is valid.

The way ANGLE exposes this is via setting a pointer
to a char* -> uint64_t hash function. Since we only have
a 32-bit hash in WebKit, I combine the 32-bit value with
a counter value that exists over the lifetime of a GC3D context.
Before calling ANGLE, I point the global hash map to the local
hash map, and then clean up after we're done. This introduces
a memory hit, in that the symbol table will build up until
the context is released.

Covered by Khronos WebGL tests, including
conformance/glsl/misc/shader-with-non-reserved-words.html

* platform/graphics/GraphicsContext3D.h: Define a ShaderNameHash type,
and add an OwnPtr to one as a member variable.
* platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp:
(WebCore::nameHashForShader): Global function used for ANGLE hashing.
(WebCore::GraphicsContext3D::compileShader): Set up the ANGLE properties,
point to the local hash map, and call compile/translate.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (156351 => 156352)


--- trunk/Source/WebCore/ChangeLog	2013-09-24 19:43:22 UTC (rev 156351)
+++ trunk/Source/WebCore/ChangeLog	2013-09-24 19:43:25 UTC (rev 156352)
@@ -1,5 +1,36 @@
 2013-09-24  Dean Jackson  <[email protected]>
 
+        Implement symbol name hashing for WebGL shaders
+        https://bugs.webkit.org/show_bug.cgi?id=121849
+
+        Reviewed by Anders Carlsson.
+
+        Turn on ANGLE's symbol name mapping for shader programs.
+        This avoids compilation failures (or worse, crashers)
+        on some hardware that doesn't like it when shaders redefine
+        symbols like "sin", even though that is valid.
+
+        The way ANGLE exposes this is via setting a pointer
+        to a char* -> uint64_t hash function. Since we only have
+        a 32-bit hash in WebKit, I combine the 32-bit value with
+        a counter value that exists over the lifetime of a GC3D context.
+        Before calling ANGLE, I point the global hash map to the local
+        hash map, and then clean up after we're done. This introduces
+        a memory hit, in that the symbol table will build up until
+        the context is released.
+
+        Covered by Khronos WebGL tests, including
+        conformance/glsl/misc/shader-with-non-reserved-words.html
+
+        * platform/graphics/GraphicsContext3D.h: Define a ShaderNameHash type,
+        and add an OwnPtr to one as a member variable.
+        * platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp:
+        (WebCore::nameHashForShader): Global function used for ANGLE hashing.
+        (WebCore::GraphicsContext3D::compileShader): Set up the ANGLE properties,
+        point to the local hash map, and call compile/translate.
+
+2013-09-24  Dean Jackson  <[email protected]>
+
         Use mapped name in attribute location binding
         https://bugs.webkit.org/show_bug.cgi?id=121847
         <rdar://problem/15067526>

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h (156351 => 156352)


--- trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h	2013-09-24 19:43:22 UTC (rev 156351)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h	2013-09-24 19:43:25 UTC (rev 156352)
@@ -108,6 +108,8 @@
 class GraphicsContext;
 #endif
 
+typedef WTF::HashMap<CString, uint64_t> ShaderNameHash;
+
 struct ActiveInfo {
     String name;
     GC3Denum type;
@@ -1024,6 +1026,8 @@
     String originalSymbolName(Platform3DObject program, ANGLEShaderSymbolType, const String& name);
 
     ANGLEWebKitBridge m_compiler;
+
+    OwnPtr<ShaderNameHash> nameHashMapForShaders;
 #endif
 
 #if PLATFORM(BLACKBERRY) || (PLATFORM(QT) && defined(QT_OPENGL_ES_2)) || ((PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN)) && USE(OPENGL_ES_2))

Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp (156351 => 156352)


--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp	2013-09-24 19:43:22 UTC (rev 156351)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp	2013-09-24 19:43:25 UTC (rev 156352)
@@ -67,6 +67,42 @@
 
 namespace WebCore {
 
+static ShaderNameHash* currentNameHashMapForShader;
+
+// Hash function used by the ANGLE translator/compiler to do
+// symbol name mangling. Since this is a static method, before
+// calling compileShader we set currentNameHashMapForShader
+// to point to the map kept by the current instance of GraphicsContext3D.
+
+static uint64_t nameHashForShader(const char* name, size_t length)
+{
+    if (!length)
+        return 0;
+
+    CString nameAsCString = CString(name);
+
+    // Look up name in our local map.
+    if (currentNameHashMapForShader) {
+        ShaderNameHash::iterator result = currentNameHashMapForShader->find(nameAsCString);
+        if (result != currentNameHashMapForShader->end())
+            return result->value;
+    }
+
+    unsigned hashValue = nameAsCString.hash();
+
+    // Convert the 32-bit hash from CString::hash into a 64-bit result
+    // by shifting then adding the size of our table. Overflow would
+    // only be a problem if we're already hashing to the same value (and
+    // we're hoping that over the lifetime of the context we
+    // don't have that many symbols).
+
+    uint64_t result = hashValue;
+    result = (result << 32) + (currentNameHashMapForShader->size() + 1);
+
+    currentNameHashMapForShader->set(nameAsCString, result);
+    return result;
+}
+
 PassRefPtr<GraphicsContext3D> GraphicsContext3D::createForCurrentGLContext()
 {
     RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(Attributes(), 0, GraphicsContext3D::RenderToCurrentGLContext));
@@ -443,15 +479,33 @@
     ASSERT(shader);
     makeContextCurrent();
 
+    // Turn on name mapping. Due to the way ANGLE name hashing works, we
+    // point a global hashmap to the map owned by this context.
+    ShBuiltInResources ANGLEResources = m_compiler.getResources();
+    ShHashFunction64 previousHashFunction = ANGLEResources.HashFunction;
+    ANGLEResources.HashFunction = nameHashForShader;
+
+    if (!nameHashMapForShaders)
+        nameHashMapForShaders = adoptPtr(new ShaderNameHash);
+    currentNameHashMapForShader = nameHashMapForShaders.get();
+    m_compiler.setResources(ANGLEResources);
+
     String translatedShaderSource = m_extensions->getTranslatedShaderSourceANGLE(shader);
 
+    ANGLEResources.HashFunction = previousHashFunction;
+    m_compiler.setResources(ANGLEResources);
+    currentNameHashMapForShader = nullptr;
+
     if (!translatedShaderSource.length())
         return;
 
     const CString& translatedShaderCString = translatedShaderSource.utf8();
     const char* translatedShaderPtr = translatedShaderCString.data();
     int translatedShaderLength = translatedShaderCString.length();
-    
+
+    LOG(WebGL, "--- begin original shader source ---\n%s\n--- end original shader source ---\n", getShaderSource(shader).utf8().data());
+    LOG(WebGL, "--- begin translated shader source ---\n%s\n--- end translated shader source ---", translatedShaderPtr);
+
     ::glShaderSource(shader, 1, &translatedShaderPtr, &translatedShaderLength);
     
     ::glCompileShader(shader);
@@ -460,32 +514,28 @@
     
     ::glGetShaderiv(shader, COMPILE_STATUS, &GLCompileSuccess);
 
+    ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
+    GraphicsContext3D::ShaderSourceEntry& entry = result->value;
+
     // Populate the shader log
     GLint length = 0;
     ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
 
     if (length) {
-        ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
-        GraphicsContext3D::ShaderSourceEntry& entry = result->value;
-
         GLsizei size = 0;
         auto info = std::make_unique<GLchar[]>(length);
         ::glGetShaderInfoLog(shader, length, &size, info.get());
 
         entry.log = info.get();
+    }
 
-        if (GLCompileSuccess != GL_TRUE) {
-            entry.isValid = false;
-            LOG(WebGL, "Error: shader translator produced a shader that OpenGL would not compile.");
-            LOG(WebGL, "--- begin original shader source ---\n%s\n--- end original shader source ---\n", getShaderSource(shader).utf8().data());
-            LOG(WebGL, "--- begin translated shader source ---\n%s\n--- end translated shader source ---", translatedShaderPtr);
-        }
-    }
-    
+    if (GLCompileSuccess != GL_TRUE) {
+        entry.isValid = false;
+        LOG(WebGL, "Error: shader translator produced a shader that OpenGL would not compile.");
 #if PLATFORM(BLACKBERRY) && !defined(NDEBUG)
-    if (GLCompileSuccess != GL_TRUE)
         BBLOG(BlackBerry::Platform::LogLevelWarn, "The shader validated, but didn't compile.\n");
 #endif
+    }
 }
 
 void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to