b=1010371, code fixes for new ANGLE version; r=jrmuizel

This commit is contained in:
Vladimir Vukicevic 2014-05-13 17:15:19 -07:00
parent f1e3bb166d
commit 997131305a
7 changed files with 640 additions and 244 deletions

View File

@ -0,0 +1,341 @@
//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
// Note - The x86 and x64 versions do _not_ produce the same results, as the
// algorithms are optimized for their respective platforms. You can still
// compile and run any of them on any platform, but your performance with the
// non-native version will be less than optimal.
#include "MurmurHash3.h"
namespace {
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if defined(_MSC_VER)
#define FORCE_INLINE __forceinline
#include <stdlib.h>
#define ROTL32(x,y) _rotl(x,y)
#define ROTL64(x,y) _rotl64(x,y)
#define BIG_CONSTANT(x) (x)
// Other compilers
#else // defined(_MSC_VER)
// We can't do always_inline, becasue -Werror -Wattribute will trigger
// a "might not be able to inline" warning.
//#define FORCE_INLINE __attribute__((always_inline))
#define FORCE_INLINE inline
inline uint32_t rotl32 ( uint32_t x, int8_t r )
{
return (x << r) | (x >> (32 - r));
}
inline uint64_t rotl64 ( uint64_t x, int8_t r )
{
return (x << r) | (x >> (64 - r));
}
#define ROTL32(x,y) rotl32(x,y)
#define ROTL64(x,y) rotl64(x,y)
#define BIG_CONSTANT(x) (x##LLU)
#endif // !defined(_MSC_VER)
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
FORCE_INLINE uint32_t getblock ( const uint32_t * p, int i )
{
return p[i];
}
FORCE_INLINE uint64_t getblock ( const uint64_t * p, int i )
{
return p[i];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
FORCE_INLINE uint32_t fmix ( uint32_t h )
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
//----------
FORCE_INLINE uint64_t fmix ( uint64_t k )
{
k ^= k >> 33;
k *= BIG_CONSTANT(0xff51afd7ed558ccd);
k ^= k >> 33;
k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
k ^= k >> 33;
return k;
}
} // unnamed namespace
//-----------------------------------------------------------------------------
void MurmurHash3_x86_32 ( const void * key, int len,
uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 4;
uint32_t h1 = seed;
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
//----------
// body
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
for(int i = -nblocks; i; i++)
{
uint32_t k1 = getblock(blocks,i);
k1 *= c1;
k1 = ROTL32(k1,15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32(h1,13);
h1 = h1*5+0xe6546b64;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
uint32_t k1 = 0;
switch(len & 3)
{
case 3: k1 ^= tail[2] << 16;
case 2: k1 ^= tail[1] << 8;
case 1: k1 ^= tail[0];
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h1 = fmix(h1);
*(uint32_t*)out = h1;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_128 ( const void * key, const int len,
uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 16;
uint32_t h1 = seed;
uint32_t h2 = seed;
uint32_t h3 = seed;
uint32_t h4 = seed;
const uint32_t c1 = 0x239b961b;
const uint32_t c2 = 0xab0e9789;
const uint32_t c3 = 0x38b34ae5;
const uint32_t c4 = 0xa1e38b93;
//----------
// body
const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
for(int i = -nblocks; i; i++)
{
uint32_t k1 = getblock(blocks,i*4+0);
uint32_t k2 = getblock(blocks,i*4+1);
uint32_t k3 = getblock(blocks,i*4+2);
uint32_t k4 = getblock(blocks,i*4+3);
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
uint32_t k1 = 0;
uint32_t k2 = 0;
uint32_t k3 = 0;
uint32_t k4 = 0;
switch(len & 15)
{
case 15: k4 ^= tail[14] << 16;
case 14: k4 ^= tail[13] << 8;
case 13: k4 ^= tail[12] << 0;
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
case 12: k3 ^= tail[11] << 24;
case 11: k3 ^= tail[10] << 16;
case 10: k3 ^= tail[ 9] << 8;
case 9: k3 ^= tail[ 8] << 0;
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
case 8: k2 ^= tail[ 7] << 24;
case 7: k2 ^= tail[ 6] << 16;
case 6: k2 ^= tail[ 5] << 8;
case 5: k2 ^= tail[ 4] << 0;
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
case 4: k1 ^= tail[ 3] << 24;
case 3: k1 ^= tail[ 2] << 16;
case 2: k1 ^= tail[ 1] << 8;
case 1: k1 ^= tail[ 0] << 0;
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
h1 += h2; h1 += h3; h1 += h4;
h2 += h1; h3 += h1; h4 += h1;
h1 = fmix(h1);
h2 = fmix(h2);
h3 = fmix(h3);
h4 = fmix(h4);
h1 += h2; h1 += h3; h1 += h4;
h2 += h1; h3 += h1; h4 += h1;
((uint32_t*)out)[0] = h1;
((uint32_t*)out)[1] = h2;
((uint32_t*)out)[2] = h3;
((uint32_t*)out)[3] = h4;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x64_128 ( const void * key, const int len,
const uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 16;
uint64_t h1 = seed;
uint64_t h2 = seed;
const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
//----------
// body
const uint64_t * blocks = (const uint64_t *)(data);
for(int i = 0; i < nblocks; i++)
{
uint64_t k1 = getblock(blocks,i*2+0);
uint64_t k2 = getblock(blocks,i*2+1);
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
uint64_t k1 = 0;
uint64_t k2 = 0;
switch(len & 15)
{
case 15: k2 ^= uint64_t(tail[14]) << 48;
case 14: k2 ^= uint64_t(tail[13]) << 40;
case 13: k2 ^= uint64_t(tail[12]) << 32;
case 12: k2 ^= uint64_t(tail[11]) << 24;
case 11: k2 ^= uint64_t(tail[10]) << 16;
case 10: k2 ^= uint64_t(tail[ 9]) << 8;
case 9: k2 ^= uint64_t(tail[ 8]) << 0;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
case 8: k1 ^= uint64_t(tail[ 7]) << 56;
case 7: k1 ^= uint64_t(tail[ 6]) << 48;
case 6: k1 ^= uint64_t(tail[ 5]) << 40;
case 5: k1 ^= uint64_t(tail[ 4]) << 32;
case 4: k1 ^= uint64_t(tail[ 3]) << 24;
case 3: k1 ^= uint64_t(tail[ 2]) << 16;
case 2: k1 ^= uint64_t(tail[ 1]) << 8;
case 1: k1 ^= uint64_t(tail[ 0]) << 0;
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len; h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix(h1);
h2 = fmix(h2);
h1 += h2;
h2 += h1;
((uint64_t*)out)[0] = h1;
((uint64_t*)out)[1] = h2;
}
//-----------------------------------------------------------------------------

View File

@ -0,0 +1,23 @@
//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
#ifndef _MURMURHASH3_H_
#define _MURMURHASH3_H_
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
#include <stdint.h>
//-----------------------------------------------------------------------------
void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out );
void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out );
void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out );
//-----------------------------------------------------------------------------
#endif // _MURMURHASH3_H_

View File

@ -19,6 +19,7 @@
#include "nsString.h"
#include "nsDebug.h"
#include "nsReadableUtils.h"
#include "gfxContext.h"
#include "gfxPlatform.h"
@ -137,9 +138,16 @@ WebGLContext::BindAttribLocation(WebGLProgram *prog, GLuint location,
if (!ValidateAttribIndex(location, "bindAttribLocation"))
return;
if (StringBeginsWith(name, NS_LITERAL_STRING("gl_")))
return ErrorInvalidOperation("bindAttribLocation: can't set the location of a name that starts with 'gl_'");
NS_LossyConvertUTF16toASCII cname(name);
nsCString mappedName;
prog->MapIdentifier(cname, &mappedName);
if (mShaderValidation) {
WebGLProgram::HashMapIdentifier(cname, &mappedName);
} else {
mappedName.Assign(cname);
}
MakeContextCurrent();
gl->fBindAttribLocation(progname, location, mappedName.get());
@ -2996,286 +3004,295 @@ WebGLContext::CompileShader(WebGLShader *shader)
shader->SetCompileStatus(false);
// nothing to do if the validator is disabled
if (!mShaderValidation)
return;
// nothing to do if translation was already done
if (!shader->NeedsTranslation())
return;
MakeContextCurrent();
ShShaderOutput targetShaderSourceLanguage = gl->IsGLES() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT;
bool useShaderSourceTranslation = true;
if (shader->NeedsTranslation() && mShaderValidation) {
ShHandle compiler = 0;
ShBuiltInResources resources;
memset(&resources, 0, sizeof(ShBuiltInResources));
ShHandle compiler = 0;
ShBuiltInResources resources;
resources.MaxVertexAttribs = mGLMaxVertexAttribs;
resources.MaxVertexUniformVectors = mGLMaxVertexUniformVectors;
resources.MaxVaryingVectors = mGLMaxVaryingVectors;
resources.MaxVertexTextureImageUnits = mGLMaxVertexTextureImageUnits;
resources.MaxCombinedTextureImageUnits = mGLMaxTextureUnits;
resources.MaxTextureImageUnits = mGLMaxTextureImageUnits;
resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
resources.MaxDrawBuffers = mGLMaxDrawBuffers;
memset(&resources, 0, sizeof(ShBuiltInResources));
if (IsExtensionEnabled(WebGLExtensionID::EXT_frag_depth))
resources.EXT_frag_depth = 1;
ShInitBuiltInResources(&resources);
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
resources.OES_standard_derivatives = 1;
resources.MaxVertexAttribs = mGLMaxVertexAttribs;
resources.MaxVertexUniformVectors = mGLMaxVertexUniformVectors;
resources.MaxVaryingVectors = mGLMaxVaryingVectors;
resources.MaxVertexTextureImageUnits = mGLMaxVertexTextureImageUnits;
resources.MaxCombinedTextureImageUnits = mGLMaxTextureUnits;
resources.MaxTextureImageUnits = mGLMaxTextureImageUnits;
resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
resources.MaxDrawBuffers = mGLMaxDrawBuffers;
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
resources.EXT_draw_buffers = 1;
if (IsExtensionEnabled(WebGLExtensionID::EXT_frag_depth))
resources.EXT_frag_depth = 1;
// Tell ANGLE to allow highp in frag shaders. (unless disabled)
// If underlying GLES doesn't have highp in frag shaders, it should complain anyways.
resources.FragmentPrecisionHigh = mDisableFragHighP ? 0 : 1;
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
resources.OES_standard_derivatives = 1;
if (gl->WorkAroundDriverBugs()) {
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
resources.EXT_draw_buffers = 1;
// Tell ANGLE to allow highp in frag shaders. (unless disabled)
// If underlying GLES doesn't have highp in frag shaders, it should complain anyways.
resources.FragmentPrecisionHigh = mDisableFragHighP ? 0 : 1;
resources.HashFunction = WebGLProgram::IdentifierHashFunction;
if (gl->WorkAroundDriverBugs()) {
#ifdef XP_MACOSX
if (gl->Vendor() == gl::GLVendor::NVIDIA) {
// Work around bug 890432
resources.MaxExpressionComplexity = 1000;
}
if (gl->Vendor() == gl::GLVendor::NVIDIA) {
// Work around bug 890432
resources.MaxExpressionComplexity = 1000;
}
#endif
}
}
// We're storing an actual instance of StripComments because, if we don't, the
// cleanSource nsAString instance will be destroyed before the reference is
// actually used.
StripComments stripComments(shader->Source());
const nsAString& cleanSource = Substring(stripComments.result().Elements(), stripComments.length());
if (!ValidateGLSLString(cleanSource, "compileShader"))
return;
// We're storing an actual instance of StripComments because, if we don't, the
// cleanSource nsAString instance will be destroyed before the reference is
// actually used.
StripComments stripComments(shader->Source());
const nsAString& cleanSource = Substring(stripComments.result().Elements(), stripComments.length());
if (!ValidateGLSLString(cleanSource, "compileShader"))
return;
// shaderSource() already checks that the source stripped of comments is in the
// 7-bit ASCII range, so we can skip the NS_IsAscii() check.
NS_LossyConvertUTF16toASCII sourceCString(cleanSource);
// shaderSource() already checks that the source stripped of comments is in the
// 7-bit ASCII range, so we can skip the NS_IsAscii() check.
NS_LossyConvertUTF16toASCII sourceCString(cleanSource);
if (gl->WorkAroundDriverBugs()) {
const uint32_t maxSourceLength = 0x3ffff;
if (sourceCString.Length() > maxSourceLength)
return ErrorInvalidValue("compileShader: source has more than %d characters",
maxSourceLength);
}
if (gl->WorkAroundDriverBugs()) {
const uint32_t maxSourceLength = 0x3ffff;
if (sourceCString.Length() > maxSourceLength)
return ErrorInvalidValue("compileShader: source has more than %d characters",
maxSourceLength);
}
const char *s = sourceCString.get();
const char *s = sourceCString.get();
#define WEBGL2_BYPASS_ANGLE
#ifdef WEBGL2_BYPASS_ANGLE
/*
* The bypass don't bring a full support for GLSL ES 3.0, but the main purpose
* is to natively bring gl_InstanceID (to do instanced rendering) and gl_FragData
*
* To remove the bypass code, just comment #define WEBGL2_BYPASS_ANGLE above
*
* To bypass angle, the context must be a WebGL 2 and the shader must have the
* following line at the very top :
* #version proto-200
*
* In this case, byPassANGLE == true and here is what we do :
* We create two shader source code:
* - one for the driver, that enable GL_EXT_gpu_shader4
* - one for the angle compilor, to get informations about vertex attributes
* and uniforms
*/
static const char *bypassPrefixSearch = "#version proto-200";
static const char *bypassANGLEPrefix[2] = {"precision mediump float;\n"
"#define gl_VertexID 0\n"
"#define gl_InstanceID 0\n",
/*
* The bypass don't bring a full support for GLSL ES 3.0, but the main purpose
* is to natively bring gl_InstanceID (to do instanced rendering) and gl_FragData
*
* To remove the bypass code, just comment #define WEBGL2_BYPASS_ANGLE above
*
* To bypass angle, the context must be a WebGL 2 and the shader must have the
* following line at the very top :
* #version proto-200
*
* In this case, byPassANGLE == true and here is what we do :
* We create two shader source code:
* - one for the driver, that enable GL_EXT_gpu_shader4
* - one for the angle compilor, to get informations about vertex attributes
* and uniforms
*/
static const char *bypassPrefixSearch = "#version proto-200";
static const char *bypassANGLEPrefix[2] = {"precision mediump float;\n"
"#define gl_VertexID 0\n"
"#define gl_InstanceID 0\n",
"precision mediump float;\n"
"#extension GL_EXT_draw_buffers : enable\n"
"#define gl_PrimitiveID 0\n"};
"precision mediump float;\n"
"#extension GL_EXT_draw_buffers : enable\n"
"#define gl_PrimitiveID 0\n"};
const bool bypassANGLE = IsWebGL2() && (strstr(s, bypassPrefixSearch) != 0);
const bool bypassANGLE = IsWebGL2() && (strstr(s, bypassPrefixSearch) != 0);
const char *angleShaderCode = s;
nsTArray<char> bypassANGLEShaderCode;
nsTArray<char> bypassDriverShaderCode;
const char *angleShaderCode = s;
nsTArray<char> bypassANGLEShaderCode;
nsTArray<char> bypassDriverShaderCode;
if (bypassANGLE) {
const int bypassStage = (shader->ShaderType() == LOCAL_GL_FRAGMENT_SHADER) ? 1 : 0;
const char *originalShader = strstr(s, bypassPrefixSearch) + strlen(bypassPrefixSearch);
int originalShaderSize = strlen(s) - (originalShader - s);
int bypassShaderCodeSize = originalShaderSize + 4096 + 1;
if (bypassANGLE) {
const int bypassStage = (shader->ShaderType() == LOCAL_GL_FRAGMENT_SHADER) ? 1 : 0;
const char *originalShader = strstr(s, bypassPrefixSearch) + strlen(bypassPrefixSearch);
int originalShaderSize = strlen(s) - (originalShader - s);
int bypassShaderCodeSize = originalShaderSize + 4096 + 1;
bypassANGLEShaderCode.SetLength(bypassShaderCodeSize);
strcpy(bypassANGLEShaderCode.Elements(), bypassANGLEPrefix[bypassStage]);
strcat(bypassANGLEShaderCode.Elements(), originalShader);
bypassANGLEShaderCode.SetLength(bypassShaderCodeSize);
strcpy(bypassANGLEShaderCode.Elements(), bypassANGLEPrefix[bypassStage]);
strcat(bypassANGLEShaderCode.Elements(), originalShader);
bypassDriverShaderCode.SetLength(bypassShaderCodeSize);
strcpy(bypassDriverShaderCode.Elements(), "#extension GL_EXT_gpu_shader4 : enable\n");
strcat(bypassDriverShaderCode.Elements(), originalShader);
bypassDriverShaderCode.SetLength(bypassShaderCodeSize);
strcpy(bypassDriverShaderCode.Elements(), "#extension GL_EXT_gpu_shader4 : enable\n");
strcat(bypassDriverShaderCode.Elements(), originalShader);
angleShaderCode = bypassANGLEShaderCode.Elements();
}
angleShaderCode = bypassANGLEShaderCode.Elements();
}
#endif
compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
SH_WEBGL_SPEC,
targetShaderSourceLanguage,
&resources);
compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
SH_WEBGL_SPEC,
targetShaderSourceLanguage,
&resources);
int compileOptions = SH_ATTRIBUTES_UNIFORMS |
SH_ENFORCE_PACKING_RESTRICTIONS;
int compileOptions = SH_VARIABLES |
SH_ENFORCE_PACKING_RESTRICTIONS |
SH_INIT_VARYINGS_WITHOUT_STATIC_USE |
SH_OBJECT_CODE;
if (resources.MaxExpressionComplexity > 0) {
compileOptions |= SH_LIMIT_EXPRESSION_COMPLEXITY;
}
if (resources.MaxExpressionComplexity > 0) {
compileOptions |= SH_LIMIT_EXPRESSION_COMPLEXITY;
}
// We want to do this everywhere, but:
#ifndef XP_MACOSX // To do this on Mac, we need to do it only on Mac OSX > 10.6 as this
// causes the shader compiler in 10.6 to crash
compileOptions |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
#ifndef XP_MACOSX
// We want to do this everywhere, but to do this on Mac, we need
// to do it only on Mac OSX > 10.6 as this causes the shader
// compiler in 10.6 to crash
compileOptions |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
#endif
if (useShaderSourceTranslation) {
compileOptions |= SH_OBJECT_CODE
| SH_MAP_LONG_VARIABLE_NAMES;
#ifdef XP_MACOSX
if (gl->WorkAroundDriverBugs()) {
// Work around bug 665578 and bug 769810
if (gl->Vendor() == gl::GLVendor::ATI) {
compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
}
// Work around bug 735560
if (gl->Vendor() == gl::GLVendor::Intel) {
compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
}
}
#endif
if (gl->WorkAroundDriverBugs()) {
// Work around bug 665578 and bug 769810
if (gl->Vendor() == gl::GLVendor::ATI) {
compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
}
// Work around bug 735560
if (gl->Vendor() == gl::GLVendor::Intel) {
compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
}
// Work around bug 636926
if (gl->Vendor() == gl::GLVendor::NVIDIA) {
compileOptions |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
}
// Work around https://bugs.webkit.org/show_bug.cgi?id=124684,
// https://chromium.googlesource.com/angle/angle/+/5e70cf9d0b1bb
compileOptions |= SH_UNFOLD_SHORT_CIRCUIT;
}
#endif
#ifdef WEBGL2_BYPASS_ANGLE
if (!ShCompile(compiler, &angleShaderCode, 1, compileOptions)) {
if (!ShCompile(compiler, &angleShaderCode, 1, compileOptions)) {
#else
if (!ShCompile(compiler, &s, 1, compileOptions)) {
if (!ShCompile(compiler, &s, 1, compileOptions)) {
#endif
size_t lenWithNull = 0;
ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &lenWithNull);
size_t lenWithNull = 0;
ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &lenWithNull);
if (!lenWithNull) {
// Error in ShGetInfo.
shader->SetTranslationFailure(NS_LITERAL_CSTRING("Internal error: failed to get shader info log"));
} else {
size_t len = lenWithNull - 1;
nsAutoCString info;
info.SetLength(len); // Allocates len+1, for the null-term.
ShGetInfoLog(compiler, info.BeginWriting());
shader->SetTranslationFailure(info);
}
ShDestruct(compiler);
shader->SetCompileStatus(false);
return;
}
size_t num_attributes = 0;
ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTES, &num_attributes);
size_t num_uniforms = 0;
ShGetInfo(compiler, SH_ACTIVE_UNIFORMS, &num_uniforms);
size_t attrib_max_length = 0;
ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attrib_max_length);
size_t uniform_max_length = 0;
ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_max_length);
size_t mapped_max_length = 0;
ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mapped_max_length);
shader->mAttribMaxNameLength = attrib_max_length;
shader->mAttributes.Clear();
shader->mUniforms.Clear();
shader->mUniformInfos.Clear();
nsAutoArrayPtr<char> attribute_name(new char[attrib_max_length+1]);
nsAutoArrayPtr<char> uniform_name(new char[uniform_max_length+1]);
nsAutoArrayPtr<char> mapped_name(new char[mapped_max_length+1]);
for (size_t i = 0; i < num_uniforms; i++) {
size_t length;
int size;
ShDataType type;
ShGetActiveUniform(compiler, (int)i,
&length, &size, &type,
uniform_name,
mapped_name);
if (useShaderSourceTranslation) {
shader->mUniforms.AppendElement(WebGLMappedIdentifier(
nsDependentCString(uniform_name),
nsDependentCString(mapped_name)));
}
// we always query uniform info, regardless of useShaderSourceTranslation,
// as we need it to validate uniform setter calls, and it doesn't rely on
// shader translation.
char mappedNameLength = strlen(mapped_name);
char mappedNameLastChar = mappedNameLength > 1
? mapped_name[mappedNameLength - 1]
: 0;
shader->mUniformInfos.AppendElement(WebGLUniformInfo(
size,
mappedNameLastChar == ']',
type));
}
if (useShaderSourceTranslation) {
for (size_t i = 0; i < num_attributes; i++) {
size_t length;
int size;
ShDataType type;
ShGetActiveAttrib(compiler, (int)i,
&length, &size, &type,
attribute_name,
mapped_name);
shader->mAttributes.AppendElement(WebGLMappedIdentifier(
nsDependentCString(attribute_name),
nsDependentCString(mapped_name)));
}
size_t lenWithNull = 0;
ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &lenWithNull);
MOZ_ASSERT(lenWithNull >= 1);
if (!lenWithNull) {
// Error in ShGetInfo.
shader->SetTranslationFailure(NS_LITERAL_CSTRING("Internal error: failed to get shader info log"));
} else {
size_t len = lenWithNull - 1;
nsAutoCString translatedSrc;
translatedSrc.SetLength(len); // Allocates len+1, for the null-term.
ShGetObjectCode(compiler, translatedSrc.BeginWriting());
nsAutoCString info;
info.SetLength(len); // Allocates len+1, for the null-term.
ShGetInfoLog(compiler, info.BeginWriting());
CopyASCIItoUTF16(translatedSrc, shader->mTranslatedSource);
shader->SetTranslationFailure(info);
}
ShDestruct(compiler);
shader->SetCompileStatus(false);
return;
}
const char *ts = translatedSrc.get();
size_t num_attributes = 0;
ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTES, &num_attributes);
size_t num_uniforms = 0;
ShGetInfo(compiler, SH_ACTIVE_UNIFORMS, &num_uniforms);
size_t attrib_max_length = 0;
ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attrib_max_length);
size_t uniform_max_length = 0;
ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_max_length);
size_t mapped_max_length = 0;
ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mapped_max_length);
shader->mAttribMaxNameLength = attrib_max_length;
shader->mAttributes.Clear();
shader->mUniforms.Clear();
shader->mUniformInfos.Clear();
nsAutoArrayPtr<char> attribute_name(new char[attrib_max_length+1]);
nsAutoArrayPtr<char> uniform_name(new char[uniform_max_length+1]);
nsAutoArrayPtr<char> mapped_name(new char[mapped_max_length+1]);
for (size_t i = 0; i < num_uniforms; i++) {
size_t length;
int size;
ShDataType type;
ShPrecisionType precision;
int staticUse;
ShGetVariableInfo(compiler, SH_ACTIVE_UNIFORMS, (int)i,
&length, &size, &type,
&precision, &staticUse,
uniform_name,
mapped_name);
shader->mUniforms.AppendElement(WebGLMappedIdentifier(
nsDependentCString(uniform_name),
nsDependentCString(mapped_name)));
// we need uniform info to validate uniform setter calls
char mappedNameLength = strlen(mapped_name);
char mappedNameLastChar = mappedNameLength > 1
? mapped_name[mappedNameLength - 1]
: 0;
shader->mUniformInfos.AppendElement(WebGLUniformInfo(
size,
mappedNameLastChar == ']',
type));
}
for (size_t i = 0; i < num_attributes; i++) {
size_t length;
int size;
ShDataType type;
ShPrecisionType precision;
int staticUse;
ShGetVariableInfo(compiler, SH_ACTIVE_ATTRIBUTES, (int)i,
&length, &size, &type,
&precision, &staticUse,
attribute_name,
mapped_name);
shader->mAttributes.AppendElement(WebGLMappedIdentifier(
nsDependentCString(attribute_name),
nsDependentCString(mapped_name)));
}
size_t lenWithNull = 0;
ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &lenWithNull);
MOZ_ASSERT(lenWithNull >= 1);
size_t len = lenWithNull - 1;
nsAutoCString translatedSrc;
translatedSrc.SetLength(len); // Allocates len+1, for the null-term.
ShGetObjectCode(compiler, translatedSrc.BeginWriting());
CopyASCIItoUTF16(translatedSrc, shader->mTranslatedSource);
const char *ts = translatedSrc.get();
#ifdef WEBGL2_BYPASS_ANGLE
if (bypassANGLE) {
const char* driverShaderCode = bypassDriverShaderCode.Elements();
gl->fShaderSource(shadername, 1, (const GLchar**) &driverShaderCode, nullptr);
}
else {
gl->fShaderSource(shadername, 1, &ts, nullptr);
}
#else
gl->fShaderSource(shadername, 1, &ts, nullptr);
#endif
} else { // not useShaderSourceTranslation
// we just pass the raw untranslated shader source. We then can't use ANGLE idenfier mapping.
// that's really bad, as that means we can't be 100% conformant. We should work towards always
// using ANGLE identifier mapping.
gl->fShaderSource(shadername, 1, &s, nullptr);
CopyASCIItoUTF16(s, shader->mTranslatedSource);
}
shader->SetTranslationSuccess();
ShDestruct(compiler);
gl->fCompileShader(shadername);
GLint ok;
gl->fGetShaderiv(shadername, LOCAL_GL_COMPILE_STATUS, &ok);
shader->SetCompileStatus(ok);
if (bypassANGLE) {
const char* driverShaderCode = bypassDriverShaderCode.Elements();
gl->fShaderSource(shadername, 1, (const GLchar**) &driverShaderCode, nullptr);
} else {
gl->fShaderSource(shadername, 1, &ts, nullptr);
}
#else
gl->fShaderSource(shadername, 1, &ts, nullptr);
#endif
shader->SetTranslationSuccess();
ShDestruct(compiler);
gl->fCompileShader(shadername);
GLint ok;
gl->fGetShaderiv(shadername, LOCAL_GL_COMPILE_STATUS, &ok);
shader->SetCompileStatus(ok);
}
void

