--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -167,17 +167,17 @@ webgl::UniformInfo::UniformInfo(WebGLAct
{
if (mSamplerTexList) {
mSamplerValues.assign(mActiveInfo->mElemCount, 0);
}
}
//////////
-//#define DUMP_SHADERVAR_MAPPINGS
+#define DUMP_SHADERVAR_MAPPINGS
static already_AddRefed<const webgl::LinkedProgramInfo>
QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
{
WebGLContext* const webgl = prog->mContext;
RefPtr<webgl::LinkedProgramInfo> info(new webgl::LinkedProgramInfo(prog));
@@ -204,24 +204,17 @@ QueryProgramInfo(WebGLProgram* prog, gl:
GLuint maxTransformFeedbackVaryingLenWithNull = 0;
if (gl->IsSupported(gl::GLFeature::transform_feedback2)) {
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
(GLint*)&maxTransformFeedbackVaryingLenWithNull);
if (maxTransformFeedbackVaryingLenWithNull < 1)
maxTransformFeedbackVaryingLenWithNull = 1;
}
-
-#ifdef DUMP_SHADERVAR_MAPPINGS
- printf_stderr("maxAttribLenWithNull: %d\n", maxAttribLenWithNull);
- printf_stderr("maxUniformLenWithNull: %d\n", maxUniformLenWithNull);
- printf_stderr("maxUniformBlockLenWithNull: %d\n", maxUniformBlockLenWithNull);
-#endif
-
- // Attribs
+ // Attribs (can't be arrays)
GLuint numActiveAttribs = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES,
(GLint*)&numActiveAttribs);
for (GLuint i = 0; i < numActiveAttribs; i++) {
nsAutoCString mappedName;
mappedName.SetLength(maxAttribLenWithNull - 1);
@@ -233,51 +226,45 @@ QueryProgramInfo(WebGLProgram* prog, gl:
&elemCount, &elemType, mappedName.BeginWriting());
GLenum error = gl->fGetError();
if (error != LOCAL_GL_NO_ERROR) {
gfxCriticalNote << "Failed to do glGetActiveAttrib: " << error;
}
mappedName.SetLength(lengthWithoutNull);
- // Attribs can't be arrays, so we can skip some of the mess we have in the Uniform
- // path.
- nsDependentCString userName;
- if (!prog->FindAttribUserNameByMappedName(mappedName, &userName))
- userName.Rebind(mappedName, 0);
+ ////
+
+ nsCString userName;
+ if (!prog->FindAttribUserNameByMappedName(mappedName, &userName)) {
+ userName = mappedName;
+ }
///////
const GLint loc = gl->fGetAttribLocation(prog->mGLName,
mappedName.BeginReading());
- if (loc == -1) {
- MOZ_ASSERT(mappedName == "gl_InstanceID",
- "Active attrib should have a location.");
- continue;
- }
-
#ifdef DUMP_SHADERVAR_MAPPINGS
- printf_stderr("[attrib %i: %i] %s/%s\n", i, loc, mappedName.BeginReading(),
- userName.BeginReading());
- printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
+ printf_stderr("[attrib %u/%u] @%i %s->%s\n", i, numActiveAttribs, loc,
+ userName.BeginReading(), mappedName.BeginReading());
#endif
///////
const bool isArray = false;
const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
elemType, isArray,
userName,
mappedName);
const GLenum baseType = AttribBaseType(elemType);
- const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc), baseType};
+ const webgl::AttribInfo attrib = {activeInfo, loc, baseType};
info->attribs.push_back(attrib);
}
- // Uniforms
+ // Uniforms (can be basically anything)
const bool needsCheckForArrays = gl->WorkAroundDriverBugs();
GLuint numActiveUniforms = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORMS,
(GLint*)&numActiveUniforms);
for (GLuint i = 0; i < numActiveUniforms; i++) {
@@ -321,21 +308,18 @@ QueryProgramInfo(WebGLProgram* prog, gl:
if (loc != -1)
isArray = true;
}
}
///////
#ifdef DUMP_SHADERVAR_MAPPINGS
- printf_stderr("[uniform %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(),
- (int)isArray, baseMappedName.BeginReading(),
- baseUserName.BeginReading());
- printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
- printf_stderr(" isArray: %d\n", (int)isArray);
+ printf_stderr("[uniform %u/%u] %s->%s\n", i, numActiveUniforms,
+ baseUserName.BeginReading(), mappedName.BeginReading());
#endif
///////
const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
elemType, isArray,
baseUserName,
baseMappedName);
@@ -343,78 +327,58 @@ QueryProgramInfo(WebGLProgram* prog, gl:
auto* uniform = new webgl::UniformInfo(activeInfo);
info->uniforms.push_back(uniform);
if (uniform->mSamplerTexList) {
info->uniformSamplers.push_back(uniform);
}
}
- // Uniform Blocks
- // (no sampler types allowed!)
+ // Uniform Blocks (can be arrays, but can't contain sampler types)
if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) {
GLuint numActiveUniformBlocks = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_BLOCKS,
(GLint*)&numActiveUniformBlocks);
for (GLuint i = 0; i < numActiveUniformBlocks; i++) {
nsAutoCString mappedName;
mappedName.SetLength(maxUniformBlockLenWithNull - 1);
GLint lengthWithoutNull;
gl->fGetActiveUniformBlockiv(prog->mGLName, i, LOCAL_GL_UNIFORM_BLOCK_NAME_LENGTH, &lengthWithoutNull);
gl->fGetActiveUniformBlockName(prog->mGLName, i, maxUniformBlockLenWithNull, &lengthWithoutNull, mappedName.BeginWriting());
mappedName.SetLength(lengthWithoutNull);
- nsAutoCString baseMappedName;
- bool isArray;
- size_t arrayIndex;
- if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
- MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
+ ////
- nsAutoCString baseUserName;
- if (!prog->FindUniformBlockByMappedName(baseMappedName, &baseUserName,
- &isArray))
- {
- baseUserName = baseMappedName;
+ nsCString userName;
+ if (!prog->UnmapUniformBlockName(mappedName, &userName))
+ continue;
- if (needsCheckForArrays && !isArray) {
- std::string mappedNameStr = baseMappedName.BeginReading();
- mappedNameStr += "[0]";
-
- GLuint loc = gl->fGetUniformBlockIndex(prog->mGLName,
- mappedNameStr.c_str());
- if (loc != LOCAL_GL_INVALID_INDEX)
- isArray = true;
- }
- }
+#ifdef DUMP_SHADERVAR_MAPPINGS
+ printf_stderr("[uniform block %u/%u] %s->%s\n", i, numActiveUniformBlocks,
+ userName.BeginReading(), mappedName.BeginReading());
+#endif
////
GLuint dataSize = 0;
gl->fGetActiveUniformBlockiv(prog->mGLName, i,
LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE,
(GLint*)&dataSize);
-#ifdef DUMP_SHADERVAR_MAPPINGS
- printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i,
- mappedName.BeginReading(), (int)isArray,
- baseMappedName.BeginReading(), baseUserName.BeginReading());
- printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
- printf_stderr(" isArray: %d\n", (int)isArray);
-#endif
- auto* block = new webgl::UniformBlockInfo(webgl, baseUserName, baseMappedName,
+ auto* block = new webgl::UniformBlockInfo(webgl, userName, mappedName,
dataSize);
info->uniformBlocks.push_back(block);
}
}
- // Transform feedback varyings
+ // Transform feedback varyings (can be arrays)
if (gl->IsSupported(gl::GLFeature::transform_feedback2)) {
GLuint numTransformFeedbackVaryings = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS,
(GLint*)&numTransformFeedbackVaryings);
for (GLuint i = 0; i < numTransformFeedbackVaryings; i++) {
nsAutoCString mappedName;
@@ -432,34 +396,29 @@ QueryProgramInfo(WebGLProgram* prog, gl:
////
nsAutoCString baseMappedName;
bool isArray;
size_t arrayIndex;
if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
-
nsAutoCString baseUserName;
if (!prog->FindVaryingByMappedName(mappedName, &baseUserName, &isArray)) {
baseUserName = baseMappedName;
-
- if (needsCheckForArrays && !isArray) {
- std::string mappedNameStr = baseMappedName.BeginReading();
- mappedNameStr += "[0]";
-
- GLuint loc = gl->fGetUniformBlockIndex(prog->mGLName,
- mappedNameStr.c_str());
- if (loc != LOCAL_GL_INVALID_INDEX)
- isArray = true;
- }
}
////
+#ifdef DUMP_SHADERVAR_MAPPINGS
+ printf_stderr("[transform feedback varying %u/%u] %s->%s\n", i,
+ numTransformFeedbackVaryings, baseUserName.BeginReading(),
+ mappedName.BeginReading());
+#endif
+
const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl,
elemCount,
elemType,
isArray,
baseUserName,
mappedName);
info->transformFeedbackVaryings.push_back(activeInfo);
}
@@ -783,23 +742,30 @@ WebGLProgram::GetUniformBlockIndex(const
if (!IsLinked()) {
mContext->ErrorInvalidOperation("getUniformBlockIndex: `program` must be linked.");
return LOCAL_GL_INVALID_INDEX;
}
const NS_LossyConvertUTF16toASCII userName(userName_wide);
- nsCString mappedName;
- if (!LinkInfo()->MapUniformBlockName(userName, &mappedName))
+ const webgl::UniformBlockInfo* info = nullptr;
+ for (const auto& cur : LinkInfo()->uniformBlocks) {
+ if (cur->mUserName == userName) {
+ info = cur;
+ break;
+ }
+ }
+ if (!info)
return LOCAL_GL_INVALID_INDEX;
+ const auto& mappedName = info->mMappedName;
+
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
-
return gl->fGetUniformBlockIndex(mGLName, mappedName.BeginReading());
}
void
WebGLProgram::GetActiveUniformBlockName(GLuint uniformBlockIndex, nsAString& retval) const
{
if (!IsLinked()) {
mContext->ErrorInvalidOperation("getActiveUniformBlockName: `program` must be linked.");
@@ -808,19 +774,18 @@ WebGLProgram::GetActiveUniformBlockName(
const webgl::LinkedProgramInfo* linkInfo = LinkInfo();
GLuint uniformBlockCount = (GLuint) linkInfo->uniformBlocks.size();
if (uniformBlockIndex >= uniformBlockCount) {
mContext->ErrorInvalidValue("getActiveUniformBlockName: index %u invalid.", uniformBlockIndex);
return;
}
- const webgl::UniformBlockInfo* blockInfo = linkInfo->uniformBlocks[uniformBlockIndex];
-
- retval.Assign(NS_ConvertASCIItoUTF16(blockInfo->mBaseUserName));
+ const auto& blockInfo = linkInfo->uniformBlocks[uniformBlockIndex];
+ retval.Assign(NS_ConvertASCIItoUTF16(blockInfo->mUserName));
}
JS::Value
WebGLProgram::GetActiveUniformBlockParam(GLuint uniformBlockIndex, GLenum pname) const
{
if (!IsLinked()) {
mContext->ErrorInvalidOperation("getActiveUniformBlockParameter: `program` must be linked.");
return JS::NullValue();
@@ -1215,16 +1180,19 @@ WebGLProgram::ValidateAfterTentativeLink
attribName.BeginReading());
return false;
}
}
}
std::map<uint32_t, const webgl::AttribInfo*> attribsByLoc;
for (const auto& attrib : linkInfo->attribs) {
+ if (attrib.mLoc == -1)
+ continue;
+
const auto& elemType = attrib.mActiveInfo->mElemType;
const auto numUsedLocs = NumUsedLocationsByElemType(elemType);
for (uint32_t i = 0; i < numUsedLocs; i++) {
const uint32_t usedLoc = attrib.mLoc + i;
const auto res = attribsByLoc.insert({usedLoc, &attrib});
const bool& didInsert = res.second;
if (!didInsert) {
@@ -1399,17 +1367,17 @@ WebGLProgram::LinkAndUpdate()
return;
mMostRecentLinkInfo = QueryProgramInfo(this, gl);
MOZ_RELEASE_ASSERT(mMostRecentLinkInfo, "GFX: most recent link info not set.");
}
bool
WebGLProgram::FindAttribUserNameByMappedName(const nsACString& mappedName,
- nsDependentCString* const out_userName) const
+ nsCString* const out_userName) const
{
if (mVertShader->FindAttribUserNameByMappedName(mappedName, out_userName))
return true;
return false;
}
bool
@@ -1494,27 +1462,34 @@ WebGLProgram::GetTransformFeedbackVaryin
return nullptr;
}
RefPtr<WebGLActiveInfo> ret = LinkInfo()->transformFeedbackVaryings[index];
return ret.forget();
}
bool
-WebGLProgram::FindUniformBlockByMappedName(const nsACString& mappedName,
- nsCString* const out_userName,
- bool* const out_isArray) const
+WebGLProgram::UnmapUniformBlockName(const nsCString& mappedName,
+ nsCString* const out_userName) const
{
- if (mVertShader->FindUniformBlockByMappedName(mappedName, out_userName, out_isArray))
- return true;
+ nsCString baseMappedName;
+ bool isArray;
+ size_t arrayIndex;
+ if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
+ return false;
- if (mFragShader->FindUniformBlockByMappedName(mappedName, out_userName, out_isArray))
- return true;
+ nsCString baseUserName;
+ if (!mVertShader->UnmapUniformBlockName(baseMappedName, &baseUserName) &&
+ !mFragShader->UnmapUniformBlockName(baseMappedName, &baseUserName))
+ {
+ return false;
+ }
- return false;
+ AssembleName(baseUserName, isArray, arrayIndex, out_userName);
+ return true;
}
void
WebGLProgram::EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const
{
MOZ_ASSERT(mFragShader);
mFragShader->EnumerateFragOutputs(out_FragOutputs);
@@ -1573,41 +1548,16 @@ webgl::LinkedProgramInfo::FindUniform(co
AssembleName(baseMappedName, isArray, arrayIndex, out_mappedName);
*out_arrayIndex = arrayIndex;
*out_info = info;
return true;
}
bool
-webgl::LinkedProgramInfo::MapUniformBlockName(const nsCString& userName,
- nsCString* const out_mappedName) const
-{
- nsCString baseUserName;
- bool isArray;
- size_t arrayIndex;
- if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
- return false;
-
- const webgl::UniformBlockInfo* info = nullptr;
- for (const auto& block : uniformBlocks) {
- if (block->mBaseUserName == baseUserName) {
- info = block;
- break;
- }
- }
- if (!info)
- return false;
-
- const auto& baseMappedName = info->mBaseMappedName;
- AssembleName(baseMappedName, isArray, arrayIndex, out_mappedName);
- return true;
-}
-
-bool
webgl::LinkedProgramInfo::MapFragDataName(const nsCString& userName,
nsCString* const out_mappedName) const
{
// FS outputs can be arrays, but not structures.
if (!fragDataMap.size()) {
// No mappings map from validation, so just forward it.
*out_mappedName = userName;
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -33,17 +33,17 @@ class OwningUnsignedLongOrUint32ArrayOrB
template<typename> class Sequence;
} // namespace dom
namespace webgl {
struct AttribInfo final
{
const RefPtr<WebGLActiveInfo> mActiveInfo;
- const uint32_t mLoc;
+ const GLint mLoc; // -1 for active built-ins
const GLenum mBaseType;
};
struct UniformInfo final
{
typedef decltype(WebGLContext::mBound2DTextures) TexListT;
const RefPtr<WebGLActiveInfo> mActiveInfo;
@@ -55,26 +55,26 @@ protected:
GetTexList(WebGLActiveInfo* activeInfo);
public:
explicit UniformInfo(WebGLActiveInfo* activeInfo);
};
struct UniformBlockInfo final
{
- const nsCString mBaseUserName;
- const nsCString mBaseMappedName;
+ const nsCString mUserName;
+ const nsCString mMappedName;
const uint32_t mDataSize;
const IndexedBufferBinding* mBinding;
- UniformBlockInfo(WebGLContext* webgl, const nsACString& baseUserName,
- const nsACString& baseMappedName, uint32_t dataSize)
- : mBaseUserName(baseUserName)
- , mBaseMappedName(baseMappedName)
+ UniformBlockInfo(WebGLContext* webgl, const nsACString& userName,
+ const nsACString& mappedName, uint32_t dataSize)
+ : mUserName(userName)
+ , mMappedName(mappedName)
, mDataSize(dataSize)
, mBinding(&webgl->mIndexedUniformBufferBindings[0])
{ }
};
struct LinkedProgramInfo final
: public RefCounted<LinkedProgramInfo>
, public SupportsWeakPtr<LinkedProgramInfo>
@@ -104,18 +104,16 @@ struct LinkedProgramInfo final
std::map<nsCString, const nsCString> fragDataMap;
explicit LinkedProgramInfo(WebGLProgram* prog);
~LinkedProgramInfo();
bool FindAttrib(const nsCString& userName, const AttribInfo** const out_info) const;
bool FindUniform(const nsCString& userName, nsCString* const out_mappedName,
size_t* const out_arrayIndex, UniformInfo** const out_info) const;
- bool MapUniformBlockName(const nsCString& userName,
- nsCString* const out_mappedName) const;
bool MapFragDataName(const nsCString& userName,
nsCString* const out_mappedName) const;
};
} // namespace webgl
class WebGLProgram final
: public nsWrapperCache
@@ -156,26 +154,25 @@ public:
void LinkProgram();
bool UseProgram() const;
void ValidateProgram() const;
////////////////
bool FindAttribUserNameByMappedName(const nsACString& mappedName,
- nsDependentCString* const out_userName) const;
+ nsCString* const out_userName) const;
bool FindVaryingByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
bool* const out_isArray) const;
bool FindUniformByMappedName(const nsACString& mappedName,
nsCString* const out_userName,
bool* const out_isArray) const;
- bool FindUniformBlockByMappedName(const nsACString& mappedName,
- nsCString* const out_userName,
- bool* const out_isArray) const;
+ bool UnmapUniformBlockName(const nsCString& mappedName,
+ nsCString* const out_userName) const;
void TransformFeedbackVaryings(const dom::Sequence<nsString>& varyings,
GLenum bufferMode);
already_AddRefed<WebGLActiveInfo> GetTransformFeedbackVarying(GLuint index) const;
void EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const;
bool IsLinked() const { return mMostRecentLinkInfo; }