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