blob: 5fe3023618c4e03669f414d5bc503b8812d71224 [file] [log] [blame]
Ethan Nicholasc8452722021-10-07 10:47:32 -04001/*
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/SkSLIRGenerator.h"
16#include "src/sksl/SkSLIntrinsicMap.h"
17
18namespace SkSL {
19
20ThreadContext::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->fIRGenerator->start(module, &fProgramElements, &fSharedElements);
50}
51
52ThreadContext::~ThreadContext() {
53 if (SymbolTable()) {
54 fCompiler->fIRGenerator->finish();
55 fProgramElements.clear();
56 } else {
57 // We should only be here with a null symbol table if ReleaseProgram was called
58 SkASSERT(fProgramElements.empty());
59 }
60 fCompiler->fContext->fErrors = &fOldErrorReporter;
61 fCompiler->fContext->fConfig = fOldConfig;
62 fCompiler->fContext->fModifiersPool = fOldModifiersPool;
63 if (fPool) {
64 fPool->detachFromThread();
65 }
66}
67
68
69SkSL::IRGenerator& ThreadContext::IRGenerator() {
70 return *Compiler().fIRGenerator;
71}
72
73SkSL::Context& ThreadContext::Context() {
74 return Compiler().context();
75}
76
77SkSL::ProgramSettings& ThreadContext::Settings() {
78 return Context().fConfig->fSettings;
79}
80
81SkSL::Program::Inputs& ThreadContext::Inputs() {
82 return IRGenerator().fInputs;
83}
84
85const std::shared_ptr<SkSL::SymbolTable>& ThreadContext::SymbolTable() {
86 return IRGenerator().fSymbolTable;
87}
88
89const SkSL::Modifiers* ThreadContext::Modifiers(const SkSL::Modifiers& modifiers) {
90 return Context().fModifiersPool->add(modifiers);
91}
92
93#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
94void ThreadContext::StartFragmentProcessor(GrFragmentProcessor::ProgramImpl* processor,
95 GrFragmentProcessor::ProgramImpl::EmitArgs* emitArgs) {
96 ThreadContext& instance = ThreadContext::Instance();
97 instance.fStack.push({processor, emitArgs, StatementArray{}});
98 CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
99 dsl::PushSymbolTable();
100}
101
102void ThreadContext::EndFragmentProcessor() {
103 ThreadContext& instance = Instance();
104 SkASSERT(!instance.fStack.empty());
105 CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
106 instance.fStack.pop();
107 dsl::PopSymbolTable();
108}
109#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
110
111void ThreadContext::SetErrorReporter(ErrorReporter* errorReporter) {
112 SkASSERT(errorReporter);
113 Context().fErrors = errorReporter;
114}
115
116void ThreadContext::ReportError(skstd::string_view msg, PositionInfo info) {
117 GetErrorReporter().error(msg, info);
118}
119
120void ThreadContext::DefaultErrorReporter::handleError(skstd::string_view msg, PositionInfo pos) {
121 if (pos.line() > -1) {
122 SK_ABORT("error: %s: %d: %.*sNo SkSL error reporter configured, treating this as a fatal "
123 "error\n", pos.file_name(), pos.line(), (int)msg.length(), msg.data());
124 } else {
125 SK_ABORT("error: %.*s\nNo SkSL error reporter configured, treating this as a fatal error\n",
126 (int)msg.length(), msg.data());
127 }
128
129}
130
131void ThreadContext::ReportErrors(PositionInfo pos) {
132 GetErrorReporter().reportPendingErrors(pos);
133}
134
135thread_local ThreadContext* instance = nullptr;
136
137bool ThreadContext::IsActive() {
138 return instance != nullptr;
139}
140
141ThreadContext& ThreadContext::Instance() {
142 SkASSERTF(instance, "dsl::Start() has not been called");
143 return *instance;
144}
145
146void ThreadContext::SetInstance(std::unique_ptr<ThreadContext> newInstance) {
147 SkASSERT((instance == nullptr) != (newInstance == nullptr));
148 delete instance;
149 instance = newInstance.release();
150}
151
152} // namespace SkSL