Broke DSLWriter into two separate classes

As DSLWriter evolved, it ended up performing two unrelated duties:

1. Holding per-thread state which is referenced throughout SkSL
   (including non-DSL code)
2. DSL-specific utility functions

There's no reason for those to be contained in the same class, and
there's also no reason the per-thread state should be held in a
DSL-specific class. This breaks out an SkSL::ThreadContext class to hold
the state info, leaving the DSL utility functions behind in DSLWriter
(which should perhaps be renamed, but that's a job for a future CL).

Change-Id: Iccd45314bd9b37d4a1d3e27920e32a50c0b07d7c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/456736
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
Ethan Nicholas 2021-10-07 10:47:32 -04:00 committed by SkCQ
parent 97bf72869a
commit c845272b4e
26 changed files with 720 additions and 663 deletions

View File

@ -75,6 +75,8 @@ skia_sksl_sources = [
"$_src/sksl/SkSLSampleUsage.cpp",
"$_src/sksl/SkSLString.cpp",
"$_src/sksl/SkSLStringStream.h",
"$_src/sksl/SkSLThreadContext.cpp",
"$_src/sksl/SkSLThreadContext.h",
"$_src/sksl/SkSLUtil.cpp",
"$_src/sksl/SkSLUtil.h",
"$_src/sksl/analysis/SkSLCanExitWithoutReturningValue.cpp",

View File

@ -14,7 +14,7 @@
#include "src/gpu/glsl/GrGLSLBlend.h"
#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
GrGLSLShaderBuilder::GrGLSLShaderBuilder(GrGLSLProgramBuilder* program)
@ -90,7 +90,7 @@ void GrGLSLShaderBuilder::emitFunctionPrototype(const char* declaration) {
}
void GrGLSLShaderBuilder::codeAppend(std::unique_ptr<SkSL::Statement> stmt) {
SkASSERT(SkSL::dsl::DSLWriter::CurrentProcessor());
SkASSERT(SkSL::ThreadContext::CurrentProcessor());
SkASSERT(stmt);
this->codeAppend(stmt->description().c_str());
if (stmt->is<SkSL::VarDeclaration>()) {

View File

@ -21,9 +21,7 @@
class GrGLSLColorSpaceXformHelper;
namespace SkSL {
namespace dsl {
class DSLWriter;
}
class ThreadContext;
}
/**
@ -290,6 +288,6 @@ protected:
friend class GrGLPathProgramBuilder; // to access fInputs.
friend class GrVkPipelineStateBuilder;
friend class GrMtlPipelineStateBuilder;
friend class SkSL::dsl::DSLWriter;
friend class SkSL::ThreadContext;
};
#endif

View File

@ -19,6 +19,7 @@
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/SkSLRehydrator.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/codegen/SkSLGLSLCodeGenerator.h"
#include "src/sksl/codegen/SkSLMetalCodeGenerator.h"
#include "src/sksl/codegen/SkSLSPIRVCodeGenerator.h"
@ -539,7 +540,7 @@ bool Compiler::toSPIRV(Program& program, OutputStream& out) {
settings.fDSLUseMemoryPool = false;
dsl::Start(this, program.fConfig->fKind, settings);
dsl::SetErrorReporter(&fErrorReporter);
dsl::DSLWriter::IRGenerator().fSymbolTable = program.fSymbols;
ThreadContext::IRGenerator().fSymbolTable = program.fSymbols;
#ifdef SK_ENABLE_SPIRV_VALIDATION
StringStream buffer;
SPIRVCodeGenerator cg(fContext.get(), &program, &buffer);

View File

@ -265,8 +265,8 @@ private:
friend class AutoSource;
friend class ::SkSLCompileBench;
friend class DSLParser;
friend class ThreadContext;
friend class dsl::DSLCore;
friend class dsl::DSLWriter;
};
} // namespace SkSL

View File

@ -9,6 +9,7 @@
#include "include/private/SkSLString.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/dsl/priv/DSL_priv.h"
@ -230,7 +231,7 @@ SkSL::LoadedModule DSLParser::moduleInheritingFrom(SkSL::ParsedModule baseModule
this->declarations();
CurrentSymbolTable()->takeOwnershipOfString(std::move(*fText));
SkSL::LoadedModule result{ fKind, CurrentSymbolTable(),
std::move(DSLWriter::ProgramElements()) };
std::move(ThreadContext::ProgramElements()) };
errorReporter->setSource(nullptr);
End();
return result;

View File

@ -157,6 +157,7 @@ private:
friend class AutoDisableInline;
friend class Compiler;
friend class DSLParser;
friend class ThreadContext;
friend class dsl::DSLCore;
friend class dsl::DSLExpression;
friend class dsl::DSLFunction;

View File

@ -0,0 +1,152 @@
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/sksl/SkSLThreadContext.h"
#include "include/sksl/DSLSymbols.h"
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLIntrinsicMap.h"
namespace SkSL {
ThreadContext::ThreadContext(SkSL::Compiler* compiler, SkSL::ProgramKind kind,
const SkSL::ProgramSettings& settings, SkSL::ParsedModule module, bool isModule)
: fCompiler(compiler)
, fOldErrorReporter(*fCompiler->fContext->fErrors)
, fSettings(settings) {
fOldModifiersPool = fCompiler->fContext->fModifiersPool;
fOldConfig = fCompiler->fContext->fConfig;
if (!isModule) {
if (compiler->context().fCaps.useNodePools() && settings.fDSLUseMemoryPool) {
fPool = Pool::Create();
fPool->attachToThread();
}
fModifiersPool = std::make_unique<SkSL::ModifiersPool>();
fCompiler->fContext->fModifiersPool = fModifiersPool.get();
}
fConfig = std::make_unique<SkSL::ProgramConfig>();
fConfig->fKind = kind;
fConfig->fSettings = settings;
fConfig->fIsBuiltinCode = isModule;
fCompiler->fContext->fConfig = fConfig.get();
fCompiler->fContext->fErrors = &fDefaultErrorReporter;
fCompiler->fContext->fIntrinsics = module.fIntrinsics.get();
if (fCompiler->fContext->fIntrinsics) {
fCompiler->fContext->fIntrinsics->resetAlreadyIncluded();
}
fCompiler->fIRGenerator->start(module, &fProgramElements, &fSharedElements);
}
ThreadContext::~ThreadContext() {
if (SymbolTable()) {
fCompiler->fIRGenerator->finish();
fProgramElements.clear();
} else {
// We should only be here with a null symbol table if ReleaseProgram was called
SkASSERT(fProgramElements.empty());
}
fCompiler->fContext->fErrors = &fOldErrorReporter;
fCompiler->fContext->fConfig = fOldConfig;
fCompiler->fContext->fModifiersPool = fOldModifiersPool;
if (fPool) {
fPool->detachFromThread();
}
}
SkSL::IRGenerator& ThreadContext::IRGenerator() {
return *Compiler().fIRGenerator;
}
SkSL::Context& ThreadContext::Context() {
return Compiler().context();
}
SkSL::ProgramSettings& ThreadContext::Settings() {
return Context().fConfig->fSettings;
}
SkSL::Program::Inputs& ThreadContext::Inputs() {
return IRGenerator().fInputs;
}
const std::shared_ptr<SkSL::SymbolTable>& ThreadContext::SymbolTable() {
return IRGenerator().fSymbolTable;
}
const SkSL::Modifiers* ThreadContext::Modifiers(const SkSL::Modifiers& modifiers) {
return Context().fModifiersPool->add(modifiers);
}
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
void ThreadContext::StartFragmentProcessor(GrFragmentProcessor::ProgramImpl* processor,
GrFragmentProcessor::ProgramImpl::EmitArgs* emitArgs) {
ThreadContext& instance = ThreadContext::Instance();
instance.fStack.push({processor, emitArgs, StatementArray{}});
CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
dsl::PushSymbolTable();
}
void ThreadContext::EndFragmentProcessor() {
ThreadContext& instance = Instance();
SkASSERT(!instance.fStack.empty());
CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
instance.fStack.pop();
dsl::PopSymbolTable();
}
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
void ThreadContext::SetErrorReporter(ErrorReporter* errorReporter) {
SkASSERT(errorReporter);
Context().fErrors = errorReporter;
}
void ThreadContext::ReportError(skstd::string_view msg, PositionInfo info) {
GetErrorReporter().error(msg, info);
}
void ThreadContext::DefaultErrorReporter::handleError(skstd::string_view msg, PositionInfo pos) {
if (pos.line() > -1) {
SK_ABORT("error: %s: %d: %.*sNo SkSL error reporter configured, treating this as a fatal "
"error\n", pos.file_name(), pos.line(), (int)msg.length(), msg.data());
} else {
SK_ABORT("error: %.*s\nNo SkSL error reporter configured, treating this as a fatal error\n",
(int)msg.length(), msg.data());
}
}
void ThreadContext::ReportErrors(PositionInfo pos) {
GetErrorReporter().reportPendingErrors(pos);
}
thread_local ThreadContext* instance = nullptr;
bool ThreadContext::IsActive() {
return instance != nullptr;
}
ThreadContext& ThreadContext::Instance() {
SkASSERTF(instance, "dsl::Start() has not been called");
return *instance;
}
void ThreadContext::SetInstance(std::unique_ptr<ThreadContext> newInstance) {
SkASSERT((instance == nullptr) != (newInstance == nullptr));
delete instance;
instance = newInstance.release();
}
} // namespace SkSL

View File

@ -0,0 +1,213 @@
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_THREADCONTEXT
#define SKSL_THREADCONTEXT
#include "include/core/SkStringView.h"
#include "include/private/SkSLModifiers.h"
#include "src/sksl/SkSLMangler.h"
#include "src/sksl/ir/SkSLProgram.h"
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include "src/gpu/GrFragmentProcessor.h"
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include <list>
#include <stack>
namespace SkSL {
class Compiler;
class Context;
class IRGenerator;
struct ParsedModule;
class ProgramElement;
class SymbolTable;
class Type;
class Variable;
namespace dsl {
class DSLCore;
class DSLWriter;
} // namespace dsl
/**
* Thread-safe class that tracks per-thread state associated with SkSL output.
*/
class ThreadContext {
public:
ThreadContext(SkSL::Compiler* compiler, SkSL::ProgramKind kind,
const SkSL::ProgramSettings& settings, SkSL::ParsedModule module, bool isModule);
~ThreadContext();
/**
* Returns true if the DSL has been started.
*/
static bool IsActive();
/**
* Returns the Compiler used by DSL operations in the current thread.
*/
static SkSL::Compiler& Compiler() { return *Instance().fCompiler; }
/**
* Returns the IRGenerator used by DSL operations in the current thread.
*/
static SkSL::IRGenerator& IRGenerator();
/**
* Returns the Context used by DSL operations in the current thread.
*/
static SkSL::Context& Context();
/**
* Returns the Settings used by DSL operations in the current thread.
*/
static SkSL::ProgramSettings& Settings();
/**
* Returns the Program::Inputs used by the current thread.
*/
static SkSL::Program::Inputs& Inputs();
/**
* Returns the collection to which DSL program elements in this thread should be appended.
*/
static std::vector<std::unique_ptr<SkSL::ProgramElement>>& ProgramElements() {
return Instance().fProgramElements;
}
static std::vector<const ProgramElement*>& SharedElements() {
return Instance().fSharedElements;
}
/**
* Returns the SymbolTable of the current thread's IRGenerator.
*/
static const std::shared_ptr<SkSL::SymbolTable>& SymbolTable();
/**
* Returns the current memory pool.
*/
static std::unique_ptr<Pool>& MemoryPool() { return Instance().fPool; }
/**
* Returns the current modifiers pool.
*/
static std::unique_ptr<ModifiersPool>& GetModifiersPool() { return Instance().fModifiersPool; }
/**
* Returns the current ProgramConfig.
*/
static std::unique_ptr<ProgramConfig>& GetProgramConfig() { return Instance().fConfig; }
static bool IsModule() { return GetProgramConfig()->fIsBuiltinCode; }
/**
* Returns the final pointer to a pooled Modifiers object that should be used to represent the
* given modifiers.
*/
static const SkSL::Modifiers* Modifiers(const SkSL::Modifiers& modifiers);
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
/**
* Returns the fragment processor for which DSL output is being generated for the current
* thread.
*/
static GrFragmentProcessor::ProgramImpl* CurrentProcessor() {
SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
return Instance().fStack.top().fProcessor;
}
/**
* Returns the EmitArgs for fragment processor output in the current thread.
*/
static GrFragmentProcessor::ProgramImpl::EmitArgs* CurrentEmitArgs() {
SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
return Instance().fStack.top().fEmitArgs;
}
static bool InFragmentProcessor() {
return !Instance().fStack.empty();
}
/**
* Pushes a new processor / emitArgs pair for the current thread.
*/
static void StartFragmentProcessor(GrFragmentProcessor::ProgramImpl* processor,
GrFragmentProcessor::ProgramImpl::EmitArgs* emitArgs);
/**
* Pops the processor / emitArgs pair associated with the current thread.
*/
static void EndFragmentProcessor();
#else
static bool InFragmentProcessor() {
return false;
}
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
/**
* Returns the ErrorReporter associated with the current thread. This object will be notified
* when any DSL errors occur.
*/
static ErrorReporter& GetErrorReporter() {
return *Context().fErrors;
}
static void SetErrorReporter(ErrorReporter* errorReporter);
/**
* Notifies the current ErrorReporter that an error has occurred. The default error handler
* prints the message to stderr and aborts.
*/
static void ReportError(skstd::string_view msg, PositionInfo info = PositionInfo::Capture());
/**
* Forwards any pending errors to the DSL ErrorReporter.
*/
static void ReportErrors(PositionInfo pos);
static ThreadContext& Instance();
static void SetInstance(std::unique_ptr<ThreadContext> instance);
private:
class DefaultErrorReporter : public ErrorReporter {
void handleError(skstd::string_view msg, PositionInfo pos) override;
};
std::unique_ptr<SkSL::ProgramConfig> fConfig;
std::unique_ptr<SkSL::ModifiersPool> fModifiersPool;
SkSL::Compiler* fCompiler;
std::unique_ptr<Pool> fPool;
SkSL::ProgramConfig* fOldConfig;
SkSL::ModifiersPool* fOldModifiersPool;
std::vector<std::unique_ptr<SkSL::ProgramElement>> fProgramElements;
std::vector<const SkSL::ProgramElement*> fSharedElements;
DefaultErrorReporter fDefaultErrorReporter;
ErrorReporter& fOldErrorReporter;
ProgramSettings fSettings;
Mangler fMangler;
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
struct StackFrame {
GrFragmentProcessor::ProgramImpl* fProcessor;
GrFragmentProcessor::ProgramImpl::EmitArgs* fEmitArgs;
SkSL::StatementArray fSavedDeclarations;
};
std::stack<StackFrame, std::list<StackFrame>> fStack;
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
friend class dsl::DSLCore;
friend class dsl::DSLWriter;
};
} // namespace SkSL
#endif

View File

@ -12,7 +12,7 @@
#include "include/sksl/DSLCore.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/ir/SkSLBlock.h"
#include "src/sksl/ir/SkSLConstructorArrayCast.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
@ -1095,8 +1095,8 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIn
this->writeWord(fn, out);
this->addRTFlipUniform(c.fLine);
using namespace dsl;
DSLExpression rtFlip(DSLWriter::IRGenerator().convertIdentifier(/*line=*/-1,
SKSL_RTFLIP_NAME));
DSLExpression rtFlip(ThreadContext::IRGenerator().convertIdentifier(/*line=*/-1,
SKSL_RTFLIP_NAME));
SpvId rtFlipY = this->vectorize(*rtFlip.y().release(), callType.columns(), out);
SpvId flipped = this->nextId(&callType);
this->writeInstruction(SpvOpFMul, this->getType(callType), flipped, result, rtFlipY,
@ -2111,12 +2111,12 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
// Use sk_RTAdjust to compute the flipped coordinate
using namespace dsl;
const char* DEVICE_COORDS_NAME = "__device_FragCoords";
SymbolTable& symbols = *dsl::DSLWriter::SymbolTable();
SymbolTable& symbols = *ThreadContext::SymbolTable();
// Use a uniform to flip the Y coordinate. The new expression will be written in
// terms of __device_FragCoords, which is a fake variable that means "access the
// underlying fragcoords directly without flipping it".
DSLExpression rtFlip(DSLWriter::IRGenerator().convertIdentifier(/*line=*/-1,
SKSL_RTFLIP_NAME));
DSLExpression rtFlip(ThreadContext::IRGenerator().convertIdentifier(/*line=*/-1,
SKSL_RTFLIP_NAME));
if (!symbols[DEVICE_COORDS_NAME]) {
AutoAttachPoolToThread attach(fProgram.fPool.get());
Modifiers modifiers;
@ -2146,12 +2146,12 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
this->addRTFlipUniform(ref.fLine);
using namespace dsl;
const char* DEVICE_CLOCKWISE_NAME = "__device_Clockwise";
SymbolTable& symbols = *dsl::DSLWriter::SymbolTable();
SymbolTable& symbols = *ThreadContext::SymbolTable();
// Use a uniform to flip the Y coordinate. The new expression will be written in
// terms of __device_Clockwise, which is a fake variable that means "access the
// underlying FrontFacing directly".
DSLExpression rtFlip(DSLWriter::IRGenerator().convertIdentifier(/*line=*/-1,
SKSL_RTFLIP_NAME));
DSLExpression rtFlip(ThreadContext::IRGenerator().convertIdentifier(/*line=*/-1,
SKSL_RTFLIP_NAME));
if (!symbols[DEVICE_CLOCKWISE_NAME]) {
AutoAttachPoolToThread attach(fProgram.fPool.get());
Modifiers modifiers;

View File

@ -12,6 +12,7 @@
#include "include/sksl/DSLVar.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLBreakStatement.h"
#include "src/sksl/ir/SkSLContinueStatement.h"
@ -37,46 +38,45 @@ void Start(SkSL::Compiler* compiler, ProgramKind kind) {
}
void Start(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings) {
DSLWriter::SetInstance(std::make_unique<DSLWriter>(compiler, kind, settings,
compiler->moduleForProgramKind(kind),
/*isModule=*/false));
ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings,
compiler->moduleForProgramKind(kind), /*isModule=*/false));
}
void StartModule(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings,
SkSL::ParsedModule baseModule) {
DSLWriter::SetInstance(std::make_unique<DSLWriter>(compiler, kind, settings,
baseModule, /*isModule=*/true));
ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings,
baseModule, /*isModule=*/true));
}
void End() {
SkASSERTF(!DSLWriter::InFragmentProcessor(),
SkASSERTF(!ThreadContext::InFragmentProcessor(),
"more calls to StartFragmentProcessor than to EndFragmentProcessor");
DSLWriter::SetInstance(nullptr);
ThreadContext::SetInstance(nullptr);
}
ErrorReporter& GetErrorReporter() {
return DSLWriter::GetErrorReporter();
return ThreadContext::GetErrorReporter();
}
void SetErrorReporter(ErrorReporter* errorReporter) {
SkASSERT(errorReporter);
DSLWriter::SetErrorReporter(errorReporter);
ThreadContext::SetErrorReporter(errorReporter);
}
class DSLCore {
public:
static std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<String> source) {
DSLWriter& instance = DSLWriter::Instance();
SkSL::IRGenerator& ir = DSLWriter::IRGenerator();
SkSL::Compiler& compiler = DSLWriter::Compiler();
const SkSL::Context& context = DSLWriter::Context();
ThreadContext& instance = ThreadContext::Instance();
SkSL::IRGenerator& ir = ThreadContext::IRGenerator();
SkSL::Compiler& compiler = ThreadContext::Compiler();
const SkSL::Context& context = ThreadContext::Context();
// Variables defined in the pre-includes need their declaring elements added to the program
if (!context.fConfig->fIsBuiltinCode && context.fIntrinsics) {
Transform::FindAndDeclareBuiltinVariables(DSLWriter::Context(),
DSLWriter::GetProgramConfig()->fKind, DSLWriter::SharedElements());
Transform::FindAndDeclareBuiltinVariables(ThreadContext::Context(),
ThreadContext::GetProgramConfig()->fKind, ThreadContext::SharedElements());
}
IRGenerator::IRBundle bundle = ir.finish();
Pool* pool = DSLWriter::Instance().fPool.get();
Pool* pool = ThreadContext::Instance().fPool.get();
auto result = std::make_unique<SkSL::Program>(std::move(source),
std::move(instance.fConfig),
compiler.fContext,
@ -96,13 +96,13 @@ public:
success = true;
}
if (!success) {
DSLWriter::ReportErrors(PositionInfo());
ThreadContext::ReportErrors(PositionInfo());
}
if (pool) {
pool->detachFromThread();
}
SkASSERT(DSLWriter::ProgramElements().empty());
SkASSERT(!DSLWriter::SymbolTable());
SkASSERT(ThreadContext::ProgramElements().empty());
SkASSERT(!ThreadContext::SymbolTable());
return success ? std::move(result) : nullptr;
}
@ -128,8 +128,8 @@ public:
int unused[] = {0, (static_cast<void>(argArray.push_back(args.release())), 0)...};
static_cast<void>(unused);
return SkSL::FunctionCall::Convert(DSLWriter::Context(), /*line=*/-1,
DSLWriter::IRGenerator().convertIdentifier(-1, name), std::move(argArray));
return SkSL::FunctionCall::Convert(ThreadContext::Context(), /*line=*/-1,
ThreadContext::IRGenerator().convertIdentifier(-1, name), std::move(argArray));
}
static DSLStatement Break(PositionInfo pos) {
@ -141,13 +141,13 @@ public:
}
static void Declare(const DSLModifiers& modifiers) {
DSLWriter::ProgramElements().push_back(std::make_unique<SkSL::ModifiersDeclaration>(
DSLWriter::Modifiers(modifiers.fModifiers)));
ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::ModifiersDeclaration>(
ThreadContext::Modifiers(modifiers.fModifiers)));
}
static DSLStatement Declare(DSLVar& var, PositionInfo pos) {
if (var.fDeclared) {
DSLWriter::ReportError("variable has already been declared", pos);
ThreadContext::ReportError("variable has already been declared", pos);
}
var.fDeclared = true;
return DSLWriter::Declaration(var);
@ -163,20 +163,20 @@ public:
static void Declare(DSLGlobalVar& var, PositionInfo pos) {
if (var.fDeclared) {
DSLWriter::ReportError("variable has already been declared", pos);
ThreadContext::ReportError("variable has already been declared", pos);
}
var.fDeclared = true;
std::unique_ptr<SkSL::Statement> stmt = DSLWriter::Declaration(var);
if (stmt) {
if (!stmt->isEmpty()) {
DSLWriter::ProgramElements().push_back(std::make_unique<SkSL::GlobalVarDeclaration>(
std::move(stmt)));
ThreadContext::ProgramElements().push_back(
std::make_unique<SkSL::GlobalVarDeclaration>(std::move(stmt)));
}
} else if (var.fName == SkSL::Compiler::FRAGCOLOR_NAME) {
// sk_FragColor can end up with a null declaration despite no error occurring due to
// specific treatment in the compiler. Ignore the null and just grab the existing
// variable from the symbol table.
const SkSL::Symbol* alreadyDeclared = (*DSLWriter::SymbolTable())[var.fName];
const SkSL::Symbol* alreadyDeclared = (*ThreadContext::SymbolTable())[var.fName];
if (alreadyDeclared && alreadyDeclared->is<Variable>()) {
var.fVar = &alreadyDeclared->as<Variable>();
var.fInitialized = true;
@ -195,20 +195,20 @@ public:
}
static DSLPossibleStatement Do(DSLStatement stmt, DSLExpression test) {
return DoStatement::Convert(DSLWriter::Context(), stmt.release(), test.release());
return DoStatement::Convert(ThreadContext::Context(), stmt.release(), test.release());
}
static DSLPossibleStatement For(DSLStatement initializer, DSLExpression test,
DSLExpression next, DSLStatement stmt, PositionInfo pos) {
return ForStatement::Convert(DSLWriter::Context(), pos.line(),
return ForStatement::Convert(ThreadContext::Context(), pos.line(),
initializer.releaseIfPossible(), test.releaseIfPossible(),
next.releaseIfPossible(), stmt.release(),
DSLWriter::SymbolTable());
ThreadContext::SymbolTable());
}
static DSLPossibleStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse,
bool isStatic) {
return IfStatement::Convert(DSLWriter::Context(), /*line=*/-1, isStatic, test.release(),
return IfStatement::Convert(ThreadContext::Context(), /*line=*/-1, isStatic, test.release(),
ifTrue.release(), ifFalse.releaseIfPossible());
}
@ -225,34 +225,34 @@ public:
if (baseType->isArray()) {
baseType = &baseType->componentType();
}
DSLWriter::IRGenerator().checkVarDeclaration(pos.line(), field.fModifiers.fModifiers,
baseType, Variable::Storage::kInterfaceBlock);
ThreadContext::IRGenerator().checkVarDeclaration(pos.line(),
field.fModifiers.fModifiers, baseType, Variable::Storage::kInterfaceBlock);
GetErrorReporter().reportPendingErrors(field.fPosition);
skslFields.push_back(SkSL::Type::Field(field.fModifiers.fModifiers, field.fName,
&field.fType.skslType()));
}
const SkSL::Type* structType = DSLWriter::SymbolTable()->takeOwnershipOfSymbol(
const SkSL::Type* structType = ThreadContext::SymbolTable()->takeOwnershipOfSymbol(
SkSL::Type::MakeStructType(pos.line(), typeName, std::move(skslFields)));
DSLType varType = arraySize > 0 ? Array(structType, arraySize) : DSLType(structType);
DSLGlobalVar var(modifiers, varType, !varName.empty() ? varName : typeName, DSLExpression(),
pos);
// Interface blocks can't be declared, so we always need to mark the var declared ourselves.
// We do this only when fDSLMarkVarDeclared is false, so we don't double-declare it.
if (!DSLWriter::Settings().fDSLMarkVarsDeclared) {
if (!ThreadContext::Settings().fDSLMarkVarsDeclared) {
DSLWriter::MarkDeclared(var);
}
const SkSL::Variable* skslVar = DSLWriter::Var(var);
if (skslVar) {
auto intf = std::make_unique<SkSL::InterfaceBlock>(pos.line(),
*skslVar, typeName, varName, arraySize, DSLWriter::SymbolTable());
DSLWriter::IRGenerator().scanInterfaceBlock(*intf);
DSLWriter::ProgramElements().push_back(std::move(intf));
*skslVar, typeName, varName, arraySize, ThreadContext::SymbolTable());
ThreadContext::IRGenerator().scanInterfaceBlock(*intf);
ThreadContext::ProgramElements().push_back(std::move(intf));
if (varName.empty()) {
const std::vector<SkSL::Type::Field>& structFields = structType->fields();
for (size_t i = 0; i < structFields.size(); ++i) {
DSLWriter::SymbolTable()->add(std::make_unique<SkSL::Field>(pos.line(),
skslVar,
i));
ThreadContext::SymbolTable()->add(std::make_unique<SkSL::Field>(pos.line(),
skslVar,
i));
}
} else {
AddToSymbolTable(var);
@ -272,7 +272,7 @@ public:
static DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
PositionInfo pos) {
return DSLExpression(Swizzle::Convert(DSLWriter::Context(), base.release(),
return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
ComponentArray{a}),
pos);
}
@ -281,7 +281,7 @@ public:
SkSL::SwizzleComponent::Type a,
SkSL::SwizzleComponent::Type b,
PositionInfo pos) {
return DSLExpression(Swizzle::Convert(DSLWriter::Context(), base.release(),
return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
ComponentArray{a, b}),
pos);
}
@ -291,7 +291,7 @@ public:
SkSL::SwizzleComponent::Type b,
SkSL::SwizzleComponent::Type c,
PositionInfo pos) {
return DSLExpression(Swizzle::Convert(DSLWriter::Context(), base.release(),
return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
ComponentArray{a, b, c}),
pos);
}
@ -302,14 +302,14 @@ public:
SkSL::SwizzleComponent::Type c,
SkSL::SwizzleComponent::Type d,
PositionInfo pos) {
return DSLExpression(Swizzle::Convert(DSLWriter::Context(), base.release(),
return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
ComponentArray{a,b,c,d}),
pos);
}
static DSLPossibleExpression Select(DSLExpression test, DSLExpression ifTrue,
DSLExpression ifFalse) {
return TernaryExpression::Convert(DSLWriter::Context(), test.release(),
return TernaryExpression::Convert(ThreadContext::Context(), test.release(),
ifTrue.release(), ifFalse.release());
}
@ -324,14 +324,14 @@ public:
caseBlocks.push_back(SkSL::Block::Make(/*line=*/-1,
std::move(c.fStatements), /*symbols=*/nullptr, /*isScope=*/false));
}
return SwitchStatement::Convert(DSLWriter::Context(), /*line=*/-1, isStatic,
return SwitchStatement::Convert(ThreadContext::Context(), /*line=*/-1, isStatic,
value.release(), std::move(values), std::move(caseBlocks),
DSLWriter::SymbolTable());
ThreadContext::SymbolTable());
}
static DSLPossibleStatement While(DSLExpression test, DSLStatement stmt) {
return ForStatement::ConvertWhile(DSLWriter::Context(), /*line=*/-1, test.release(),
stmt.release(), DSLWriter::SymbolTable());
return ForStatement::ConvertWhile(ThreadContext::Context(), /*line=*/-1, test.release(),
stmt.release(), ThreadContext::SymbolTable());
}
};
@ -352,8 +352,8 @@ DSLExpression sk_Position() {
}
void AddExtension(skstd::string_view name, PositionInfo pos) {
DSLWriter::ProgramElements().push_back(std::make_unique<SkSL::Extension>(pos.line(), name));
DSLWriter::ReportErrors(pos);
ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::Extension>(pos.line(), name));
ThreadContext::ReportErrors(pos);
}
DSLStatement Break(PositionInfo pos) {
@ -365,10 +365,11 @@ DSLStatement Continue(PositionInfo pos) {
}
void Declare(const DSLModifiers& modifiers, PositionInfo pos) {
SkSL::ProgramKind kind = DSLWriter::GetProgramConfig()->fKind;
SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind;
if (kind != ProgramKind::kFragment &&
kind != ProgramKind::kVertex) {
DSLWriter::ReportError("layout qualifiers are not allowed in this kind of program", pos);
ThreadContext::ReportError("layout qualifiers are not allowed in this kind of program",
pos);
return;
}
DSLCore::Declare(modifiers);
@ -403,8 +404,8 @@ void Declare(SkTArray<DSLGlobalVar>& vars, PositionInfo pos) {
}
DSLStatement Discard(PositionInfo pos) {
if (DSLWriter::GetProgramConfig()->fKind != ProgramKind::kFragment) {
DSLWriter::ReportError("discard statement is only permitted in fragment shaders", pos);
if (ThreadContext::GetProgramConfig()->fKind != ProgramKind::kFragment) {
ThreadContext::ReportError("discard statement is only permitted in fragment shaders", pos);
}
return DSLCore::Discard(pos);
}
@ -428,10 +429,10 @@ DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, P
DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, skstd::string_view typeName,
SkTArray<DSLField> fields, skstd::string_view varName, int arraySize,
PositionInfo pos) {
SkSL::ProgramKind kind = DSLWriter::GetProgramConfig()->fKind;
SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind;
if (kind != ProgramKind::kFragment &&
kind != ProgramKind::kVertex) {
DSLWriter::ReportError("interface blocks are not allowed in this kind of program", pos);
ThreadContext::ReportError("interface blocks are not allowed in this kind of program", pos);
return DSLGlobalVar();
}
return DSLCore::InterfaceBlock(modifiers, typeName, std::move(fields), varName, arraySize, pos);

View File

@ -11,6 +11,7 @@
#include "include/sksl/DSLVar.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
@ -42,35 +43,35 @@ DSLExpression::DSLExpression(std::unique_ptr<SkSL::Expression> expression)
}
DSLExpression::DSLExpression(float value, PositionInfo pos)
: fExpression(SkSL::Literal::MakeFloat(DSLWriter::Context(),
: fExpression(SkSL::Literal::MakeFloat(ThreadContext::Context(),
pos.line(),
value)) {
if (!isfinite(value)) {
if (isinf(value)) {
DSLWriter::ReportError("floating point value is infinite");
ThreadContext::ReportError("floating point value is infinite");
} else if (isnan(value)) {
DSLWriter::ReportError("floating point value is NaN");
ThreadContext::ReportError("floating point value is NaN");
}
}
}
DSLExpression::DSLExpression(int value, PositionInfo pos)
: fExpression(SkSL::Literal::MakeInt(DSLWriter::Context(),
: fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
pos.line(),
value)) {}
DSLExpression::DSLExpression(int64_t value, PositionInfo pos)
: fExpression(SkSL::Literal::MakeInt(DSLWriter::Context(),
: fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
pos.line(),
value)) {}
DSLExpression::DSLExpression(unsigned int value, PositionInfo pos)
: fExpression(SkSL::Literal::MakeInt(DSLWriter::Context(),
: fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
pos.line(),
value)) {}
DSLExpression::DSLExpression(bool value, PositionInfo pos)
: fExpression(SkSL::Literal::MakeBool(DSLWriter::Context(),
: fExpression(SkSL::Literal::MakeBool(ThreadContext::Context(),
pos.line(),
value)) {}
@ -83,27 +84,27 @@ DSLExpression::DSLExpression(DSLVarBase&& var, PositionInfo pos)
: DSLExpression(var) {}
DSLExpression::DSLExpression(DSLPossibleExpression expr, PositionInfo pos) {
DSLWriter::ReportErrors(pos);
ThreadContext::ReportErrors(pos);
if (expr.valid()) {
fExpression = std::move(expr.fExpression);
} else {
fExpression = SkSL::Poison::Make(pos.line(), DSLWriter::Context());
fExpression = SkSL::Poison::Make(pos.line(), ThreadContext::Context());
}
}
DSLExpression DSLExpression::Poison(PositionInfo pos) {
return DSLExpression(SkSL::Poison::Make(pos.line(), DSLWriter::Context()));
return DSLExpression(SkSL::Poison::Make(pos.line(), ThreadContext::Context()));
}
DSLExpression::~DSLExpression() {
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
if (fExpression && DSLWriter::InFragmentProcessor()) {
DSLWriter::CurrentEmitArgs()->fFragBuilder->codeAppend(
if (fExpression && ThreadContext::InFragmentProcessor()) {
ThreadContext::CurrentEmitArgs()->fFragBuilder->codeAppend(
DSLStatement(this->release()).release());
return;
}
#endif
SkASSERTF(!fExpression || !DSLWriter::Settings().fAssertDSLObjectsReleased,
SkASSERTF(!fExpression || !ThreadContext::Settings().fAssertDSLObjectsReleased,
"Expression destroyed without being incorporated into program (see "
"ProgramSettings::fAssertDSLObjectsReleased)");
}
@ -165,17 +166,17 @@ DSLExpression DSLExpression::a(PositionInfo pos) {
}
DSLExpression DSLExpression::field(skstd::string_view name, PositionInfo pos) {
return DSLExpression(FieldAccess::Convert(DSLWriter::Context(), *DSLWriter::SymbolTable(),
this->release(), name), pos);
return DSLExpression(FieldAccess::Convert(ThreadContext::Context(),
*ThreadContext::SymbolTable(), this->release(), name), pos);
}
DSLPossibleExpression DSLExpression::operator=(DSLExpression right) {
return BinaryExpression::Convert(DSLWriter::Context(), this->release(),
return BinaryExpression::Convert(ThreadContext::Context(), this->release(),
SkSL::Token::Kind::TK_EQ, right.release());
}
DSLPossibleExpression DSLExpression::operator[](DSLExpression right) {
return IndexExpression::Convert(DSLWriter::Context(), *DSLWriter::SymbolTable(),
return IndexExpression::Convert(ThreadContext::Context(), *ThreadContext::SymbolTable(),
this->release(), right.release());
}
@ -190,25 +191,25 @@ DSLPossibleExpression DSLExpression::operator()(SkTArray<DSLWrapper<DSLExpressio
}
DSLPossibleExpression DSLExpression::operator()(ExpressionArray args, PositionInfo pos) {
return SkSL::FunctionCall::Convert(DSLWriter::Context(), pos.line(), this->release(),
return SkSL::FunctionCall::Convert(ThreadContext::Context(), pos.line(), this->release(),
std::move(args));
}
#define OP(op, token) \
DSLPossibleExpression operator op(DSLExpression left, DSLExpression right) { \
return BinaryExpression::Convert(DSLWriter::Context(), left.release(), \
return BinaryExpression::Convert(ThreadContext::Context(), left.release(), \
SkSL::Token::Kind::token, right.release()); \
}
#define PREFIXOP(op, token) \
DSLPossibleExpression operator op(DSLExpression expr) { \
return PrefixExpression::Convert(DSLWriter::Context(), SkSL::Token::Kind::token, \
return PrefixExpression::Convert(ThreadContext::Context(), SkSL::Token::Kind::token, \
expr.release()); \
}
#define POSTFIXOP(op, token) \
DSLPossibleExpression operator op(DSLExpression expr, int) { \
return PostfixExpression::Convert(DSLWriter::Context(), expr.release(), \
return PostfixExpression::Convert(ThreadContext::Context(), expr.release(), \
SkSL::Token::Kind::token); \
}
@ -235,7 +236,7 @@ OP(|=, TK_BITWISEOREQ)
OP(^, TK_BITWISEXOR)
OP(^=, TK_BITWISEXOREQ)
DSLPossibleExpression LogicalXor(DSLExpression left, DSLExpression right) {
return BinaryExpression::Convert(DSLWriter::Context(), left.release(),
return BinaryExpression::Convert(ThreadContext::Context(), left.release(),
SkSL::Token::Kind::TK_LOGICALXOR, right.release());
}
OP(==, TK_EQEQ)
@ -255,23 +256,24 @@ PREFIXOP(--, TK_MINUSMINUS)
POSTFIXOP(--, TK_MINUSMINUS)
DSLPossibleExpression operator,(DSLExpression left, DSLExpression right) {
return BinaryExpression::Convert(DSLWriter::Context(), left.release(),
return BinaryExpression::Convert(ThreadContext::Context(), left.release(),
SkSL::Token::Kind::TK_COMMA, right.release());
}
DSLPossibleExpression operator,(DSLPossibleExpression left, DSLExpression right) {
return BinaryExpression::Convert(DSLWriter::Context(), DSLExpression(std::move(left)).release(),
SkSL::Token::Kind::TK_COMMA, right.release());
return BinaryExpression::Convert(ThreadContext::Context(),
DSLExpression(std::move(left)).release(), SkSL::Token::Kind::TK_COMMA, right.release());
}
DSLPossibleExpression operator,(DSLExpression left, DSLPossibleExpression right) {
return BinaryExpression::Convert(DSLWriter::Context(), left.release(),
return BinaryExpression::Convert(ThreadContext::Context(), left.release(),
SkSL::Token::Kind::TK_COMMA, DSLExpression(std::move(right)).release());
}
DSLPossibleExpression operator,(DSLPossibleExpression left, DSLPossibleExpression right) {
return BinaryExpression::Convert(DSLWriter::Context(), DSLExpression(std::move(left)).release(),
SkSL::Token::Kind::TK_COMMA, DSLExpression(std::move(right)).release());
return BinaryExpression::Convert(ThreadContext::Context(),
DSLExpression(std::move(left)).release(), SkSL::Token::Kind::TK_COMMA,
DSLExpression(std::move(right)).release());
}
DSLPossibleExpression::DSLPossibleExpression(std::unique_ptr<SkSL::Expression> expr)
@ -289,7 +291,7 @@ DSLPossibleExpression::~DSLPossibleExpression() {
void DSLPossibleExpression::reportErrors(PositionInfo pos) {
SkASSERT(!this->valid());
DSLWriter::ReportErrors(pos);
ThreadContext::ReportErrors(pos);
}
DSLType DSLPossibleExpression::type() {

View File

@ -11,6 +11,7 @@
#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLFunctionCall.h"
#include "src/sksl/ir/SkSLFunctionPrototype.h"
@ -24,11 +25,11 @@ void DSLFunction::init(DSLModifiers modifiers, const DSLType& returnType, skstd:
SkTArray<DSLParameter*> params, PositionInfo pos) {
fPosition = pos;
// Conservatively assume all user-defined functions have side effects.
if (!DSLWriter::IsModule()) {
if (!ThreadContext::IsModule()) {
modifiers.fModifiers.fFlags |= Modifiers::kHasSideEffects_Flag;
}
if (DSLWriter::Settings().fForceNoInline) {
if (ThreadContext::Settings().fForceNoInline) {
// Apply the `noinline` modifier to every function. This allows us to test Runtime
// Effects without any inlining, even when the code is later added to a paint.
modifiers.fModifiers.fFlags &= ~Modifiers::kInline_Flag;
@ -39,7 +40,7 @@ void DSLFunction::init(DSLModifiers modifiers, const DSLType& returnType, skstd:
paramVars.reserve(params.size());
for (DSLParameter* param : params) {
if (param->fDeclared) {
DSLWriter::ReportError("parameter has already been used in another function");
ThreadContext::ReportError("parameter has already been used in another function");
}
SkASSERT(!param->fInitialValue.hasValue());
SkASSERT(!param->fDeclaration);
@ -51,13 +52,13 @@ void DSLFunction::init(DSLModifiers modifiers, const DSLType& returnType, skstd:
paramVars.push_back(std::move(paramVar));
}
SkASSERT(paramVars.size() == params.size());
fDecl = SkSL::FunctionDeclaration::Convert(DSLWriter::Context(),
*DSLWriter::SymbolTable(),
fDecl = SkSL::FunctionDeclaration::Convert(ThreadContext::Context(),
*ThreadContext::SymbolTable(),
pos.line(),
DSLWriter::Modifiers(modifiers.fModifiers),
ThreadContext::Modifiers(modifiers.fModifiers),
name == "main" ? name : DSLWriter::Name(name),
std::move(paramVars), &returnType.skslType());
DSLWriter::ReportErrors(pos);
ThreadContext::ReportErrors(pos);
if (fDecl) {
for (size_t i = 0; i < params.size(); ++i) {
params[i]->fVar = fDecl->parameters()[i];
@ -66,8 +67,8 @@ void DSLFunction::init(DSLModifiers modifiers, const DSLType& returnType, skstd:
// We don't know when this function is going to be defined; go ahead and add a prototype in
// case the definition is delayed. If we end up defining the function immediately, we'll
// remove the prototype in define().
DSLWriter::ProgramElements().push_back(std::make_unique<SkSL::FunctionPrototype>(
pos.line(), fDecl, DSLWriter::IsModule()));
ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::FunctionPrototype>(
pos.line(), fDecl, ThreadContext::IsModule()));
}
}
@ -78,33 +79,34 @@ void DSLFunction::define(DSLBlock block, PositionInfo pos) {
// Release the block so we don't fail its destructor assert.
return;
}
if (!DSLWriter::ProgramElements().empty()) {
if (!ThreadContext::ProgramElements().empty()) {
// If the last ProgramElement was the prototype for this function, it was unnecessary and we
// can remove it.
const SkSL::ProgramElement& last = *DSLWriter::ProgramElements().back();
const SkSL::ProgramElement& last = *ThreadContext::ProgramElements().back();
if (last.is<SkSL::FunctionPrototype>()) {
const SkSL::FunctionPrototype& prototype = last.as<SkSL::FunctionPrototype>();
if (&prototype.declaration() == fDecl) {
DSLWriter::ProgramElements().pop_back();
ThreadContext::ProgramElements().pop_back();
}
}
}
if (fDecl->definition()) {
DSLWriter::ReportError(String::printf("function '%s' was already defined",
ThreadContext::ReportError(String::printf("function '%s' was already defined",
fDecl->description().c_str()), pos);
block.release();
return;
}
// Append sk_Position fixup to the bottom of main() if this is a vertex program.
DSLWriter::IRGenerator().appendRTAdjustFixupToVertexMain(*fDecl, body.get());
std::unique_ptr<FunctionDefinition> function = FunctionDefinition::Convert(DSLWriter::Context(),
pos.line(),
*fDecl,
std::move(body),
/*builtin=*/false);
DSLWriter::ReportErrors(fPosition);
ThreadContext::IRGenerator().appendRTAdjustFixupToVertexMain(*fDecl, body.get());
std::unique_ptr<FunctionDefinition> function = FunctionDefinition::Convert(
ThreadContext::Context(),
pos.line(),
*fDecl,
std::move(body),
/*builtin=*/false);
ThreadContext::ReportErrors(fPosition);
fDecl->setDefinition(function.get());
DSLWriter::ProgramElements().push_back(std::move(function));
ThreadContext::ProgramElements().push_back(std::move(function));
}
DSLExpression DSLFunction::call(SkTArray<DSLWrapper<DSLExpression>> args, PositionInfo pos) {
@ -117,7 +119,7 @@ DSLExpression DSLFunction::call(SkTArray<DSLWrapper<DSLExpression>> args, Positi
}
DSLExpression DSLFunction::call(ExpressionArray args, PositionInfo pos) {
std::unique_ptr<SkSL::Expression> result = SkSL::FunctionCall::Convert(DSLWriter::Context(),
std::unique_ptr<SkSL::Expression> result = SkSL::FunctionCall::Convert(ThreadContext::Context(),
pos.line(), *fDecl, std::move(args));
return DSLExpression(std::move(result), pos);
}

View File

@ -7,7 +7,7 @@
#include "include/sksl/DSLLayout.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/SkSLThreadContext.h"
namespace SkSL {
@ -15,7 +15,7 @@ namespace dsl {
DSLLayout& DSLLayout::flag(SkSL::Layout::Flag mask, const char* name, PositionInfo pos) {
if (fSkSLLayout.fFlags & mask) {
DSLWriter::ReportError("layout qualifier '" + String(name) + "' appears more than once",
ThreadContext::ReportError("layout qualifier '" + String(name) + "' appears more than once",
pos);
}
fSkSLLayout.fFlags |= mask;

View File

@ -11,7 +11,7 @@
#include "include/sksl/DSLCore.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/SkSLThreadContext.h"
namespace SkSL {
@ -21,7 +21,7 @@ namespace dsl {
void StartRuntimeShader(SkSL::Compiler* compiler) {
Start(compiler, SkSL::ProgramKind::kRuntimeShader);
SkSL::ProgramSettings& settings = DSLWriter::Settings();
SkSL::ProgramSettings& settings = ThreadContext::Settings();
SkASSERT(settings.fInlineThreshold == SkSL::kDefaultInlineThreshold);
settings.fInlineThreshold = 0;
SkASSERT(!settings.fAllowNarrowingConversions);

View File

@ -10,7 +10,7 @@
#include "include/sksl/DSLBlock.h"
#include "include/sksl/DSLExpression.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/ir/SkSLBlock.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLNop.h"
@ -31,12 +31,12 @@ DSLStatement::DSLStatement(DSLBlock block)
DSLStatement::DSLStatement(DSLExpression expr) {
std::unique_ptr<SkSL::Expression> skslExpr = expr.release();
if (skslExpr) {
fStatement = SkSL::ExpressionStatement::Make(DSLWriter::Context(), std::move(skslExpr));
fStatement = SkSL::ExpressionStatement::Make(ThreadContext::Context(), std::move(skslExpr));
}
}
DSLStatement::DSLStatement(std::unique_ptr<SkSL::Expression> expr)
: fStatement(SkSL::ExpressionStatement::Make(DSLWriter::Context(), std::move(expr))) {
: fStatement(SkSL::ExpressionStatement::Make(ThreadContext::Context(), std::move(expr))) {
SkASSERT(this->hasValue());
}
@ -49,7 +49,7 @@ DSLStatement::DSLStatement(DSLPossibleExpression expr, PositionInfo pos)
: DSLStatement(DSLExpression(std::move(expr), pos)) {}
DSLStatement::DSLStatement(DSLPossibleStatement stmt, PositionInfo pos) {
DSLWriter::ReportErrors(pos);
ThreadContext::ReportErrors(pos);
if (stmt.hasValue()) {
fStatement = std::move(stmt.fStatement);
} else {
@ -62,12 +62,12 @@ DSLStatement::DSLStatement(DSLPossibleStatement stmt, PositionInfo pos) {
DSLStatement::~DSLStatement() {
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
if (fStatement && DSLWriter::InFragmentProcessor()) {
DSLWriter::CurrentEmitArgs()->fFragBuilder->codeAppend(this->release());
if (fStatement && ThreadContext::InFragmentProcessor()) {
ThreadContext::CurrentEmitArgs()->fFragBuilder->codeAppend(this->release());
return;
}
#endif
SkASSERTF(!fStatement || !DSLWriter::Settings().fAssertDSLObjectsReleased,
SkASSERTF(!fStatement || !ThreadContext::Settings().fAssertDSLObjectsReleased,
"Statement destroyed without being incorporated into program (see "
"ProgramSettings::fAssertDSLObjectsReleased)");
}

View File

@ -8,6 +8,7 @@
#include "include/sksl/DSLSymbols.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
namespace SkSL {
@ -15,19 +16,19 @@ namespace SkSL {
namespace dsl {
void PushSymbolTable() {
SymbolTable::Push(&DSLWriter::IRGenerator().symbolTable());
SymbolTable::Push(&ThreadContext::IRGenerator().symbolTable());
}
void PopSymbolTable() {
SymbolTable::Pop(&DSLWriter::IRGenerator().symbolTable());
SymbolTable::Pop(&ThreadContext::IRGenerator().symbolTable());
}
std::shared_ptr<SymbolTable> CurrentSymbolTable() {
return DSLWriter::IRGenerator().symbolTable();
return ThreadContext::IRGenerator().symbolTable();
}
DSLPossibleExpression Symbol(skstd::string_view name, PositionInfo pos) {
return DSLWriter::IRGenerator().convertIdentifier(pos.line(), name);
return ThreadContext::IRGenerator().convertIdentifier(pos.line(), name);
}
bool IsType(skstd::string_view name) {
@ -40,7 +41,7 @@ void AddToSymbolTable(DSLVarBase& var, PositionInfo pos) {
if (skslVar) {
CurrentSymbolTable()->addWithoutOwnership(skslVar);
}
DSLWriter::ReportErrors(pos);
ThreadContext::ReportErrors(pos);
}
const String* Retain(String string) {

View File

@ -7,7 +7,7 @@
#include "include/sksl/DSLType.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLStructDefinition.h"
@ -35,7 +35,7 @@ static const SkSL::Type* verify_type(const Context& context,
static const SkSL::Type* find_type(const Context& context,
skstd::string_view name,
PositionInfo pos) {
const Symbol* symbol = (*DSLWriter::SymbolTable())[name];
const Symbol* symbol = (*ThreadContext::SymbolTable())[name];
if (!symbol) {
context.fErrors->error(String::printf("no symbol named '%.*s'",
(int)name.length(), name.data()), pos);
@ -55,9 +55,9 @@ static const SkSL::Type* find_type(const Context& context,
Modifiers* modifiers,
PositionInfo pos) {
const Type* type = find_type(context, name, pos);
type = type->applyPrecisionQualifiers(context, modifiers, DSLWriter::SymbolTable().get(),
type = type->applyPrecisionQualifiers(context, modifiers, ThreadContext::SymbolTable().get(),
pos.line());
DSLWriter::ReportErrors(pos);
ThreadContext::ReportErrors(pos);
return type;
}
@ -167,13 +167,13 @@ static const SkSL::Type* get_type_from_type_constant(const Context& context, Typ
}
DSLType::DSLType(skstd::string_view name)
: fSkSLType(find_type(DSLWriter::Context(), name, PositionInfo())) {}
: fSkSLType(find_type(ThreadContext::Context(), name, PositionInfo())) {}
DSLType::DSLType(skstd::string_view name, DSLModifiers* modifiers, PositionInfo position)
: fSkSLType(find_type(DSLWriter::Context(), name, &modifiers->fModifiers, position)) {}
: fSkSLType(find_type(ThreadContext::Context(), name, &modifiers->fModifiers, position)) {}
DSLType::DSLType(const SkSL::Type* type)
: fSkSLType(verify_type(DSLWriter::Context(), type, /*allowPrivateTypes=*/true,
: fSkSLType(verify_type(ThreadContext::Context(), type, /*allowPrivateTypes=*/true,
PositionInfo())) {}
bool DSLType::isBoolean() const {
@ -228,7 +228,7 @@ const SkSL::Type& DSLType::skslType() const {
if (fSkSLType) {
return *fSkSLType;
}
const Context& context = DSLWriter::Context();
const Context& context = ThreadContext::Context();
return *verify_type(context,
get_type_from_type_constant(context, fTypeConstant),
/*allowPrivateTypes=*/true,
@ -245,18 +245,18 @@ DSLPossibleExpression DSLType::Construct(DSLType type, SkSpan<DSLExpression> arg
}
skslArgs.push_back(arg.release());
}
return SkSL::Constructor::Convert(DSLWriter::Context(), /*line=*/-1, type.skslType(),
return SkSL::Constructor::Convert(ThreadContext::Context(), /*line=*/-1, type.skslType(),
std::move(skslArgs));
}
DSLType Array(const DSLType& base, int count, PositionInfo pos) {
count = base.skslType().convertArraySize(DSLWriter::Context(),
count = base.skslType().convertArraySize(ThreadContext::Context(),
DSLExpression(count, pos).release());
DSLWriter::ReportErrors(pos);
ThreadContext::ReportErrors(pos);
if (!count) {
return DSLType(kPoison_Type);
}
return DSLWriter::SymbolTable()->addArrayDimension(&base.skslType(), count);
return ThreadContext::SymbolTable()->addArrayDimension(&base.skslType(), count);
}
DSLType Struct(skstd::string_view name, SkSpan<DSLField> fields, PositionInfo pos) {
@ -266,25 +266,24 @@ DSLType Struct(skstd::string_view name, SkSpan<DSLField> fields, PositionInfo po
if (field.fModifiers.fModifiers.fFlags != Modifiers::kNo_Flag) {
String desc = field.fModifiers.fModifiers.description();
desc.pop_back(); // remove trailing space
DSLWriter::ReportError("modifier '" + desc + "' is not permitted on a struct field",
ThreadContext::ReportError("modifier '" + desc + "' is not permitted on a struct field",
field.fPosition);
}
const SkSL::Type& type = field.fType.skslType();
if (type.isOpaque()) {
DSLWriter::ReportError("opaque type '" + type.displayName() +
ThreadContext::ReportError("opaque type '" + type.displayName() +
"' is not permitted in a struct", field.fPosition);
}
skslFields.emplace_back(field.fModifiers.fModifiers, field.fName, &type);
}
const SkSL::Type* result = DSLWriter::SymbolTable()->add(Type::MakeStructType(pos.line(),
name,
skslFields));
const SkSL::Type* result = ThreadContext::SymbolTable()->add(Type::MakeStructType(pos.line(),
name, skslFields));
if (result->isTooDeeplyNested()) {
DSLWriter::ReportError("struct '" + String(name) + "' is too deeply nested", pos);
ThreadContext::ReportError("struct '" + String(name) + "' is too deeply nested", pos);
}
DSLWriter::ProgramElements().push_back(std::make_unique<SkSL::StructDefinition>(/*line=*/-1,
*result));
ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::StructDefinition>(/*line=*/-1,
*result));
return result;
}

View File

@ -10,6 +10,7 @@
#include "include/sksl/DSLModifiers.h"
#include "include/sksl/DSLType.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
@ -44,30 +45,25 @@ DSLVarBase::DSLVarBase(const DSLModifiers& modifiers, DSLType type, skstd::strin
, fPosition(pos) {
if (fModifiers.fModifiers.fFlags & Modifiers::kUniform_Flag) {
#if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
if (DSLWriter::InFragmentProcessor()) {
if (ThreadContext::InFragmentProcessor()) {
const SkSL::Type& skslType = type.skslType();
GrSLType grslType;
int count;
if (skslType.isArray()) {
SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(),
skslType.componentType(),
&grslType));
SkAssertResult(SkSL::type_to_grsltype(ThreadContext::Context(),
skslType.componentType(), &grslType));
count = skslType.columns();
SkASSERT(count > 0);
} else {
SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(), skslType,
&grslType));
SkAssertResult(SkSL::type_to_grsltype(ThreadContext::Context(), skslType,
&grslType));
count = 0;
}
const char* uniformName;
SkASSERT(DSLWriter::CurrentEmitArgs());
fUniformHandle = DSLWriter::CurrentEmitArgs()->fUniformHandler->addUniformArray(
&DSLWriter::CurrentEmitArgs()->fFp,
kFragment_GrShaderFlag,
grslType,
String(this->name()).c_str(),
count,
&uniformName).toIndex();
SkASSERT(ThreadContext::CurrentEmitArgs());
fUniformHandle = ThreadContext::CurrentEmitArgs()->fUniformHandler->addUniformArray(
&ThreadContext::CurrentEmitArgs()->fFp, kFragment_GrShaderFlag, grslType,
String(this->name()).c_str(), count, &uniformName).toIndex();
fName = uniformName;
}
#endif // SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
@ -76,10 +72,10 @@ DSLVarBase::DSLVarBase(const DSLModifiers& modifiers, DSLType type, skstd::strin
DSLVarBase::~DSLVarBase() {
if (fDeclaration && !fDeclared) {
DSLWriter::ReportError(String::printf("variable '%.*s' was destroyed without being "
"declared",
(int)fRawName.length(),
fRawName.data()).c_str());
ThreadContext::ReportError(String::printf("variable '%.*s' was destroyed without being "
"declared",
(int)fRawName.length(),
fRawName.data()).c_str());
}
}
@ -112,30 +108,30 @@ DSLGlobalVar::DSLGlobalVar(const char* name)
DSLWriter::MarkDeclared(*this);
#if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
if (!strcmp(name, "sk_SampleCoord")) {
fName = DSLWriter::CurrentEmitArgs()->fSampleCoord;
fName = ThreadContext::CurrentEmitArgs()->fSampleCoord;
// The actual sk_SampleCoord variable hasn't been created by GrGLSLFPFragmentBuilder yet, so
// if we attempt to look it up in the symbol table we'll get null. As we are currently
// converting all DSL code into strings rather than nodes, all we really need is a
// correctly-named variable with the right type, so we just create a placeholder for it.
// TODO(skia/11330): we'll need to fix this when switching over to nodes.
const SkSL::Modifiers* modifiers = DSLWriter::Context().fModifiersPool->add(
const SkSL::Modifiers* modifiers = ThreadContext::Context().fModifiersPool->add(
SkSL::Modifiers(SkSL::Layout(/*flags=*/0, /*location=*/-1, /*offset=*/-1,
/*binding=*/-1, /*index=*/-1, /*set=*/-1,
SK_MAIN_COORDS_BUILTIN, /*inputAttachmentIndex=*/-1),
SkSL::Modifiers::kNo_Flag));
fVar = DSLWriter::SymbolTable()->takeOwnershipOfIRNode(std::make_unique<SkSL::Variable>(
fVar = ThreadContext::SymbolTable()->takeOwnershipOfIRNode(std::make_unique<SkSL::Variable>(
/*line=*/-1,
modifiers,
fName,
DSLWriter::Context().fTypes.fFloat2.get(),
ThreadContext::Context().fTypes.fFloat2.get(),
/*builtin=*/true,
SkSL::VariableStorage::kGlobal));
fInitialized = true;
return;
}
#endif
const SkSL::Symbol* result = (*DSLWriter::SymbolTable())[fName];
const SkSL::Symbol* result = (*ThreadContext::SymbolTable())[fName];
SkASSERTF(result, "could not find '%.*s' in symbol table", (int)fName.length(), fName.data());
fVar = &result->as<SkSL::Variable>();
fInitialized = true;
@ -163,7 +159,7 @@ DSLPossibleExpression DSLVarBase::operator[](DSLExpression&& index) {
}
DSLPossibleExpression DSLVarBase::assign(DSLExpression expr) {
return BinaryExpression::Convert(DSLWriter::Context(),
return BinaryExpression::Convert(ThreadContext::Context(),
DSLExpression(*this, PositionInfo()).release(), SkSL::Token::Kind::TK_EQ,
expr.release());
}
@ -183,17 +179,17 @@ DSLPossibleExpression DSLParameter::operator=(DSLExpression expr) {
std::unique_ptr<SkSL::Expression> DSLGlobalVar::methodCall(skstd::string_view methodName,
PositionInfo pos) {
if (!this->fType.isEffectChild()) {
DSLWriter::ReportError("type does not support method calls", pos);
ThreadContext::ReportError("type does not support method calls", pos);
return nullptr;
}
return FieldAccess::Convert(DSLWriter::Context(), *DSLWriter::SymbolTable(),
return FieldAccess::Convert(ThreadContext::Context(), *ThreadContext::SymbolTable(),
DSLExpression(*this, PositionInfo()).release(), methodName);
}
DSLExpression DSLGlobalVar::eval(ExpressionArray args, PositionInfo pos) {
auto method = this->methodCall("eval", pos);
return DSLExpression(
method ? SkSL::FunctionCall::Convert(DSLWriter::Context(), pos.line(),
method ? SkSL::FunctionCall::Convert(ThreadContext::Context(), pos.line(),
std::move(method), std::move(args))
: nullptr,
pos);

View File

@ -7,6 +7,7 @@
#include "src/sksl/dsl/priv/DSLFPs.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLCodeStringExpression.h"
@ -18,11 +19,11 @@ namespace dsl {
void StartFragmentProcessor(GrFragmentProcessor::ProgramImpl* processor,
GrFragmentProcessor::ProgramImpl::EmitArgs* emitArgs) {
DSLWriter::StartFragmentProcessor(processor, emitArgs);
ThreadContext::StartFragmentProcessor(processor, emitArgs);
}
void EndFragmentProcessor() {
DSLWriter::EndFragmentProcessor();
ThreadContext::EndFragmentProcessor();
}
DSLGlobalVar sk_SampleCoord() {
@ -36,8 +37,8 @@ DSLExpression SampleChild(int index, DSLExpression sampleExpr) {
SkASSERT(expr->type().componentType().isFloat());
}
GrFragmentProcessor::ProgramImpl* proc = DSLWriter::CurrentProcessor();
GrFragmentProcessor::ProgramImpl::EmitArgs& emitArgs = *DSLWriter::CurrentEmitArgs();
GrFragmentProcessor::ProgramImpl* proc = ThreadContext::CurrentProcessor();
GrFragmentProcessor::ProgramImpl::EmitArgs& emitArgs = *ThreadContext::CurrentEmitArgs();
SkString code;
switch (expr ? expr->type().columns() : 0) {
default:
@ -55,7 +56,7 @@ DSLExpression SampleChild(int index, DSLExpression sampleExpr) {
}
return DSLExpression(std::make_unique<SkSL::CodeStringExpression>(
code.c_str(), DSLWriter::Context().fTypes.fHalf4.get()));
code.c_str(), ThreadContext::Context().fTypes.fHalf4.get()));
}
GrGLSLUniformHandler::UniformHandle VarUniformHandle(const DSLGlobalVar& var) {

View File

@ -7,178 +7,33 @@
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "include/private/SkSLDefines.h"
#include "include/sksl/DSLCore.h"
#include "include/sksl/DSLStatement.h"
#include "include/sksl/DSLSymbols.h"
#include "include/sksl/SkSLErrorReporter.h"
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/mock/GrMockCaps.h"
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include "src/sksl/SkSLCompiler.h"
#include "include/sksl/DSLVar.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLIntrinsicMap.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBlock.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/ir/SkSLNop.h"
#include "src/sksl/ir/SkSLPostfixExpression.h"
#include "src/sksl/ir/SkSLPrefixExpression.h"
#include "src/sksl/ir/SkSLSwitchStatement.h"
#include "src/sksl/ir/SkSLVariable.h"
namespace SkSL {
namespace dsl {
DSLWriter::DSLWriter(SkSL::Compiler* compiler, SkSL::ProgramKind kind,
const SkSL::ProgramSettings& settings, SkSL::ParsedModule module,
bool isModule)
: fCompiler(compiler)
, fOldErrorReporter(*fCompiler->fContext->fErrors)
, fSettings(settings) {
fOldModifiersPool = fCompiler->fContext->fModifiersPool;
fOldConfig = fCompiler->fContext->fConfig;
if (!isModule) {
if (compiler->context().fCaps.useNodePools() && settings.fDSLUseMemoryPool) {
fPool = Pool::Create();
fPool->attachToThread();
}
fModifiersPool = std::make_unique<SkSL::ModifiersPool>();
fCompiler->fContext->fModifiersPool = fModifiersPool.get();
}
fConfig = std::make_unique<SkSL::ProgramConfig>();
fConfig->fKind = kind;
fConfig->fSettings = settings;
fConfig->fIsBuiltinCode = isModule;
fCompiler->fContext->fConfig = fConfig.get();
fCompiler->fContext->fErrors = &fDefaultErrorReporter;
fCompiler->fContext->fIntrinsics = module.fIntrinsics.get();
if (fCompiler->fContext->fIntrinsics) {
fCompiler->fContext->fIntrinsics->resetAlreadyIncluded();
}
fCompiler->fIRGenerator->start(module, &fProgramElements, &fSharedElements);
}
DSLWriter::~DSLWriter() {
if (SymbolTable()) {
fCompiler->fIRGenerator->finish();
fProgramElements.clear();
} else {
// We should only be here with a null symbol table if ReleaseProgram was called
SkASSERT(fProgramElements.empty());
}
fCompiler->fContext->fErrors = &fOldErrorReporter;
fCompiler->fContext->fConfig = fOldConfig;
fCompiler->fContext->fModifiersPool = fOldModifiersPool;
if (fPool) {
fPool->detachFromThread();
}
}
SkSL::IRGenerator& DSLWriter::IRGenerator() {
return *Compiler().fIRGenerator;
}
SkSL::Context& DSLWriter::Context() {
return Compiler().context();
}
SkSL::ProgramSettings& DSLWriter::Settings() {
return Context().fConfig->fSettings;
}
SkSL::Program::Inputs& DSLWriter::Inputs() {
return IRGenerator().fInputs;
}
const std::shared_ptr<SkSL::SymbolTable>& DSLWriter::SymbolTable() {
return IRGenerator().fSymbolTable;
}
void DSLWriter::Reset() {
dsl::PopSymbolTable();
dsl::PushSymbolTable();
ProgramElements().clear();
GetModifiersPool()->clear();
}
const SkSL::Modifiers* DSLWriter::Modifiers(const SkSL::Modifiers& modifiers) {
return Context().fModifiersPool->add(modifiers);
bool DSLWriter::ManglingEnabled() {
return ThreadContext::Instance().fSettings.fDSLMangling;
}
skstd::string_view DSLWriter::Name(skstd::string_view name) {
if (ManglingEnabled()) {
const String* s = SymbolTable()->takeOwnershipOfString(
Instance().fMangler.uniqueName(name, SymbolTable().get()));
const String* s = ThreadContext::SymbolTable()->takeOwnershipOfString(
ThreadContext::Instance().fMangler.uniqueName(name,
ThreadContext::SymbolTable().get()));
return s->c_str();
}
return name;
}
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
void DSLWriter::StartFragmentProcessor(GrFragmentProcessor::ProgramImpl* processor,
GrFragmentProcessor::ProgramImpl::EmitArgs* emitArgs) {
DSLWriter& instance = Instance();
instance.fStack.push({processor, emitArgs, StatementArray{}});
CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
dsl::PushSymbolTable();
}
void DSLWriter::EndFragmentProcessor() {
DSLWriter& instance = Instance();
SkASSERT(!instance.fStack.empty());
CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
instance.fStack.pop();
dsl::PopSymbolTable();
}
GrGLSLUniformHandler::UniformHandle DSLWriter::VarUniformHandle(const DSLGlobalVar& var) {
return GrGLSLUniformHandler::UniformHandle(var.fUniformHandle);
}
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
void DSLWriter::AddVarDeclaration(DSLStatement& existing, DSLVar& additional) {
if (existing.fStatement->is<Block>()) {
SkSL::Block& block = existing.fStatement->as<Block>();
SkASSERT(!block.isScope());
block.children().push_back(Declare(additional).release());
} else if (existing.fStatement->is<VarDeclaration>()) {
StatementArray stmts;
stmts.reserve_back(2);
stmts.push_back(std::move(existing.fStatement));
stmts.push_back(Declare(additional).release());
existing.fStatement = SkSL::Block::MakeUnscoped(/*line=*/-1, std::move(stmts));
} else if (existing.fStatement->isEmpty()) {
// If the variable declaration generated an error, we can end up with a Nop statement here.
existing.fStatement = Declare(additional).release();
}
}
void DSLWriter::SetErrorReporter(ErrorReporter* errorReporter) {
SkASSERT(errorReporter);
Context().fErrors = errorReporter;
}
void DSLWriter::ReportError(skstd::string_view msg, PositionInfo info) {
GetErrorReporter().error(msg, info);
}
void DSLWriter::DefaultErrorReporter::handleError(skstd::string_view msg, PositionInfo pos) {
if (pos.line() > -1) {
SK_ABORT("error: %s: %d: %.*sNo SkSL DSL error reporter configured, treating this as a "
"fatal error\n", pos.file_name(), pos.line(), (int)msg.length(), msg.data());
} else {
SK_ABORT("error: %.*s\nNo SkSL DSL error reporter configured, treating this as a fatal "
"error\n", (int)msg.length(), msg.data());
}
}
const SkSL::Variable* DSLWriter::Var(DSLVarBase& var) {
// fInitialized is true if we have attempted to create a var, whether or not we actually
// succeeded. If it's true, we don't want to try again, to avoid reporting the same error
@ -192,19 +47,12 @@ const SkSL::Variable* DSLWriter::Var(DSLVarBase& var) {
if (baseType->isArray()) {
baseType = &baseType->componentType();
}
DSLWriter::IRGenerator().checkVarDeclaration(var.fPosition.line(),
var.fModifiers.fModifiers,
baseType,
var.storage());
ThreadContext::IRGenerator().checkVarDeclaration(var.fPosition.line(),
var.fModifiers.fModifiers, baseType, var.storage());
}
std::unique_ptr<SkSL::Variable> skslvar = DSLWriter::IRGenerator().convertVar(
var.fPosition.line(),
var.fModifiers.fModifiers,
&var.fType.skslType(),
var.fName,
/*isArray=*/false,
/*arraySize=*/nullptr,
var.storage());
std::unique_ptr<SkSL::Variable> skslvar = ThreadContext::IRGenerator().convertVar(
var.fPosition.line(), var.fModifiers.fModifiers, &var.fType.skslType(), var.fName,
/*isArray=*/false, /*arraySize=*/nullptr, var.storage());
SkSL::Variable* varPtr = skslvar.get();
if (var.storage() != SkSL::VariableStorage::kParameter) {
// We can't call VarDeclaration::Convert directly here, because the IRGenerator has
@ -214,7 +62,7 @@ const SkSL::Variable* DSLWriter::Var(DSLVarBase& var) {
// FunctionDeclaration is created which makes this the wrong spot for them, and outside
// of DSLParser we don't even need DSL variables to show up in the symbol table in the
// first place.
var.fDeclaration = DSLWriter::IRGenerator().convertVarDeclaration(
var.fDeclaration = ThreadContext::IRGenerator().convertVarDeclaration(
std::move(skslvar), var.fInitialValue.releaseIfPossible(),
/*addToSymbolTable=*/false);
if (var.fDeclaration) {
@ -222,7 +70,7 @@ const SkSL::Variable* DSLWriter::Var(DSLVarBase& var) {
var.fInitialized = true;
}
}
ReportErrors(var.fPosition);
ThreadContext::ReportErrors(var.fPosition);
}
return var.fVar;
}
@ -231,9 +79,9 @@ std::unique_ptr<SkSL::Variable> DSLWriter::CreateParameterVar(DSLParameter& var)
// This should only be called on undeclared parameter variables, but we allow the creation to go
// ahead regardless so we don't have to worry about null pointers potentially sneaking in and
// breaking things. DSLFunction is responsible for reporting errors for invalid parameters.
return DSLWriter::IRGenerator().convertVar(var.fPosition.line(), var.fModifiers.fModifiers,
&var.fType.skslType(), var.fName, /*isArray=*/false,
/*arraySize=*/nullptr, var.storage());
return ThreadContext::IRGenerator().convertVar(var.fPosition.line(), var.fModifiers.fModifiers,
&var.fType.skslType(), var.fName, /*isArray=*/false, /*arraySize=*/nullptr,
var.storage());
}
std::unique_ptr<SkSL::Statement> DSLWriter::Declaration(DSLVarBase& var) {
@ -252,25 +100,38 @@ void DSLWriter::MarkDeclared(DSLVarBase& var) {
var.fDeclared = true;
}
void DSLWriter::ReportErrors(PositionInfo pos) {
GetErrorReporter().reportPendingErrors(pos);
bool DSLWriter::MarkVarsDeclared() {
return ThreadContext::Instance().fSettings.fDSLMarkVarsDeclared;
}
thread_local DSLWriter* instance = nullptr;
bool DSLWriter::IsActive() {
return instance != nullptr;
void DSLWriter::AddVarDeclaration(DSLStatement& existing, DSLVar& additional) {
if (existing.fStatement->is<Block>()) {
SkSL::Block& block = existing.fStatement->as<Block>();
SkASSERT(!block.isScope());
block.children().push_back(Declare(additional).release());
} else if (existing.fStatement->is<VarDeclaration>()) {
StatementArray stmts;
stmts.reserve_back(2);
stmts.push_back(std::move(existing.fStatement));
stmts.push_back(Declare(additional).release());
existing.fStatement = SkSL::Block::MakeUnscoped(/*line=*/-1, std::move(stmts));
} else if (existing.fStatement->isEmpty()) {
// If the variable declaration generated an error, we can end up with a Nop statement here.
existing.fStatement = Declare(additional).release();
}
}
DSLWriter& DSLWriter::Instance() {
SkASSERTF(instance, "dsl::Start() has not been called");
return *instance;
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
GrGLSLUniformHandler::UniformHandle DSLWriter::VarUniformHandle(const DSLGlobalVar& var) {
return GrGLSLUniformHandler::UniformHandle(var.fUniformHandle);
}
#endif
void DSLWriter::SetInstance(std::unique_ptr<DSLWriter> newInstance) {
SkASSERT((instance == nullptr) != (newInstance == nullptr));
delete instance;
instance = newInstance.release();
void DSLWriter::Reset() {
dsl::PopSymbolTable();
dsl::PushSymbolTable();
ThreadContext::ProgramElements().clear();
ThreadContext::GetModifiersPool()->clear();
}
} // namespace dsl

View File

@ -8,214 +8,33 @@
#ifndef SKSL_DSLWRITER
#define SKSL_DSLWRITER
#include "include/core/SkSpan.h"
#include "include/core/SkStringView.h"
#include "include/private/SkSLModifiers.h"
#include "include/private/SkSLStatement.h"
#include "include/sksl/DSLExpression.h"
#include "include/sksl/DSLStatement.h"
#include "src/sksl/SkSLMangler.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLParsedModule.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLProgram.h"
#include "include/core/SkTypes.h"
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include <list>
#include <stack>
class AutoDSLContext;
#include <memory>
namespace SkSL {
class Compiler;
class Context;
class IRGenerator;
class ProgramElement;
class SymbolTable;
class Type;
class Variable;
class Statement;
namespace dsl {
class DSLGlobalVar;
class DSLParameter;
class DSLStatement;
class DSLVarBase;
class DSLVar;
/**
* Thread-safe class that tracks per-thread state associated with DSL output. This class is for
* internal use only.
* Various utility methods needed by DSL code.
*/
class DSLWriter {
public:
DSLWriter(SkSL::Compiler* compiler, SkSL::ProgramKind kind,
const SkSL::ProgramSettings& settings, SkSL::ParsedModule module, bool isModule);
~DSLWriter();
/**
* Returns true if the DSL has been started.
*/
static bool IsActive();
/**
* Returns the Compiler used by DSL operations in the current thread.
*/
static SkSL::Compiler& Compiler() { return *Instance().fCompiler; }
/**
* Returns the IRGenerator used by DSL operations in the current thread.
*/
static SkSL::IRGenerator& IRGenerator();
/**
* Returns the Context used by DSL operations in the current thread.
*/
static SkSL::Context& Context();
/**
* Returns the Settings used by DSL operations in the current thread.
*/
static SkSL::ProgramSettings& Settings();
/**
* Returns the Program::Inputs used by the current thread.
*/
static SkSL::Program::Inputs& Inputs();
/**
* Returns the collection to which DSL program elements in this thread should be appended.
*/
static std::vector<std::unique_ptr<SkSL::ProgramElement>>& ProgramElements() {
return Instance().fProgramElements;
}
static std::vector<const ProgramElement*>& SharedElements() {
return Instance().fSharedElements;
}
/**
* Returns the SymbolTable of the current thread's IRGenerator.
*/
static const std::shared_ptr<SkSL::SymbolTable>& SymbolTable();
/**
* Returns the current memory pool.
*/
static std::unique_ptr<Pool>& MemoryPool() { return Instance().fPool; }
/**
* Returns the current modifiers pool.
*/
static std::unique_ptr<ModifiersPool>& GetModifiersPool() { return Instance().fModifiersPool; }
/**
* Returns the current ProgramConfig.
*/
static std::unique_ptr<ProgramConfig>& GetProgramConfig() { return Instance().fConfig; }
static bool IsModule() { return GetProgramConfig()->fIsBuiltinCode; }
static void Reset();
/**
* Returns the final pointer to a pooled Modifiers object that should be used to represent the
* given modifiers.
*/
static const SkSL::Modifiers* Modifiers(const SkSL::Modifiers& modifiers);
/**
* Returns the SkSL variable corresponding to a DSL var.
*/
static const SkSL::Variable* Var(DSLVarBase& var);
/**
* Creates an SkSL variable corresponding to a DSLParameter.
*/
static std::unique_ptr<SkSL::Variable> CreateParameterVar(DSLParameter& var);
/**
* Returns the SkSL declaration corresponding to a DSLVar.
*/
static std::unique_ptr<SkSL::Statement> Declaration(DSLVarBase& var);
/**
* For use in testing only: marks the variable as having been declared, so that it can be
* destroyed without generating errors.
*/
static void MarkDeclared(DSLVarBase& var);
/**
* Returns the (possibly mangled) final name that should be used for an entity with the given
* raw name.
*/
static skstd::string_view Name(skstd::string_view name);
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
/**
* Returns the fragment processor for which DSL output is being generated for the current
* thread.
*/
static GrFragmentProcessor::ProgramImpl* CurrentProcessor() {
SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
return Instance().fStack.top().fProcessor;
}
/**
* Returns the EmitArgs for fragment processor output in the current thread.
*/
static GrFragmentProcessor::ProgramImpl::EmitArgs* CurrentEmitArgs() {
SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
return Instance().fStack.top().fEmitArgs;
}
static bool InFragmentProcessor() {
return !Instance().fStack.empty();
}
/**
* Pushes a new processor / emitArgs pair for the current thread.
*/
static void StartFragmentProcessor(GrFragmentProcessor::ProgramImpl* processor,
GrFragmentProcessor::ProgramImpl::EmitArgs* emitArgs);
/**
* Pops the processor / emitArgs pair associated with the current thread.
*/
static void EndFragmentProcessor();
static GrGLSLUniformHandler::UniformHandle VarUniformHandle(const DSLGlobalVar& var);
#else
static bool InFragmentProcessor() {
return false;
}
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
/**
* Adds a new declaration into an existing declaration statement. This either turns the original
* declaration into an unscoped block or, if it already was, appends a new statement to the end
* of it.
*/
static void AddVarDeclaration(DSLStatement& existing, DSLVar& additional);
/**
* Returns the ErrorReporter associated with the current thread. This object will be notified
* when any DSL errors occur.
*/
static ErrorReporter& GetErrorReporter() {
return *Context().fErrors;
}
static void SetErrorReporter(ErrorReporter* errorReporter);
/**
* Notifies the current ErrorReporter that a DSL error has occurred. The default error handler
* prints the message to stderr and aborts.
*/
static void ReportError(skstd::string_view msg, PositionInfo info = PositionInfo::Capture());
/**
* Returns whether name mangling is enabled. Mangling is important for the DSL because its
* variables normally all go into the same symbol table; for instance if you were to translate
@ -234,52 +53,52 @@ public:
* with x1 and x2 ending up in the same symbol table. This is fine as long as their effective
* names are different, so mangling prevents this situation from causing problems.
*/
static bool ManglingEnabled() {
return Instance().fSettings.fDSLMangling;
}
static bool ManglingEnabled();
static skstd::string_view Name(skstd::string_view name);
/**
* Returns the SkSL variable corresponding to a DSL var.
*/
static const SkSL::Variable* Var(DSLVarBase& var);
/**
* Creates an SkSL variable corresponding to a DSLParameter.
*/
static std::unique_ptr<SkSL::Variable> CreateParameterVar(DSLParameter& var);
/**
* Returns the SkSL declaration corresponding to a DSLVar.
*/
static std::unique_ptr<SkSL::Statement> Declaration(DSLVarBase& var);
/**
* For use in testing only: marks the variable as having been declared, so that it can be
* destroyed without generating errors.
*/
static void MarkDeclared(DSLVarBase& var);
/**
* Returns whether DSLVars should automatically be marked declared upon creation. This is used
* to simplify testing.
*/
static bool MarkVarsDeclared() {
return Instance().fSettings.fDSLMarkVarsDeclared;
}
static bool MarkVarsDeclared();
/**
* Forwards any pending errors to the DSL ErrorReporter.
* Adds a new declaration into an existing declaration statement. This either turns the original
* declaration into an unscoped block or, if it already was, appends a new statement to the end
* of it.
*/
static void ReportErrors(PositionInfo pos);
static void AddVarDeclaration(DSLStatement& existing, DSLVar& additional);
static DSLWriter& Instance();
/**
* Clears any elements or symbols which have been output.
*/
static void Reset();
static void SetInstance(std::unique_ptr<DSLWriter> instance);
private:
class DefaultErrorReporter : public ErrorReporter {
void handleError(skstd::string_view msg, PositionInfo pos) override;
};
std::unique_ptr<SkSL::ProgramConfig> fConfig;
std::unique_ptr<SkSL::ModifiersPool> fModifiersPool;
SkSL::Compiler* fCompiler;
std::unique_ptr<Pool> fPool;
SkSL::ProgramConfig* fOldConfig;
SkSL::ModifiersPool* fOldModifiersPool;
std::vector<std::unique_ptr<SkSL::ProgramElement>> fProgramElements;
std::vector<const SkSL::ProgramElement*> fSharedElements;
DefaultErrorReporter fDefaultErrorReporter;
ErrorReporter& fOldErrorReporter;
ProgramSettings fSettings;
Mangler fMangler;
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
struct StackFrame {
GrFragmentProcessor::ProgramImpl* fProcessor;
GrFragmentProcessor::ProgramImpl::EmitArgs* fEmitArgs;
SkSL::StatementArray fSavedDeclarations;
};
std::stack<StackFrame, std::list<StackFrame>> fStack;
#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
static GrGLSLUniformHandler::UniformHandle VarUniformHandle(const DSLGlobalVar& var);
#endif
friend class DSLCore;
friend class DSLVar;

View File

@ -9,7 +9,7 @@
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLIntrinsicMap.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/ir/SkSLFunctionCall.h"
#include "src/sksl/ir/SkSLFunctionDefinition.h"
#include "src/sksl/ir/SkSLReturnStatement.h"
@ -64,7 +64,7 @@ std::unique_ptr<FunctionDefinition> FunctionDefinition::Convert(const Context& c
this->copyIntrinsicIfNeeded(*f);
}
dsl::DSLWriter::SharedElements().push_back(found);
ThreadContext::SharedElements().push_back(found);
}
}
@ -77,7 +77,7 @@ std::unique_ptr<FunctionDefinition> FunctionDefinition::Convert(const Context& c
const FunctionDeclaration& func = expr.as<FunctionCall>().function();
if (func.isBuiltin()) {
if (func.intrinsicKind() == k_dFdy_IntrinsicKind) {
dsl::DSLWriter::Inputs().fUseFlipRTUniform = true;
ThreadContext::Inputs().fUseFlipRTUniform = true;
}
if (func.definition()) {
fReferencedIntrinsics->insert(&func);

View File

@ -11,8 +11,8 @@
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLIntrinsicMap.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/analysis/SkSLProgramVisitor.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLFunctionDefinition.h"
#include "src/sksl/ir/SkSLInterfaceBlock.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
@ -67,7 +67,7 @@ void FindAndDeclareBuiltinVariables(const Context& context,
};
BuiltinVariableScanner scanner(context);
for (auto& e : dsl::DSLWriter::ProgramElements()) {
for (auto& e : ThreadContext::ProgramElements()) {
scanner.visitProgramElement(*e);
}

View File

@ -11,6 +11,7 @@
#include "src/gpu/GrGpu.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "tests/Test.h"
@ -42,7 +43,7 @@ public:
msg.data());
REPORTER_ASSERT(fReporter, pos.line() == fLine,
"Line number mismatch: expected %d, but received %d\n", fLine, pos.line());
DSLWriter::Compiler().handleError(msg, pos);
SkSL::ThreadContext::Compiler().handleError(msg, pos);
fMsg = nullptr;
}

View File

@ -11,6 +11,7 @@
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "tests/Test.h"
@ -1250,14 +1251,15 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLDecrement, r, ctxInfo) {
DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLCall, r, ctxInfo) {
AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
{
DSLExpression sqrt(DSLWriter::IRGenerator().convertIdentifier(/*line=*/-1, "sqrt"));
DSLExpression sqrt(SkSL::ThreadContext::IRGenerator().convertIdentifier(/*line=*/-1,
"sqrt"));
SkTArray<DSLWrapper<DSLExpression>> args;
args.emplace_back(16);
EXPECT_EQUAL(sqrt(std::move(args)), "4.0"); // sqrt(16) gets optimized to 4
}
{
DSLExpression pow(DSLWriter::IRGenerator().convertIdentifier(/*line=*/-1, "pow"));
DSLExpression pow(SkSL::ThreadContext::IRGenerator().convertIdentifier(/*line=*/-1, "pow"));
DSLVar a(kFloat_Type, "a");
DSLVar b(kFloat_Type, "b");
SkTArray<DSLWrapper<DSLExpression>> args;
@ -1289,8 +1291,8 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLBreak, r, ctxInfo) {
If(i > 5, Break())
))
);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0],
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
"void success() { for (int i = 0; (i < 10); ++i) { if ((i > 5)) break; } }");
{
@ -1309,8 +1311,8 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLContinue, r, ctxInfo) {
If(i < 5, Continue())
))
);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0],
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
"void success() { for (int i = 0; (i < 10); ++i) { if ((i < 5)) continue; } }");
{
@ -1339,25 +1341,25 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLDeclare, r, ctxInfo) {
{
DSLWriter::Reset();
REPORTER_ASSERT(r, DSLWriter::ProgramElements().empty());
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().empty());
GlobalVar a(kHalf4_Type, "a"), b(kHalf4_Type, "b", Half4(1));
Declare(a);
Declare(b);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 2);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "half4 a;");
EXPECT_EQUAL(*DSLWriter::ProgramElements()[1], "half4 b = half4(1.0);");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "half4 a;");
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1], "half4 b = half4(1.0);");
}
{
DSLWriter::Reset();
REPORTER_ASSERT(r, DSLWriter::ProgramElements().empty());
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().empty());
SkTArray<GlobalVar> vars;
vars.push_back(GlobalVar(kHalf4_Type, "a"));
vars.push_back(GlobalVar(kHalf4_Type, "b", Half4(1)));
Declare(vars);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 2);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "half4 a;");
EXPECT_EQUAL(*DSLWriter::ProgramElements()[1], "half4 b = half4(1.0);");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "half4 a;");
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1], "half4 b = half4(1.0);");
}
{
@ -1389,9 +1391,9 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLDeclareGlobal, r, ctxInfo) {
Declare(x);
DSLGlobalVar y(kUniform_Modifier, kFloat2_Type, "y");
Declare(y);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 2);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "int x = 0;");
EXPECT_EQUAL(*DSLWriter::ProgramElements()[1], "uniform float2 y;");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "int x = 0;");
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1], "uniform float2 y;");
}
DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLDiscard, r, ctxInfo) {
@ -1451,8 +1453,8 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLFunction, r, ctxInfo) {
DSLFunction(kVoid_Type, "main", coords).define(
sk_FragColor() = Half4(coords, 0, 1)
);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0],
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
"void main(float2 coords) { (sk_FragColor = half4(half2(coords), 0.0, 1.0)); }");
{
@ -1463,8 +1465,9 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLFunction, r, ctxInfo) {
Return(x * x)
);
EXPECT_EQUAL(sqr(sk_FragCoord().x()), "sqr(sk_FragCoord.x)");
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "float sqr(float x) { return (x * x); }");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
"float sqr(float x) { return (x * x); }");
}
{
@ -1477,8 +1480,8 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLFunction, r, ctxInfo) {
);
EXPECT_EQUAL(dot(Float2(1.0f, 2.0f), Float2(3.0f, 4.0f)),
"dot(float2(1.0, 2.0), float2(3.0, 4.0))");
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0],
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
"float2 dot(float2 x, float2 y) { return ((x * x) + (y * y)); }");
}
@ -1571,23 +1574,23 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLInterfaceBlock, r, ctxInfo) {
AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
DSLGlobalVar intf = InterfaceBlock(kUniform_Modifier, "InterfaceBlock1",
{ Field(kFloat_Type, "a"), Field(kInt_Type, "b") });
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements().back(),
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements().back(),
"uniform InterfaceBlock1 { float a; int b; };");
EXPECT_EQUAL(intf.field("a"), "InterfaceBlock1.a");
DSLGlobalVar intf2 = InterfaceBlock(kUniform_Modifier, "InterfaceBlock2",
{ Field(kFloat2_Type, "x"), Field(kHalf2x2_Type, "y") },
"blockVar");
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 2);
EXPECT_EQUAL(*DSLWriter::ProgramElements().back(),
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements().back(),
"uniform InterfaceBlock2 { float2 x; half2x2 y; } blockVar;");
EXPECT_EQUAL(intf2.field("x"), "blockVar.x");
DSLGlobalVar intf3 = InterfaceBlock(kUniform_Modifier, "InterfaceBlock3",
{ Field(kFloat_Type, "z") },"arrayVar", 4);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 3);
EXPECT_EQUAL(*DSLWriter::ProgramElements().back(),
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 3);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements().back(),
"uniform InterfaceBlock3 { float z; } arrayVar[4];");
EXPECT_EQUAL(intf3[1].field("z"), "arrayVar[1].z");
}
@ -1983,10 +1986,10 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLStruct, r, ctxInfo) {
result.field("a")[0] = result.field("x"),
Return(result)
);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 2);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0],
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
"struct SimpleStruct { float x; bool b; float[3] a; };");
EXPECT_EQUAL(*DSLWriter::ProgramElements()[1],
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1],
"SimpleStruct returnStruct() { SimpleStruct result; (result.x = 123.0);"
"(result.b = (result.x > 0.0)); (result.a[0] = result.x); return result; }");
@ -1994,8 +1997,8 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLStruct, r, ctxInfo) {
Field(kInt_Type, "x"),
Field(simpleStruct, "simple")
);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 3);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[2],
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 3);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[2],
"struct NestedStruct { int x; SimpleStruct simple; };");
}
@ -2021,8 +2024,8 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLRTAdjust, r, ctxInfo) {
DSLFunction(kVoid_Type, "main").define(
sk_Position() = Half4(0)
);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 2);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[1],
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1],
"void main() {"
"(sk_PerVertex.sk_Position = float4(0.0));"
"(sk_PerVertex.sk_Position = float4(((sk_PerVertex.sk_Position.xy * sk_RTAdjust.xz) + "
@ -2033,13 +2036,13 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLRTAdjust, r, ctxInfo) {
{
AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), no_mark_vars_declared(),
SkSL::ProgramKind::kVertex);
REPORTER_ASSERT(r, !DSLWriter::IRGenerator().haveRTAdjustInterfaceBlock());
REPORTER_ASSERT(r, !SkSL::ThreadContext::IRGenerator().haveRTAdjustInterfaceBlock());
DSLGlobalVar intf = InterfaceBlock(kUniform_Modifier, "uniforms",
{ Field(kInt_Type, "unused"),
Field(kFloat4_Type, "sk_RTAdjust") });
REPORTER_ASSERT(r, DSLWriter::IRGenerator().haveRTAdjustInterfaceBlock());
REPORTER_ASSERT(r, DSLWriter::IRGenerator().getRTAdjustFieldIndex() == 1);
REPORTER_ASSERT(r, SkSL::ThreadContext::IRGenerator().haveRTAdjustInterfaceBlock());
REPORTER_ASSERT(r, SkSL::ThreadContext::IRGenerator().getRTAdjustFieldIndex() == 1);
}
{
@ -2098,30 +2101,32 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLPrototypes, r, ctxInfo) {
{
DSLParameter x(kFloat_Type, "x");
DSLFunction sqr(kFloat_Type, "sqr", x);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "float sqr(float x);");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "float sqr(float x);");
sqr.define(
Return(x * x)
);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "float sqr(float x) { return (x * x); }");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
"float sqr(float x) { return (x * x); }");
}
{
DSLWriter::Reset();
DSLParameter x(kFloat_Type, "x");
DSLFunction sqr(kFloat_Type, "sqr", x);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "float sqr(float x);");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "float sqr(float x);");
DSLFunction(kVoid_Type, "main").define(sqr(5));
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 2);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "float sqr(float x);");
EXPECT_EQUAL(*DSLWriter::ProgramElements()[1], "void main() { sqr(5.0); }");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 2);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "float sqr(float x);");
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[1], "void main() { sqr(5.0); }");
sqr.define(
Return(x * x)
);
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 3);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[2], "float sqr(float x) { return (x * x); }");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 3);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[2],
"float sqr(float x) { return (x * x); }");
const char* source = "source test";
std::unique_ptr<SkSL::Program> p = ReleaseProgram(std::make_unique<SkSL::String>(source));
@ -2138,15 +2143,16 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLPrototypes, r, ctxInfo) {
DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLExtension, r, ctxInfo) {
AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
AddExtension("test_extension");
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "#extension test_extension : enable");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0], "#extension test_extension : enable");
}
DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLModifiersDeclaration, r, ctxInfo) {
AutoDSLContext context(ctxInfo.directContext()->priv().getGpu());
Declare(Modifiers(Layout().blendSupportAllEquations(), kOut_Modifier));
REPORTER_ASSERT(r, DSLWriter::ProgramElements().size() == 1);
EXPECT_EQUAL(*DSLWriter::ProgramElements()[0], "layout(blend_support_all_equations) out;");
REPORTER_ASSERT(r, SkSL::ThreadContext::ProgramElements().size() == 1);
EXPECT_EQUAL(*SkSL::ThreadContext::ProgramElements()[0],
"layout(blend_support_all_equations) out;");
}
DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLES3Types, r, ctxInfo) {