use same signature for shader/colorfilters in sksl
'void main(float x, float y, inout half4 color)' For colorfilters, x,y are uninitialized For shaders, color is paint-color Change-Id: I21c2f570702f117d33646bd8fba0ab4def20a118 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/227439 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
parent
0f78174b39
commit
8c31f2bf7f
@ -28,7 +28,7 @@ class GrRenderTargetContext;
|
||||
const char* SKSL_TEST_SRC = R"(
|
||||
layout(ctype=float) in uniform half b;
|
||||
|
||||
void main(inout half4 color) {
|
||||
void main(float x, float y, inout half4 color) {
|
||||
color.a = color.r*0.3 + color.g*0.6 + color.b*0.1;
|
||||
color.r = 0;
|
||||
color.g = 0;
|
||||
|
@ -25,13 +25,15 @@ extern sk_sp<SkShader> SkRuntimeShaderMaker(SkString sksl, sk_sp<SkData> inputs,
|
||||
const SkMatrix* localMatrix, bool isOpaque);
|
||||
|
||||
const char* gProg = R"(
|
||||
layout(ctype=float) in uniform half4 gColor;
|
||||
layout(ctype=SkRect) in uniform half4 gColor;
|
||||
|
||||
half4 main(in float x, in float y) {
|
||||
return half4(half(x)*(1.0/255), half(y)*(1.0/255), gColor.b, 1);
|
||||
void main(float x, float y, inout half4 color) {
|
||||
color = half4(half(x)*(1.0/255), half(y)*(1.0/255), gColor.b, 1);
|
||||
}
|
||||
)";
|
||||
|
||||
static sk_sp<SkShader> gShader;
|
||||
|
||||
class RuntimeShader : public skiagm::GM {
|
||||
public:
|
||||
RuntimeShader() {
|
||||
@ -50,24 +52,26 @@ protected:
|
||||
}
|
||||
|
||||
void onOnceBeforeDraw() override {
|
||||
SkMatrix localM;
|
||||
localM.setRotate(90, 128, 128);
|
||||
// use global to pass gl persistent cache test in dm
|
||||
if (!gShader) {
|
||||
SkMatrix localM;
|
||||
localM.setRotate(90, 128, 128);
|
||||
|
||||
fData = SkData::MakeUninitialized(sizeof(SkColor4f));
|
||||
SkColor4f* c = (SkColor4f*)fData->writable_data();
|
||||
*c = {1, 1, 0, 1};
|
||||
fShader = SkRuntimeShaderMaker(SkString(gProg), fData, &localM, true);
|
||||
fData = SkData::MakeUninitialized(sizeof(SkColor4f));
|
||||
SkColor4f* c = (SkColor4f*)fData->writable_data();
|
||||
*c = {1, 0, 0, 1};
|
||||
gShader = SkRuntimeShaderMaker(SkString(gProg), fData, &localM, true);
|
||||
}
|
||||
}
|
||||
|
||||
void onDraw(SkCanvas* canvas) override {
|
||||
SkPaint p;
|
||||
p.setShader(fShader);
|
||||
p.setShader(gShader);
|
||||
canvas->drawRect({0, 0, 256, 256}, p);
|
||||
}
|
||||
private:
|
||||
SkString fName;
|
||||
sk_sp<SkData> fData;
|
||||
sk_sp<SkShader> fShader;
|
||||
|
||||
typedef skiagm::GM INHERITED;
|
||||
};
|
||||
|
@ -405,9 +405,10 @@ public:
|
||||
rec.fPipeline->append(SkRasterPipeline::callback, ctx);
|
||||
} else {
|
||||
auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
|
||||
// don't need to set ctx->paintColor
|
||||
ctx->inputs = fInputs->data();
|
||||
ctx->ninputs = fInputs->size() / 4;
|
||||
ctx->shader_convention = false;
|
||||
ctx->shaderConvention = false;
|
||||
|
||||
SkAutoMutexExclusive ama(fByteCodeMutex);
|
||||
if (!fByteCode) {
|
||||
|
@ -159,9 +159,10 @@ struct SkRasterPipeline_InterpreterCtx {
|
||||
SkSL::ByteCode* byteCode;
|
||||
SkSL::ByteCodeFunction* fn;
|
||||
|
||||
SkColor4f paintColor;
|
||||
const void* inputs;
|
||||
int ninputs;
|
||||
bool shader_convention; // if false, we're a colorfilter
|
||||
bool shaderConvention; // if false, we're a colorfilter
|
||||
};
|
||||
|
||||
struct SkRasterPipeline_GradientCtx {
|
||||
|
@ -47,7 +47,7 @@ GR_FP_SRC_STRING SKSL_DITHER_SRC = R"(
|
||||
// This controls the range of values added to color channels
|
||||
layout(key) in int rangeType;
|
||||
|
||||
void main(int x, int y, inout half4 color) {
|
||||
void main(float x, float y, inout half4 color) {
|
||||
half value;
|
||||
half range;
|
||||
@switch (rangeType) {
|
||||
@ -73,7 +73,7 @@ void main(int x, int y, inout half4 color) {
|
||||
} else {
|
||||
// Simulate the integer effect used above using step/mod. For speed, simulates a 4x4
|
||||
// dither pattern rather than an 8x8 one.
|
||||
half4 modValues = mod(half4(x, y, x, y), half4(2.0, 2.0, 4.0, 4.0));
|
||||
half4 modValues = mod(half4(half(x), half(y), half(x), half(y)), half4(2.0, 2.0, 4.0, 4.0));
|
||||
half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.0));
|
||||
value = dot(stepValues, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
|
||||
}
|
||||
|
@ -2555,31 +2555,33 @@ STAGE(callback, SkRasterPipeline_CallbackCtx* c) {
|
||||
load4(c->read_from,0, &r,&g,&b,&a);
|
||||
}
|
||||
|
||||
// void main(int x, int h, inout half4 color)
|
||||
STAGE(interpreter, SkRasterPipeline_InterpreterCtx* c) {
|
||||
// If N is less than the interpreter's VecWidth, then we are doing more work than necessary in
|
||||
// the interpreter. This is a known issue, and will be addressed at some point.
|
||||
float rr[N];
|
||||
float gg[N];
|
||||
float bb[N];
|
||||
float aa[N];
|
||||
size_t in_count, out_count;
|
||||
float xx[N], yy[N],
|
||||
rr[N], gg[N], bb[N], aa[N];
|
||||
|
||||
float* args[] = { rr, gg, bb, aa };
|
||||
float* args[] = { xx, yy, rr, gg, bb, aa };
|
||||
|
||||
sk_unaligned_store(rr, r); // x if we're a shader
|
||||
sk_unaligned_store(gg, g); // y if we're a shader
|
||||
if (c->shader_convention) {
|
||||
in_count = 2; // x, y
|
||||
out_count = 4; // r, g, b, a
|
||||
if (c->shaderConvention) {
|
||||
// our caller must have called seed_shader to set these
|
||||
sk_unaligned_store(xx, r);
|
||||
sk_unaligned_store(yy, g);
|
||||
sk_unaligned_store(rr, F(c->paintColor.fR));
|
||||
sk_unaligned_store(gg, F(c->paintColor.fG));
|
||||
sk_unaligned_store(bb, F(c->paintColor.fB));
|
||||
sk_unaligned_store(aa, F(c->paintColor.fA));
|
||||
} else {
|
||||
in_count = 4; // r, g, b, a (in/out)
|
||||
// leave xx,yy uninitialized for colorfilters
|
||||
sk_unaligned_store(rr, r);
|
||||
sk_unaligned_store(gg, g);
|
||||
sk_unaligned_store(bb, b);
|
||||
sk_unaligned_store(aa, a);
|
||||
out_count = 0;
|
||||
}
|
||||
|
||||
c->byteCode->runStriped(c->fn, args, in_count, tail ? tail : N,
|
||||
(const float*)c->inputs, c->ninputs, args, out_count);
|
||||
c->byteCode->runStriped(c->fn, args, 6, tail ? tail : N,
|
||||
(const float*)c->inputs, c->ninputs, nullptr, 0);
|
||||
|
||||
r = sk_unaligned_load<F>(rr);
|
||||
g = sk_unaligned_load<F>(gg);
|
||||
|
@ -12,33 +12,44 @@
|
||||
#include "src/core/SkReadBuffer.h"
|
||||
#include "src/core/SkWriteBuffer.h"
|
||||
|
||||
#include "src/sksl/SkSLByteCode.h"
|
||||
#include "src/sksl/SkSLCompiler.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "include/private/GrRecordingContext.h"
|
||||
#include "src/gpu/GrCaps.h"
|
||||
#include "src/gpu/GrColorSpaceInfo.h"
|
||||
#include "src/gpu/GrRecordingContextPriv.h"
|
||||
#include "src/gpu/SkGr.h"
|
||||
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
#include "src/gpu/effects/generated/GrMixerEffect.h"
|
||||
#include "src/gpu/effects/GrSkSLFP.h"
|
||||
#endif
|
||||
|
||||
#include "src/sksl/SkSLByteCode.h"
|
||||
#include "src/sksl/SkSLCompiler.h"
|
||||
static inline uint32_t new_sksl_unique_id() {
|
||||
return GrSkSLFP::NewIndex();
|
||||
}
|
||||
#else
|
||||
static inline uint32_t new_sksl_unique_id() {
|
||||
return 0; // not used w/o GPU
|
||||
}
|
||||
#endif
|
||||
|
||||
SkRTShader::SkRTShader(SkString sksl, sk_sp<SkData> inputs, const SkMatrix* localMatrix,
|
||||
bool isOpaque)
|
||||
: SkShaderBase(localMatrix)
|
||||
, fSkSL(std::move(sksl))
|
||||
, fInputs(std::move(inputs))
|
||||
, fUniqueID(new_sksl_unique_id())
|
||||
, fIsOpaque(isOpaque)
|
||||
{}
|
||||
|
||||
bool SkRTShader::onAppendStages(const SkStageRec& rec) const {
|
||||
SkMatrix inverse;
|
||||
if (!this->computeTotalInverse(rec.fCTM, rec.fLocalM, &inverse)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
|
||||
ctx->paintColor = rec.fPaint.getColor4f();
|
||||
ctx->inputs = fInputs->data();
|
||||
ctx->ninputs = fInputs->size() / 4;
|
||||
ctx->shader_convention = true;
|
||||
ctx->shaderConvention = true;
|
||||
|
||||
SkAutoMutexExclusive ama(fByteCodeMutex);
|
||||
if (!fByteCode) {
|
||||
@ -61,7 +72,6 @@ bool SkRTShader::onAppendStages(const SkStageRec& rec) const {
|
||||
ctx->fn = ctx->byteCode->fFunctions[0].get();
|
||||
|
||||
rec.fPipeline->append(SkRasterPipeline::seed_shader);
|
||||
rec.fPipeline->append_matrix(rec.fAlloc, inverse);
|
||||
rec.fPipeline->append(SkRasterPipeline::interpreter, ctx);
|
||||
return true;
|
||||
}
|
||||
@ -114,3 +124,11 @@ sk_sp<SkShader> SkRuntimeShaderMaker(SkString sksl, sk_sp<SkData> inputs,
|
||||
return sk_sp<SkShader>(new SkRTShader(std::move(sksl), std::move(inputs),
|
||||
localMatrix, isOpaque));
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
std::unique_ptr<GrFragmentProcessor> SkRTShader::asFragmentProcessor(const GrFPArgs& args) const {
|
||||
return GrSkSLFP::Make(args.fContext, fUniqueID, "runtime-shader", fSkSL,
|
||||
fInputs->data(), fInputs->size());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -24,15 +24,12 @@ class SkRTShader : public SkShaderBase {
|
||||
public:
|
||||
SkRTShader(SkString sksl, sk_sp<SkData> inputs, const SkMatrix* localMatrix, bool isOpaque);
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override {
|
||||
// TODO
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isOpaque() const override { return fIsOpaque; }
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onAppendStages(const SkStageRec& rec) const override;
|
||||
@ -42,6 +39,7 @@ private:
|
||||
|
||||
SkString fSkSL;
|
||||
sk_sp<SkData> fInputs;
|
||||
const uint32_t fUniqueID;
|
||||
const bool fIsOpaque;
|
||||
|
||||
mutable SkMutex fByteCodeMutex;
|
||||
|
@ -756,9 +756,9 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
bool valid;
|
||||
switch (parameters.size()) {
|
||||
case 3:
|
||||
valid = parameters[0]->fType == *fContext.fInt_Type &&
|
||||
valid = parameters[0]->fType == *fContext.fFloat_Type &&
|
||||
parameters[0]->fModifiers.fFlags == 0 &&
|
||||
parameters[1]->fType == *fContext.fInt_Type &&
|
||||
parameters[1]->fType == *fContext.fFloat_Type &&
|
||||
parameters[1]->fModifiers.fFlags == 0 &&
|
||||
parameters[2]->fType == *fContext.fHalf4_Type &&
|
||||
parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag |
|
||||
@ -773,8 +773,8 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
valid = false;
|
||||
}
|
||||
if (!valid) {
|
||||
fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(int, "
|
||||
"int, inout half4) or main(inout half4)");
|
||||
fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(float, "
|
||||
"float, inout half4) or main(inout half4)");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user