1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/sksl/SkSLThreadContext.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/sksl/DSLSymbols.h"
11cb93a386Sopenharmony_ci#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
12cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
13cb93a386Sopenharmony_ci#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
14cb93a386Sopenharmony_ci#include "src/sksl/SkSLCompiler.h"
15cb93a386Sopenharmony_ci#include "src/sksl/SkSLIntrinsicMap.h"
16cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLExternalFunction.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_cinamespace SkSL {
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ciThreadContext::ThreadContext(SkSL::Compiler* compiler, SkSL::ProgramKind kind,
21cb93a386Sopenharmony_ci        const SkSL::ProgramSettings& settings, SkSL::ParsedModule module, bool isModule)
22cb93a386Sopenharmony_ci    : fCompiler(compiler)
23cb93a386Sopenharmony_ci    , fOldErrorReporter(*fCompiler->fContext->fErrors)
24cb93a386Sopenharmony_ci    , fSettings(settings) {
25cb93a386Sopenharmony_ci    fOldModifiersPool = fCompiler->fContext->fModifiersPool;
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ci    fOldConfig = fCompiler->fContext->fConfig;
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci    if (!isModule) {
30cb93a386Sopenharmony_ci        if (compiler->context().fCaps.useNodePools() && settings.fDSLUseMemoryPool) {
31cb93a386Sopenharmony_ci            fPool = Pool::Create();
32cb93a386Sopenharmony_ci            fPool->attachToThread();
33cb93a386Sopenharmony_ci        }
34cb93a386Sopenharmony_ci        fModifiersPool = std::make_unique<SkSL::ModifiersPool>();
35cb93a386Sopenharmony_ci        fCompiler->fContext->fModifiersPool = fModifiersPool.get();
36cb93a386Sopenharmony_ci    }
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ci    fConfig = std::make_unique<SkSL::ProgramConfig>();
39cb93a386Sopenharmony_ci    fConfig->fKind = kind;
40cb93a386Sopenharmony_ci    fConfig->fSettings = settings;
41cb93a386Sopenharmony_ci    fConfig->fIsBuiltinCode = isModule;
42cb93a386Sopenharmony_ci    fCompiler->fContext->fConfig = fConfig.get();
43cb93a386Sopenharmony_ci    fCompiler->fContext->fErrors = &fDefaultErrorReporter;
44cb93a386Sopenharmony_ci    fCompiler->fContext->fIntrinsics = module.fIntrinsics.get();
45cb93a386Sopenharmony_ci    if (fCompiler->fContext->fIntrinsics) {
46cb93a386Sopenharmony_ci        fCompiler->fContext->fIntrinsics->resetAlreadyIncluded();
47cb93a386Sopenharmony_ci    }
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    fCompiler->fSymbolTable = module.fSymbols;
50cb93a386Sopenharmony_ci    this->setupSymbolTable();
51cb93a386Sopenharmony_ci}
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ciThreadContext::~ThreadContext() {
54cb93a386Sopenharmony_ci    if (SymbolTable()) {
55cb93a386Sopenharmony_ci        fCompiler->fSymbolTable = nullptr;
56cb93a386Sopenharmony_ci        fProgramElements.clear();
57cb93a386Sopenharmony_ci    } else {
58cb93a386Sopenharmony_ci        // We should only be here with a null symbol table if ReleaseProgram was called
59cb93a386Sopenharmony_ci        SkASSERT(fProgramElements.empty());
60cb93a386Sopenharmony_ci    }
61cb93a386Sopenharmony_ci    fCompiler->fContext->fErrors = &fOldErrorReporter;
62cb93a386Sopenharmony_ci    fCompiler->fContext->fConfig = fOldConfig;
63cb93a386Sopenharmony_ci    fCompiler->fContext->fModifiersPool = fOldModifiersPool;
64cb93a386Sopenharmony_ci    if (fPool) {
65cb93a386Sopenharmony_ci        fPool->detachFromThread();
66cb93a386Sopenharmony_ci    }
67cb93a386Sopenharmony_ci}
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_civoid ThreadContext::setupSymbolTable() {
70cb93a386Sopenharmony_ci    SkSL::Context& context = *fCompiler->fContext;
71cb93a386Sopenharmony_ci    SymbolTable::Push(&fCompiler->fSymbolTable, context.fConfig->fIsBuiltinCode);
72cb93a386Sopenharmony_ci    SkSL::SymbolTable& symbols = *fCompiler->fSymbolTable;
73cb93a386Sopenharmony_ci
74cb93a386Sopenharmony_ci    if (fSettings.fExternalFunctions) {
75cb93a386Sopenharmony_ci        // Add any external values to the new symbol table, so they're only visible to this Program.
76cb93a386Sopenharmony_ci        for (const std::unique_ptr<ExternalFunction>& ef : *fSettings.fExternalFunctions) {
77cb93a386Sopenharmony_ci            symbols.addWithoutOwnership(ef.get());
78cb93a386Sopenharmony_ci        }
79cb93a386Sopenharmony_ci    }
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    bool runtimeEffect = ProgramConfig::IsRuntimeEffect(context.fConfig->fKind);
82cb93a386Sopenharmony_ci    if (runtimeEffect && !context.fConfig->fSettings.fEnforceES2Restrictions) {
83cb93a386Sopenharmony_ci        // We're compiling a runtime effect, but we're not enforcing ES2 restrictions. Add various
84cb93a386Sopenharmony_ci        // non-ES2 types to our symbol table to allow them to be tested.
85cb93a386Sopenharmony_ci        symbols.addAlias("mat2x2", context.fTypes.fFloat2x2.get());
86cb93a386Sopenharmony_ci        symbols.addAlias("mat2x3", context.fTypes.fFloat2x3.get());
87cb93a386Sopenharmony_ci        symbols.addAlias("mat2x4", context.fTypes.fFloat2x4.get());
88cb93a386Sopenharmony_ci        symbols.addAlias("mat3x2", context.fTypes.fFloat3x2.get());
89cb93a386Sopenharmony_ci        symbols.addAlias("mat3x3", context.fTypes.fFloat3x3.get());
90cb93a386Sopenharmony_ci        symbols.addAlias("mat3x4", context.fTypes.fFloat3x4.get());
91cb93a386Sopenharmony_ci        symbols.addAlias("mat4x2", context.fTypes.fFloat4x2.get());
92cb93a386Sopenharmony_ci        symbols.addAlias("mat4x3", context.fTypes.fFloat4x3.get());
93cb93a386Sopenharmony_ci        symbols.addAlias("mat4x4", context.fTypes.fFloat4x4.get());
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci        symbols.addAlias("float2x3", context.fTypes.fFloat2x3.get());
96cb93a386Sopenharmony_ci        symbols.addAlias("float2x4", context.fTypes.fFloat2x4.get());
97cb93a386Sopenharmony_ci        symbols.addAlias("float3x2", context.fTypes.fFloat3x2.get());
98cb93a386Sopenharmony_ci        symbols.addAlias("float3x4", context.fTypes.fFloat3x4.get());
99cb93a386Sopenharmony_ci        symbols.addAlias("float4x2", context.fTypes.fFloat4x2.get());
100cb93a386Sopenharmony_ci        symbols.addAlias("float4x3", context.fTypes.fFloat4x3.get());
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci        symbols.addAlias("half2x3", context.fTypes.fHalf2x3.get());
103cb93a386Sopenharmony_ci        symbols.addAlias("half2x4", context.fTypes.fHalf2x4.get());
104cb93a386Sopenharmony_ci        symbols.addAlias("half3x2", context.fTypes.fHalf3x2.get());
105cb93a386Sopenharmony_ci        symbols.addAlias("half3x4", context.fTypes.fHalf3x4.get());
106cb93a386Sopenharmony_ci        symbols.addAlias("half4x2", context.fTypes.fHalf4x2.get());
107cb93a386Sopenharmony_ci        symbols.addAlias("half4x3", context.fTypes.fHalf4x3.get());
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci        symbols.addAlias("uint", context.fTypes.fUInt.get());
110cb93a386Sopenharmony_ci        symbols.addAlias("uint2", context.fTypes.fUInt2.get());
111cb93a386Sopenharmony_ci        symbols.addAlias("uint3", context.fTypes.fUInt3.get());
112cb93a386Sopenharmony_ci        symbols.addAlias("uint4", context.fTypes.fUInt4.get());
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci        symbols.addAlias("short", context.fTypes.fShort.get());
115cb93a386Sopenharmony_ci        symbols.addAlias("short2", context.fTypes.fShort2.get());
116cb93a386Sopenharmony_ci        symbols.addAlias("short3", context.fTypes.fShort3.get());
117cb93a386Sopenharmony_ci        symbols.addAlias("short4", context.fTypes.fShort4.get());
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_ci        symbols.addAlias("ushort", context.fTypes.fUShort.get());
120cb93a386Sopenharmony_ci        symbols.addAlias("ushort2", context.fTypes.fUShort2.get());
121cb93a386Sopenharmony_ci        symbols.addAlias("ushort3", context.fTypes.fUShort3.get());
122cb93a386Sopenharmony_ci        symbols.addAlias("ushort4", context.fTypes.fUShort4.get());
123cb93a386Sopenharmony_ci    }
124cb93a386Sopenharmony_ci}
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ciSkSL::Context& ThreadContext::Context() {
127cb93a386Sopenharmony_ci    return Compiler().context();
128cb93a386Sopenharmony_ci}
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ciSkSL::ProgramSettings& ThreadContext::Settings() {
131cb93a386Sopenharmony_ci    return Context().fConfig->fSettings;
132cb93a386Sopenharmony_ci}
133cb93a386Sopenharmony_ci
134cb93a386Sopenharmony_cistd::shared_ptr<SkSL::SymbolTable>& ThreadContext::SymbolTable() {
135cb93a386Sopenharmony_ci    return Compiler().fSymbolTable;
136cb93a386Sopenharmony_ci}
137cb93a386Sopenharmony_ci
138cb93a386Sopenharmony_ciconst SkSL::Modifiers* ThreadContext::Modifiers(const SkSL::Modifiers& modifiers) {
139cb93a386Sopenharmony_ci    return Context().fModifiersPool->add(modifiers);
140cb93a386Sopenharmony_ci}
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ciThreadContext::RTAdjustData& ThreadContext::RTAdjustState() {
143cb93a386Sopenharmony_ci    return Instance().fRTAdjust;
144cb93a386Sopenharmony_ci}
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
147cb93a386Sopenharmony_civoid ThreadContext::StartFragmentProcessor(GrFragmentProcessor::ProgramImpl* processor,
148cb93a386Sopenharmony_ci        GrFragmentProcessor::ProgramImpl::EmitArgs* emitArgs) {
149cb93a386Sopenharmony_ci    ThreadContext& instance = ThreadContext::Instance();
150cb93a386Sopenharmony_ci    instance.fStack.push({processor, emitArgs, StatementArray{}});
151cb93a386Sopenharmony_ci    CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
152cb93a386Sopenharmony_ci    dsl::PushSymbolTable();
153cb93a386Sopenharmony_ci}
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_civoid ThreadContext::EndFragmentProcessor() {
156cb93a386Sopenharmony_ci    ThreadContext& instance = Instance();
157cb93a386Sopenharmony_ci    SkASSERT(!instance.fStack.empty());
158cb93a386Sopenharmony_ci    CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
159cb93a386Sopenharmony_ci    instance.fStack.pop();
160cb93a386Sopenharmony_ci    dsl::PopSymbolTable();
161cb93a386Sopenharmony_ci}
162cb93a386Sopenharmony_ci#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_civoid ThreadContext::SetErrorReporter(ErrorReporter* errorReporter) {
165cb93a386Sopenharmony_ci    SkASSERT(errorReporter);
166cb93a386Sopenharmony_ci    Context().fErrors = errorReporter;
167cb93a386Sopenharmony_ci}
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_civoid ThreadContext::ReportError(skstd::string_view msg, PositionInfo info) {
170cb93a386Sopenharmony_ci    GetErrorReporter().error(msg, info);
171cb93a386Sopenharmony_ci}
172cb93a386Sopenharmony_ci
173cb93a386Sopenharmony_civoid ThreadContext::DefaultErrorReporter::handleError(skstd::string_view msg, PositionInfo pos) {
174cb93a386Sopenharmony_ci    if (pos.line() > -1) {
175cb93a386Sopenharmony_ci        SK_ABORT("error: %s: %d: %.*sNo SkSL error reporter configured, treating this as a fatal "
176cb93a386Sopenharmony_ci                 "error\n", pos.file_name(), pos.line(), (int)msg.length(), msg.data());
177cb93a386Sopenharmony_ci    } else {
178cb93a386Sopenharmony_ci        SK_ABORT("error: %.*s\nNo SkSL error reporter configured, treating this as a fatal error\n",
179cb93a386Sopenharmony_ci                 (int)msg.length(), msg.data());
180cb93a386Sopenharmony_ci    }
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_ci}
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_civoid ThreadContext::ReportErrors(PositionInfo pos) {
185cb93a386Sopenharmony_ci    GetErrorReporter().reportPendingErrors(pos);
186cb93a386Sopenharmony_ci}
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_cithread_local ThreadContext* instance = nullptr;
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_cibool ThreadContext::IsActive() {
191cb93a386Sopenharmony_ci    return instance != nullptr;
192cb93a386Sopenharmony_ci}
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ciThreadContext& ThreadContext::Instance() {
195cb93a386Sopenharmony_ci    SkASSERTF(instance, "dsl::Start() has not been called");
196cb93a386Sopenharmony_ci    return *instance;
197cb93a386Sopenharmony_ci}
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_civoid ThreadContext::SetInstance(std::unique_ptr<ThreadContext> newInstance) {
200cb93a386Sopenharmony_ci    SkASSERT((instance == nullptr) != (newInstance == nullptr));
201cb93a386Sopenharmony_ci    delete instance;
202cb93a386Sopenharmony_ci    instance = newInstance.release();
203cb93a386Sopenharmony_ci}
204cb93a386Sopenharmony_ci
205cb93a386Sopenharmony_ci} // namespace SkSL
206