зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1319426 - Don't keep ANGLE shader compilers around. r=lsalzman
This will also make it easier if we want to reuse compilers/validators. Differential Revision: https://phabricator.services.mozilla.com/D35398 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
ccda45f8e3
Коммит
07c032ccbd
|
@ -6,6 +6,7 @@
|
|||
#ifndef WEBGLCONTEXT_H_
|
||||
#define WEBGLCONTEXT_H_
|
||||
|
||||
#include <memory>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "GLContextTypes.h"
|
||||
|
@ -1507,7 +1508,8 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
|
|||
|
||||
mutable GLenum mWebGLError;
|
||||
|
||||
webgl::ShaderValidator* CreateShaderValidator(GLenum shaderType) const;
|
||||
std::unique_ptr<webgl::ShaderValidator> CreateShaderValidator(
|
||||
GLenum shaderType) const;
|
||||
|
||||
// some GL constants
|
||||
uint32_t mGLMaxTextureUnits = 0;
|
||||
|
|
|
@ -474,51 +474,46 @@ static RefPtr<const webgl::LinkedProgramInfo> QueryProgramInfo(
|
|||
|
||||
{
|
||||
const auto& fragShader = prog->FragShader();
|
||||
MOZ_RELEASE_ASSERT(fragShader);
|
||||
MOZ_RELEASE_ASSERT(fragShader->Validator());
|
||||
const auto& handle = fragShader->Validator()->mHandle;
|
||||
const auto version = sh::GetShaderVersion(handle);
|
||||
const auto& compileResults = fragShader->CompileResults();
|
||||
const auto version = compileResults->mShaderVersion;
|
||||
|
||||
const auto fnAddInfo = [&](const webgl::FragOutputInfo& x) {
|
||||
info->fragOutputs.insert({x.loc, x});
|
||||
};
|
||||
|
||||
if (version == 300) {
|
||||
const auto& fragOutputs = sh::GetOutputVariables(handle);
|
||||
if (fragOutputs) {
|
||||
for (const auto& cur : *fragOutputs) {
|
||||
auto loc = cur.location;
|
||||
if (loc == -1) loc = 0;
|
||||
for (const auto& cur : compileResults->mOutputVariables) {
|
||||
auto loc = cur.location;
|
||||
if (loc == -1) loc = 0;
|
||||
|
||||
const auto info = webgl::FragOutputInfo{
|
||||
uint8_t(loc), nsCString(cur.name.c_str()),
|
||||
nsCString(cur.mappedName.c_str()), FragOutputBaseType(cur.type)};
|
||||
if (!cur.isArray()) {
|
||||
fnAddInfo(info);
|
||||
continue;
|
||||
}
|
||||
MOZ_ASSERT(cur.arraySizes.size() == 1);
|
||||
for (uint32_t i = 0; i < cur.arraySizes[0]; ++i) {
|
||||
const auto indexStr = nsPrintfCString("[%u]", i);
|
||||
const auto info = webgl::FragOutputInfo{
|
||||
uint8_t(loc), nsCString(cur.name.c_str()),
|
||||
nsCString(cur.mappedName.c_str()), FragOutputBaseType(cur.type)};
|
||||
if (!cur.isArray()) {
|
||||
fnAddInfo(info);
|
||||
continue;
|
||||
}
|
||||
MOZ_ASSERT(cur.arraySizes.size() == 1);
|
||||
for (uint32_t i = 0; i < cur.arraySizes[0]; ++i) {
|
||||
const auto indexStr = nsPrintfCString("[%u]", i);
|
||||
|
||||
auto userName = info.userName;
|
||||
userName.Append(indexStr);
|
||||
auto mappedName = info.mappedName;
|
||||
mappedName.Append(indexStr);
|
||||
auto userName = info.userName;
|
||||
userName.Append(indexStr);
|
||||
auto mappedName = info.mappedName;
|
||||
mappedName.Append(indexStr);
|
||||
|
||||
const auto indexedInfo = webgl::FragOutputInfo{
|
||||
uint8_t(info.loc + i), userName, mappedName, info.baseType};
|
||||
fnAddInfo(indexedInfo);
|
||||
}
|
||||
const auto indexedInfo = webgl::FragOutputInfo{
|
||||
uint8_t(info.loc + i), userName, mappedName, info.baseType};
|
||||
fnAddInfo(indexedInfo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// ANGLE's translator doesn't tell us about non-user frag outputs. :(
|
||||
|
||||
const auto& translatedSource = fragShader->TranslatedSource();
|
||||
const auto& translatedSource = compileResults->mObjectCode;
|
||||
uint32_t drawBuffers = 1;
|
||||
if (translatedSource.Find("(gl_FragData[1]") != -1 ||
|
||||
translatedSource.Find("(webgl_FragData[1]") != -1) {
|
||||
if (translatedSource.find("(gl_FragData[1]") != std::string::npos ||
|
||||
translatedSource.find("(webgl_FragData[1]") != std::string::npos) {
|
||||
// The matching with the leading '(' prevents cleverly-named user vars
|
||||
// breaking this. Since ANGLE initializes all outputs, if this is an MRT
|
||||
// shader, FragData[1] will be present. FragData[0] is valid for non-MRT
|
||||
|
@ -536,10 +531,8 @@ static RefPtr<const webgl::LinkedProgramInfo> QueryProgramInfo(
|
|||
}
|
||||
|
||||
const auto& vertShader = prog->VertShader();
|
||||
MOZ_RELEASE_ASSERT(vertShader);
|
||||
MOZ_RELEASE_ASSERT(vertShader->Validator());
|
||||
const auto& handle = vertShader->Validator()->mHandle;
|
||||
const auto numViews = sh::GetVertexShaderNumViews(handle);
|
||||
const auto& vertCompileResults = vertShader->CompileResults();
|
||||
const auto numViews = vertCompileResults->mVertexShaderNumViews;
|
||||
if (numViews != -1) {
|
||||
info->zLayerCount = AssertedCast<uint8_t>(numViews);
|
||||
}
|
||||
|
@ -1153,13 +1146,15 @@ bool WebGLProgram::ValidateForLink() {
|
|||
mLinkLog.AssignLiteral("Must have a compiled vertex shader attached.");
|
||||
return false;
|
||||
}
|
||||
const auto& vertInfo = *mVertShader->CompileResults();
|
||||
|
||||
if (!mFragShader || !mFragShader->IsCompiled()) {
|
||||
mLinkLog.AssignLiteral("Must have an compiled fragment shader attached.");
|
||||
return false;
|
||||
}
|
||||
const auto& fragInfo = *mFragShader->CompileResults();
|
||||
|
||||
if (!mFragShader->CanLinkTo(mVertShader, &mLinkLog)) return false;
|
||||
if (!fragInfo.CanLinkTo(vertInfo, &mLinkLog)) return false;
|
||||
|
||||
const auto& gl = mContext->gl;
|
||||
|
||||
|
|
|
@ -38,25 +38,6 @@ static void PrintLongString(const char* const begin, const size_t len) {
|
|||
printf_stderr("%s", chunkBegin);
|
||||
}
|
||||
|
||||
// On success, writes to out_validator and out_translatedSource.
|
||||
// On failure, writes to out_translationLog.
|
||||
static bool Translate(const nsACString& source,
|
||||
webgl::ShaderValidator* validator,
|
||||
nsACString* const out_translationLog,
|
||||
nsACString* const out_translatedSource) {
|
||||
if (!validator->ValidateAndTranslate(source.BeginReading())) {
|
||||
const std::string& log = sh::GetInfoLog(validator->mHandle);
|
||||
out_translationLog->Assign(log.data(), log.length());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
const std::string& output = sh::GetObjectCode(validator->mHandle);
|
||||
out_translatedSource->Assign(output.data(), output.length());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
static bool SubstringStartsWith(const std::string& testStr, size_t offset,
|
||||
const char (&refStr)[N]) {
|
||||
|
@ -93,9 +74,8 @@ static void GetCompilationStatusAndLog(gl::GLContext* gl, GLuint shader,
|
|||
WebGLShader::WebGLShader(WebGLContext* webgl, GLenum type)
|
||||
: WebGLRefCountedObject(webgl),
|
||||
mGLName(webgl->gl->fCreateShader(type)),
|
||||
mType(type),
|
||||
mTranslationSuccessful(false),
|
||||
mCompilationSuccessful(false) {
|
||||
mType(type) {
|
||||
mCompileResults = std::make_unique<webgl::ShaderValidatorResults>();
|
||||
mContext->mShaders.insertBack(this);
|
||||
}
|
||||
|
||||
|
@ -119,41 +99,44 @@ void WebGLShader::ShaderSource(const nsAString& source) {
|
|||
}
|
||||
|
||||
void WebGLShader::CompileShader() {
|
||||
mValidator = nullptr;
|
||||
mTranslationSuccessful = false;
|
||||
mCompilationSuccessful = false;
|
||||
|
||||
gl::GLContext* gl = mContext->gl;
|
||||
|
||||
mValidator.reset(mContext->CreateShaderValidator(mType));
|
||||
MOZ_ASSERT(mValidator);
|
||||
|
||||
static const bool kDumpShaders = PR_GetEnv("MOZ_WEBGL_DUMP_SHADERS");
|
||||
if (MOZ_UNLIKELY(kDumpShaders)) {
|
||||
printf_stderr("==== begin MOZ_WEBGL_DUMP_SHADERS ====\n");
|
||||
PrintLongString(mCleanSource.BeginReading(), mCleanSource.Length());
|
||||
}
|
||||
|
||||
const bool success = Translate(mCleanSource, mValidator.get(),
|
||||
&mValidationLog, &mTranslatedSource);
|
||||
{
|
||||
const auto validator = mContext->CreateShaderValidator(mType);
|
||||
MOZ_ASSERT(validator);
|
||||
|
||||
mCompileResults =
|
||||
validator->ValidateAndTranslate(mCleanSource.BeginReading());
|
||||
}
|
||||
|
||||
mCompilationLog = mCompileResults->mInfoLog.c_str();
|
||||
const auto& success = mCompileResults->mValid;
|
||||
|
||||
if (MOZ_UNLIKELY(kDumpShaders)) {
|
||||
printf_stderr("\n==== \\/ \\/ \\/ ====\n");
|
||||
if (success) {
|
||||
PrintLongString(mTranslatedSource.BeginReading(),
|
||||
mTranslatedSource.Length());
|
||||
const auto& translated = mCompileResults->mObjectCode;
|
||||
PrintLongString(translated.data(), translated.length());
|
||||
} else {
|
||||
printf_stderr("Validation failed:\n%s", mValidationLog.BeginReading());
|
||||
printf_stderr("Validation failed:\n%s",
|
||||
mCompileResults->mInfoLog.c_str());
|
||||
}
|
||||
printf_stderr("\n==== end ====\n");
|
||||
}
|
||||
|
||||
if (!success) return;
|
||||
|
||||
mTranslationSuccessful = true;
|
||||
|
||||
const char* const parts[] = {mTranslatedSource.BeginReading()};
|
||||
gl->fShaderSource(mGLName, ArrayLength(parts), parts, nullptr);
|
||||
const std::array<const char*, 1> parts = {
|
||||
mCompileResults->mObjectCode.c_str()};
|
||||
gl->fShaderSource(mGLName, parts.size(), parts.data(), nullptr);
|
||||
|
||||
gl->fCompileShader(mGLName);
|
||||
|
||||
|
@ -161,10 +144,8 @@ void WebGLShader::CompileShader() {
|
|||
&mCompilationLog);
|
||||
}
|
||||
|
||||
void WebGLShader::GetShaderInfoLog(nsAString* out) const {
|
||||
const nsCString& log =
|
||||
!mTranslationSuccessful ? mValidationLog : mCompilationLog;
|
||||
CopyASCIItoUTF16(log, *out);
|
||||
void WebGLShader::GetShaderInfoLog(nsAString* const out) const {
|
||||
CopyASCIItoUTF16(mCompilationLog, *out);
|
||||
}
|
||||
|
||||
JS::Value WebGLShader::GetShaderParameter(GLenum pname) const {
|
||||
|
@ -191,20 +172,16 @@ void WebGLShader::GetShaderSource(nsAString* out) const {
|
|||
|
||||
void WebGLShader::GetShaderTranslatedSource(nsAString* out) const {
|
||||
out->SetIsVoid(false);
|
||||
CopyASCIItoUTF16(mTranslatedSource, *out);
|
||||
const auto& wrapper =
|
||||
nsDependentCString(mCompileResults->mObjectCode.c_str());
|
||||
CopyASCIItoUTF16(wrapper, *out);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool WebGLShader::CanLinkTo(const WebGLShader* prev,
|
||||
nsCString* const out_log) const {
|
||||
return mValidator->CanLinkTo(prev->mValidator.get(), out_log);
|
||||
}
|
||||
|
||||
size_t WebGLShader::CalcNumSamplerUniforms() const {
|
||||
const auto& uniforms = *sh::GetUniforms(mValidator->mHandle);
|
||||
size_t accum = 0;
|
||||
for (const auto& cur : uniforms) {
|
||||
for (const auto& cur : mCompileResults->mUniforms) {
|
||||
const auto& type = cur.type;
|
||||
if (type == LOCAL_GL_SAMPLER_2D || type == LOCAL_GL_SAMPLER_CUBE) {
|
||||
accum += cur.getArraySizeProduct();
|
||||
|
@ -214,13 +191,12 @@ size_t WebGLShader::CalcNumSamplerUniforms() const {
|
|||
}
|
||||
|
||||
size_t WebGLShader::NumAttributes() const {
|
||||
return sh::GetAttributes(mValidator->mHandle)->size();
|
||||
return mCompileResults->mAttributes.size();
|
||||
}
|
||||
|
||||
void WebGLShader::BindAttribLocation(GLuint prog, const std::string& userName,
|
||||
GLuint index) const {
|
||||
const auto& attribs = *sh::GetAttributes(mValidator->mHandle);
|
||||
for (const auto& attrib : attribs) {
|
||||
for (const auto& attrib : mCompileResults->mAttributes) {
|
||||
if (attrib.name == userName) {
|
||||
mContext->gl->fBindAttribLocation(prog, index, attrib.mappedName.c_str());
|
||||
return;
|
||||
|
@ -232,8 +208,7 @@ bool WebGLShader::FindAttribUserNameByMappedName(
|
|||
const nsACString& mappedName, nsCString* const out_userName) const {
|
||||
const std::string mappedNameStr(mappedName.BeginReading());
|
||||
|
||||
const auto& attribs = *sh::GetAttributes(mValidator->mHandle);
|
||||
for (const auto& cur : attribs) {
|
||||
for (const auto& cur : mCompileResults->mAttributes) {
|
||||
if (cur.mappedName == mappedNameStr) {
|
||||
*out_userName = cur.name.c_str();
|
||||
return true;
|
||||
|
@ -247,8 +222,7 @@ bool WebGLShader::FindVaryingByMappedName(const nsACString& mappedName,
|
|||
bool* const out_isArray) const {
|
||||
const std::string mappedNameStr(mappedName.BeginReading());
|
||||
|
||||
const auto& varyings = *sh::GetVaryings(mValidator->mHandle);
|
||||
for (const auto& cur : varyings) {
|
||||
for (const auto& cur : mCompileResults->mVaryings) {
|
||||
const sh::ShaderVariable* found;
|
||||
std::string userName;
|
||||
if (!cur.findInfoByMappedName(mappedNameStr, &found, &userName)) continue;
|
||||
|
@ -267,8 +241,8 @@ bool WebGLShader::FindUniformByMappedName(const nsACString& mappedName,
|
|||
const std::string mappedNameStr(mappedName.BeginReading(),
|
||||
mappedName.Length());
|
||||
std::string userNameStr;
|
||||
if (!mValidator->FindUniformByMappedName(mappedNameStr, &userNameStr,
|
||||
out_isArray))
|
||||
if (!mCompileResults->FindUniformByMappedName(mappedNameStr, &userNameStr,
|
||||
out_isArray))
|
||||
return false;
|
||||
|
||||
*out_userName = userNameStr.c_str();
|
||||
|
@ -277,8 +251,7 @@ bool WebGLShader::FindUniformByMappedName(const nsACString& mappedName,
|
|||
|
||||
bool WebGLShader::UnmapUniformBlockName(
|
||||
const nsACString& baseMappedName, nsCString* const out_baseUserName) const {
|
||||
const auto& interfaces = *sh::GetInterfaceBlocks(mValidator->mHandle);
|
||||
for (const auto& interface : interfaces) {
|
||||
for (const auto& interface : mCompileResults->mInterfaceBlocks) {
|
||||
const nsDependentCString interfaceMappedName(interface.mappedName.data(),
|
||||
interface.mappedName.size());
|
||||
if (baseMappedName == interfaceMappedName) {
|
||||
|
@ -299,7 +272,7 @@ void WebGLShader::MapTransformFeedbackVaryings(
|
|||
out_mappedVaryings->clear();
|
||||
out_mappedVaryings->reserve(varyings.size());
|
||||
|
||||
const auto& shaderVaryings = *sh::GetVaryings(mValidator->mHandle);
|
||||
const auto& shaderVaryings = mCompileResults->mVaryings;
|
||||
|
||||
for (const auto& wideUserName : varyings) {
|
||||
const NS_LossyConvertUTF16toASCII mozUserName(
|
||||
|
@ -326,13 +299,10 @@ JSObject* WebGLShader::WrapObject(JSContext* js,
|
|||
}
|
||||
|
||||
size_t WebGLShader::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
|
||||
size_t validatorSize = mValidator ? mallocSizeOf(mValidator.get()) : 0;
|
||||
return mallocSizeOf(this) +
|
||||
mSource.SizeOfExcludingThisIfUnshared(mallocSizeOf) +
|
||||
mCleanSource.SizeOfExcludingThisIfUnshared(mallocSizeOf) +
|
||||
validatorSize +
|
||||
mValidationLog.SizeOfExcludingThisIfUnshared(mallocSizeOf) +
|
||||
mTranslatedSource.SizeOfExcludingThisIfUnshared(mallocSizeOf) +
|
||||
mCompileResults->SizeOfIncludingThis(mallocSizeOf) +
|
||||
mCompilationLog.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define WEBGL_SHADER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -21,7 +22,7 @@
|
|||
namespace mozilla {
|
||||
|
||||
namespace webgl {
|
||||
class ShaderValidator;
|
||||
class ShaderValidatorResults;
|
||||
} // namespace webgl
|
||||
|
||||
class WebGLShader final : public nsWrapperCache,
|
||||
|
@ -46,7 +47,6 @@ class WebGLShader final : public nsWrapperCache,
|
|||
void ShaderSource(const nsAString& source);
|
||||
|
||||
// Util funcs
|
||||
bool CanLinkTo(const WebGLShader* prev, nsCString* const out_log) const;
|
||||
size_t CalcNumSamplerUniforms() const;
|
||||
size_t NumAttributes() const;
|
||||
bool FindAttribUserNameByMappedName(const nsACString& mappedName,
|
||||
|
@ -60,11 +60,8 @@ class WebGLShader final : public nsWrapperCache,
|
|||
bool UnmapUniformBlockName(const nsACString& baseMappedName,
|
||||
nsCString* const out_baseUserName) const;
|
||||
|
||||
bool IsCompiled() const {
|
||||
return mTranslationSuccessful && mCompilationSuccessful;
|
||||
}
|
||||
const auto* Validator() const { return mValidator.get(); }
|
||||
const auto& TranslatedSource() const { return mTranslatedSource; }
|
||||
bool IsCompiled() const { return mCompilationSuccessful; }
|
||||
const auto& CompileResults() const { return mCompileResults; }
|
||||
|
||||
private:
|
||||
void BindAttribLocation(GLuint prog, const std::string& userName,
|
||||
|
@ -94,12 +91,9 @@ class WebGLShader final : public nsWrapperCache,
|
|||
nsString mSource;
|
||||
nsCString mCleanSource;
|
||||
|
||||
UniquePtr<webgl::ShaderValidator> mValidator;
|
||||
nsCString mValidationLog;
|
||||
bool mTranslationSuccessful;
|
||||
nsCString mTranslatedSource;
|
||||
|
||||
bool mCompilationSuccessful;
|
||||
std::unique_ptr<const webgl::ShaderValidatorResults>
|
||||
mCompileResults; // Never null.
|
||||
bool mCompilationSuccessful = false;
|
||||
nsCString mCompilationLog;
|
||||
};
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ static ShShaderOutput ShaderOutput(gl::GLContext* gl) {
|
|||
return SH_GLSL_COMPATIBILITY_OUTPUT;
|
||||
}
|
||||
|
||||
webgl::ShaderValidator* WebGLContext::CreateShaderValidator(
|
||||
std::unique_ptr<webgl::ShaderValidator> WebGLContext::CreateShaderValidator(
|
||||
GLenum shaderType) const {
|
||||
const auto spec = (IsWebGL2() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC);
|
||||
const auto outputLanguage = ShaderOutput(gl);
|
||||
|
@ -212,27 +212,46 @@ webgl::ShaderValidator* WebGLContext::CreateShaderValidator(
|
|||
namespace webgl {
|
||||
|
||||
/*static*/
|
||||
ShaderValidator* ShaderValidator::Create(GLenum shaderType, ShShaderSpec spec,
|
||||
ShShaderOutput outputLanguage,
|
||||
const ShBuiltInResources& resources,
|
||||
ShCompileOptions compileOptions) {
|
||||
std::unique_ptr<ShaderValidator> ShaderValidator::Create(
|
||||
GLenum shaderType, ShShaderSpec spec, ShShaderOutput outputLanguage,
|
||||
const ShBuiltInResources& resources, ShCompileOptions compileOptions) {
|
||||
ShHandle handle =
|
||||
sh::ConstructCompiler(shaderType, spec, outputLanguage, &resources);
|
||||
MOZ_RELEASE_ASSERT(handle);
|
||||
if (!handle) return nullptr;
|
||||
|
||||
return new ShaderValidator(handle, compileOptions,
|
||||
resources.MaxVaryingVectors);
|
||||
return std::unique_ptr<ShaderValidator>(
|
||||
new ShaderValidator(handle, compileOptions, resources.MaxVaryingVectors));
|
||||
}
|
||||
|
||||
ShaderValidator::~ShaderValidator() { sh::Destruct(mHandle); }
|
||||
|
||||
bool ShaderValidator::ValidateAndTranslate(const char* source) {
|
||||
MOZ_ASSERT(!mHasRun);
|
||||
mHasRun = true;
|
||||
std::unique_ptr<const ShaderValidatorResults>
|
||||
ShaderValidator::ValidateAndTranslate(const char* const source) const {
|
||||
auto ret = std::make_unique<ShaderValidatorResults>();
|
||||
|
||||
const char* const parts[] = {source};
|
||||
return sh::Compile(mHandle, parts, ArrayLength(parts), mCompileOptions);
|
||||
const std::array<const char*, 1> parts = {source};
|
||||
ret->mValid =
|
||||
sh::Compile(mHandle, parts.data(), parts.size(), mCompileOptions);
|
||||
|
||||
ret->mInfoLog = sh::GetInfoLog(mHandle);
|
||||
|
||||
if (ret->mValid) {
|
||||
ret->mObjectCode = sh::GetObjectCode(mHandle);
|
||||
ret->mShaderVersion = sh::GetShaderVersion(mHandle);
|
||||
ret->mVertexShaderNumViews = sh::GetVertexShaderNumViews(mHandle);
|
||||
|
||||
ret->mAttributes = *sh::GetAttributes(mHandle);
|
||||
ret->mInterfaceBlocks = *sh::GetInterfaceBlocks(mHandle);
|
||||
ret->mOutputVariables = *sh::GetOutputVariables(mHandle);
|
||||
ret->mUniforms = *sh::GetUniforms(mHandle);
|
||||
ret->mVaryings = *sh::GetVaryings(mHandle);
|
||||
|
||||
ret->mMaxVaryingVectors = mMaxVaryingVectors;
|
||||
}
|
||||
|
||||
sh::ClearResults(mHandle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
|
@ -240,91 +259,58 @@ static bool StartsWith(const std::string& haystack, const char (&needle)[N]) {
|
|||
return haystack.compare(0, N - 1, needle) == 0;
|
||||
}
|
||||
|
||||
bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
||||
nsCString* const out_log) const {
|
||||
if (!prev) {
|
||||
nsPrintfCString error("Passed in NULL prev ShaderValidator.");
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
bool ShaderValidatorResults::CanLinkTo(const ShaderValidatorResults& vert,
|
||||
nsCString* const out_log) const {
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(vert.mValid);
|
||||
|
||||
const auto shaderVersion = sh::GetShaderVersion(mHandle);
|
||||
if (sh::GetShaderVersion(prev->mHandle) != shaderVersion) {
|
||||
if (vert.mShaderVersion != mShaderVersion) {
|
||||
nsPrintfCString error(
|
||||
"Vertex shader version %d does not match"
|
||||
" fragment shader version %d.",
|
||||
sh::GetShaderVersion(prev->mHandle), sh::GetShaderVersion(mHandle));
|
||||
vert.mShaderVersion, mShaderVersion);
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
const std::vector<sh::Uniform>* vertPtr = sh::GetUniforms(prev->mHandle);
|
||||
const std::vector<sh::Uniform>* fragPtr = sh::GetUniforms(mHandle);
|
||||
if (!vertPtr || !fragPtr) {
|
||||
nsPrintfCString error("Could not create uniform list.");
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
for (const auto& itrFrag : mUniforms) {
|
||||
for (const auto& itrVert : vert.mUniforms) {
|
||||
if (itrVert.name != itrFrag.name) continue;
|
||||
|
||||
for (auto itrFrag = fragPtr->begin(); itrFrag != fragPtr->end();
|
||||
++itrFrag) {
|
||||
for (auto itrVert = vertPtr->begin(); itrVert != vertPtr->end();
|
||||
++itrVert) {
|
||||
if (itrVert->name != itrFrag->name) continue;
|
||||
|
||||
if (!itrVert->isSameUniformAtLinkTime(*itrFrag)) {
|
||||
nsPrintfCString error(
|
||||
"Uniform `%s` is not linkable between"
|
||||
" attached shaders.",
|
||||
itrFrag->name.c_str());
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
if (!itrVert.isSameUniformAtLinkTime(itrFrag)) {
|
||||
nsPrintfCString error(
|
||||
"Uniform `%s` is not linkable between"
|
||||
" attached shaders.",
|
||||
itrFrag.name.c_str());
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const auto vertVars = sh::GetInterfaceBlocks(prev->mHandle);
|
||||
const auto fragVars = sh::GetInterfaceBlocks(mHandle);
|
||||
if (!vertVars || !fragVars) {
|
||||
nsPrintfCString error("Could not create uniform block list.");
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& fragVar : *fragVars) {
|
||||
for (const auto& vertVar : *vertVars) {
|
||||
if (vertVar.name != fragVar.name) continue;
|
||||
|
||||
if (!vertVar.isSameInterfaceBlockAtLinkTime(fragVar)) {
|
||||
nsPrintfCString error(
|
||||
"Interface block `%s` is not linkable between"
|
||||
" attached shaders.",
|
||||
fragVar.name.c_str());
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto& vertVaryings = sh::GetVaryings(prev->mHandle);
|
||||
const auto& fragVaryings = sh::GetVaryings(mHandle);
|
||||
if (!vertVaryings || !fragVaryings) {
|
||||
nsPrintfCString error("Could not create varying list.");
|
||||
*out_log = error;
|
||||
return false;
|
||||
for (const auto& fragVar : mInterfaceBlocks) {
|
||||
for (const auto& vertVar : vert.mInterfaceBlocks) {
|
||||
if (vertVar.name != fragVar.name) continue;
|
||||
|
||||
if (!vertVar.isSameInterfaceBlockAtLinkTime(fragVar)) {
|
||||
nsPrintfCString error(
|
||||
"Interface block `%s` is not linkable between"
|
||||
" attached shaders.",
|
||||
fragVar.name.c_str());
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<sh::ShaderVariable> staticUseVaryingList;
|
||||
|
||||
for (const auto& fragVarying : *fragVaryings) {
|
||||
for (const auto& fragVarying : mVaryings) {
|
||||
static const char prefix[] = "gl_";
|
||||
if (StartsWith(fragVarying.name, prefix)) {
|
||||
if (fragVarying.staticUse) {
|
||||
|
@ -336,10 +322,10 @@ bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
|||
bool definedInVertShader = false;
|
||||
bool staticVertUse = false;
|
||||
|
||||
for (const auto& vertVarying : *vertVaryings) {
|
||||
for (const auto& vertVarying : vert.mVaryings) {
|
||||
if (vertVarying.name != fragVarying.name) continue;
|
||||
|
||||
if (!vertVarying.isSameVaryingAtLinkTime(fragVarying, shaderVersion)) {
|
||||
if (!vertVarying.isSameVaryingAtLinkTime(fragVarying, mShaderVersion)) {
|
||||
nsPrintfCString error(
|
||||
"Varying `%s`is not linkable between"
|
||||
" attached shaders.",
|
||||
|
@ -377,14 +363,14 @@ bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
|||
}
|
||||
}
|
||||
|
||||
if (shaderVersion == 100) {
|
||||
if (mShaderVersion == 100) {
|
||||
// Enforce ESSL1 invariant linking rules.
|
||||
bool isInvariant_Position = false;
|
||||
bool isInvariant_PointSize = false;
|
||||
bool isInvariant_FragCoord = false;
|
||||
bool isInvariant_PointCoord = false;
|
||||
|
||||
for (const auto& varying : *vertVaryings) {
|
||||
for (const auto& varying : vert.mVaryings) {
|
||||
if (varying.name == "gl_Position") {
|
||||
isInvariant_Position = varying.isInvariant;
|
||||
} else if (varying.name == "gl_PointSize") {
|
||||
|
@ -392,7 +378,7 @@ bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
|||
}
|
||||
}
|
||||
|
||||
for (const auto& varying : *fragVaryings) {
|
||||
for (const auto& varying : mVaryings) {
|
||||
if (varying.name == "gl_FragCoord") {
|
||||
isInvariant_FragCoord = varying.isInvariant;
|
||||
} else if (varying.name == "gl_PointCoord") {
|
||||
|
@ -428,13 +414,12 @@ bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
|||
}
|
||||
|
||||
// This must handle names like "foo.bar[0]".
|
||||
bool ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
|
||||
std::string* const out_userName,
|
||||
bool* const out_isArray) const {
|
||||
const std::vector<sh::Uniform>& uniforms = *sh::GetUniforms(mHandle);
|
||||
for (auto itr = uniforms.begin(); itr != uniforms.end(); ++itr) {
|
||||
bool ShaderValidatorResults::FindUniformByMappedName(
|
||||
const std::string& mappedName, std::string* const out_userName,
|
||||
bool* const out_isArray) const {
|
||||
for (const auto& cur : mUniforms) {
|
||||
const sh::ShaderVariable* found;
|
||||
if (!itr->findInfoByMappedName(mappedName, &found, out_userName)) continue;
|
||||
if (!cur.findInfoByMappedName(mappedName, &found, out_userName)) continue;
|
||||
|
||||
*out_isArray = found->isArray();
|
||||
return true;
|
||||
|
@ -442,9 +427,7 @@ bool ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
|
|||
|
||||
const size_t dotPos = mappedName.find(".");
|
||||
|
||||
const std::vector<sh::InterfaceBlock>& interfaces =
|
||||
*sh::GetInterfaceBlocks(mHandle);
|
||||
for (const auto& interface : interfaces) {
|
||||
for (const auto& interface : mInterfaceBlocks) {
|
||||
std::string mappedFieldName;
|
||||
const bool hasInstanceName = !interface.instanceName.empty();
|
||||
|
||||
|
@ -483,5 +466,30 @@ bool ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t ShaderValidatorResults::SizeOfIncludingThis(
|
||||
const MallocSizeOf fnSizeOf) const {
|
||||
auto ret = fnSizeOf(this);
|
||||
ret += mInfoLog.size();
|
||||
ret += mObjectCode.size();
|
||||
|
||||
for (const auto& cur : mAttributes) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
for (const auto& cur : mInterfaceBlocks) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
for (const auto& cur : mOutputVariables) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
for (const auto& cur : mUniforms) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
for (const auto& cur : mVaryings) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace webgl
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -15,6 +15,31 @@
|
|||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
||||
class ShaderValidatorResults final {
|
||||
public:
|
||||
std::string mInfoLog;
|
||||
bool mValid = false;
|
||||
|
||||
std::string mObjectCode;
|
||||
int mShaderVersion = 0;
|
||||
int mVertexShaderNumViews = 0;
|
||||
|
||||
std::vector<sh::Attribute> mAttributes;
|
||||
std::vector<sh::InterfaceBlock> mInterfaceBlocks;
|
||||
std::vector<sh::OutputVariable> mOutputVariables;
|
||||
std::vector<sh::Uniform> mUniforms;
|
||||
std::vector<sh::Varying> mVaryings;
|
||||
|
||||
int mMaxVaryingVectors = 0;
|
||||
|
||||
bool CanLinkTo(const ShaderValidatorResults& vert,
|
||||
nsCString* const out_log) const;
|
||||
bool FindUniformByMappedName(const std::string& mappedName,
|
||||
std::string* const out_userName,
|
||||
bool* const out_isArray) const;
|
||||
size_t SizeOfIncludingThis(MallocSizeOf) const;
|
||||
};
|
||||
|
||||
class ShaderValidator final {
|
||||
public:
|
||||
const ShHandle mHandle;
|
||||
|
@ -22,36 +47,24 @@ class ShaderValidator final {
|
|||
private:
|
||||
const ShCompileOptions mCompileOptions;
|
||||
const int mMaxVaryingVectors;
|
||||
bool mHasRun;
|
||||
|
||||
public:
|
||||
static ShaderValidator* Create(GLenum shaderType, ShShaderSpec spec,
|
||||
ShShaderOutput outputLanguage,
|
||||
const ShBuiltInResources& resources,
|
||||
ShCompileOptions compileOptions);
|
||||
static std::unique_ptr<ShaderValidator> Create(
|
||||
GLenum shaderType, ShShaderSpec spec, ShShaderOutput outputLanguage,
|
||||
const ShBuiltInResources& resources, ShCompileOptions compileOptions);
|
||||
|
||||
private:
|
||||
ShaderValidator(ShHandle handle, ShCompileOptions compileOptions,
|
||||
int maxVaryingVectors)
|
||||
: mHandle(handle),
|
||||
mCompileOptions(compileOptions),
|
||||
mMaxVaryingVectors(maxVaryingVectors),
|
||||
mHasRun(false) {}
|
||||
mMaxVaryingVectors(maxVaryingVectors) {}
|
||||
|
||||
public:
|
||||
~ShaderValidator();
|
||||
|
||||
bool ValidateAndTranslate(const char* source);
|
||||
bool CanLinkTo(const ShaderValidator* prev, nsCString* const out_log) const;
|
||||
|
||||
bool FindUniformByMappedName(const std::string& mappedName,
|
||||
std::string* const out_userName,
|
||||
bool* const out_isArray) const;
|
||||
|
||||
bool ValidateTransformFeedback(
|
||||
const std::vector<nsString>& userNames, uint32_t maxComponents,
|
||||
nsCString* const out_errorText,
|
||||
std::vector<std::string>* const out_mappedNames);
|
||||
std::unique_ptr<const ShaderValidatorResults> ValidateAndTranslate(
|
||||
const char*) const;
|
||||
};
|
||||
|
||||
} // namespace webgl
|
||||
|
|
|
@ -1921,8 +1921,9 @@ static bool ValidateCopyTexImageForFeedback(const WebGLContext& webgl,
|
|||
}
|
||||
|
||||
static bool DoCopyTexOrSubImage(WebGLContext* webgl, bool isSubImage,
|
||||
WebGLTexture* const tex, const TexImageTarget target,
|
||||
GLint level, GLint xWithinSrc, GLint yWithinSrc,
|
||||
WebGLTexture* const tex,
|
||||
const TexImageTarget target, GLint level,
|
||||
GLint xWithinSrc, GLint yWithinSrc,
|
||||
uint32_t srcTotalWidth, uint32_t srcTotalHeight,
|
||||
const webgl::FormatUsageInfo* srcUsage,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
|
|
Загрузка…
Ссылка в новой задаче