blob: cb712856f639764960b2303b19e3121f82abd977 [file] [log] [blame]
/*
* 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 "include/sksl/DSLVar.h"
#include "include/sksl/DSLModifiers.h"
#include "include/sksl/DSLType.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
#include "src/sksl/ir/SkSLVariable.h"
#include "src/sksl/ir/SkSLVariableReference.h"
namespace SkSL {
namespace dsl {
DSLVar::DSLVar(const char* name)
: fType(kVoid_Type)
, fRawName(name)
, fName(name)
, fDeclared(true) {
#if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
if (!strcmp(name, "sk_SampleCoord")) {
fName = DSLWriter::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.
fVar = DSLWriter::SymbolTable()->takeOwnershipOfIRNode(
std::make_unique<SkSL::Variable>(
/*offset=*/-1,
DSLWriter::IRGenerator().fModifiers->addToPool(
SkSL::Modifiers(
SkSL::Layout(/*flags=*/0, /*location=*/-1, /*offset=*/-1,
/*binding=*/-1, /*index=*/-1, /*set=*/-1,
SK_MAIN_COORDS_BUILTIN,
/*inputAttachmentIndex=*/-1,
Layout::kUnspecified_Primitive,
/*maxVertices=*/1, /*invocations=*/-1,
/*when=*/"", Layout::CType::kDefault),
SkSL::Modifiers::kNo_Flag)),
fName,
DSLWriter::Context().fTypes.fFloat2.get(),
/*builtin=*/true,
SkSL::VariableStorage::kGlobal));
return;
}
#endif
const SkSL::Symbol* result = (*DSLWriter::SymbolTable())[fName];
SkASSERTF(result, "could not find '%s' in symbol table", fName);
fVar = &result->as<SkSL::Variable>();
}
DSLVar::DSLVar(DSLType type, const char* name, DSLExpression initialValue)
: DSLVar(DSLModifiers(), std::move(type), name, std::move(initialValue)) {}
DSLVar::DSLVar(DSLType type, DSLExpression initialValue)
: DSLVar(type, "var", std::move(initialValue)) {}
DSLVar::DSLVar(DSLModifiers modifiers, DSLType type, DSLExpression initialValue)
: DSLVar(modifiers, type, "var", std::move(initialValue)) {}
DSLVar::DSLVar(DSLModifiers modifiers, DSLType type, const char* name, DSLExpression initialValue)
: fModifiers(std::move(modifiers))
, fType(std::move(type))
, fRawName(name)
, fName(fType.skslType().isOpaque() ? name : DSLWriter::Name(name))
, fInitialValue(std::move(initialValue))
, fStorage(Variable::Storage::kLocal)
, fDeclared(DSLWriter::Instance().fMarkVarsDeclared) {
#if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
if (fModifiers.fModifiers.fFlags & Modifiers::kUniform_Flag) {
fStorage = Variable::Storage::kGlobal;
if (DSLWriter::InFragmentProcessor()) {
const SkSL::Type& skslType = type.skslType();
GrSLType grslType;
int count;
if (skslType.isArray()) {
SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(),
skslType.componentType(),
&grslType));
count = skslType.columns();
SkASSERT(count > 0);
} else {
SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(), skslType,
&grslType));
count = 0;
}
const char* name;
SkASSERT(DSLWriter::CurrentEmitArgs());
fUniformHandle = DSLWriter::CurrentEmitArgs()->fUniformHandler->addUniformArray(
&DSLWriter::CurrentEmitArgs()->fFp,
kFragment_GrShaderFlag,
grslType,
this->name(),
count,
&name).toIndex();
fName = name;
}
fDeclared = true;
}
#endif // SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
}
DSLVar::~DSLVar() {
if (!fDeclared) {
DSLWriter::ReportError(String::printf("error: variable '%s' was destroyed without being "
"declared\n", fRawName).c_str());
}
}
DSLPossibleExpression DSLVar::operator[](DSLExpression&& index) {
return DSLExpression(*this)[std::move(index)];
}
DSLPossibleExpression DSLVar::operator=(DSLExpression expr) {
return DSLWriter::ConvertBinary(DSLExpression(*this).release(), SkSL::Token::Kind::TK_EQ,
expr.release());
}
} // namespace dsl
} // namespace SkSL