Test & implement "vector relational intrinsics"
Add missing "not" intrinsic to SPIR-V, and several relational/logical opcodes to runtime effect's skvm converter. Bug: skia:10913 Change-Id: Ic349d491d980d0018134801260073414485f9059 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/339316 Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
831a5a10f4
commit
540c13a791
@ -269,3 +269,98 @@ DEF_SIMPLE_GM_BG(runtime_intrinsics_geometric,
|
||||
plot(canvas, "refract(v1.x0, v1.0x, x).x", 0.0f, 1.0f, -1.0f, 1.0f, "refract().x"); col(canvas);
|
||||
plot(canvas, "refract(v1.x0, v1.0x, x).y", 0.0f, 1.0f, -1.0f, 1.0f, "refract().y"); row(canvas);
|
||||
}
|
||||
|
||||
/*
|
||||
Specialized shader for testing relational operators.
|
||||
*/
|
||||
static SkString make_bvec_sksl(const char* fn) {
|
||||
return SkStringPrintf(
|
||||
"half4 main(float2 p) {"
|
||||
" float2 v1 = float2(1.0);"
|
||||
" p.x = p.x < 0.33 ? 0.0 : (p.x < 0.66 ? 1.0 : 2.0);"
|
||||
" p.y = p.y < 0.33 ? 0.0 : (p.y < 0.66 ? 1.0 : 2.0);"
|
||||
" bool2 cmp = %s;"
|
||||
" return half4(cmp.x ? 1.0 : 0.0, cmp.y ? 1.0 : 0.0, 0, 1);"
|
||||
"}",
|
||||
fn);
|
||||
}
|
||||
|
||||
static void plot_bvec(SkCanvas* canvas, const char* fn, const char* label = nullptr) {
|
||||
canvas->save();
|
||||
|
||||
SkFont font(ToolUtils::create_portable_typeface());
|
||||
SkPaint p(SkColors::kBlack);
|
||||
SkRect bounds;
|
||||
if (!label) {
|
||||
label = fn;
|
||||
}
|
||||
font.measureText(label, strlen(label), SkTextEncoding::kUTF8, &bounds);
|
||||
|
||||
canvas->drawSimpleText(label, strlen(label), SkTextEncoding::kUTF8,
|
||||
(kBoxSize - bounds.width()) * 0.5f,
|
||||
(kLabelHeight + bounds.height()) * 0.5f, font, p);
|
||||
canvas->translate(0, kLabelHeight);
|
||||
|
||||
{
|
||||
auto [effect, error] = SkRuntimeEffect::Make(make_bvec_sksl(fn));
|
||||
if (!effect) {
|
||||
SkDebugf("Error: %s\n", error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
SkRuntimeShaderBuilder builder(effect);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setShader(builder.makeShader(nullptr, false));
|
||||
|
||||
SkImageInfo info = SkImageInfo::MakeN32Premul({ kBoxSize, kBoxSize});
|
||||
auto surface = canvas->makeSurface(info);
|
||||
if (!surface) {
|
||||
surface = SkSurface::MakeRaster(info);
|
||||
}
|
||||
|
||||
surface->getCanvas()->clear(SK_ColorWHITE);
|
||||
surface->getCanvas()->scale(kBoxSize, kBoxSize);
|
||||
surface->getCanvas()->drawRect({0, 0, 1, 1}, paint);
|
||||
|
||||
SkBitmap bitmap;
|
||||
bitmap.allocPixels(info);
|
||||
surface->readPixels(bitmap, 0, 0);
|
||||
|
||||
canvas->drawBitmap(bitmap, 0, 0);
|
||||
}
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
// The OpenGL ES Shading Language, Version 1.00, Section 8.6
|
||||
DEF_SIMPLE_GM_BG(runtime_intrinsics_relational,
|
||||
canvas,
|
||||
columns_to_width(2),
|
||||
rows_to_height(6),
|
||||
SK_ColorWHITE) {
|
||||
canvas->translate(kPadding, kPadding);
|
||||
canvas->save();
|
||||
|
||||
// TODO: ivec versions of these. (Not declared in sksl_public.sksl yet).
|
||||
|
||||
plot_bvec(canvas, "lessThan(p, v1)", "lessThan"); col(canvas);
|
||||
plot_bvec(canvas, "lessThanEqual(p, v1)", "lessThanEqual"); row(canvas);
|
||||
|
||||
plot_bvec(canvas, "greaterThan(p, v1)", "greaterThan"); col(canvas);
|
||||
plot_bvec(canvas, "greaterThanEqual(p, v1)", "greaterThanEqual"); row(canvas);
|
||||
|
||||
plot_bvec(canvas, "equal(p, v1)", "equal"); col(canvas);
|
||||
plot_bvec(canvas, "notEqual(p, v1)", "notEqual"); row(canvas);
|
||||
|
||||
plot_bvec(canvas, "equal(lessThanEqual(p, v1), greaterThanEqual(p, v1))",
|
||||
"equal(bvec)"); col(canvas);
|
||||
plot_bvec(canvas, "notEqual(lessThanEqual(p, v1), greaterThanEqual(p, v1))",
|
||||
"notequal(bvec)"); row(canvas);
|
||||
|
||||
plot_bvec(canvas, "not(notEqual(p, v1))", "not(notEqual)"); col(canvas);
|
||||
plot_bvec(canvas, "not(equal(p, v1))", "not(equal)"); row(canvas);
|
||||
|
||||
plot_bvec(canvas, "bool2(any(equal(p, v1)))", "any(equal)"); col(canvas);
|
||||
plot_bvec(canvas, "bool2(all(equal(p, v1)))", "all(equal)"); row(canvas);
|
||||
}
|
||||
|
@ -648,9 +648,41 @@ static skvm::Color program_fn(skvm::Builder* p,
|
||||
|
||||
// Comparisons all should write their results to the main data stack;
|
||||
// maskpush moves them from there onto the mask stack as needed.
|
||||
case Inst::kCompareFEQ:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(x==y); });
|
||||
break;
|
||||
case Inst::kCompareFNEQ:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(x!=y); });
|
||||
break;
|
||||
case Inst::kCompareFGT:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(x>y); });
|
||||
break;
|
||||
case Inst::kCompareFGTEQ:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(x>=y); });
|
||||
break;
|
||||
case Inst::kCompareFLT:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(x<y); });
|
||||
break;
|
||||
case Inst::kCompareFLTEQ:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(x<=y); });
|
||||
break;
|
||||
|
||||
case Inst::kCompareIEQ:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(bit_cast(x)==bit_cast(y)); });
|
||||
break;
|
||||
case Inst::kCompareINEQ:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(bit_cast(x)!=bit_cast(y)); });
|
||||
break;
|
||||
|
||||
case Inst::kAndB:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(bit_cast(x)&bit_cast(y)); });
|
||||
break;
|
||||
case Inst::kOrB:
|
||||
binary([](skvm::F32 x, skvm::F32 y) { return bit_cast(bit_cast(x)|bit_cast(y)); });
|
||||
break;
|
||||
case Inst::kNotB:
|
||||
unary([](skvm::F32 x) { return bit_cast(~bit_cast(x)); });
|
||||
break;
|
||||
|
||||
case Inst::kMaskBlend: {
|
||||
std::vector<skvm::F32> if_true,
|
||||
|
@ -114,6 +114,9 @@ void SPIRVCodeGenerator::setupIntrinsics() {
|
||||
SpvOpUndef, SpvOpUndef, SpvOpAny);
|
||||
fIntrinsicMap[String("all")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef,
|
||||
SpvOpUndef, SpvOpUndef, SpvOpAll);
|
||||
fIntrinsicMap[String("not")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef,
|
||||
SpvOpUndef, SpvOpUndef,
|
||||
SpvOpLogicalNot);
|
||||
fIntrinsicMap[String("equal")] = std::make_tuple(kSPIRV_IntrinsicKind,
|
||||
SpvOpFOrdEqual, SpvOpIEqual,
|
||||
SpvOpIEqual, SpvOpLogicalEqual);
|
||||
|
Loading…
Reference in New Issue
Block a user