View File

@ -9,6 +9,8 @@
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "GLContext.h"
#include "MurmurHash3.h"
using namespace mozilla;
/** Takes an ASCII string like "foo[i]", turns it into "foo" and returns "[i]" in bracketPart
@ -237,6 +239,25 @@ WebGLProgram::GetUniformInfoForMappedIdentifier(const nsACString& name) {
return info;
}
/* static */ uint64_t
WebGLProgram::IdentifierHashFunction(const char *ident, size_t size)
{
uint64_t outhash[2];
// NB: we use the x86 function everywhere, even though it's suboptimal perf
// on x64. They return different results; not sure if that's a requirement.
MurmurHash3_x86_128(ident, size, 0, &outhash[0]);
return outhash[0];
}
/* static */ void
WebGLProgram::HashMapIdentifier(const nsACString& name, nsCString *hashedName)
{
uint64_t hash = IdentifierHashFunction(name.BeginReading(), name.Length());
hashedName->Truncate();
// This MUST MATCH angle/src/compiler/translator/HashNames.h HASHED_NAME_PREFIX
hashedName->AppendPrintf("webgl_%llx", hash);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLProgram, mAttachedShaders)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLProgram, AddRef)

View File

@ -110,6 +110,9 @@ public:
// public post-link data
std::map<GLint, nsCString> mActiveAttribMap;
static uint64_t IdentifierHashFunction(const char *ident, size_t size);
static void HashMapIdentifier(const nsACString& name, nsCString *hashedName);
protected:
~WebGLProgram() {
DeleteOnce();

View File

@ -25,6 +25,7 @@ UNIFIED_SOURCES += [
if CONFIG['MOZ_WEBGL']:
UNIFIED_SOURCES += [
'MurmurHash3.cpp',
'WebGL1Context.cpp',
'WebGL2Context.cpp',
'WebGLActiveInfo.cpp',

View File

@ -178,16 +178,6 @@ opus_encoder_ctl
opus_encode
opus_encode_float
#endif
ShInitialize
ShFinalize
ShGetObjectCode
ShDestruct
ShGetInfoLog
ShCompile
ShGetInfo
ShConstructCompiler
ShGetActiveAttrib
ShGetActiveUniform
#ifndef MOZ_NATIVE_PNG
MOZ_APNG_get_first_frame_is_hidden
MOZ_APNG_get_next_frame_blend_op