// // 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/WorkerThread.h" #include "common/debug.h" #include "libANGLE/Context.h" #include "libANGLE/Shader.h" #include "libANGLE/renderer/metal/ContextMtl.h" #include "libANGLE/renderer/metal/DisplayMtl.h" #include "libANGLE/trace.h" namespace rx { namespace { class ShaderTranslateTaskMtl final : public ShaderTranslateTask { public: ShaderTranslateTaskMtl(const SharedCompiledShaderStateMtl &shader) : mShader(shader) {} ~ShaderTranslateTaskMtl() override = default; void postTranslate(ShHandle compiler, const gl::CompiledShaderState &compiledState) override { sh::TranslatorMSL *translatorMSL = static_cast(compiler)->getAsTranslatorMSL(); if (translatorMSL != nullptr) { // Copy reflection data from translation mShader->translatorMetalReflection = *translatorMSL->getTranslatorMetalReflection(); translatorMSL->getTranslatorMetalReflection()->reset(); } } private: SharedCompiledShaderStateMtl mShader; }; } // anonymous namespace ShaderMtl::ShaderMtl(const gl::ShaderState &state) : ShaderImpl(state) {} ShaderMtl::~ShaderMtl() {} std::shared_ptr ShaderMtl::compile(const gl::Context *context, ShCompileOptions *options) { ContextMtl *contextMtl = mtl::GetImpl(context); DisplayMtl *displayMtl = contextMtl->getDisplay(); // Create a new compiled shader state. Currently running program link jobs will use the // previous state. mCompiledState = std::make_shared(); // TODO(jcunningham): Remove this workaround once correct fix to move validation to the very end // is in place. https://bugs.webkit.org/show_bug.cgi?id=224991 options->validateAST = false; options->simplifyLoopConditions = true; options->initializeUninitializedLocals = true; options->separateCompoundStructDeclarations = true; options->forceDeferNonConstGlobalInitializers = true; const bool isHardened = context->isWebGL() || context->isHardenedContext(); if (isHardened && mState.getShaderType() != gl::ShaderType::Compute) { options->initOutputVariables = true; } options->metal.generateShareableShaders = displayMtl->getFeatures().generateShareableShaders.enabled; options->clampPointSize = true; #if TARGET_OS_IPHONE && !TARGET_OS_MACCATALYST options->clampFragDepth = true; #endif if (displayMtl->getFeatures().emulateAlphaToCoverage.enabled) { options->emulateAlphaToCoverage = true; } options->removeInactiveVariables = true; options->retainInactiveFragmentOutputs = true; // Constants: options->metal.driverUniformsBindingIndex = mtl::kDriverUniformsBindingIndex; options->metal.defaultUniformsBindingIndex = mtl::kDefaultUniformsBindingIndex; options->metal.UBOArgumentBufferBindingIndex = mtl::kUBOArgumentBufferBindingIndex; // GL_ANGLE_shader_pixel_local_storage. if (displayMtl->getNativeExtensions().shaderPixelLocalStorageANGLE) { options->pls = displayMtl->getNativePixelLocalStorageOptions(); } options->preTransformTextureCubeGradDerivatives = displayMtl->getFeatures().preTransformTextureCubeGradDerivatives.enabled; options->rescopeGlobalVariables = displayMtl->getFeatures().rescopeGlobalVariables.enabled; if (displayMtl->getFeatures().injectAsmStatementIntoLoopBodies.enabled) { options->metal.injectAsmStatementIntoLoopBodies = true; } if (displayMtl->getFeatures().ensureLoopForwardProgress.enabled) { options->ensureLoopForwardProgress = true; } return std::shared_ptr(new ShaderTranslateTaskMtl(mCompiledState)); } std::shared_ptr ShaderMtl::load(const gl::Context *context, gl::BinaryInputStream *stream) { UNREACHABLE(); return std::shared_ptr(new ShaderTranslateTask); } std::string ShaderMtl::getDebugInfo() const { return *mState.getCompiledState()->translatedSource; } } // namespace rx