diff --git a/gn/sksl.gni b/gn/sksl.gni index c5c147a6cb..e9126d5211 100644 --- a/gn/sksl.gni +++ b/gn/sksl.gni @@ -13,6 +13,7 @@ skia_sksl_sources = [ "$_include/private/SkSLLayout.h", "$_include/private/SkSLModifiers.h", "$_include/private/SkSLProgramElement.h", + "$_include/private/SkSLProgramKind.h", "$_include/private/SkSLSampleUsage.h", "$_include/private/SkSLStatement.h", "$_include/private/SkSLString.h", diff --git a/include/private/SkSLProgramKind.h b/include/private/SkSLProgramKind.h new file mode 100644 index 0000000000..0af73f4e07 --- /dev/null +++ b/include/private/SkSLProgramKind.h @@ -0,0 +1,29 @@ +/* + * 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 SkSLProgramKind_DEFINED +#define SkSLProgramKind_DEFINED + +#include + +namespace SkSL { + +/** + * SkSL supports several different program kinds. + */ +enum class ProgramKind : int8_t { + kFragment, + kVertex, + kGeometry, + kFragmentProcessor, + kRuntimeEffect, + kGeneric, +}; + +} // namespace SkSL + +#endif diff --git a/include/sksl/DSLCore.h b/include/sksl/DSLCore.h index 9aaa692012..ab031e1c80 100644 --- a/include/sksl/DSLCore.h +++ b/include/sksl/DSLCore.h @@ -8,6 +8,7 @@ #ifndef SKSL_DSL_CORE #define SKSL_DSL_CORE +#include "include/private/SkSLProgramKind.h" #include "include/private/SkTArray.h" #include "include/sksl/DSLBlock.h" #include "include/sksl/DSLCase.h" @@ -34,7 +35,7 @@ using namespace SkSL::SwizzleComponent; * Starts DSL output on the current thread using the specified compiler. This must be called * prior to any other DSL functions. */ -void Start(SkSL::Compiler* compiler); +void Start(SkSL::Compiler* compiler, SkSL::ProgramKind kind = SkSL::ProgramKind::kFragment); /** * Signals the end of DSL output. This must be called sometime between a call to Start() and the @@ -350,6 +351,27 @@ DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos = Posit DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, PositionInfo pos = PositionInfo()); +/** + * Samples the child processor at the current coordinates. + */ +DSLExpression Sample(DSLExpression fp, PositionInfo pos = PositionInfo()); + +/** + * Implements the following functions: + * half4 sample(fragmentProcessor fp, float3x3 transform); + * half4 sample(fragmentProcessor fp, float2 coords); + * half4 sample(fragmentProcessor fp, half4 input); + */ +DSLExpression Sample(DSLExpression target, DSLExpression x, PositionInfo pos = PositionInfo()); + +/** + * Implements the following functions: + * half4 sample(fragmentProcessor fp, half4 input, float3x3 transform); + * half4 sample(fragmentProcessor fp, half4 input, float2 coords); + */ +DSLExpression Sample(DSLExpression childProcessor, DSLExpression x, DSLExpression y, + PositionInfo pos = PositionInfo()); + /** * Returns x clamped to the range [0, 1]. If x is a vector, operates componentwise. */ diff --git a/include/sksl/DSLType.h b/include/sksl/DSLType.h index 645f9ba426..bc2eb82e9b 100644 --- a/include/sksl/DSLType.h +++ b/include/sksl/DSLType.h @@ -34,6 +34,7 @@ enum TypeConstant : uint8_t { kFloat2_Type, kFloat3_Type, kFloat4_Type, + kFragmentProcessor_Type, kInt_Type, kInt2_Type, kInt3_Type, diff --git a/src/sksl/SkSLProgramSettings.h b/src/sksl/SkSLProgramSettings.h index f2edddd6ad..66260a1678 100644 --- a/src/sksl/SkSLProgramSettings.h +++ b/src/sksl/SkSLProgramSettings.h @@ -9,21 +9,10 @@ #define SKSL_PROGRAMSETTINGS #include "include/private/SkSLDefines.h" +#include "include/private/SkSLProgramKind.h" namespace SkSL { -/** - * SkSL supports several different program kinds. - */ -enum class ProgramKind : int8_t { - kFragment, - kVertex, - kGeometry, - kFragmentProcessor, - kRuntimeEffect, - kGeneric, -}; - /** * Holds the compiler settings for a program. */ diff --git a/src/sksl/dsl/DSLCore.cpp b/src/sksl/dsl/DSLCore.cpp index 28c2f275cd..ebdb9f9907 100644 --- a/src/sksl/dsl/DSLCore.cpp +++ b/src/sksl/dsl/DSLCore.cpp @@ -25,9 +25,8 @@ namespace SkSL { namespace dsl { -#if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE) -void Start(SkSL::Compiler* compiler) { - DSLWriter::SetInstance(std::make_unique(compiler)); +void Start(SkSL::Compiler* compiler, ProgramKind kind) { + DSLWriter::SetInstance(std::make_unique(compiler, kind)); } void End() { @@ -35,7 +34,6 @@ void End() { "more calls to StartFragmentProcessor than to EndFragmentProcessor"); DSLWriter::SetInstance(nullptr); } -#endif // SK_SUPPORT_GPU && !defined(SKSL_STANDALONE) void SetErrorHandler(ErrorHandler* errorHandler) { DSLWriter::SetErrorHandler(errorHandler); @@ -361,6 +359,20 @@ DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, Posit return DSLExpression(DSLCore::Call("refract", std::move(i), std::move(n), std::move(eta)), pos); } +DSLExpression Sample(DSLExpression target, PositionInfo pos) { + return DSLExpression(DSLCore::Call("sample", std::move(target)), pos); +} + + +DSLExpression Sample(DSLExpression target, DSLExpression x, PositionInfo pos) { + return DSLExpression(DSLCore::Call("sample", std::move(target), std::move(x)), pos); +} + +DSLExpression Sample(DSLExpression target, DSLExpression x, DSLExpression y, PositionInfo pos) { + return DSLExpression(DSLCore::Call("sample", std::move(target), std::move(x), std::move(y)), + pos); +} + DSLExpression Saturate(DSLExpression x, PositionInfo pos) { return DSLExpression(DSLCore::Call("saturate", std::move(x)), pos); } diff --git a/src/sksl/dsl/DSLType.cpp b/src/sksl/dsl/DSLType.cpp index e7a920f02a..bd6600ecc4 100644 --- a/src/sksl/dsl/DSLType.cpp +++ b/src/sksl/dsl/DSLType.cpp @@ -45,6 +45,8 @@ const SkSL::Type& DSLType::skslType() const { return *context.fTypes.fFloat3; case kFloat4_Type: return *context.fTypes.fFloat4; + case kFragmentProcessor_Type: + return *context.fTypes.fFragmentProcessor; case kInt_Type: return *context.fTypes.fInt; case kInt2_Type: diff --git a/src/sksl/dsl/priv/DSLWriter.cpp b/src/sksl/dsl/priv/DSLWriter.cpp index b1720d59de..a5ee744667 100644 --- a/src/sksl/dsl/priv/DSLWriter.cpp +++ b/src/sksl/dsl/priv/DSLWriter.cpp @@ -31,10 +31,10 @@ namespace SkSL { namespace dsl { -DSLWriter::DSLWriter(SkSL::Compiler* compiler) +DSLWriter::DSLWriter(SkSL::Compiler* compiler, SkSL::ProgramKind kind) : fCompiler(compiler) { - SkSL::ParsedModule module = fCompiler->moduleForProgramKind(SkSL::ProgramKind::kFragment); - fConfig.fKind = SkSL::ProgramKind::kFragment; + SkSL::ParsedModule module = fCompiler->moduleForProgramKind(kind); + fConfig.fKind = kind; SkSL::IRGenerator& ir = *fCompiler->fIRGenerator; fOldSymbolTable = ir.fSymbolTable; diff --git a/src/sksl/dsl/priv/DSLWriter.h b/src/sksl/dsl/priv/DSLWriter.h index a60b975c7b..5a2a5a6794 100644 --- a/src/sksl/dsl/priv/DSLWriter.h +++ b/src/sksl/dsl/priv/DSLWriter.h @@ -43,7 +43,7 @@ class ErrorHandler; */ class DSLWriter { public: - DSLWriter(SkSL::Compiler* compiler); + DSLWriter(SkSL::Compiler* compiler, SkSL::ProgramKind kind); ~DSLWriter(); @@ -140,6 +140,10 @@ public: static void EndFragmentProcessor(); static GrGLSLUniformHandler::UniformHandle VarUniformHandle(const DSLVar& var); +#else + static bool InFragmentProcessor() { + return false; + } #endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU static std::unique_ptr Call(const FunctionDeclaration& function, diff --git a/tests/SkSLDSLTest.cpp b/tests/SkSLDSLTest.cpp index 4fdd82a9cf..e15b0fdb13 100644 --- a/tests/SkSLDSLTest.cpp +++ b/tests/SkSLDSLTest.cpp @@ -27,8 +27,9 @@ using namespace SkSL::dsl; */ class AutoDSLContext { public: - AutoDSLContext(GrGpu* gpu, bool markVarsDeclared = true) { - Start(gpu->shaderCompiler()); + AutoDSLContext(GrGpu* gpu, bool markVarsDeclared = true, + SkSL::ProgramKind kind = SkSL::ProgramKind::kFragment) { + Start(gpu->shaderCompiler(), kind); DSLWriter::Instance().fMangle = false; DSLWriter::Instance().fMarkVarsDeclared = markVarsDeclared; } @@ -1394,6 +1395,21 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLModifiers, r, ctxInfo) { // Uniforms do not need to be explicitly declared } +DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLSample, r, ctxInfo) { + AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), /*markVarsDeclared=*/true, + SkSL::ProgramKind::kFragmentProcessor); + DSLVar child(kUniform_Modifier, kFragmentProcessor_Type, "child"); + EXPECT_EQUAL(Sample(child), "sample(child)"); + EXPECT_EQUAL(Sample(child, Float2(0, 0)), "sample(child, float2(0.0, 0.0))"); + EXPECT_EQUAL(Sample(child, Half4(1)), "sample(child, half4(1.0))"); + EXPECT_EQUAL(Sample(child, Half4(1), Float2(0)), "sample(child, half4(1.0), float2(0.0))"); + + { + ExpectError error(r, "error: no match for sample(fragmentProcessor, bool)\n"); + Sample(child, true).release(); + } +} + DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLStruct, r, ctxInfo) { AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), /*markVarsDeclared=*/false);