Revert "Reland "Revert "Reland "GPU support for SkMixers""""

This reverts commit 1263889f3a.

Bug: skia:
Change-Id: I647cb228e4a8169f12f4afadaf1db06843e4e5fd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/206391
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2019-04-08 09:46:01 -04:00 committed by Skia Commit-Bot
parent 7656b2c18c
commit 0d997665e6
14 changed files with 252 additions and 104 deletions

View File

@ -34,7 +34,9 @@ DEF_SIMPLE_GPU_GM(runtimecolorfilter, context, rtc, canvas, 768, 256) {
float b = 0.75;
sk_sp<SkData> data = SkData::MakeWithCopy(&b, sizeof(b));
auto cf1 = SkRuntimeColorFilterFactory(SkString(SKSL_TEST_SRC), runtimeCpuFunc).make(data);
static SkRuntimeColorFilterFactory fact = SkRuntimeColorFilterFactory(SkString(SKSL_TEST_SRC),
runtimeCpuFunc);
auto cf1 = fact.make(data);
SkPaint p;
p.setColorFilter(cf1);
canvas->drawImage(img, 256, 0, &p);
@ -57,7 +59,9 @@ DEF_SIMPLE_GM(runtimecolorfilter_interpreted, canvas, 768, 256) {
float b = 0.75;
sk_sp<SkData> data = SkData::MakeWithCopy(&b, sizeof(b));
auto cf1 = SkRuntimeColorFilterFactory(SkString(SKSL_TEST_SRC), nullptr).make(data);
static SkRuntimeColorFilterFactory fact = SkRuntimeColorFilterFactory(SkString(SKSL_TEST_SRC),
nullptr);
auto cf1 = fact.make(data);
SkPaint p;
p.setColorFilter(cf1);
canvas->drawImage(img, 256, 0, &p);

View File

@ -8,13 +8,36 @@
#include "SkBlendModePriv.h"
#include "SkEffectPriv.h"
#include "SkMixerBase.h"
#include "SkMixerShader.h"
#include "SkReadBuffer.h"
#include "SkRasterPipeline.h"
#include "SkWriteBuffer.h"
#if SK_SUPPORT_GPU
#include "GrRecordingContext.h"
#include "effects/GrConstColorProcessor.h"
#include "effects/GrSkSLFP.h"
#include "effects/GrXfermodeFragmentProcessor.h"
static std::unique_ptr<GrFragmentProcessor> sksl_mixer_fp(
const GrFPArgs& args,
int index,
const char* sksl,
sk_sp<SkData> inputs,
std::unique_ptr<GrFragmentProcessor> fp1,
std::unique_ptr<GrFragmentProcessor> fp2,
std::unique_ptr<GrFragmentProcessor> fp3 = nullptr) {
std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(args.fContext, index, "Runtime Mixer", sksl,
inputs ? inputs->data() : nullptr,
inputs ? inputs->size() : 0,
SkSL::Program::kMixer_Kind);
result->addChild(std::move(fp1));
result->addChild(std::move(fp2));
if (fp3) {
result->addChild(std::move(fp3));
}
return std::move(result);
}
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -37,9 +60,9 @@ public:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor>
asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
// return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
return nullptr;
asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
const sk_sp<SkShader> shader2) const override {
return GrConstColorProcessor::Make(fPM, GrConstColorProcessor::InputMode::kIgnore);
}
#endif
};
@ -82,9 +105,9 @@ public:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor>
asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
// return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
return nullptr;
asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
const sk_sp<SkShader> shader2) const override {
return as_MB(fProxy)->asFragmentProcessor(args, shader2, shader1);
}
#endif
};
@ -114,9 +137,18 @@ public:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor>
asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
// return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
return nullptr;
asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
const sk_sp<SkShader> shader2) const override {
std::unique_ptr<GrFragmentProcessor> fp1 = as_SB(shader1)->asFragmentProcessor(args);
if (!fp1) {
return nullptr;
}
std::unique_ptr<GrFragmentProcessor> fp2 = as_SB(shader2)->asFragmentProcessor(args);
if (!fp2) {
return nullptr;
}
return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fp2), std::move(fp1),
fMode);
}
#endif
};
@ -151,9 +183,26 @@ public:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor>
asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
// return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
return nullptr;
asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
const sk_sp<SkShader> shader2) const override {
std::unique_ptr<GrFragmentProcessor> fp1 = as_SB(shader1)->asFragmentProcessor(args);
if (!fp1) {
return nullptr;
}
std::unique_ptr<GrFragmentProcessor> fp2 = as_SB(shader2)->asFragmentProcessor(args);
if (!fp2) {
return nullptr;
}
static int index = GrSkSLFP::NewIndex();
return sksl_mixer_fp(args,
index,
"in uniform float weight;"
"void main(half4 input1, half4 input2) {"
" sk_OutColor = mix(input1, input2, half(weight));"
"}",
SkData::MakeWithCopy(&fWeight, sizeof(fWeight)),
std::move(fp1),
std::move(fp2));
}
#endif
};
@ -206,8 +255,31 @@ public:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor>
asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
return nullptr;
asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
const sk_sp<SkShader> shader2) const override {
std::unique_ptr<GrFragmentProcessor> fp1 = as_SB(shader1)->asFragmentProcessor(args);
if (!fp1) {
return nullptr;
}
std::unique_ptr<GrFragmentProcessor> fp2 = as_SB(shader2)->asFragmentProcessor(args);
if (!fp2) {
return nullptr;
}
std::unique_ptr<GrFragmentProcessor> fp3 = as_SB(fShader)->asFragmentProcessor(args);
if (!fp3) {
return nullptr;
}
static int index = GrSkSLFP::NewIndex();
return sksl_mixer_fp(args,
index,
"in fragmentProcessor lerpControl;"
"void main(half4 input1, half4 input2) {"
" sk_OutColor = mix(input1, input2, process(lerpControl).r);"
"}",
nullptr,
std::move(fp1),
std::move(fp2),
std::move(fp3));
}
#endif
};
@ -276,9 +348,11 @@ public:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor>
asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
// return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
return nullptr;
asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
const sk_sp<SkShader> shader2) const override {
return SkShader_Mixer(sk_sp<SkShader>(new SkShader_Mixer(shader1, shader2, fM0)),
sk_sp<SkShader>(new SkShader_Mixer(shader1, shader2, fM1)),
fCombine).asFragmentProcessor(args);
}
#endif
};

View File

@ -5,13 +5,14 @@
* found in the LICENSE file.
*/
#ifndef SkMixerPriv_DEFINED
#define SkMixerPriv_DEFINED
#ifndef SkMixerBase_DEFINED
#define SkMixerBase_DEFINED
#include "SkMixer.h"
#include "SkColorData.h"
class GrColorSpaceInfo;
struct GrFPArgs;
class GrFragmentProcessor;
class GrRecordingContext;
struct SkStageRec;
@ -31,8 +32,9 @@ public:
*
* A null return indicates that the color filter isn't implemented for the GPU backend.
*/
virtual std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const = 0;
virtual std::unique_ptr<GrFragmentProcessor>
asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
const sk_sp<SkShader> shader2) const = 0;
#endif
static void RegisterFlattenables();

View File

@ -16,13 +16,13 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramBuilder.h"
GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl)
: fName(name) {
GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl,
SkSL::Program::Kind kind)
: fKind(kind)
, fName(name) {
SkSL::Program::Settings settings;
settings.fCaps = shaderCaps;
fBaseProgram = fCompiler.convertProgram(SkSL::Program::kPipelineStage_Kind,
SkSL::String(sksl),
settings);
fBaseProgram = fCompiler.convertProgram(fKind, SkSL::String(sksl), settings);
if (fCompiler.errorCount()) {
SkDebugf("%s\n", fCompiler.errorText().c_str());
}
@ -83,7 +83,11 @@ const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key,
}
std::unique_ptr<SkSL::Program> specialized = fCompiler.specialize(*fBaseProgram, inputMap);
SkAssertResult(fCompiler.optimize(*specialized));
bool optimized = fCompiler.optimize(*specialized);
if (!optimized) {
SkDebugf("%s\n", fCompiler.errorText().c_str());
SkASSERT(false);
}
const SkSL::Program* result = specialized.get();
fSpecializations.insert(std::make_pair(key, std::move(specialized)));
return result;
@ -269,34 +273,38 @@ public:
std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, const char* name,
const char* sksl, const void* inputs,
size_t inputSize) {
size_t inputSize, SkSL::Program::Kind kind) {
return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
context->priv().caps()->shaderCaps(),
index, name, sksl, SkString(), inputs,
inputSize));
kind, index, name, sksl, SkString(),
inputs, inputSize));
}
std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, const char* name,
SkString sksl, const void* inputs, size_t inputSize) {
SkString sksl, const void* inputs, size_t inputSize,
SkSL::Program::Kind kind) {
return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
context->priv().caps()->shaderCaps(),
index, name, nullptr, std::move(sksl), inputs,
inputSize));
kind, index, name, nullptr, std::move(sksl),
inputs, inputSize));
}
GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
int index, const char* name, const char* sksl, SkString skslString,
const void* inputs, size_t inputSize)
SkSL::Program::Kind kind, int index, const char* name, const char* sksl,
SkString skslString, const void* inputs, size_t inputSize)
: INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
, fFactoryCache(factoryCache)
, fShaderCaps(sk_ref_sp(shaderCaps))
, fKind(kind)
, fIndex(index)
, fName(name)
, fSkSLString(skslString)
, fSkSL(sksl ? sksl : fSkSLString.c_str())
, fInputs(new int8_t[inputSize])
, fInputSize(inputSize) {
memcpy(fInputs.get(), inputs, inputSize);
if (fInputSize) {
memcpy(fInputs.get(), inputs, inputSize);
}
}
GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
@ -304,13 +312,16 @@ GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
, fFactoryCache(other.fFactoryCache)
, fShaderCaps(other.fShaderCaps)
, fFactory(other.fFactory)
, fKind(other.fKind)
, fIndex(other.fIndex)
, fName(other.fName)
, fSkSLString(other.fSkSLString)
, fSkSL(other.fSkSL)
, fInputs(new int8_t[other.fInputSize])
, fInputSize(other.fInputSize) {
memcpy(fInputs.get(), other.fInputs.get(), fInputSize);
if (fInputSize) {
memcpy(fInputs.get(), other.fInputs.get(), fInputSize);
}
}
const char* GrSkSLFP::name() const {
@ -321,7 +332,8 @@ void GrSkSLFP::createFactory() const {
if (!fFactory) {
fFactory = fFactoryCache->get(fIndex);
if (!fFactory) {
fFactory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(fName, fShaderCaps.get(), fSkSL));
fFactory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(fName, fShaderCaps.get(), fSkSL,
fKind));
fFactoryCache->set(fIndex, fFactory);
}
}
@ -346,6 +358,7 @@ GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {
this->createFactory();
b->add32(fIndex);
size_t offset = 0;
char* inputs = (char*) fInputs.get();
const SkSL::Context& context = fFactory->fCompiler.context();

View File

@ -73,7 +73,8 @@ public:
const char* name,
const char* sksl,
const void* inputs,
size_t inputSize);
size_t inputSize,
SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
static std::unique_ptr<GrSkSLFP> Make(
GrContext_Base* context,
@ -81,7 +82,8 @@ public:
const char* name,
SkString sksl,
const void* inputs,
size_t inputSize);
size_t inputSize,
SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
const char* name() const override;
@ -90,9 +92,9 @@ public:
std::unique_ptr<GrFragmentProcessor> clone() const override;
private:
GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps, int fIndex,
const char* name, const char* sksl, SkString skslString, const void* inputs,
size_t inputSize);
GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
SkSL::Program::Kind kind, int fIndex, const char* name, const char* sksl,
SkString skslString, const void* inputs, size_t inputSize);
GrSkSLFP(const GrSkSLFP& other);
@ -110,6 +112,8 @@ private:
mutable sk_sp<GrSkSLFPFactory> fFactory;
SkSL::Program::Kind fKind;
int fIndex;
const char* fName;
@ -152,11 +156,14 @@ public:
* the produced shaders to differ), so it is important to reuse the same factory instance for
* the same shader in order to avoid repeatedly re-parsing the SkSL.
*/
GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl);
GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl,
SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs,
size_t inputSize);
SkSL::Program::Kind fKind;
const char* fName;
SkSL::Compiler fCompiler;

View File

@ -73,17 +73,6 @@ bool SkShader_Mixer::onAppendStages(const SkStageRec& rec) const {
std::unique_ptr<GrFragmentProcessor>
SkShader_Mixer::asFragmentProcessor(const GrFPArgs& args) const {
std::unique_ptr<GrFragmentProcessor> fpA(as_SB(fShader0)->asFragmentProcessor(args));
if (!fpA) {
return nullptr;
}
std::unique_ptr<GrFragmentProcessor> fpB(as_SB(fShader1)->asFragmentProcessor(args));
if (!fpB) {
return nullptr;
}
// TODO: need to make a mixer-processor...
return nullptr;
//return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
return as_MB(fMixer)->asFragmentProcessor(args, fShader0, fShader1);
}
#endif

View File

@ -451,6 +451,10 @@ void CFGGenerator::addLValue(CFG& cfg, std::unique_ptr<Expression>* e) {
}
}
static bool is_true(Expression& expr) {
return expr.fKind == Expression::kBoolLiteral_Kind && ((BoolLiteral&) expr).fValue;
}
void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
switch ((*s)->fKind) {
case Statement::kBlock_Kind:
@ -536,7 +540,9 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
fLoopExits.push(loopExit);
this->addExpression(cfg, &w.fTest, true);
BlockId test = cfg.fCurrent;
cfg.addExit(test, loopExit);
if (!is_true(*w.fTest)) {
cfg.addExit(test, loopExit);
}
cfg.newBlock();
this->addStatement(cfg, &w.fStatement);
cfg.addExit(cfg.fCurrent, loopStart);

View File

@ -61,6 +61,10 @@ static const char* SKSL_PIPELINE_STAGE_INCLUDE =
#include "sksl_pipeline.inc"
;
static const char* SKSL_MIXER_INCLUDE =
#include "sksl_mixer.inc"
;
namespace SkSL {
Compiler::Compiler(Flags flags)
@ -1268,6 +1272,13 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
strlen(SKSL_PIPELINE_STAGE_INCLUDE), *fTypes, &elements);
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
break;
case Program::kMixer_Kind:
inherited = nullptr;
fIRGenerator->start(&settings, nullptr);
fIRGenerator->convertProgram(kind, SKSL_MIXER_INCLUDE, strlen(SKSL_MIXER_INCLUDE),
*fTypes, &elements);
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
break;
}
for (auto& element : elements) {
if (element->fKind == ProgramElement::kEnum_Kind) {

View File

@ -673,6 +673,10 @@ std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
}
// returns true if the modifiers are (explicitly or implicitly) nothing but 'in'
static bool is_in(const Modifiers& modifiers) {
return (modifiers.fFlags & ~Modifiers::kIn_Flag) == 0;
}
void IRGenerator::convertFunction(const ASTFunction& f) {
const Type* returnType = this->convertType(*f.fReturnType);
@ -700,33 +704,51 @@ void IRGenerator::convertFunction(const ASTFunction& f) {
}
if (f.fName == "main") {
if (fKind == Program::kPipelineStage_Kind) {
bool valid;
switch (parameters.size()) {
case 3:
valid = parameters[0]->fType == *fContext.fInt_Type &&
parameters[0]->fModifiers.fFlags == 0 &&
parameters[1]->fType == *fContext.fInt_Type &&
parameters[1]->fModifiers.fFlags == 0 &&
parameters[2]->fType == *fContext.fHalf4_Type &&
parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag |
Modifiers::kOut_Flag);
break;
case 1:
valid = parameters[0]->fType == *fContext.fHalf4_Type &&
parameters[0]->fModifiers.fFlags == (Modifiers::kIn_Flag |
Modifiers::kOut_Flag);
break;
default:
valid = false;
switch (fKind) {
case Program::kPipelineStage_Kind: {
bool valid;
switch (parameters.size()) {
case 3:
valid = parameters[0]->fType == *fContext.fInt_Type &&
parameters[0]->fModifiers.fFlags == 0 &&
parameters[1]->fType == *fContext.fInt_Type &&
parameters[1]->fModifiers.fFlags == 0 &&
parameters[2]->fType == *fContext.fHalf4_Type &&
parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag |
Modifiers::kOut_Flag);
break;
case 1:
valid = parameters[0]->fType == *fContext.fHalf4_Type &&
parameters[0]->fModifiers.fFlags == (Modifiers::kIn_Flag |
Modifiers::kOut_Flag);
break;
default:
valid = false;
}
if (!valid) {
fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(int, "
"int, inout half4) or main(inout half4)");
return;
}
break;
}
if (!valid) {
fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(int, "
"int, inout half4) or main(inout half4)");
return;
case Program::kMixer_Kind: {
if (*returnType != *fContext.fVoid_Type ||
parameters.size() != 2 ||
parameters[0]->fType != *fContext.fHalf4_Type ||
!is_in(parameters[0]->fModifiers) ||
parameters[1]->fType != *fContext.fHalf4_Type ||
!is_in(parameters[1]->fModifiers)) {
fErrors.error(f.fOffset, "mixer stage 'main' must be declared void main("
"half4, half4)");
return;
}
break;
}
} else if (parameters.size()) {
fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
default:
if (parameters.size()) {
fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
}
}
}

View File

@ -59,7 +59,7 @@ String PipelineStageCodeGenerator::getTypeName(const Type& type) {
}
void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Precedence parentPrecedence) {
Precedence parentPrecedence) {
if (b.fOperator == Token::PERCENT) {
// need to use "%%" instead of "%" b/c the code will be inside of a printf
Precedence precedence = GetBinaryPrecedence(b.fOperator);
@ -147,8 +147,7 @@ void PipelineStageCodeGenerator::writeVariableReference(const VariableReference&
found = true;
break;
}
if (var.fModifiers.fFlags & (Modifiers::kIn_Flag |
Modifiers::kUniform_Flag)) {
if (var.fModifiers.fFlags & Modifiers::kUniform_Flag) {
++index;
}
}
@ -157,8 +156,20 @@ void PipelineStageCodeGenerator::writeVariableReference(const VariableReference&
SkASSERT(found);
fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform,
index));
}
else {
} else if (fProgramKind == Program::kMixer_Kind &&
ref.fVariable.fStorage == Variable::kParameter_Storage &&
fCurrentFunction->fName == "main") {
this->write("%s");
for (size_t i = 0; i < fCurrentFunction->fParameters.size(); ++i) {
if (fCurrentFunction->fParameters[i] == &ref.fVariable) {
fFormatArgs->push_back(Compiler::FormatArg(
Compiler::FormatArg::Kind::kChildProcessor,
i));
return;
}
}
SkASSERT(false);
} else {
this->write(ref.fVariable.fName);
}
}
@ -179,6 +190,7 @@ void PipelineStageCodeGenerator::writeSwitchStatement(const SwitchStatement& s)
}
void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
fCurrentFunction = &f.fDeclaration;
if (f.fDeclaration.fName == "main") {
fFunctionHeader = "";
OutputStream* oldOut = fOut;

View File

@ -58,6 +58,7 @@ private:
String fExtraEmitCodeCode;
std::set<int> fWrittenTransformedCoords;
std::vector<Compiler::FormatArg>* fFormatArgs;
const FunctionDeclaration* fCurrentFunction;
typedef GLSLCodeGenerator INHERITED;
};

View File

@ -2954,23 +2954,16 @@ void SPIRVCodeGenerator::writeForStatement(const ForStatement& f, OutputStream&
}
void SPIRVCodeGenerator::writeWhileStatement(const WhileStatement& w, OutputStream& out) {
// We believe the while loop code below will work, but Skia doesn't actually use them and
// adequately testing this code in the absence of Skia exercising it isn't straightforward. For
// the time being, we just fail with an error due to the lack of testing. If you encounter this
// message, simply remove the error call below to see whether our while loop support actually
// works.
fErrors.error(w.fOffset, "internal error: while loop support has been disabled in SPIR-V, "
"see SkSLSPIRVCodeGenerator.cpp for details");
SpvId header = this->nextId();
SpvId start = this->nextId();
SpvId body = this->nextId();
fContinueTarget.push(start);
SpvId continueTarget = this->nextId();
fContinueTarget.push(continueTarget);
SpvId end = this->nextId();
fBreakTarget.push(end);
this->writeInstruction(SpvOpBranch, header, out);
this->writeLabel(header, out);
this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out);
this->writeInstruction(SpvOpLoopMerge, end, continueTarget, SpvLoopControlMaskNone, out);
this->writeInstruction(SpvOpBranch, start, out);
this->writeLabel(start, out);
SpvId test = this->writeExpression(*w.fTest, out);
@ -2978,8 +2971,10 @@ void SPIRVCodeGenerator::writeWhileStatement(const WhileStatement& w, OutputStre
this->writeLabel(body, out);
this->writeStatement(*w.fStatement, out);
if (fCurrentBlock) {
this->writeInstruction(SpvOpBranch, start, out);
this->writeInstruction(SpvOpBranch, continueTarget, out);
}
this->writeLabel(continueTarget, out);
this->writeInstruction(SpvOpBranch, header, out);
this->writeLabel(end, out);
fBreakTarget.pop();
fContinueTarget.pop();
@ -2997,12 +2992,13 @@ void SPIRVCodeGenerator::writeDoStatement(const DoStatement& d, OutputStream& ou
SpvId header = this->nextId();
SpvId start = this->nextId();
SpvId next = this->nextId();
fContinueTarget.push(next);
SpvId continueTarget = this->nextId();
fContinueTarget.push(continueTarget);
SpvId end = this->nextId();
fBreakTarget.push(end);
this->writeInstruction(SpvOpBranch, header, out);
this->writeLabel(header, out);
this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out);
this->writeInstruction(SpvOpLoopMerge, end, continueTarget, SpvLoopControlMaskNone, out);
this->writeInstruction(SpvOpBranch, start, out);
this->writeLabel(start, out);
this->writeStatement(*d.fStatement, out);
@ -3011,7 +3007,9 @@ void SPIRVCodeGenerator::writeDoStatement(const DoStatement& d, OutputStream& ou
}
this->writeLabel(next, out);
SpvId test = this->writeExpression(*d.fTest, out);
this->writeInstruction(SpvOpBranchConditional, test, start, end, out);
this->writeInstruction(SpvOpBranchConditional, test, continueTarget, end, out);
this->writeLabel(continueTarget, out);
this->writeInstruction(SpvOpBranch, header, out);
this->writeLabel(end, out);
fBreakTarget.pop();
fContinueTarget.pop();

View File

@ -213,7 +213,8 @@ struct Program {
kVertex_Kind,
kGeometry_Kind,
kFragmentProcessor_Kind,
kPipelineStage_Kind
kPipelineStage_Kind,
kMixer_Kind
};
Program(Kind kind,

8
src/sksl/sksl_mixer.inc Normal file
View File

@ -0,0 +1,8 @@
STRINGIFY(
in fragmentProcessor _child1;
in fragmentProcessor _child2;
layout(builtin=10004) out half4 sk_OutColor;
half4 process(fragmentProcessor fp);
)