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:
parent
7656b2c18c
commit
0d997665e6
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -58,6 +58,7 @@ private:
|
||||
String fExtraEmitCodeCode;
|
||||
std::set<int> fWrittenTransformedCoords;
|
||||
std::vector<Compiler::FormatArg>* fFormatArgs;
|
||||
const FunctionDeclaration* fCurrentFunction;
|
||||
|
||||
typedef GLSLCodeGenerator INHERITED;
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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
8
src/sksl/sksl_mixer.inc
Normal file
@ -0,0 +1,8 @@
|
||||
STRINGIFY(
|
||||
in fragmentProcessor _child1;
|
||||
in fragmentProcessor _child2;
|
||||
|
||||
layout(builtin=10004) out half4 sk_OutColor;
|
||||
|
||||
half4 process(fragmentProcessor fp);
|
||||
)
|
Loading…
Reference in New Issue
Block a user