Hash :
b3cbfd55
Author :
Date :
2021-07-07T12:31:57
Fix multiple end2end crashes in direct-to-MSL compiler. This set of changes: - Adds a single place (CompilerMtl::useDirectToMSLCompiler) where the direct-to-MSL compiler can be enabled, still at compile time rather than run time. It is still disabled by default. - Initializes MTLWaitableCompileEventImpl::mShader, without which all shader compiles crash. - Fixes a mismatch of the ANGLERasterizerDisabled variable name in the generated MSL. - Removes the transform feedback bindings as an argument to the vertex shader's main0(). Transform feedback support needs to be reimplemented in this compiler backend. - Added an option to the DriverUniform class to emit as either an interface block or a struct. The direct-to-MSL backend assumes it is a struct. - Disable variable reference validation when referencing either sample mask or rasterizer discard functionality in the shader. - Disable struct usage validation when inserting references to ANGLE_TextureEnv. This occurs during pipeline rewriting and it's infeasible to disable it at that point, so disable it during pipeline rewriting - which means it's disabled for all shaders. - For angle_end2end_tests, disable the file API hooking which disables the Metal shader cache. This speeds up the tests significantly - by roughly a factor of 5. With these changes, several hundred angle_end2end_tests run without any assertion failures, though still with many test failures. The next crash is in: GLSLTest.NamelessScopedStructs/ES2_Metal and will likely require a larger bug fix, or more changes to be upstreamed from WebKit's repository. Bug: angleproject:5505 Change-Id: Ia1ea9a13867f00035d4aeccf907fd032255588e3 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3010486 Commit-Queue: Kenneth Russell <kbr@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ShaderMtl.mm:
// Implements the class methods for ShaderMtl.
//
#include "libANGLE/renderer/metal/ShaderMtl.h"
#include "common/debug.h"
#include "compiler/translator/TranslatorMetal.h"
#include "libANGLE/Context.h"
#include "libANGLE/Shader.h"
#include "libANGLE/WorkerThread.h"
#include "libANGLE/renderer/metal/ContextMtl.h"
#include "libANGLE/renderer/metal/DisplayMtl.h"
namespace rx
{
ShaderMtl::ShaderMtl(const gl::ShaderState &state) : ShaderImpl(state) {}
ShaderMtl::~ShaderMtl() {}
class TranslateTask : public angle::Closure
{
public:
TranslateTask(ShHandle handle, ShCompileOptions options, const std::string &source)
: mHandle(handle), mOptions(options), mSource(source), mResult(false)
{}
void operator()() override
{
const char *source = mSource.c_str();
mResult = sh::Compile(mHandle, &source, 1, mOptions);
}
bool getResult() { return mResult; }
ShHandle getHandle() { return mHandle; }
private:
ShHandle mHandle;
ShCompileOptions mOptions;
std::string mSource;
bool mResult;
};
class MTLWaitableCompileEventImpl final : public WaitableCompileEvent
{
public:
MTLWaitableCompileEventImpl(ShaderMtl *shader,
std::shared_ptr<angle::WaitableEvent> waitableEvent,
std::shared_ptr<TranslateTask> translateTask)
: WaitableCompileEvent(waitableEvent), mTranslateTask(translateTask), mShader(shader)
{}
bool getResult() override { return mTranslateTask->getResult(); }
bool postTranslate(std::string *infoLog) override
{
sh::TShHandleBase *base = static_cast<sh::TShHandleBase *>(mTranslateTask->getHandle());
auto translatorMetalDirect = base->getAsTranslatorMetalDirect();
if (translatorMetalDirect != nullptr)
{
// Copy reflection from translation.
mShader->translatorMetalReflection =
*(translatorMetalDirect->getTranslatorMetalReflection());
translatorMetalDirect->getTranslatorMetalReflection()->reset();
}
return true;
}
private:
std::shared_ptr<TranslateTask> mTranslateTask;
ShaderMtl *mShader;
};
std::shared_ptr<WaitableCompileEvent> ShaderMtl::compileImplMtl(
const gl::Context *context,
gl::ShCompilerInstance *compilerInstance,
const std::string &source,
ShCompileOptions compileOptions)
{
#if defined(ANGLE_ENABLE_ASSERTS)
compileOptions |= SH_VALIDATE_AST;
#endif
auto workerThreadPool = context->getWorkerThreadPool();
auto translateTask =
std::make_shared<TranslateTask>(compilerInstance->getHandle(), compileOptions, source);
return std::make_shared<MTLWaitableCompileEventImpl>(
this, angle::WorkerThreadPool::PostWorkerTask(workerThreadPool, translateTask),
translateTask);
}
std::shared_ptr<WaitableCompileEvent> ShaderMtl::compile(const gl::Context *context,
gl::ShCompilerInstance *compilerInstance,
ShCompileOptions options)
{
ContextMtl *contextMtl = mtl::GetImpl(context);
if (getState().getShaderType() == gl::ShaderType::Vertex &&
!contextMtl->getDisplay()->getFeatures().hasBaseVertexInstancedDraw.enabled)
{
// Emulate gl_InstanceID
sh::TShHandleBase *base = static_cast<sh::TShHandleBase *>(compilerInstance->getHandle());
auto translatorMetalDirect = base->getAsTranslatorMetalDirect();
if (translatorMetalDirect == nullptr)
{
// TODO(jonahr): This isn't implemented in TranslatorMetal. Do we care? That should be
// deprecated. auto translatorMetal = static_cast<sh::TranslatorMetal
// *>(base->getAsCompiler()); translatorMetal->enableEmulatedInstanceID(true);
}
else
{
translatorMetalDirect->enableEmulatedInstanceID(true);
}
}
ShCompileOptions compileOptions = SH_INITIALIZE_UNINITIALIZED_LOCALS;
bool isWebGL = context->getExtensions().webglCompatibility;
if (isWebGL && mState.getShaderType() != gl::ShaderType::Compute)
{
compileOptions |= SH_INIT_OUTPUT_VARIABLES;
}
compileOptions |= SH_CLAMP_POINT_SIZE;
#if defined(ANGLE_PLATFORM_IOS) && !defined(ANGLE_PLATFORM_MACCATALYST)
compileOptions |= SH_CLAMP_FRAG_DEPTH;
#endif
if (contextMtl->getDisplay()->getFeatures().rewriteRowMajorMatrices.enabled)
{
compileOptions |= SH_REWRITE_ROW_MAJOR_MATRICES;
}
// IF SPIRV
compileOptions |= SH_ADD_VULKAN_XFB_EMULATION_SUPPORT_CODE;
return compileImplMtl(context, compilerInstance, getState().getSource(),
compileOptions | options);
}
std::string ShaderMtl::getDebugInfo() const
{
return mState.getCompiledBinary().empty() ? "" : "<binary blob>";
}
} // namespace rx