Bug 1251487 - r?jrmuizel - Detect and error on RTT+texture use on
From 10348dab4268f8ee1bb037f004f42d35c187e924 Mon Sep 17 00:00:00 2001
draw.
---
dom/canvas/WebGLActiveInfo.cpp | 2 +
dom/canvas/WebGLActiveInfo.h | 6 ++-
dom/canvas/WebGLContext.cpp | 34 +++++++++++++
dom/canvas/WebGLContext.h | 5 ++
dom/canvas/WebGLContextDraw.cpp | 104 ++++++++++++++++++++++------------------
dom/canvas/WebGLContextGL.cpp | 16 +++++++
dom/canvas/WebGLFramebuffer.cpp | 24 +++++++++-
dom/canvas/WebGLFramebuffer.h | 1 +
dom/canvas/WebGLProgram.cpp | 14 ++++--
dom/canvas/WebGLProgram.h | 2 +
10 files changed, 156 insertions(+), 52 deletions(-)
MozReview-Commit-ID: 10FotSyWesA
--- a/dom/canvas/WebGLActiveInfo.cpp
+++ b/dom/canvas/WebGLActiveInfo.cpp
@@ -81,16 +81,18 @@ WebGLActiveInfo::WebGLActiveInfo(WebGLCo
const nsACString& baseMappedName)
: mWebGL(webgl)
, mElemCount(elemCount)
, mElemType(elemType)
, mBaseUserName(baseUserName)
, mIsArray(isArray)
, mElemSize(ElemSizeFromType(elemType))
, mBaseMappedName(baseMappedName)
+ , mTexArrayForUniformSampler(webgl->GetTexArrayForUniformSamplerType(elemType))
+ , mUniformSamplerValue{0}
{ }
////////////////////////////////////////////////////////////////////////////////
JSObject*
WebGLActiveInfo::WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto)
{
return dom::WebGLActiveInfoBinding::Wrap(js, this, givenProto);
--- a/dom/canvas/WebGLActiveInfo.h
+++ b/dom/canvas/WebGLActiveInfo.h
@@ -25,29 +25,31 @@ public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLActiveInfo)
virtual JSObject* WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto) override;
WebGLContext* GetParentObject() const {
return mWebGL;
}
-
WebGLContext* const mWebGL;
// ActiveInfo state:
const GLint mElemCount; // `size`
const GLenum mElemType; // `type`
const nsCString mBaseUserName; // `name`, but ASCII, and without any final "[0]".
// Not actually part of ActiveInfo:
const bool mIsArray;
const uint8_t mElemSize;
const nsCString mBaseMappedName; // Without any final "[0]".
+ const nsTArray<WebGLRefPtr<WebGLTexture>>* const mTexArrayForUniformSampler;
+ mutable GLint mUniformSamplerValue[4];
+
WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArray,
const nsACString& baseUserName, const nsACString& baseMappedName);
/* GLES 2.0.25, p33:
* This command will return as much information about active
* attributes as possible. If no information is available, length will
* be set to zero and name will be an empty string. This situation
* could arise if GetActiveAttrib is issued after a failed link.
@@ -77,16 +79,18 @@ private:
explicit WebGLActiveInfo(WebGLContext* webgl)
: mWebGL(webgl)
, mElemCount(0)
, mElemType(0)
, mBaseUserName("")
, mIsArray(false)
, mElemSize(0)
, mBaseMappedName("")
+ , mTexArrayForUniformSampler(nullptr)
+ , mUniformSamplerValue{0}
{ }
// Private destructor, to discourage deletion outside of Release():
~WebGLActiveInfo() { }
};
} // namespace mozilla
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -2166,16 +2166,50 @@ WebGLContext::GetUnpackSize(bool isFunc3
CheckedUint32 totalBytes = strideBytesPerImage * (usedImages - 1);
totalBytes += strideBytesPerRow * (usedRowsPerImage - 1);
totalBytes += usedBytesPerRow;
return totalBytes;
}
////////////////////////////////////////////////////////////////////////////////
+
+const nsTArray<WebGLRefPtr<WebGLTexture> >*
+WebGLContext::GetTexArrayForUniformSamplerType(GLenum elemType) const
+{
+ switch (elemType) {
+ case LOCAL_GL_SAMPLER_2D:
+ case LOCAL_GL_SAMPLER_2D_SHADOW:
+ case LOCAL_GL_INT_SAMPLER_2D:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D:
+ return &mBound2DTextures;
+
+ case LOCAL_GL_SAMPLER_CUBE:
+ case LOCAL_GL_SAMPLER_CUBE_SHADOW:
+ case LOCAL_GL_INT_SAMPLER_CUBE:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE:
+ return &mBoundCubeMapTextures;
+
+ case LOCAL_GL_SAMPLER_3D:
+ case LOCAL_GL_INT_SAMPLER_3D:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D:
+ return &mBound3DTextures;
+
+ case LOCAL_GL_SAMPLER_2D_ARRAY:
+ case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW:
+ case LOCAL_GL_INT_SAMPLER_2D_ARRAY:
+ case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ return &mBound2DArrayTextures;
+
+ default:
+ return nullptr;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
// XPCOM goop
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
mCanvasElement,
mOffscreenCanvas,
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -183,16 +183,17 @@ class WebGLContext
, public nsICanvasRenderingContextInternal
, public nsSupportsWeakReference
, public WebGLContextUnchecked
, public WebGLRectangleObject
, public nsWrapperCache
, public SupportsWeakPtr<WebGLContext>
{
friend class WebGL2Context;
+ friend class WebGLActiveInfo;
friend class WebGLContextUserData;
friend class WebGLExtensionCompressedTextureATC;
friend class WebGLExtensionCompressedTextureES3;
friend class WebGLExtensionCompressedTextureETC1;
friend class WebGLExtensionCompressedTexturePVRTC;
friend class WebGLExtensionCompressedTextureS3TC;
friend class WebGLExtensionDepthTexture;
friend class WebGLExtensionDisjointTimerQuery;
@@ -1030,16 +1031,17 @@ public:
private:
// Cache the max number of vertices and instances that can be read from
// bound VBOs (result of ValidateBuffers).
bool mBufferFetchingIsVerified;
bool mBufferFetchingHasPerVertex;
uint32_t mMaxFetchedVertices;
uint32_t mMaxFetchedInstances;
+ bool Draw_check(const char* funcName);
bool DrawArrays_check(GLint first, GLsizei count, GLsizei primcount,
const char* info);
bool DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOffset,
GLsizei primcount, const char* info,
GLuint* out_upperBound);
bool DrawInstanced_check(const char* info);
void Draw_cleanup(const char* funcName);
@@ -1372,16 +1374,19 @@ protected:
void ForceRestoreContext();
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBound3DTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DArrayTextures;
nsTArray<WebGLRefPtr<WebGLSampler> > mBoundSamplers;
+ const nsTArray<WebGLRefPtr<WebGLTexture> >*
+ GetTexArrayForUniformSamplerType(GLenum elemType) const;
+
void ResolveTexturesForDraw() const;
WebGLRefPtr<WebGLProgram> mCurrentProgram;
RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;
bool ValidateFramebufferTarget(GLenum target, const char* const info);
WebGLRefPtr<WebGLFramebuffer> mBoundDrawFramebuffer;
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -168,47 +168,87 @@ WebGLContext::DrawInstanced_check(const
ErrorInvalidOperation("%s: at least one vertex attribute divisor should be 0", info);
return false;
}
return true;
}
bool
+WebGLContext::Draw_check(const char* funcName)
+{
+ if (!ValidateStencilParamsForDrawCall())
+ return false;
+
+ // Any checks below this depend on a program being available.
+ if (!mCurrentProgram) {
+ ErrorInvalidOperation("%s: null CURRENT_PROGRAM", funcName);
+ return false;
+ }
+ MOZ_ASSERT(mActiveProgramLinkInfo);
+
+ if (!ValidateBufferFetching(funcName))
+ return false;
+
+ MakeContextCurrent();
+
+ if (mBoundDrawFramebuffer) {
+ if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
+ return false;
+ } else {
+ ClearBackbufferIfNeeded();
+ }
+
+ // Check for sampling+render-to-texture (rtt) feedback loops.
+ if (mBoundDrawFramebuffer) {
+ MOZ_ASSERT(mBoundDrawFramebuffer->mIsKnownFBComplete);
+ const auto& rttSet = mBoundDrawFramebuffer->mCached_AttachedTextures;
+
+ const auto rttSetEnd = rttSet.cend();
+
+ for (const auto& sampler : mActiveProgramLinkInfo->activeSamplerUniforms) {
+ MOZ_ASSERT(sampler->mTexArrayForUniformSampler);
+ const auto& texArrayForCurSampler = *(sampler->mTexArrayForUniformSampler);
+
+ for (const auto& texIndex : sampler->mUniformSamplerValue) {
+ const auto& tex = texArrayForCurSampler[texIndex];
+ if (rttSet.find(tex.get()) != rttSetEnd) {
+ ErrorInvalidOperation("%s: Feedback loop detected: A sampled texture"
+ " is also attached to draw framebuffer.",
+ funcName);
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool
WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount,
const char* info)
{
if (first < 0 || count < 0) {
ErrorInvalidValue("%s: negative first or count", info);
return false;
}
if (primcount < 0) {
ErrorInvalidValue("%s: negative primcount", info);
return false;
}
- if (!ValidateStencilParamsForDrawCall()) {
- return false;
- }
-
// If count is 0, there's nothing to do.
if (count == 0 || primcount == 0) {
return false;
}
- // Any checks below this depend on a program being available.
- if (!mCurrentProgram) {
- ErrorInvalidOperation("%s: null CURRENT_PROGRAM", info);
- return false;
- }
-
- if (!ValidateBufferFetching(info)) {
- return false;
- }
+ if (!Draw_check(info))
+ return false;
CheckedInt<GLsizei> checked_firstPlusCount = CheckedInt<GLsizei>(first) + count;
if (!checked_firstPlusCount.isValid()) {
ErrorInvalidOperation("%s: overflow in first+count", info);
return false;
}
@@ -217,28 +257,18 @@ WebGLContext::DrawArrays_check(GLint fir
return false;
}
if (uint32_t(primcount) > mMaxFetchedInstances) {
ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info);
return false;
}
- MOZ_ASSERT(gl->IsCurrent());
-
- if (mBoundDrawFramebuffer) {
- if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(info))
- return false;
- } else {
- ClearBackbufferIfNeeded();
- }
-
- if (!DoFakeVertexAttrib0(checked_firstPlusCount.value())) {
+ if (!DoFakeVertexAttrib0(checked_firstPlusCount.value()))
return false;
- }
return true;
}
void
WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
{
const char funcName[] = "drawArrays";
@@ -311,20 +341,16 @@ WebGLContext::DrawElements_check(GLsizei
return false;
}
if (primcount < 0) {
ErrorInvalidValue("%s: negative primcount", info);
return false;
}
- if (!ValidateStencilParamsForDrawCall()) {
- return false;
- }
-
// If count is 0, there's nothing to do.
if (count == 0 || primcount == 0)
return false;
uint8_t bytesPerElem = 0;
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
bytesPerElem = 1;
@@ -355,22 +381,16 @@ WebGLContext::DrawElements_check(GLsizei
const GLsizei first = byteOffset / bytesPerElem;
const CheckedUint32 checked_byteCount = bytesPerElem * CheckedUint32(count);
if (!checked_byteCount.isValid()) {
ErrorInvalidValue("%s: overflow in byteCount", info);
return false;
}
- // Any checks below this depend on a program being available.
- if (!mCurrentProgram) {
- ErrorInvalidOperation("%s: null CURRENT_PROGRAM", info);
- return false;
- }
-
if (!mBoundVertexArray->mElementArrayBuffer) {
ErrorInvalidOperation("%s: must have element array buffer binding", info);
return false;
}
WebGLBuffer& elemArrayBuffer = *mBoundVertexArray->mElementArrayBuffer;
if (!elemArrayBuffer.ByteLength()) {
@@ -385,19 +405,16 @@ WebGLContext::DrawElements_check(GLsizei
return false;
}
if (uint32_t(checked_neededByteCount.value()) > elemArrayBuffer.ByteLength()) {
ErrorInvalidOperation("%s: bound element array buffer is too small for given count and offset", info);
return false;
}
- if (!ValidateBufferFetching(info))
- return false;
-
if (!mMaxFetchedVertices ||
!elemArrayBuffer.Validate(type, mMaxFetchedVertices - 1, first, count, out_upperBound))
{
ErrorInvalidOperation(
"%s: bound vertex attribute buffers do not have sufficient "
"size for given indices from the bound element array", info);
return false;
}
@@ -410,28 +427,21 @@ WebGLContext::DrawElements_check(GLsizei
// Bug 1008310 - Check if buffer has been used with a different previous type
if (elemArrayBuffer.IsElementArrayUsedWithMultipleTypes()) {
GenerateWarning("%s: bound element array buffer previously used with a type other than "
"%s, this will affect performance.",
info,
WebGLContext::EnumName(type));
}
- MOZ_ASSERT(gl->IsCurrent());
+ if (!Draw_check(info))
+ return false;
- if (mBoundDrawFramebuffer) {
- if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(info))
- return false;
- } else {
- ClearBackbufferIfNeeded();
- }
-
- if (!DoFakeVertexAttrib0(mMaxFetchedVertices)) {
+ if (!DoFakeVertexAttrib0(mMaxFetchedVertices))
return false;
- }
return true;
}
void
WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
WebGLintptr byteOffset)
{
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1858,16 +1858,18 @@ WebGLContext::Uniform1i(WebGLUniformLoca
return;
// Only uniform1i can take sampler settings.
if (!loc->ValidateSamplerSetter(a1, this, "uniform1i"))
return;
MakeContextCurrent();
gl->fUniform1i(rawLoc, a1);
+
+ loc->mActiveInfo->mUniformSamplerValue[0] = a1;
}
void
WebGLContext::Uniform2i(WebGLUniformLocation* loc, GLint a1, GLint a2)
{
GLuint rawLoc;
if (!ValidateUniformSetter(loc, 2, LOCAL_GL_INT, "uniform2i", &rawLoc))
return;
@@ -1961,16 +1963,18 @@ WebGLContext::Uniform1iv_base(WebGLUnifo
return;
}
if (!loc->ValidateSamplerSetter(data[0], this, "uniform1iv"))
return;
MakeContextCurrent();
gl->fUniform1iv(rawLoc, numElementsToUpload, data);
+
+ loc->mActiveInfo->mUniformSamplerValue[0] = data[0];
}
void
WebGLContext::Uniform2iv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLint* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
@@ -1984,16 +1988,19 @@ WebGLContext::Uniform2iv_base(WebGLUnifo
if (!loc->ValidateSamplerSetter(data[0], this, "uniform2iv") ||
!loc->ValidateSamplerSetter(data[1], this, "uniform2iv"))
{
return;
}
MakeContextCurrent();
gl->fUniform2iv(rawLoc, numElementsToUpload, data);
+
+ loc->mActiveInfo->mUniformSamplerValue[0] = data[0];
+ loc->mActiveInfo->mUniformSamplerValue[1] = data[1];
}
void
WebGLContext::Uniform3iv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLint* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
@@ -2008,16 +2015,20 @@ WebGLContext::Uniform3iv_base(WebGLUnifo
!loc->ValidateSamplerSetter(data[1], this, "uniform3iv") ||
!loc->ValidateSamplerSetter(data[2], this, "uniform3iv"))
{
return;
}
MakeContextCurrent();
gl->fUniform3iv(rawLoc, numElementsToUpload, data);
+
+ loc->mActiveInfo->mUniformSamplerValue[0] = data[0];
+ loc->mActiveInfo->mUniformSamplerValue[1] = data[1];
+ loc->mActiveInfo->mUniformSamplerValue[2] = data[2];
}
void
WebGLContext::Uniform4iv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLint* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
@@ -2033,16 +2044,21 @@ WebGLContext::Uniform4iv_base(WebGLUnifo
!loc->ValidateSamplerSetter(data[2], this, "uniform4iv") ||
!loc->ValidateSamplerSetter(data[3], this, "uniform4iv"))
{
return;
}
MakeContextCurrent();
gl->fUniform4iv(rawLoc, numElementsToUpload, data);
+
+ loc->mActiveInfo->mUniformSamplerValue[0] = data[0];
+ loc->mActiveInfo->mUniformSamplerValue[1] = data[1];
+ loc->mActiveInfo->mUniformSamplerValue[2] = data[2];
+ loc->mActiveInfo->mUniformSamplerValue[3] = data[3];
}
void
WebGLContext::Uniform1fv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLfloat* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -861,17 +861,17 @@ WebGLFramebuffer::AllImageSamplesMatch()
bool needsInit = true;
uint32_t samples = 0;
const auto fnInitializeOrMatch = [&needsInit,
&samples](const WebGLFBAttachPoint& attach)
{
if (!attach.HasImage())
- return true;
+ return true;
const uint32_t curSamples = attach.Samples();
if (needsInit) {
needsInit = false;
samples = curSamples;
return true;
}
@@ -939,16 +939,38 @@ WebGLFramebuffer::CheckFramebufferStatus
// Ok, attach our chosen flavor of {DEPTH, STENCIL, DEPTH_STENCIL}.
FinalizeAttachments();
// TODO: This should not be unconditionally GL_FRAMEBUFFER.
ret = mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
if (ret == LOCAL_GL_FRAMEBUFFER_COMPLETE) {
mIsKnownFBComplete = true;
+
+ // Cache anything that only invalidates on FB completeness changes.
+ auto& attachedTextures = mCached_AttachedTextures;
+ attachedTextures.clear();
+ const auto fnAddIfTexture = [&attachedTextures](const WebGLFBAttachPoint& attach)
+ {
+ if (!attach.HasImage())
+ return;
+
+ if (!attach.Texture())
+ return;
+
+ attachedTextures.insert(attach.Texture());
+ };
+
+ fnAddIfTexture(mColorAttachment0);
+ fnAddIfTexture(mDepthAttachment);
+ fnAddIfTexture(mStencilAttachment);
+ fnAddIfTexture(mDepthStencilAttachment);
+ for (const auto& cur : mMoreColorAttachments) {
+ fnAddIfTexture(cur);
+ }
} else {
out_info->AssignLiteral("Bad status according to the driver");
}
return ret;
}
bool
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -171,16 +171,17 @@ class WebGLFramebuffer final
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLFramebuffer)
const GLuint mGLName;
private:
mutable bool mIsKnownFBComplete;
+ mutable std::set<const WebGLTexture*> mCached_AttachedTextures;
GLenum mReadBufferMode;
// No need to chase pointers for the oft-used color0.
WebGLFBAttachPoint mColorAttachment0;
WebGLFBAttachPoint mDepthAttachment;
WebGLFBAttachPoint mStencilAttachment;
WebGLFBAttachPoint mDepthStencilAttachment;
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -63,28 +63,30 @@ ParseName(const nsCString& name, nsCStri
return false;
*out_baseName = StringHead(name, indexOpenBracket);
*out_isArray = true;
*out_arrayIndex = indexNum;
return true;
}
-static void
+static WebGLActiveInfo*
AddActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArray,
const nsACString& baseUserName, const nsACString& baseMappedName,
std::vector<RefPtr<WebGLActiveInfo>>* activeInfoList,
std::map<nsCString, const WebGLActiveInfo*>* infoLocMap)
{
RefPtr<WebGLActiveInfo> info = new WebGLActiveInfo(webgl, elemCount, elemType,
isArray, baseUserName,
baseMappedName);
activeInfoList->push_back(info);
infoLocMap->insert(std::make_pair(info->mBaseUserName, info.get()));
+
+ return info.get();
}
static void
AddActiveBlockInfo(const nsACString& baseUserName,
const nsACString& baseMappedName,
std::vector<RefPtr<webgl::UniformBlockInfo>>* activeInfoList)
{
RefPtr<webgl::UniformBlockInfo> info = new webgl::UniformBlockInfo(baseUserName, baseMappedName);
@@ -229,18 +231,23 @@ QueryProgramInfo(WebGLProgram* prog, gl:
#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);
#endif
- AddActiveInfo(prog->mContext, elemCount, elemType, isArray, baseUserName,
- baseMappedName, &info->activeUniforms, &info->uniformMap);
+ auto activeInfo = AddActiveInfo(prog->mContext, elemCount, elemType, isArray,
+ baseUserName, baseMappedName,
+ &info->activeUniforms, &info->uniformMap);
+
+ if (activeInfo->mTexArrayForUniformSampler) {
+ info->activeSamplerUniforms.push_back(activeInfo);
+ }
}
// Uniform Blocks
if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) {
GLuint numActiveUniformBlocks = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_BLOCKS,
(GLint*)&numActiveUniformBlocks);
@@ -281,16 +288,17 @@ QueryProgramInfo(WebGLProgram* prog, gl:
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
AddActiveBlockInfo(baseUserName, baseMappedName, &info->uniformBlocks);
+ // Thankfully, uniform blocks cannot contain samplers.
}
}
// Transform feedback varyings
if (gl->IsSupported(gl::GLFeature::transform_feedback2)) {
GLuint numTransformFeedbackVaryings = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS,
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -57,16 +57,18 @@ struct LinkedProgramInfo final
MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo)
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo)
WebGLProgram* const prog;
std::vector<RefPtr<WebGLActiveInfo>> activeAttribs;
std::vector<RefPtr<WebGLActiveInfo>> activeUniforms;
std::vector<RefPtr<WebGLActiveInfo>> transformFeedbackVaryings;
+ std::vector<const WebGLActiveInfo*> activeSamplerUniforms;
+
// Needed for Get{Attrib,Uniform}Location. The keys for these are non-mapped
// user-facing `GLActiveInfo::name`s, without any final "[0]".
std::map<nsCString, const WebGLActiveInfo*> attribMap;
std::map<nsCString, const WebGLActiveInfo*> uniformMap;
std::map<nsCString, const WebGLActiveInfo*> transformFeedbackVaryingsMap;
std::vector<RefPtr<UniformBlockInfo>> uniformBlocks;