xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/ProgramMtl.mm (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker//
2*8975f5c5SAndroid Build Coastguard Worker// Copyright 2019 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker// found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker//
6*8975f5c5SAndroid Build Coastguard Worker// ProgramMtl.mm:
7*8975f5c5SAndroid Build Coastguard Worker//    Implements the class methods for ProgramMtl.
8*8975f5c5SAndroid Build Coastguard Worker//
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ProgramMtl.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker#include <TargetConditionals.h>
13*8975f5c5SAndroid Build Coastguard Worker
14*8975f5c5SAndroid Build Coastguard Worker#include <sstream>
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Worker#include "common/WorkerThread.h"
17*8975f5c5SAndroid Build Coastguard Worker#include "common/debug.h"
18*8975f5c5SAndroid Build Coastguard Worker#include "common/system_utils.h"
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/Context.h"
21*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/ProgramLinkedResources.h"
22*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/CompilerMtl.h"
23*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ContextMtl.h"
24*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/DisplayMtl.h"
25*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/blocklayoutMetal.h"
26*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/mtl_msl_utils.h"
27*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/mtl_utils.h"
28*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/renderermtl_utils.h"
29*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/renderer_utils.h"
30*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/trace.h"
31*8975f5c5SAndroid Build Coastguard Worker
32*8975f5c5SAndroid Build Coastguard Workernamespace rx
33*8975f5c5SAndroid Build Coastguard Worker{
34*8975f5c5SAndroid Build Coastguard Worker
35*8975f5c5SAndroid Build Coastguard Workernamespace
36*8975f5c5SAndroid Build Coastguard Worker{
37*8975f5c5SAndroid Build Coastguard Workerinline std::map<std::string, std::string> GetDefaultSubstitutionDictionary()
38*8975f5c5SAndroid Build Coastguard Worker{
39*8975f5c5SAndroid Build Coastguard Worker    return {};
40*8975f5c5SAndroid Build Coastguard Worker}
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Workerclass Std140BlockLayoutEncoderFactory : public gl::CustomBlockLayoutEncoderFactory
43*8975f5c5SAndroid Build Coastguard Worker{
44*8975f5c5SAndroid Build Coastguard Worker  public:
45*8975f5c5SAndroid Build Coastguard Worker    sh::BlockLayoutEncoder *makeEncoder() override { return new sh::Std140BlockEncoder(); }
46*8975f5c5SAndroid Build Coastguard Worker};
47*8975f5c5SAndroid Build Coastguard Worker
48*8975f5c5SAndroid Build Coastguard Workerclass CompileMslTask final : public LinkSubTask
49*8975f5c5SAndroid Build Coastguard Worker{
50*8975f5c5SAndroid Build Coastguard Worker  public:
51*8975f5c5SAndroid Build Coastguard Worker    CompileMslTask(mtl::Context *context,
52*8975f5c5SAndroid Build Coastguard Worker                   mtl::TranslatedShaderInfo *translatedMslInfo,
53*8975f5c5SAndroid Build Coastguard Worker                   const std::map<std::string, std::string> &substitutionMacros)
54*8975f5c5SAndroid Build Coastguard Worker        : mContext(context),
55*8975f5c5SAndroid Build Coastguard Worker          mTranslatedMslInfo(translatedMslInfo),
56*8975f5c5SAndroid Build Coastguard Worker          mSubstitutionMacros(substitutionMacros)
57*8975f5c5SAndroid Build Coastguard Worker    {}
58*8975f5c5SAndroid Build Coastguard Worker    ~CompileMslTask() override = default;
59*8975f5c5SAndroid Build Coastguard Worker
60*8975f5c5SAndroid Build Coastguard Worker    void operator()() override
61*8975f5c5SAndroid Build Coastguard Worker    {
62*8975f5c5SAndroid Build Coastguard Worker        mResult = CreateMslShaderLib(mContext, mInfoLog, mTranslatedMslInfo, mSubstitutionMacros);
63*8975f5c5SAndroid Build Coastguard Worker    }
64*8975f5c5SAndroid Build Coastguard Worker
65*8975f5c5SAndroid Build Coastguard Worker    angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override
66*8975f5c5SAndroid Build Coastguard Worker    {
67*8975f5c5SAndroid Build Coastguard Worker        if (!mInfoLog.empty())
68*8975f5c5SAndroid Build Coastguard Worker        {
69*8975f5c5SAndroid Build Coastguard Worker            infoLog << mInfoLog.str();
70*8975f5c5SAndroid Build Coastguard Worker        }
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker        return mResult;
73*8975f5c5SAndroid Build Coastguard Worker    }
74*8975f5c5SAndroid Build Coastguard Worker
75*8975f5c5SAndroid Build Coastguard Worker  private:
76*8975f5c5SAndroid Build Coastguard Worker    mtl::Context *mContext;
77*8975f5c5SAndroid Build Coastguard Worker    gl::InfoLog mInfoLog;
78*8975f5c5SAndroid Build Coastguard Worker    mtl::TranslatedShaderInfo *mTranslatedMslInfo;
79*8975f5c5SAndroid Build Coastguard Worker    std::map<std::string, std::string> mSubstitutionMacros;
80*8975f5c5SAndroid Build Coastguard Worker    angle::Result mResult = angle::Result::Continue;
81*8975f5c5SAndroid Build Coastguard Worker};
82*8975f5c5SAndroid Build Coastguard Worker}  // namespace
83*8975f5c5SAndroid Build Coastguard Worker
84*8975f5c5SAndroid Build Coastguard Workerclass ProgramMtl::LinkTaskMtl final : public mtl::Context, public LinkTask
85*8975f5c5SAndroid Build Coastguard Worker{
86*8975f5c5SAndroid Build Coastguard Worker  public:
87*8975f5c5SAndroid Build Coastguard Worker    LinkTaskMtl(DisplayMtl *displayMtl, ProgramMtl *program)
88*8975f5c5SAndroid Build Coastguard Worker        : mtl::Context(displayMtl), mProgram(program)
89*8975f5c5SAndroid Build Coastguard Worker    {}
90*8975f5c5SAndroid Build Coastguard Worker    ~LinkTaskMtl() override = default;
91*8975f5c5SAndroid Build Coastguard Worker
92*8975f5c5SAndroid Build Coastguard Worker    void link(const gl::ProgramLinkedResources &resources,
93*8975f5c5SAndroid Build Coastguard Worker              const gl::ProgramMergedVaryings &mergedVaryings,
94*8975f5c5SAndroid Build Coastguard Worker              std::vector<std::shared_ptr<LinkSubTask>> *linkSubTasksOut,
95*8975f5c5SAndroid Build Coastguard Worker              std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut) override
96*8975f5c5SAndroid Build Coastguard Worker    {
97*8975f5c5SAndroid Build Coastguard Worker        ASSERT(linkSubTasksOut && linkSubTasksOut->empty());
98*8975f5c5SAndroid Build Coastguard Worker        ASSERT(postLinkSubTasksOut && postLinkSubTasksOut->empty());
99*8975f5c5SAndroid Build Coastguard Worker
100*8975f5c5SAndroid Build Coastguard Worker        mResult = mProgram->linkJobImpl(this, resources, linkSubTasksOut);
101*8975f5c5SAndroid Build Coastguard Worker        return;
102*8975f5c5SAndroid Build Coastguard Worker    }
103*8975f5c5SAndroid Build Coastguard Worker
104*8975f5c5SAndroid Build Coastguard Worker    angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override
105*8975f5c5SAndroid Build Coastguard Worker    {
106*8975f5c5SAndroid Build Coastguard Worker        // Forward any errors
107*8975f5c5SAndroid Build Coastguard Worker        if (mErrorCode != GL_NO_ERROR)
108*8975f5c5SAndroid Build Coastguard Worker        {
109*8975f5c5SAndroid Build Coastguard Worker            mtl::GetImpl(context)->handleError(mErrorCode, mErrorMessage.c_str(), mErrorFile,
110*8975f5c5SAndroid Build Coastguard Worker                                               mErrorFunction, mErrorLine);
111*8975f5c5SAndroid Build Coastguard Worker            return angle::Result::Stop;
112*8975f5c5SAndroid Build Coastguard Worker        }
113*8975f5c5SAndroid Build Coastguard Worker
114*8975f5c5SAndroid Build Coastguard Worker        return mResult;
115*8975f5c5SAndroid Build Coastguard Worker    }
116*8975f5c5SAndroid Build Coastguard Worker
117*8975f5c5SAndroid Build Coastguard Worker    // override mtl::ErrorHandler
118*8975f5c5SAndroid Build Coastguard Worker    void handleError(GLenum glErrorCode,
119*8975f5c5SAndroid Build Coastguard Worker                     const char *message,
120*8975f5c5SAndroid Build Coastguard Worker                     const char *file,
121*8975f5c5SAndroid Build Coastguard Worker                     const char *function,
122*8975f5c5SAndroid Build Coastguard Worker                     unsigned int line) override
123*8975f5c5SAndroid Build Coastguard Worker    {
124*8975f5c5SAndroid Build Coastguard Worker        mErrorCode     = glErrorCode;
125*8975f5c5SAndroid Build Coastguard Worker        mErrorMessage  = message;
126*8975f5c5SAndroid Build Coastguard Worker        mErrorFile     = file;
127*8975f5c5SAndroid Build Coastguard Worker        mErrorFunction = function;
128*8975f5c5SAndroid Build Coastguard Worker        mErrorLine     = line;
129*8975f5c5SAndroid Build Coastguard Worker    }
130*8975f5c5SAndroid Build Coastguard Worker
131*8975f5c5SAndroid Build Coastguard Worker    void handleError(NSError *error,
132*8975f5c5SAndroid Build Coastguard Worker                     const char *message,
133*8975f5c5SAndroid Build Coastguard Worker                     const char *file,
134*8975f5c5SAndroid Build Coastguard Worker                     const char *function,
135*8975f5c5SAndroid Build Coastguard Worker                     unsigned int line) override
136*8975f5c5SAndroid Build Coastguard Worker    {
137*8975f5c5SAndroid Build Coastguard Worker        if (!error)
138*8975f5c5SAndroid Build Coastguard Worker        {
139*8975f5c5SAndroid Build Coastguard Worker            return;
140*8975f5c5SAndroid Build Coastguard Worker        }
141*8975f5c5SAndroid Build Coastguard Worker
142*8975f5c5SAndroid Build Coastguard Worker        mErrorCode     = GL_INVALID_OPERATION;
143*8975f5c5SAndroid Build Coastguard Worker        mErrorMessage  = message;
144*8975f5c5SAndroid Build Coastguard Worker        mErrorFile     = file;
145*8975f5c5SAndroid Build Coastguard Worker        mErrorFunction = function;
146*8975f5c5SAndroid Build Coastguard Worker        mErrorLine     = line;
147*8975f5c5SAndroid Build Coastguard Worker    }
148*8975f5c5SAndroid Build Coastguard Worker
149*8975f5c5SAndroid Build Coastguard Worker  private:
150*8975f5c5SAndroid Build Coastguard Worker    ProgramMtl *mProgram;
151*8975f5c5SAndroid Build Coastguard Worker    angle::Result mResult = angle::Result::Continue;
152*8975f5c5SAndroid Build Coastguard Worker
153*8975f5c5SAndroid Build Coastguard Worker    // Error handling
154*8975f5c5SAndroid Build Coastguard Worker    GLenum mErrorCode          = GL_NO_ERROR;
155*8975f5c5SAndroid Build Coastguard Worker    // Error message might be dynamically allocated at the callsite.
156*8975f5c5SAndroid Build Coastguard Worker    std::string mErrorMessage;
157*8975f5c5SAndroid Build Coastguard Worker    const char *mErrorFile     = nullptr;
158*8975f5c5SAndroid Build Coastguard Worker    const char *mErrorFunction = nullptr;
159*8975f5c5SAndroid Build Coastguard Worker    unsigned int mErrorLine    = 0;
160*8975f5c5SAndroid Build Coastguard Worker};
161*8975f5c5SAndroid Build Coastguard Worker
162*8975f5c5SAndroid Build Coastguard Workerclass ProgramMtl::LoadTaskMtl final : public LinkTask
163*8975f5c5SAndroid Build Coastguard Worker{
164*8975f5c5SAndroid Build Coastguard Worker  public:
165*8975f5c5SAndroid Build Coastguard Worker    LoadTaskMtl(std::vector<std::shared_ptr<LinkSubTask>> &&subTasks)
166*8975f5c5SAndroid Build Coastguard Worker        : mSubTasks(std::move(subTasks))
167*8975f5c5SAndroid Build Coastguard Worker    {}
168*8975f5c5SAndroid Build Coastguard Worker    ~LoadTaskMtl() override = default;
169*8975f5c5SAndroid Build Coastguard Worker
170*8975f5c5SAndroid Build Coastguard Worker    void load(std::vector<std::shared_ptr<LinkSubTask>> *linkSubTasksOut,
171*8975f5c5SAndroid Build Coastguard Worker              std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut) override
172*8975f5c5SAndroid Build Coastguard Worker    {
173*8975f5c5SAndroid Build Coastguard Worker        ASSERT(linkSubTasksOut && linkSubTasksOut->empty());
174*8975f5c5SAndroid Build Coastguard Worker        ASSERT(postLinkSubTasksOut && postLinkSubTasksOut->empty());
175*8975f5c5SAndroid Build Coastguard Worker
176*8975f5c5SAndroid Build Coastguard Worker        *linkSubTasksOut = mSubTasks;
177*8975f5c5SAndroid Build Coastguard Worker        return;
178*8975f5c5SAndroid Build Coastguard Worker    }
179*8975f5c5SAndroid Build Coastguard Worker
180*8975f5c5SAndroid Build Coastguard Worker    angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override
181*8975f5c5SAndroid Build Coastguard Worker    {
182*8975f5c5SAndroid Build Coastguard Worker        return angle::Result::Continue;
183*8975f5c5SAndroid Build Coastguard Worker    }
184*8975f5c5SAndroid Build Coastguard Worker
185*8975f5c5SAndroid Build Coastguard Worker  private:
186*8975f5c5SAndroid Build Coastguard Worker    std::vector<std::shared_ptr<LinkSubTask>> mSubTasks;
187*8975f5c5SAndroid Build Coastguard Worker};
188*8975f5c5SAndroid Build Coastguard Worker
189*8975f5c5SAndroid Build Coastguard Worker// ProgramArgumentBufferEncoderMtl implementation
190*8975f5c5SAndroid Build Coastguard Workervoid ProgramArgumentBufferEncoderMtl::reset(ContextMtl *contextMtl)
191*8975f5c5SAndroid Build Coastguard Worker{
192*8975f5c5SAndroid Build Coastguard Worker    metalArgBufferEncoder = nil;
193*8975f5c5SAndroid Build Coastguard Worker    bufferPool.destroy(contextMtl);
194*8975f5c5SAndroid Build Coastguard Worker}
195*8975f5c5SAndroid Build Coastguard Worker
196*8975f5c5SAndroid Build Coastguard Worker// ProgramShaderObjVariantMtl implementation
197*8975f5c5SAndroid Build Coastguard Workervoid ProgramShaderObjVariantMtl::reset(ContextMtl *contextMtl)
198*8975f5c5SAndroid Build Coastguard Worker{
199*8975f5c5SAndroid Build Coastguard Worker    metalShader = nil;
200*8975f5c5SAndroid Build Coastguard Worker
201*8975f5c5SAndroid Build Coastguard Worker    uboArgBufferEncoder.reset(contextMtl);
202*8975f5c5SAndroid Build Coastguard Worker
203*8975f5c5SAndroid Build Coastguard Worker    translatedSrcInfo = nullptr;
204*8975f5c5SAndroid Build Coastguard Worker}
205*8975f5c5SAndroid Build Coastguard Worker
206*8975f5c5SAndroid Build Coastguard Worker// ProgramMtl implementation
207*8975f5c5SAndroid Build Coastguard WorkerProgramMtl::ProgramMtl(const gl::ProgramState &state) : ProgramImpl(state) {}
208*8975f5c5SAndroid Build Coastguard Worker
209*8975f5c5SAndroid Build Coastguard WorkerProgramMtl::~ProgramMtl() = default;
210*8975f5c5SAndroid Build Coastguard Worker
211*8975f5c5SAndroid Build Coastguard Workervoid ProgramMtl::destroy(const gl::Context *context)
212*8975f5c5SAndroid Build Coastguard Worker{
213*8975f5c5SAndroid Build Coastguard Worker    getExecutable()->reset(mtl::GetImpl(context));
214*8975f5c5SAndroid Build Coastguard Worker}
215*8975f5c5SAndroid Build Coastguard Worker
216*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramMtl::load(const gl::Context *context,
217*8975f5c5SAndroid Build Coastguard Worker                               gl::BinaryInputStream *stream,
218*8975f5c5SAndroid Build Coastguard Worker                               std::shared_ptr<LinkTask> *loadTaskOut,
219*8975f5c5SAndroid Build Coastguard Worker                               egl::CacheGetResult *resultOut)
220*8975f5c5SAndroid Build Coastguard Worker{
221*8975f5c5SAndroid Build Coastguard Worker
222*8975f5c5SAndroid Build Coastguard Worker    ContextMtl *contextMtl = mtl::GetImpl(context);
223*8975f5c5SAndroid Build Coastguard Worker    // NOTE(hqle): No transform feedbacks for now, since we only support ES 2.0 atm
224*8975f5c5SAndroid Build Coastguard Worker
225*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(getExecutable()->load(contextMtl, stream));
226*8975f5c5SAndroid Build Coastguard Worker
227*8975f5c5SAndroid Build Coastguard Worker    // TODO: parallelize the above too.  http://anglebug.com/41488637
228*8975f5c5SAndroid Build Coastguard Worker    std::vector<std::shared_ptr<LinkSubTask>> subTasks;
229*8975f5c5SAndroid Build Coastguard Worker
230*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(compileMslShaderLibs(contextMtl, &subTasks));
231*8975f5c5SAndroid Build Coastguard Worker
232*8975f5c5SAndroid Build Coastguard Worker    *loadTaskOut = std::shared_ptr<LinkTask>(new LoadTaskMtl(std::move(subTasks)));
233*8975f5c5SAndroid Build Coastguard Worker    *resultOut   = egl::CacheGetResult::Success;
234*8975f5c5SAndroid Build Coastguard Worker
235*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
236*8975f5c5SAndroid Build Coastguard Worker}
237*8975f5c5SAndroid Build Coastguard Worker
238*8975f5c5SAndroid Build Coastguard Workervoid ProgramMtl::save(const gl::Context *context, gl::BinaryOutputStream *stream)
239*8975f5c5SAndroid Build Coastguard Worker{
240*8975f5c5SAndroid Build Coastguard Worker    getExecutable()->save(stream);
241*8975f5c5SAndroid Build Coastguard Worker}
242*8975f5c5SAndroid Build Coastguard Worker
243*8975f5c5SAndroid Build Coastguard Workervoid ProgramMtl::setBinaryRetrievableHint(bool retrievable) {}
244*8975f5c5SAndroid Build Coastguard Worker
245*8975f5c5SAndroid Build Coastguard Workervoid ProgramMtl::setSeparable(bool separable)
246*8975f5c5SAndroid Build Coastguard Worker{
247*8975f5c5SAndroid Build Coastguard Worker    UNIMPLEMENTED();
248*8975f5c5SAndroid Build Coastguard Worker}
249*8975f5c5SAndroid Build Coastguard Worker
250*8975f5c5SAndroid Build Coastguard Workervoid ProgramMtl::prepareForLink(const gl::ShaderMap<ShaderImpl *> &shaders)
251*8975f5c5SAndroid Build Coastguard Worker{
252*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::AllShaderTypes())
253*8975f5c5SAndroid Build Coastguard Worker    {
254*8975f5c5SAndroid Build Coastguard Worker        mAttachedShaders[shaderType].reset();
255*8975f5c5SAndroid Build Coastguard Worker
256*8975f5c5SAndroid Build Coastguard Worker        if (shaders[shaderType] != nullptr)
257*8975f5c5SAndroid Build Coastguard Worker        {
258*8975f5c5SAndroid Build Coastguard Worker            const ShaderMtl *shaderMtl   = GetAs<ShaderMtl>(shaders[shaderType]);
259*8975f5c5SAndroid Build Coastguard Worker            mAttachedShaders[shaderType] = shaderMtl->getCompiledState();
260*8975f5c5SAndroid Build Coastguard Worker        }
261*8975f5c5SAndroid Build Coastguard Worker    }
262*8975f5c5SAndroid Build Coastguard Worker}
263*8975f5c5SAndroid Build Coastguard Worker
264*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramMtl::link(const gl::Context *context, std::shared_ptr<LinkTask> *linkTaskOut)
265*8975f5c5SAndroid Build Coastguard Worker{
266*8975f5c5SAndroid Build Coastguard Worker    DisplayMtl *displayMtl = mtl::GetImpl(context)->getDisplay();
267*8975f5c5SAndroid Build Coastguard Worker
268*8975f5c5SAndroid Build Coastguard Worker    *linkTaskOut = std::shared_ptr<LinkTask>(new LinkTaskMtl(displayMtl, this));
269*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
270*8975f5c5SAndroid Build Coastguard Worker}
271*8975f5c5SAndroid Build Coastguard Worker
272*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramMtl::linkJobImpl(mtl::Context *context,
273*8975f5c5SAndroid Build Coastguard Worker                                      const gl::ProgramLinkedResources &resources,
274*8975f5c5SAndroid Build Coastguard Worker                                      std::vector<std::shared_ptr<LinkSubTask>> *subTasksOut)
275*8975f5c5SAndroid Build Coastguard Worker{
276*8975f5c5SAndroid Build Coastguard Worker    ProgramExecutableMtl *executableMtl = getExecutable();
277*8975f5c5SAndroid Build Coastguard Worker
278*8975f5c5SAndroid Build Coastguard Worker    // Link resources before calling GetShaderSource to make sure they are ready for the set/binding
279*8975f5c5SAndroid Build Coastguard Worker    // assignment done in that function.
280*8975f5c5SAndroid Build Coastguard Worker    linkResources(resources);
281*8975f5c5SAndroid Build Coastguard Worker
282*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(executableMtl->initDefaultUniformBlocks(context, mState.getAttachedShaders()));
283*8975f5c5SAndroid Build Coastguard Worker    executableMtl->linkUpdateHasFlatAttributes(mState.getAttachedShader(gl::ShaderType::Vertex));
284*8975f5c5SAndroid Build Coastguard Worker
285*8975f5c5SAndroid Build Coastguard Worker    gl::ShaderMap<std::string> shaderSources;
286*8975f5c5SAndroid Build Coastguard Worker    mtl::MSLGetShaderSource(mState, resources, &shaderSources);
287*8975f5c5SAndroid Build Coastguard Worker
288*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(mtl::MTLGetMSL(context->getDisplay()->getFeatures(), mState.getExecutable(),
289*8975f5c5SAndroid Build Coastguard Worker                             shaderSources, mAttachedShaders,
290*8975f5c5SAndroid Build Coastguard Worker                             &executableMtl->mMslShaderTranslateInfo));
291*8975f5c5SAndroid Build Coastguard Worker    executableMtl->mMslXfbOnlyVertexShaderInfo =
292*8975f5c5SAndroid Build Coastguard Worker        executableMtl->mMslShaderTranslateInfo[gl::ShaderType::Vertex];
293*8975f5c5SAndroid Build Coastguard Worker
294*8975f5c5SAndroid Build Coastguard Worker    return compileMslShaderLibs(context, subTasksOut);
295*8975f5c5SAndroid Build Coastguard Worker}
296*8975f5c5SAndroid Build Coastguard Worker
297*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramMtl::compileMslShaderLibs(
298*8975f5c5SAndroid Build Coastguard Worker    mtl::Context *context,
299*8975f5c5SAndroid Build Coastguard Worker    std::vector<std::shared_ptr<LinkSubTask>> *subTasksOut)
300*8975f5c5SAndroid Build Coastguard Worker{
301*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRACE_EVENT0("gpu.angle", "ProgramMtl::compileMslShaderLibs");
302*8975f5c5SAndroid Build Coastguard Worker    gl::InfoLog &infoLog = mState.getExecutable().getInfoLog();
303*8975f5c5SAndroid Build Coastguard Worker
304*8975f5c5SAndroid Build Coastguard Worker    DisplayMtl *displayMtl              = context->getDisplay();
305*8975f5c5SAndroid Build Coastguard Worker    ProgramExecutableMtl *executableMtl = getExecutable();
306*8975f5c5SAndroid Build Coastguard Worker    bool asyncCompile = displayMtl->getFeatures().enableParallelMtlLibraryCompilation.enabled;
307*8975f5c5SAndroid Build Coastguard Worker    mtl::LibraryCache &libraryCache = displayMtl->getLibraryCache();
308*8975f5c5SAndroid Build Coastguard Worker
309*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
310*8975f5c5SAndroid Build Coastguard Worker    {
311*8975f5c5SAndroid Build Coastguard Worker        mtl::TranslatedShaderInfo *translateInfo =
312*8975f5c5SAndroid Build Coastguard Worker            &executableMtl->mMslShaderTranslateInfo[shaderType];
313*8975f5c5SAndroid Build Coastguard Worker        std::map<std::string, std::string> macros = GetDefaultSubstitutionDictionary();
314*8975f5c5SAndroid Build Coastguard Worker        const bool disableFastMath = displayMtl->getFeatures().intelDisableFastMath.enabled ||
315*8975f5c5SAndroid Build Coastguard Worker                                     translateInfo->hasIsnanOrIsinf;
316*8975f5c5SAndroid Build Coastguard Worker        const bool usesInvariance = translateInfo->hasInvariant;
317*8975f5c5SAndroid Build Coastguard Worker
318*8975f5c5SAndroid Build Coastguard Worker        // Check if the shader is already in the cache and use it instead of spawning a new thread
319*8975f5c5SAndroid Build Coastguard Worker        translateInfo->metalLibrary = libraryCache.get(translateInfo->metalShaderSource, macros,
320*8975f5c5SAndroid Build Coastguard Worker                                                       disableFastMath, usesInvariance);
321*8975f5c5SAndroid Build Coastguard Worker
322*8975f5c5SAndroid Build Coastguard Worker        if (!translateInfo->metalLibrary)
323*8975f5c5SAndroid Build Coastguard Worker        {
324*8975f5c5SAndroid Build Coastguard Worker            if (asyncCompile)
325*8975f5c5SAndroid Build Coastguard Worker            {
326*8975f5c5SAndroid Build Coastguard Worker                subTasksOut->emplace_back(new CompileMslTask(context, translateInfo, macros));
327*8975f5c5SAndroid Build Coastguard Worker            }
328*8975f5c5SAndroid Build Coastguard Worker            else
329*8975f5c5SAndroid Build Coastguard Worker            {
330*8975f5c5SAndroid Build Coastguard Worker                ANGLE_TRY(CreateMslShaderLib(context, infoLog, translateInfo, macros));
331*8975f5c5SAndroid Build Coastguard Worker            }
332*8975f5c5SAndroid Build Coastguard Worker        }
333*8975f5c5SAndroid Build Coastguard Worker    }
334*8975f5c5SAndroid Build Coastguard Worker
335*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
336*8975f5c5SAndroid Build Coastguard Worker}
337*8975f5c5SAndroid Build Coastguard Worker
338*8975f5c5SAndroid Build Coastguard Workervoid ProgramMtl::linkResources(const gl::ProgramLinkedResources &resources)
339*8975f5c5SAndroid Build Coastguard Worker{
340*8975f5c5SAndroid Build Coastguard Worker    Std140BlockLayoutEncoderFactory std140EncoderFactory;
341*8975f5c5SAndroid Build Coastguard Worker    gl::ProgramLinkedResourcesLinker linker(&std140EncoderFactory);
342*8975f5c5SAndroid Build Coastguard Worker
343*8975f5c5SAndroid Build Coastguard Worker    linker.linkResources(mState, resources);
344*8975f5c5SAndroid Build Coastguard Worker}
345*8975f5c5SAndroid Build Coastguard Worker
346*8975f5c5SAndroid Build Coastguard WorkerGLboolean ProgramMtl::validate(const gl::Caps &caps)
347*8975f5c5SAndroid Build Coastguard Worker{
348*8975f5c5SAndroid Build Coastguard Worker    // No-op. The spec is very vague about the behavior of validation.
349*8975f5c5SAndroid Build Coastguard Worker    return GL_TRUE;
350*8975f5c5SAndroid Build Coastguard Worker}
351*8975f5c5SAndroid Build Coastguard Worker
352*8975f5c5SAndroid Build Coastguard Worker}  // namespace rx
353