26 uint64_t red = 0x3c00000000003c00ull,
27 blue = 0x3800380000000000ull,
31 load_d_ctx = { &red, 0 },
32 store_ctx = { &
result, 0 };
35 p.append(SkRasterPipelineOp::load_f16, &load_s_ctx);
36 p.append(SkRasterPipelineOp::load_f16_dst, &load_d_ctx);
37 p.append(SkRasterPipelineOp::srcover);
38 p.append(SkRasterPipelineOp::store_f16, &store_ctx);
48DEF_TEST(SkRasterPipeline_PackSmallContext, r) {
49 struct PackableObject {
50 std::array<uint8_t,
sizeof(
void*)>
data;
54 using StorageArray = std::array<char, 128>;
55 StorageArray storage = {};
59 PackableObject object;
60 std::fill(
object.
data.begin(),
object.data.end(), 123);
68 uintptr_t objectBits = sk_bit_cast<uintptr_t>(packed);
69 for (
size_t index = 0; index <
sizeof(
void*); ++index) {
83 std::array<uint8_t,
sizeof(
void*) + 1>
data;
87 using StorageArray = std::array<char, 128>;
88 StorageArray storage = {};
93 std::fill(
object.
data.begin(),
object.data.end(), 123);
108 alignas(64) int32_t mask[16] = {~0, 0, ~0, 0, ~0, ~0, ~0, 0, ~0, 0, ~0, 0, ~0, ~0, ~0, 0};
116 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
117 p.append(SkRasterPipelineOp::load_condition_mask, mask);
118 p.append(SkRasterPipelineOp::store_condition_mask, maskCopy);
119 p.append(SkRasterPipelineOp::store_src,
src);
131 for (; index <
std::size(maskCopy); ++index) {
152 alignas(64) int32_t mask[16] = {~0, 0, ~0, 0, ~0, ~0, ~0, 0, ~0, 0, ~0, 0, ~0, ~0, ~0, 0};
160 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
161 p.append(SkRasterPipelineOp::load_loop_mask, mask);
162 p.append(SkRasterPipelineOp::store_loop_mask, maskCopy);
163 p.append(SkRasterPipelineOp::store_src,
src);
175 for (; index <
std::size(maskCopy); ++index) {
196 alignas(64) int32_t mask[16] = {~0, 0, ~0, 0, ~0, ~0, ~0, 0, ~0, 0, ~0, 0, ~0, ~0, ~0, 0};
204 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
205 p.append(SkRasterPipelineOp::load_return_mask, mask);
206 p.append(SkRasterPipelineOp::store_return_mask, maskCopy);
207 p.append(SkRasterPipelineOp::store_src,
src);
219 for (; index <
std::size(maskCopy); ++index) {
240 alignas(64) int32_t mask[32] = { 0, 0, ~0, ~0, 0, ~0, 0, ~0,
241 ~0, ~0, ~0, ~0, 0, 0, 0, 0,
242 0, 0, ~0, ~0, 0, ~0, 0, ~0,
243 ~0, ~0, ~0, ~0, 0, 0, 0, 0};
249 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
250 p.append(SkRasterPipelineOp::merge_condition_mask, mask);
251 p.append(SkRasterPipelineOp::store_src,
src);
270 alignas(64) int32_t initial[64] = {~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
271 ~0, 0, ~0, 0, ~0, ~0, ~0, ~0,
272 ~0, ~0, ~0, ~0, ~0, ~0, 0, ~0,
273 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
274 ~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
275 ~0, 0, ~0, 0, ~0, ~0, ~0, ~0,
276 ~0, ~0, ~0, ~0, ~0, ~0, 0, ~0,
277 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0};
278 alignas(64) int32_t mask[16] = {0, ~0, ~0, 0, ~0, ~0, ~0, ~0, 0, ~0, ~0, 0, ~0, ~0, ~0, ~0};
283 p.append(SkRasterPipelineOp::load_src, initial);
284 p.append(SkRasterPipelineOp::merge_loop_mask, mask);
285 p.append(SkRasterPipelineOp::store_src,
src);
306 alignas(64) int32_t initial[64] = {~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
307 ~0, 0, ~0, 0, ~0, ~0, 0, ~0,
308 0, ~0, ~0, ~0, 0, 0, 0, ~0,
309 0, 0, ~0, 0, 0, 0, 0, ~0,
310 ~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
311 ~0, 0, ~0, 0, ~0, ~0, 0, ~0,
312 0, ~0, ~0, ~0, 0, 0, 0, ~0,
313 0, 0, ~0, 0, 0, 0, 0, ~0};
314 alignas(64) int32_t mask[16] = { 0, ~0, 0, 0, 0, 0, ~0, 0, 0, ~0, 0, 0, 0, 0, ~0, 0};
319 p.append(SkRasterPipelineOp::load_src, initial);
320 p.append(SkRasterPipelineOp::reenable_loop_mask, mask);
321 p.append(SkRasterPipelineOp::store_src,
src);
342 alignas(64) int32_t initial[64] = {~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
343 0, ~0, ~0, 0, ~0, ~0, 0, ~0,
344 ~0, 0, ~0, ~0, 0, 0, 0, ~0,
345 0, 0, ~0, 0, 0, 0, 0, ~0,
346 ~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
347 0, ~0, ~0, 0, ~0, ~0, 0, ~0,
348 ~0, 0, ~0, ~0, 0, 0, 0, ~0,
349 0, 0, ~0, 0, 0, 0, 0, ~0};
353 constexpr int32_t actualValues[16] = { 2, 1, 2, 4, 5, 2, 2, 8};
368 p.append(SkRasterPipelineOp::load_src, initial);
369 p.append(SkRasterPipelineOp::set_base_pointer, &caseOpData[0]);
371 p.append(SkRasterPipelineOp::store_src,
src);
383 int32_t expected = (actualValues[index] == 2) ? ~0 : initial[g + index];
397 expected = (actualValues[index] == 2) ? 0 : ~0;
403 alignas(64) int32_t initial[64] = {~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
404 ~0, 0, ~0, ~0, 0, 0, 0, ~0,
405 ~0, ~0, 0, ~0, 0, 0, ~0, ~0,
406 ~0, 0, 0, ~0, 0, 0, 0, ~0,
407 ~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
408 ~0, 0, ~0, ~0, 0, 0, 0, ~0,
409 ~0, ~0, 0, ~0, 0, 0, ~0, ~0,
410 ~0, 0, 0, ~0, 0, 0, 0, ~0};
415 p.append(SkRasterPipelineOp::load_src, initial);
416 p.append(SkRasterPipelineOp::mask_off_loop_mask);
417 p.append(SkRasterPipelineOp::store_src,
src);
426 int32_t expected = initial[g + index] & ~initial[
a + index];
430 expected =
src[r + index] &
src[g + index] &
src[
b + index];
436 alignas(64) int32_t initial[64] = {~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
437 ~0, 0, ~0, ~0, 0, 0, 0, ~0,
438 ~0, ~0, 0, ~0, 0, 0, ~0, ~0,
439 ~0, 0, 0, ~0, 0, 0, 0, ~0,
440 ~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
441 ~0, 0, ~0, ~0, 0, 0, 0, ~0,
442 ~0, ~0, 0, ~0, 0, 0, ~0, ~0,
443 ~0, 0, 0, ~0, 0, 0, 0, ~0};
448 p.append(SkRasterPipelineOp::load_src, initial);
449 p.append(SkRasterPipelineOp::mask_off_return_mask);
450 p.append(SkRasterPipelineOp::store_src,
src);
459 int32_t expected = initial[
b + index] & ~initial[
a + index];
463 expected =
src[r + index] &
src[g + index] &
src[
b + index];
474 alignas(64)
static constexpr float kArbitraryColor[4] = {0.0f, 0.25f, 0.50f, 0.75f};
475 p.appendConstantColor(&alloc, kArbitraryColor);
479 p.append(SkRasterPipelineOp::init_lane_masks, &ctx);
483 p.append(SkRasterPipelineOp::store_src, RGBA);
491 int32_t* channelR = RGBA;
495 for (; index <
width; ++index) {
524DEF_TEST(SkRasterPipeline_CopyFromIndirectUnmasked, r) {
531 alignas(64)
const uint32_t kOffsets1[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
532 alignas(64)
const uint32_t kOffsets2[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
533 alignas(64)
const uint32_t kOffsets3[16] = {0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2};
534 alignas(64)
const uint32_t kOffsets4[16] = {99, 99, 0, 0, 99, 99, 0, 0,
535 99, 99, 0, 0, 99, 99, 0, 0};
539 for (
const uint32_t*
offsets : {kOffsets1, kOffsets2, kOffsets3, kOffsets4}) {
540 for (
int copySize = 1; copySize <= 5; ++copySize) {
542 std::iota(&
dst[0], &
dst[5 *
N], 0);
552 ctx->indirectLimit = 5 - copySize;
553 ctx->slots = copySize;
555 p.append(SkRasterPipelineOp::copy_from_indirect_unmasked, ctx);
563 if (copySize + maxOffset > 5) {
569 int expectedUnchanged = 0;
570 int expectedFromZero =
src[0 *
N], expectedFromTwo =
src[2 *
N];
572 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
573 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
574 if (checkSlot < copySize) {
577 }
else if (
offsets[checkLane] == 2) {
580 ERRORF(r,
"unexpected offset value");
587 expectedUnchanged += 1;
588 expectedFromZero += 1;
589 expectedFromTwo += 1;
596DEF_TEST(SkRasterPipeline_CopyFromIndirectUniformUnmasked, r) {
599 alignas(64)
int src[5];
604 alignas(64)
const uint32_t kOffsets1[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
605 alignas(64)
const uint32_t kOffsets2[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
606 alignas(64)
const uint32_t kOffsets3[16] = {0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2};
607 alignas(64)
const uint32_t kOffsets4[16] = {99, ~99u, 0, 0, ~99u, 99, 0, 0,
608 99, ~99u, 0, 0, ~99u, 99, 0, 0};
612 for (
const uint32_t*
offsets : {kOffsets1, kOffsets2, kOffsets3, kOffsets4}) {
613 for (
int copySize = 1; copySize <= 5; ++copySize) {
615 std::iota(&
dst[0], &
dst[5 *
N], 0);
625 ctx->indirectLimit = 5 - copySize;
626 ctx->slots = copySize;
628 p.append(SkRasterPipelineOp::copy_from_indirect_uniform_unmasked, ctx);
636 if (copySize + maxOffset > 5) {
641 int expectedUnchanged = 0;
642 int expectedFromZero =
src[0], expectedFromTwo =
src[2];
644 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
645 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
646 if (checkSlot < copySize) {
649 }
else if (
offsets[checkLane] == 2) {
652 ERRORF(r,
"unexpected offset value");
659 expectedUnchanged += 1;
661 expectedFromZero += 1;
662 expectedFromTwo += 1;
668DEF_TEST(SkRasterPipeline_CopyToIndirectMasked, r) {
675 alignas(64)
const uint32_t kOffsets1[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
676 alignas(64)
const uint32_t kOffsets2[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
677 alignas(64)
const uint32_t kOffsets3[16] = {0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2};
678 alignas(64)
const uint32_t kOffsets4[16] = {99, ~99u, 0, 0, ~99u, 99, 0, 0,
679 99, ~99u, 0, 0, ~99u, 99, 0, 0};
682 alignas(64)
const int32_t kMask1[16] = {~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
683 ~0, ~0, ~0, ~0, ~0, 0, ~0, ~0};
684 alignas(64)
const int32_t kMask2[16] = {~0, 0, ~0, ~0, 0, 0, 0, ~0,
685 ~0, 0, ~0, ~0, 0, 0, 0, ~0};
686 alignas(64)
const int32_t kMask3[16] = {~0, ~0, 0, ~0, 0, 0, ~0, ~0,
687 ~0, ~0, 0, ~0, 0, 0, ~0, ~0};
688 alignas(64)
const int32_t kMask4[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
689 0, 0, 0, 0, 0, 0, 0, 0};
693 for (
const int32_t* mask : {kMask1, kMask2, kMask3, kMask4}) {
694 for (
const uint32_t*
offsets : {kOffsets1, kOffsets2, kOffsets3, kOffsets4}) {
695 for (
int copySize = 1; copySize <= 5; ++copySize) {
697 std::iota(&
dst[0], &
dst[5 *
N], 0);
707 ctx->indirectLimit = 5 - copySize;
708 ctx->slots = copySize;
711 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
712 p.append(SkRasterPipelineOp::load_condition_mask, mask);
713 p.append(SkRasterPipelineOp::copy_to_indirect_masked, ctx);
721 if (copySize + maxOffset > 5) {
727 int expectedUnchanged = 0;
728 int expectedFromZero =
src[0], expectedFromTwo =
src[0] - (2 *
N);
731 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
732 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
733 int rangeStart =
offsets[checkLane] *
N;
734 int rangeEnd = (
offsets[checkLane] + copySize) *
N;
735 if (mask[checkLane] &&
pos >= rangeStart &&
pos < rangeEnd) {
738 }
else if (
offsets[checkLane] == 2) {
741 ERRORF(r,
"unexpected offset value");
749 expectedUnchanged += 1;
750 expectedFromZero += 1;
751 expectedFromTwo += 1;
759DEF_TEST(SkRasterPipeline_SwizzleCopyToIndirectMasked, r) {
766 alignas(64)
const uint32_t kOffsets1[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
767 alignas(64)
const uint32_t kOffsets2[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
768 alignas(64)
const uint32_t kOffsets3[16] = {0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2};
769 alignas(64)
const uint32_t kOffsets4[16] = {99, ~99u, 0, 0, ~99u, 99, 0, 0,
770 99, ~99u, 0, 0, ~99u, 99, 0, 0};
773 alignas(64)
const int32_t kMask1[16] = {~0, ~0, ~0, ~0, ~0, 0, ~0, ~0,
774 ~0, ~0, ~0, ~0, ~0, 0, ~0, ~0};
775 alignas(64)
const int32_t kMask2[16] = {~0, 0, ~0, ~0, 0, 0, 0, ~0,
776 ~0, 0, ~0, ~0, 0, 0, 0, ~0};
777 alignas(64)
const int32_t kMask3[16] = {~0, ~0, 0, ~0, 0, 0, ~0, ~0,
778 ~0, ~0, 0, ~0, 0, 0, ~0, ~0};
779 alignas(64)
const int32_t kMask4[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
780 0, 0, 0, 0, 0, 0, 0, 0};
785 int swizzleUpperBound;
789 static const TestPattern kPatterns[] = {
793 {4, 4, {3, 0, 1, 2}},
807#define XX kOutOfBounds
808 static const Result kExpectationsAtZero[4][5] = {
810 {
__,
__,
__,
S0,
__}, {
S1,
S0,
__,
__,
__}, {
S2,
S1,
S0,
__,
__}, {
S1,
S2,
S3,
S0,
__},
812 static const Result kExpectationsAtTwo[4][5] = {
814 {
XX,
XX,
XX,
XX,
XX}, {
__,
__,
S1,
S0,
__}, {
__,
__,
S2,
S1,
S0}, {
XX,
XX,
XX,
XX,
XX},
821 for (
const int32_t* mask : {kMask1, kMask2, kMask3, kMask4}) {
822 for (
const uint32_t*
offsets : {kOffsets1, kOffsets2, kOffsets3, kOffsets4}) {
823 for (
size_t patternIndex = 0; patternIndex <
std::size(kPatterns); ++patternIndex) {
824 const TestPattern& pattern = kPatterns[patternIndex];
827 std::iota(&
dst[0], &
dst[5 *
N], 0);
837 ctx->indirectLimit = 5 - pattern.swizzleUpperBound;
838 ctx->slots = pattern.swizzleSize;
839 ctx->offsets[0] = pattern.swizzle[0] *
N *
sizeof(
float);
840 ctx->offsets[1] = pattern.swizzle[1] *
N *
sizeof(
float);
841 ctx->offsets[2] = pattern.swizzle[2] *
N *
sizeof(
float);
842 ctx->offsets[3] = pattern.swizzle[3] *
N *
sizeof(
float);
845 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
846 p.append(SkRasterPipelineOp::load_condition_mask, mask);
847 p.append(SkRasterPipelineOp::swizzle_copy_to_indirect_masked, ctx);
855 if (pattern.swizzleUpperBound + maxOffset > 5) {
861 int expectedUnchanged = 0;
863 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
864 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
865 Result expectedType = kUnchanged;
867 expectedType = kExpectationsAtZero[patternIndex][checkSlot];
868 }
else if (
offsets[checkLane] == 2) {
869 expectedType = kExpectationsAtTwo[patternIndex][checkSlot];
871 if (!mask[checkLane]) {
872 expectedType = kUnchanged;
874 switch (expectedType) {
898 expectedUnchanged += 1;
911 void line(
int)
override { fBuffer.push_back(-9999999); }
912 void enter(
int)
override { fBuffer.push_back(-9999999); }
913 void exit(
int)
override { fBuffer.push_back(-9999999); }
914 void scope(
int)
override { fBuffer.push_back(-9999999); }
915 void var(
int slot, int32_t val)
override {
916 fBuffer.push_back(slot);
917 fBuffer.push_back(val);
924 alignas(64)
static constexpr int32_t kMaskOn [16] = {~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
925 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0};
926 alignas(64)
static constexpr int32_t kMaskOff [16] = { 0, 0, 0, 0, 0, 0, 0, 0,
927 0, 0, 0, 0, 0, 0, 0, 0};
928 alignas(64)
static constexpr uint32_t kIndirect0[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
929 0, 0, 0, 0, 0, 0, 0, 0};
930 alignas(64)
static constexpr uint32_t kIndirect1[16] = { 1, 1, 1, 1, 1, 1, 1, 1,
931 1, 1, 1, 1, 1, 1, 1, 1};
932 alignas(64) int32_t kData333[16];
933 alignas(64) int32_t kData555[16];
934 alignas(64) int32_t kData666[16];
935 alignas(64) int32_t kData777[32];
936 alignas(64) int32_t kData999[32];
937 std::fill(kData333, kData333 +
N, 333);
938 std::fill(kData555, kData555 +
N, 555);
939 std::fill(kData666, kData666 +
N, 666);
940 std::fill(kData777, kData777 +
N, 777);
941 std::fill(kData777 +
N, kData777 + 2*
N, 707);
942 std::fill(kData999, kData999 +
N, 999);
943 std::fill(kData999 +
N, kData999 + 2*
N, 909);
949 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
951 &trace, 2, 1, kData333,
955 &trace, 4, 1, kData555,
959 &trace, 5, 1, kData666,
963 &trace, 6, 2, kData777,
967 &trace, 8, 2, kData999,
971 &trace, 9, 1, kData999,
975 &trace, 9, 1, kData999,
979 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
980 p.append(SkRasterPipelineOp::trace_var, &kTraceVar1);
981 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
982 p.append(SkRasterPipelineOp::trace_var, &kTraceVar2);
983 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOff);
984 p.append(SkRasterPipelineOp::trace_var, &kTraceVar3);
985 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
986 p.append(SkRasterPipelineOp::trace_var, &kTraceVar4);
987 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOff);
988 p.append(SkRasterPipelineOp::trace_var, &kTraceVar5);
989 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
990 p.append(SkRasterPipelineOp::trace_var, &kTraceVar6);
991 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
992 p.append(SkRasterPipelineOp::trace_var, &kTraceVar7);
995 REPORTER_ASSERT(r, (trace.fBuffer ==
TArray<int>{4, 555, 6, 777, 7, 707, 9, 999, 10, 909}));
1003 void var(
int, int32_t)
override { fBuffer.push_back(-9999999); }
1004 void enter(
int)
override { fBuffer.push_back(-9999999); }
1005 void exit(
int)
override { fBuffer.push_back(-9999999); }
1006 void scope(
int)
override { fBuffer.push_back(-9999999); }
1007 void line(
int lineNum)
override { fBuffer.push_back(lineNum); }
1013 alignas(64)
static constexpr int32_t kMaskOn [16] = {~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
1014 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0};
1015 alignas(64)
static constexpr int32_t kMaskOff[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
1016 0, 0, 0, 0, 0, 0, 0, 0};
1018 TestTraceHook trace;
1022 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
1029 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
1030 p.append(SkRasterPipelineOp::trace_line, &kTraceLine1);
1031 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
1032 p.append(SkRasterPipelineOp::trace_line, &kTraceLine2);
1033 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOff);
1034 p.append(SkRasterPipelineOp::trace_line, &kTraceLine3);
1035 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOff);
1036 p.append(SkRasterPipelineOp::trace_line, &kTraceLine4);
1037 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
1038 p.append(SkRasterPipelineOp::trace_line, &kTraceLine5);
1049 void line(
int)
override { fBuffer.push_back(-9999999); }
1050 void var(
int, int32_t)
override { fBuffer.push_back(-9999999); }
1051 void scope(
int)
override { fBuffer.push_back(-9999999); }
1052 void enter(
int fnIdx)
override {
1053 fBuffer.push_back(fnIdx);
1054 fBuffer.push_back(1);
1056 void exit(
int fnIdx)
override {
1057 fBuffer.push_back(fnIdx);
1058 fBuffer.push_back(0);
1065 alignas(64)
static constexpr int32_t kMaskOn [16] = {~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
1066 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0};
1067 alignas(64)
static constexpr int32_t kMaskOff[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
1068 0, 0, 0, 0, 0, 0, 0, 0};
1070 TestTraceHook trace;
1074 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
1082 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOff);
1083 p.append(SkRasterPipelineOp::trace_enter, &kTraceFunc1);
1084 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
1085 p.append(SkRasterPipelineOp::trace_enter, &kTraceFunc2);
1086 p.append(SkRasterPipelineOp::trace_enter, &kTraceFunc3);
1087 p.append(SkRasterPipelineOp::trace_exit, &kTraceFunc4);
1088 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOff);
1089 p.append(SkRasterPipelineOp::trace_exit, &kTraceFunc5);
1090 p.append(SkRasterPipelineOp::trace_exit, &kTraceFunc6);
1101 void line(
int)
override { fBuffer.push_back(-9999999); }
1102 void var(
int, int32_t)
override { fBuffer.push_back(-9999999); }
1103 void enter(
int)
override { fBuffer.push_back(-9999999); }
1104 void exit(
int)
override { fBuffer.push_back(-9999999); }
1105 void scope(
int delta)
override { fBuffer.push_back(
delta); }
1111 alignas(64)
static constexpr int32_t kMaskOn [16] = {~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
1112 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0};
1113 alignas(64)
static constexpr int32_t kMaskOff[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
1114 0, 0, 0, 0, 0, 0, 0, 0};
1116 TestTraceHook trace;
1120 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
1127 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
1128 p.append(SkRasterPipelineOp::trace_scope, &kTraceScope1);
1129 p.append(SkRasterPipelineOp::trace_scope, &kTraceScope2);
1130 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOff);
1131 p.append(SkRasterPipelineOp::trace_scope, &kTraceScope3);
1132 p.append(SkRasterPipelineOp::trace_scope, &kTraceScope4);
1133 p.append(SkRasterPipelineOp::load_condition_mask, kMaskOn);
1134 p.append(SkRasterPipelineOp::trace_scope, &kTraceScope5);
1143 const int srcIndex = 0, dstIndex = 5;
1145 struct CopySlotsOp {
1147 int numSlotsAffected;
1150 static const CopySlotsOp kCopyOps[] = {
1151 {SkRasterPipelineOp::copy_slot_masked, 1},
1152 {SkRasterPipelineOp::copy_2_slots_masked, 2},
1153 {SkRasterPipelineOp::copy_3_slots_masked, 3},
1154 {SkRasterPipelineOp::copy_4_slots_masked, 4},
1158 alignas(64)
const int32_t kMask1[16] = {~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
1159 ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0};
1160 alignas(64)
const int32_t kMask2[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
1161 0, 0, 0, 0, 0, 0, 0, 0};
1162 alignas(64)
const int32_t kMask3[16] = {~0, 0, ~0, ~0, ~0, ~0, 0, ~0,
1163 ~0, 0, ~0, ~0, ~0, ~0, 0, ~0};
1164 alignas(64)
const int32_t kMask4[16] = { 0, ~0, 0, 0, 0, ~0, ~0, 0,
1165 0, ~0, 0, 0, 0, ~0, ~0, 0};
1169 for (
const CopySlotsOp& op : kCopyOps) {
1170 for (
const int32_t* mask : {kMask1, kMask2, kMask3, kMask4}) {
1172 std::iota(&slots[
N * dstIndex], &slots[
N * (dstIndex + 5)], 0);
1183 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
1184 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1185 p.append(SkRasterPipelineOp::load_condition_mask, mask);
1192 int* destPtr = &slots[
N * dstIndex];
1193 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
1194 for (
int checkMask = 0; checkMask <
N; ++checkMask) {
1195 if (checkSlot < op.numSlotsAffected && mask[checkMask]) {
1202 expectedUnchanged += 1;
1203 expectedChanged += 1;
1213 const int srcIndex = 0, dstIndex = 5;
1216 struct CopySlotsOp {
1218 int numSlotsAffected;
1221 static const CopySlotsOp kCopyOps[] = {
1222 {SkRasterPipelineOp::copy_slot_unmasked, 1},
1223 {SkRasterPipelineOp::copy_2_slots_unmasked, 2},
1224 {SkRasterPipelineOp::copy_3_slots_unmasked, 3},
1225 {SkRasterPipelineOp::copy_4_slots_unmasked, 4},
1228 for (
const CopySlotsOp& op : kCopyOps) {
1230 std::iota(&slots[
N * dstIndex], &slots[
N * (dstIndex + 5)], 0);
1239 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1245 int* destPtr = &slots[
N * dstIndex];
1246 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
1247 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1248 if (checkSlot < op.numSlotsAffected) {
1255 expectedUnchanged += 1;
1256 expectedChanged += 1;
1268 struct CopyUniformsOp {
1270 int numSlotsAffected;
1273 static const CopyUniformsOp kCopyOps[] = {
1274 {SkRasterPipelineOp::copy_uniform, 1},
1275 {SkRasterPipelineOp::copy_2_uniforms, 2},
1276 {SkRasterPipelineOp::copy_3_uniforms, 3},
1277 {SkRasterPipelineOp::copy_4_uniforms, 4},
1280 for (
const CopyUniformsOp& op : kCopyOps) {
1282 std::iota(&slots[0], &slots[5 *
N], 1);
1291 ctx->src = uniforms;
1292 p.append(op.stage, ctx);
1296 int expectedUnchanged = 1;
1298 int* destPtr = &slots[0];
1299 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
1300 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1301 if (checkSlot < op.numSlotsAffected) {
1308 expectedUnchanged += 1;
1310 expectedChanged += 1;
1320 for (
int index = 0; index < 5; ++index) {
1322 std::iota(&slots[0], &slots[5 *
N], 1);
1330 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1335 int expectedUnchanged = 1;
1336 int* destPtr = &slots[0];
1337 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
1338 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1339 if (checkSlot == index) {
1346 expectedUnchanged += 1;
1357 struct TestPattern {
1362 static const TestPattern kPatterns[] = {
1363 {SkRasterPipelineOp::swizzle_1, {3}, {3, 1, 2, 3}},
1364 {SkRasterPipelineOp::swizzle_2, {1, 0}, {1, 0, 2, 3}},
1365 {SkRasterPipelineOp::swizzle_3, {2, 2, 2}, {2, 2, 2, 3}},
1366 {SkRasterPipelineOp::swizzle_4, {0, 0, 1, 2}, {0, 0, 1, 2}},
1370 for (
const TestPattern& pattern : kPatterns) {
1380 ctx.
offsets[index] = pattern.swizzle[index] *
N *
sizeof(
float);
1382 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1387 int* destPtr = &slots[0];
1388 for (
int checkSlot = 0; checkSlot < 4; ++checkSlot) {
1390 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1403 struct TestPattern {
1405 uint16_t swizzle[4];
1408 constexpr uint16_t _ = ~0;
1409 static const TestPattern kPatterns[] = {
1410 {SkRasterPipelineOp::swizzle_copy_slot_masked, {3,_,_,_}, {_,_,_,0}},
1411 {SkRasterPipelineOp::swizzle_copy_2_slots_masked, {1,0,_,_}, {1,0,_,_}},
1412 {SkRasterPipelineOp::swizzle_copy_3_slots_masked, {2,3,0,_}, {2,_,0,1}},
1413 {SkRasterPipelineOp::swizzle_copy_4_slots_masked, {3,0,1,2}, {1,2,3,0}},
1417 for (
const TestPattern& pattern : kPatterns) {
1433 if (pattern.swizzle[index] != _) {
1434 ctx.
offsets[index] = pattern.swizzle[index] *
N *
sizeof(
float);
1437 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
1438 p.append(pattern.op, &ctx);
1442 int* destPtr = &
dest[0];
1443 for (
int checkSlot = 0; checkSlot < 4; ++checkSlot) {
1444 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1445 if (pattern.expectation[checkSlot] == _) {
1448 int expectedIdx = pattern.expectation[checkSlot] *
N + checkLane;
1463 struct TestPattern {
1468 static const TestPattern kPatterns[] = {
1471 2, 5, 8, 0, 0, 0, 0, 0, 0, 0},
1474 2, 5, 8, 9, 10, 11, 12, 13, 14, 15}},
1486 for (
const TestPattern& pattern : kPatterns) {
1495 ctx.
count = pattern.count;
1497 ctx.
offsets[index] = pattern.shuffle[index] *
N *
sizeof(
float);
1503 int* destPtr = &slots[0];
1504 for (
int checkSlot = 0; checkSlot < 16; ++checkSlot) {
1506 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1521 std::iota(&slots[4 *
N], &slots[12 *
N], 1.0f);
1529 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1534 const float*
const destPtr[2][2] = {
1535 {&slots[0 *
N], &slots[1 *
N]},
1536 {&slots[2 *
N], &slots[3 *
N]},
1538 const float*
const leftMtx[2][2] = {
1539 {&slots[4 *
N], &slots[5 *
N]},
1540 {&slots[6 *
N], &slots[7 *
N]},
1542 const float*
const rightMtx[2][2] = {
1543 {&slots[8 *
N], &slots[9 *
N]},
1544 {&slots[10 *
N], &slots[11 *
N]},
1547 for (
int c = 0; c < 2; ++c) {
1548 for (
int r = 0; r < 2; ++r) {
1549 for (
int lane = 0; lane <
N; ++lane) {
1552 for (
int n = 0; n < 2; ++n) {
1553 dot += leftMtx[n][r][lane] * rightMtx[c][n][lane];
1568 for (
int idx = 9 *
N; idx < 27 *
N; ++idx) {
1579 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1584 const float*
const destPtr[3][3] = {
1585 {&slots[0 *
N], &slots[1 *
N], &slots[2 *
N]},
1586 {&slots[3 *
N], &slots[4 *
N], &slots[5 *
N]},
1587 {&slots[6 *
N], &slots[7 *
N], &slots[8 *
N]},
1589 const float*
const leftMtx[3][3] = {
1590 {&slots[9 *
N], &slots[10 *
N], &slots[11 *
N]},
1591 {&slots[12 *
N], &slots[13 *
N], &slots[14 *
N]},
1592 {&slots[15 *
N], &slots[16 *
N], &slots[17 *
N]},
1594 const float*
const rightMtx[3][3] = {
1595 {&slots[18 *
N], &slots[19 *
N], &slots[20 *
N]},
1596 {&slots[21 *
N], &slots[22 *
N], &slots[23 *
N]},
1597 {&slots[24 *
N], &slots[25 *
N], &slots[26 *
N]},
1600 for (
int c = 0; c < 3; ++c) {
1601 for (
int r = 0; r < 3; ++r) {
1602 for (
int lane = 0; lane <
N; ++lane) {
1605 for (
int n = 0; n < 3; ++n) {
1606 dot += leftMtx[n][r][lane] * rightMtx[c][n][lane];
1621 for (
int idx = 16 *
N; idx < 48 *
N; ++idx) {
1632 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1637 const float*
const destPtr[4][4] = {
1638 {&slots[0 *
N], &slots[1 *
N], &slots[2 *
N], &slots[3 *
N]},
1639 {&slots[4 *
N], &slots[5 *
N], &slots[6 *
N], &slots[7 *
N]},
1640 {&slots[8 *
N], &slots[9 *
N], &slots[10 *
N], &slots[11 *
N]},
1641 {&slots[12 *
N], &slots[13 *
N], &slots[14 *
N], &slots[15 *
N]},
1643 const float*
const leftMtx[4][4] = {
1644 {&slots[16 *
N], &slots[17 *
N], &slots[18 *
N], &slots[19 *
N]},
1645 {&slots[20 *
N], &slots[21 *
N], &slots[22 *
N], &slots[23 *
N]},
1646 {&slots[24 *
N], &slots[25 *
N], &slots[26 *
N], &slots[27 *
N]},
1647 {&slots[28 *
N], &slots[29 *
N], &slots[30 *
N], &slots[31 *
N]},
1649 const float*
const rightMtx[4][4] = {
1650 {&slots[32 *
N], &slots[33 *
N], &slots[34 *
N], &slots[35 *
N]},
1651 {&slots[36 *
N], &slots[37 *
N], &slots[38 *
N], &slots[39 *
N]},
1652 {&slots[40 *
N], &slots[41 *
N], &slots[42 *
N], &slots[43 *
N]},
1653 {&slots[44 *
N], &slots[45 *
N], &slots[46 *
N], &slots[47 *
N]},
1656 for (
int c = 0; c < 4; ++c) {
1657 for (
int r = 0; r < 4; ++r) {
1658 for (
int lane = 0; lane <
N; ++lane) {
1661 for (
int n = 0; n < 4; ++n) {
1662 dot += leftMtx[n][r][lane] * rightMtx[c][n][lane];
1670DEF_TEST(SkRasterPipeline_FloatArithmeticWithNSlots, r) {
1675 struct ArithmeticOp {
1680 static const ArithmeticOp kArithmeticOps[] = {
1681 {SkRasterPipelineOp::add_n_floats, [](
float a,
float b) {
return a +
b; }},
1682 {SkRasterPipelineOp::sub_n_floats, [](
float a,
float b) {
return a -
b; }},
1683 {SkRasterPipelineOp::mul_n_floats, [](
float a,
float b) {
return a *
b; }},
1684 {SkRasterPipelineOp::div_n_floats, [](
float a,
float b) {
return a /
b; }},
1687 for (
const ArithmeticOp& op : kArithmeticOps) {
1688 for (
int numSlotsAffected = 1; numSlotsAffected <= 5; ++numSlotsAffected) {
1690 std::iota(&slots[0], &slots[10 *
N], 1.0f);
1697 ctx.
src = numSlotsAffected *
N *
sizeof(
float);
1698 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1703 float leftValue = 1.0f;
1704 float rightValue =
float(numSlotsAffected *
N) + 1.0f;
1705 float* destPtr = &slots[0];
1706 for (
int checkSlot = 0; checkSlot < 10; ++checkSlot) {
1707 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1708 if (checkSlot < numSlotsAffected) {
1723DEF_TEST(SkRasterPipeline_FloatArithmeticWithHardcodedSlots, r) {
1728 struct ArithmeticOp {
1730 int numSlotsAffected;
1734 static const ArithmeticOp kArithmeticOps[] = {
1735 {SkRasterPipelineOp::add_float, 1, [](
float a,
float b) {
return a +
b; }},
1736 {SkRasterPipelineOp::sub_float, 1, [](
float a,
float b) {
return a -
b; }},
1737 {SkRasterPipelineOp::mul_float, 1, [](
float a,
float b) {
return a *
b; }},
1738 {SkRasterPipelineOp::div_float, 1, [](
float a,
float b) {
return a /
b; }},
1740 {SkRasterPipelineOp::add_2_floats, 2, [](
float a,
float b) {
return a +
b; }},
1741 {SkRasterPipelineOp::sub_2_floats, 2, [](
float a,
float b) {
return a -
b; }},
1742 {SkRasterPipelineOp::mul_2_floats, 2, [](
float a,
float b) {
return a *
b; }},
1743 {SkRasterPipelineOp::div_2_floats, 2, [](
float a,
float b) {
return a /
b; }},
1745 {SkRasterPipelineOp::add_3_floats, 3, [](
float a,
float b) {
return a +
b; }},
1746 {SkRasterPipelineOp::sub_3_floats, 3, [](
float a,
float b) {
return a -
b; }},
1747 {SkRasterPipelineOp::mul_3_floats, 3, [](
float a,
float b) {
return a *
b; }},
1748 {SkRasterPipelineOp::div_3_floats, 3, [](
float a,
float b) {
return a /
b; }},
1750 {SkRasterPipelineOp::add_4_floats, 4, [](
float a,
float b) {
return a +
b; }},
1751 {SkRasterPipelineOp::sub_4_floats, 4, [](
float a,
float b) {
return a -
b; }},
1752 {SkRasterPipelineOp::mul_4_floats, 4, [](
float a,
float b) {
return a *
b; }},
1753 {SkRasterPipelineOp::div_4_floats, 4, [](
float a,
float b) {
return a /
b; }},
1756 for (
const ArithmeticOp& op : kArithmeticOps) {
1758 std::iota(&slots[0], &slots[10 *
N], 1.0f);
1763 p.append(op.stage, &slots[0]);
1767 float leftValue = 1.0f;
1768 float rightValue =
float(op.numSlotsAffected *
N) + 1.0f;
1769 float* destPtr = &slots[0];
1770 for (
int checkSlot = 0; checkSlot < 10; ++checkSlot) {
1771 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1772 if (checkSlot < op.numSlotsAffected) {
1795 struct ArithmeticOp {
1800 static const ArithmeticOp kArithmeticOps[] = {
1801 {SkRasterPipelineOp::add_n_ints, [](
int a,
int b) {
return a +
b; }},
1802 {SkRasterPipelineOp::sub_n_ints, [](
int a,
int b) {
return a -
b; }},
1803 {SkRasterPipelineOp::mul_n_ints, [](
int a,
int b) {
return a *
b; }},
1804 {SkRasterPipelineOp::div_n_ints, [](
int a,
int b) {
return a /
b; }},
1806 {SkRasterPipelineOp::bitwise_and_n_ints, [](
int a,
int b) {
return a &
b; }},
1807 {SkRasterPipelineOp::bitwise_or_n_ints, [](
int a,
int b) {
return a |
b; }},
1808 {SkRasterPipelineOp::bitwise_xor_n_ints, [](
int a,
int b) {
return a ^
b; }},
1809 {SkRasterPipelineOp::min_n_ints, [](
int a,
int b) {
return a <
b ?
a :
b; }},
1811 {SkRasterPipelineOp::max_n_ints, [](
int a,
int b) {
return a >
b ?
a :
b; }},
1815 for (
const ArithmeticOp& op : kArithmeticOps) {
1816 for (
int numSlotsAffected = 1; numSlotsAffected <= 5; ++numSlotsAffected) {
1818 std::iota(&slots[0], &slots[10 *
N], 1);
1819 int leftValue = slots[0];
1820 int rightValue = slots[numSlotsAffected *
N];
1827 ctx.
src = numSlotsAffected *
N *
sizeof(
float);
1828 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1833 int* destPtr = &slots[0];
1834 for (
int checkSlot = 0; checkSlot < 10; ++checkSlot) {
1835 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1836 if (checkSlot < numSlotsAffected) {
1851DEF_TEST(SkRasterPipeline_IntArithmeticWithHardcodedSlots, r) {
1856 struct ArithmeticOp {
1858 int numSlotsAffected;
1862 static const ArithmeticOp kArithmeticOps[] = {
1863 {SkRasterPipelineOp::add_int, 1, [](
int a,
int b) {
return a +
b; }},
1864 {SkRasterPipelineOp::sub_int, 1, [](
int a,
int b) {
return a -
b; }},
1865 {SkRasterPipelineOp::mul_int, 1, [](
int a,
int b) {
return a *
b; }},
1866 {SkRasterPipelineOp::div_int, 1, [](
int a,
int b) {
return a /
b; }},
1868 {SkRasterPipelineOp::bitwise_and_int, 1, [](
int a,
int b) {
return a &
b; }},
1869 {SkRasterPipelineOp::bitwise_or_int, 1, [](
int a,
int b) {
return a |
b; }},
1870 {SkRasterPipelineOp::bitwise_xor_int, 1, [](
int a,
int b) {
return a ^
b; }},
1871 {SkRasterPipelineOp::min_int, 1, [](
int a,
int b) {
return a <
b ?
a:
b; }},
1873 {SkRasterPipelineOp::max_int, 1, [](
int a,
int b) {
return a >
b ?
a:
b; }},
1876 {SkRasterPipelineOp::add_2_ints, 2, [](
int a,
int b) {
return a +
b; }},
1877 {SkRasterPipelineOp::sub_2_ints, 2, [](
int a,
int b) {
return a -
b; }},
1878 {SkRasterPipelineOp::mul_2_ints, 2, [](
int a,
int b) {
return a *
b; }},
1879 {SkRasterPipelineOp::div_2_ints, 2, [](
int a,
int b) {
return a /
b; }},
1881 {SkRasterPipelineOp::bitwise_and_2_ints, 2, [](
int a,
int b) {
return a &
b; }},
1882 {SkRasterPipelineOp::bitwise_or_2_ints, 2, [](
int a,
int b) {
return a |
b; }},
1883 {SkRasterPipelineOp::bitwise_xor_2_ints, 2, [](
int a,
int b) {
return a ^
b; }},
1884 {SkRasterPipelineOp::min_2_ints, 2, [](
int a,
int b) {
return a <
b ?
a:
b; }},
1886 {SkRasterPipelineOp::max_2_ints, 2, [](
int a,
int b) {
return a >
b ?
a:
b; }},
1889 {SkRasterPipelineOp::add_3_ints, 3, [](
int a,
int b) {
return a +
b; }},
1890 {SkRasterPipelineOp::sub_3_ints, 3, [](
int a,
int b) {
return a -
b; }},
1891 {SkRasterPipelineOp::mul_3_ints, 3, [](
int a,
int b) {
return a *
b; }},
1892 {SkRasterPipelineOp::div_3_ints, 3, [](
int a,
int b) {
return a /
b; }},
1894 {SkRasterPipelineOp::bitwise_and_3_ints, 3, [](
int a,
int b) {
return a &
b; }},
1895 {SkRasterPipelineOp::bitwise_or_3_ints, 3, [](
int a,
int b) {
return a |
b; }},
1896 {SkRasterPipelineOp::bitwise_xor_3_ints, 3, [](
int a,
int b) {
return a ^
b; }},
1897 {SkRasterPipelineOp::min_3_ints, 3, [](
int a,
int b) {
return a <
b ?
a:
b; }},
1899 {SkRasterPipelineOp::max_3_ints, 3, [](
int a,
int b) {
return a >
b ?
a:
b; }},
1902 {SkRasterPipelineOp::add_4_ints, 4, [](
int a,
int b) {
return a +
b; }},
1903 {SkRasterPipelineOp::sub_4_ints, 4, [](
int a,
int b) {
return a -
b; }},
1904 {SkRasterPipelineOp::mul_4_ints, 4, [](
int a,
int b) {
return a *
b; }},
1905 {SkRasterPipelineOp::div_4_ints, 4, [](
int a,
int b) {
return a /
b; }},
1907 {SkRasterPipelineOp::bitwise_and_4_ints, 4, [](
int a,
int b) {
return a &
b; }},
1908 {SkRasterPipelineOp::bitwise_or_4_ints, 4, [](
int a,
int b) {
return a |
b; }},
1909 {SkRasterPipelineOp::bitwise_xor_4_ints, 4, [](
int a,
int b) {
return a ^
b; }},
1910 {SkRasterPipelineOp::min_4_ints, 4, [](
int a,
int b) {
return a <
b ?
a:
b; }},
1912 {SkRasterPipelineOp::max_4_ints, 4, [](
int a,
int b) {
return a >
b ?
a:
b; }},
1916 for (
const ArithmeticOp& op : kArithmeticOps) {
1918 std::iota(&slots[0], &slots[10 *
N], 1);
1919 int leftValue = slots[0];
1920 int rightValue = slots[op.numSlotsAffected *
N];
1925 p.append(op.stage, &slots[0]);
1929 int* destPtr = &slots[0];
1930 for (
int checkSlot = 0; checkSlot < 10; ++checkSlot) {
1931 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1932 if (checkSlot < op.numSlotsAffected) {
1956 static const CompareOp kCompareOps[] = {
1957 {SkRasterPipelineOp::cmpeq_n_floats, [](
float a,
float b) {
return a ==
b; }},
1958 {SkRasterPipelineOp::cmpne_n_floats, [](
float a,
float b) {
return a !=
b; }},
1959 {SkRasterPipelineOp::cmplt_n_floats, [](
float a,
float b) {
return a <
b; }},
1960 {SkRasterPipelineOp::cmple_n_floats, [](
float a,
float b) {
return a <=
b; }},
1963 for (
const CompareOp& op : kCompareOps) {
1964 for (
int numSlotsAffected = 1; numSlotsAffected <= 5; ++numSlotsAffected) {
1966 for (
int index = 0; index < 10 *
N; ++index) {
1967 slots[index] = std::fmod(index, 3.0f);
1970 float leftValue = slots[0];
1971 float rightValue = slots[numSlotsAffected *
N];
1978 ctx.
src = numSlotsAffected *
N *
sizeof(
float);
1979 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
1984 float* destPtr = &slots[0];
1985 for (
int checkSlot = 0; checkSlot < 10; ++checkSlot) {
1986 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
1987 if (checkSlot < numSlotsAffected) {
1988 bool compareIsTrue = op.verify(leftValue, rightValue);
1995 leftValue = std::fmod(leftValue + 1.0f, 3.0f);
1996 rightValue = std::fmod(rightValue + 1.0f, 3.0f);
2003DEF_TEST(SkRasterPipeline_CompareFloatsWithHardcodedSlots, r) {
2010 int numSlotsAffected;
2014 static const CompareOp kCompareOps[] = {
2015 {SkRasterPipelineOp::cmpeq_float, 1, [](
float a,
float b) {
return a ==
b; }},
2016 {SkRasterPipelineOp::cmpne_float, 1, [](
float a,
float b) {
return a !=
b; }},
2017 {SkRasterPipelineOp::cmplt_float, 1, [](
float a,
float b) {
return a <
b; }},
2018 {SkRasterPipelineOp::cmple_float, 1, [](
float a,
float b) {
return a <=
b; }},
2020 {SkRasterPipelineOp::cmpeq_2_floats, 2, [](
float a,
float b) {
return a ==
b; }},
2021 {SkRasterPipelineOp::cmpne_2_floats, 2, [](
float a,
float b) {
return a !=
b; }},
2022 {SkRasterPipelineOp::cmplt_2_floats, 2, [](
float a,
float b) {
return a <
b; }},
2023 {SkRasterPipelineOp::cmple_2_floats, 2, [](
float a,
float b) {
return a <=
b; }},
2025 {SkRasterPipelineOp::cmpeq_3_floats, 3, [](
float a,
float b) {
return a ==
b; }},
2026 {SkRasterPipelineOp::cmpne_3_floats, 3, [](
float a,
float b) {
return a !=
b; }},
2027 {SkRasterPipelineOp::cmplt_3_floats, 3, [](
float a,
float b) {
return a <
b; }},
2028 {SkRasterPipelineOp::cmple_3_floats, 3, [](
float a,
float b) {
return a <=
b; }},
2030 {SkRasterPipelineOp::cmpeq_4_floats, 4, [](
float a,
float b) {
return a ==
b; }},
2031 {SkRasterPipelineOp::cmpne_4_floats, 4, [](
float a,
float b) {
return a !=
b; }},
2032 {SkRasterPipelineOp::cmplt_4_floats, 4, [](
float a,
float b) {
return a <
b; }},
2033 {SkRasterPipelineOp::cmple_4_floats, 4, [](
float a,
float b) {
return a <=
b; }},
2036 for (
const CompareOp& op : kCompareOps) {
2038 for (
int index = 0; index < 10 *
N; ++index) {
2039 slots[index] = std::fmod(index, 3.0f);
2042 float leftValue = slots[0];
2043 float rightValue = slots[op.numSlotsAffected *
N];
2048 p.append(op.stage, &slots[0]);
2052 float* destPtr = &slots[0];
2053 for (
int checkSlot = 0; checkSlot < 10; ++checkSlot) {
2054 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2055 if (checkSlot < op.numSlotsAffected) {
2056 bool compareIsTrue = op.verify(leftValue, rightValue);
2063 leftValue = std::fmod(leftValue + 1.0f, 3.0f);
2064 rightValue = std::fmod(rightValue + 1.0f, 3.0f);
2083 static const CompareOp kCompareOps[] = {
2084 {SkRasterPipelineOp::cmpeq_n_ints, [](
int a,
int b) {
return a ==
b; }},
2085 {SkRasterPipelineOp::cmpne_n_ints, [](
int a,
int b) {
return a !=
b; }},
2086 {SkRasterPipelineOp::cmplt_n_ints, [](
int a,
int b) {
return a <
b; }},
2087 {SkRasterPipelineOp::cmple_n_ints, [](
int a,
int b) {
return a <=
b; }},
2092 for (
const CompareOp& op : kCompareOps) {
2093 for (
int numSlotsAffected = 1; numSlotsAffected <= 5; ++numSlotsAffected) {
2095 for (
int index = 0; index < 10 *
N; ++index) {
2096 slots[index] = (index % 3) - 1;
2099 int leftValue = slots[0];
2100 int rightValue = slots[numSlotsAffected *
N];
2107 ctx.
src =
sizeof(
float) * numSlotsAffected *
N;
2108 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
2113 int* destPtr = &slots[0];
2114 for (
int checkSlot = 0; checkSlot < 10; ++checkSlot) {
2115 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2116 if (checkSlot < numSlotsAffected) {
2117 bool compareIsTrue = op.verify(leftValue, rightValue);
2124 if (++leftValue == 2) {
2127 if (++rightValue == 2) {
2136DEF_TEST(SkRasterPipeline_CompareIntsWithHardcodedSlots, r) {
2143 int numSlotsAffected;
2147 static const CompareOp kCompareOps[] = {
2148 {SkRasterPipelineOp::cmpeq_int, 1, [](
int a,
int b) {
return a ==
b; }},
2149 {SkRasterPipelineOp::cmpne_int, 1, [](
int a,
int b) {
return a !=
b; }},
2150 {SkRasterPipelineOp::cmplt_int, 1, [](
int a,
int b) {
return a <
b; }},
2151 {SkRasterPipelineOp::cmple_int, 1, [](
int a,
int b) {
return a <=
b; }},
2155 {SkRasterPipelineOp::cmpeq_2_ints, 2, [](
int a,
int b) {
return a ==
b; }},
2156 {SkRasterPipelineOp::cmpne_2_ints, 2, [](
int a,
int b) {
return a !=
b; }},
2157 {SkRasterPipelineOp::cmplt_2_ints, 2, [](
int a,
int b) {
return a <
b; }},
2158 {SkRasterPipelineOp::cmple_2_ints, 2, [](
int a,
int b) {
return a <=
b; }},
2162 {SkRasterPipelineOp::cmpeq_3_ints, 3, [](
int a,
int b) {
return a ==
b; }},
2163 {SkRasterPipelineOp::cmpne_3_ints, 3, [](
int a,
int b) {
return a !=
b; }},
2164 {SkRasterPipelineOp::cmplt_3_ints, 3, [](
int a,
int b) {
return a <
b; }},
2165 {SkRasterPipelineOp::cmple_3_ints, 3, [](
int a,
int b) {
return a <=
b; }},
2169 {SkRasterPipelineOp::cmpeq_4_ints, 4, [](
int a,
int b) {
return a ==
b; }},
2170 {SkRasterPipelineOp::cmpne_4_ints, 4, [](
int a,
int b) {
return a !=
b; }},
2171 {SkRasterPipelineOp::cmplt_4_ints, 4, [](
int a,
int b) {
return a <
b; }},
2172 {SkRasterPipelineOp::cmple_4_ints, 4, [](
int a,
int b) {
return a <=
b; }},
2177 for (
const CompareOp& op : kCompareOps) {
2179 for (
int index = 0; index < 10 *
N; ++index) {
2180 slots[index] = (index % 3) - 1;
2183 int leftValue = slots[0];
2184 int rightValue = slots[op.numSlotsAffected *
N];
2189 p.append(op.stage, &slots[0]);
2193 int* destPtr = &slots[0];
2194 for (
int checkSlot = 0; checkSlot < 10; ++checkSlot) {
2195 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2196 if (checkSlot < op.numSlotsAffected) {
2197 bool compareIsTrue = op.verify(leftValue, rightValue);
2204 if (++leftValue == 2) {
2207 if (++rightValue == 2) {
2224 int numSlotsAffected;
2228 static const UnaryOp kUnaryOps[] = {
2229 {SkRasterPipelineOp::cast_to_float_from_int, 1,
to_float},
2230 {SkRasterPipelineOp::cast_to_float_from_2_ints, 2,
to_float},
2231 {SkRasterPipelineOp::cast_to_float_from_3_ints, 3,
to_float},
2232 {SkRasterPipelineOp::cast_to_float_from_4_ints, 4,
to_float},
2234 {SkRasterPipelineOp::abs_int, 1, [](
int a) {
return a < 0 ? -
a :
a; }},
2235 {SkRasterPipelineOp::abs_2_ints, 2, [](
int a) {
return a < 0 ? -
a :
a; }},
2236 {SkRasterPipelineOp::abs_3_ints, 3, [](
int a) {
return a < 0 ? -
a :
a; }},
2237 {SkRasterPipelineOp::abs_4_ints, 4, [](
int a) {
return a < 0 ? -
a :
a; }},
2240 for (
const UnaryOp& op : kUnaryOps) {
2242 std::iota(&slots[0], &slots[5 *
N], -10);
2243 int inputValue = slots[0];
2248 p.append(op.stage, &slots[0]);
2252 int* destPtr = &slots[0];
2253 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
2254 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2255 if (checkSlot < op.numSlotsAffected) {
2256 int expected = op.verify(inputValue);
2269static float to_int(
float a) {
return sk_bit_cast<float>((
int)
a); }
2270static float to_uint(
float a) {
return sk_bit_cast<float>((
unsigned int)
a); }
2279 int numSlotsAffected;
2283 static const UnaryOp kUnaryOps[] = {
2284 {SkRasterPipelineOp::cast_to_int_from_float, 1,
to_int},
2285 {SkRasterPipelineOp::cast_to_int_from_2_floats, 2,
to_int},
2286 {SkRasterPipelineOp::cast_to_int_from_3_floats, 3,
to_int},
2287 {SkRasterPipelineOp::cast_to_int_from_4_floats, 4,
to_int},
2289 {SkRasterPipelineOp::cast_to_uint_from_float, 1,
to_uint},
2290 {SkRasterPipelineOp::cast_to_uint_from_2_floats, 2,
to_uint},
2291 {SkRasterPipelineOp::cast_to_uint_from_3_floats, 3,
to_uint},
2292 {SkRasterPipelineOp::cast_to_uint_from_4_floats, 4,
to_uint},
2294 {SkRasterPipelineOp::floor_float, 1, [](
float a) {
return floorf(
a); }},
2295 {SkRasterPipelineOp::floor_2_floats, 2, [](
float a) {
return floorf(
a); }},
2296 {SkRasterPipelineOp::floor_3_floats, 3, [](
float a) {
return floorf(
a); }},
2297 {SkRasterPipelineOp::floor_4_floats, 4, [](
float a) {
return floorf(
a); }},
2299 {SkRasterPipelineOp::ceil_float, 1, [](
float a) {
return ceilf(
a); }},
2300 {SkRasterPipelineOp::ceil_2_floats, 2, [](
float a) {
return ceilf(
a); }},
2301 {SkRasterPipelineOp::ceil_3_floats, 3, [](
float a) {
return ceilf(
a); }},
2302 {SkRasterPipelineOp::ceil_4_floats, 4, [](
float a) {
return ceilf(
a); }},
2305 for (
const UnaryOp& op : kUnaryOps) {
2307 bool positiveOnly = (op.stage == SkRasterPipelineOp::cast_to_uint_from_float ||
2308 op.stage == SkRasterPipelineOp::cast_to_uint_from_2_floats ||
2309 op.stage == SkRasterPipelineOp::cast_to_uint_from_3_floats ||
2310 op.stage == SkRasterPipelineOp::cast_to_uint_from_4_floats);
2312 float iotaStart = positiveOnly ? 1.0f : -9.75f;
2313 std::iota(&slots[0], &slots[5 *
N], iotaStart);
2314 float inputValue = slots[0];
2319 p.append(op.stage, &slots[0]);
2323 float* destPtr = &slots[0];
2324 for (
int checkSlot = 0; checkSlot < 5; ++checkSlot) {
2325 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2326 if (checkSlot < op.numSlotsAffected) {
2327 float expected = op.verify(inputValue);
2333 bool bitwiseMatch = (0 == memcmp(destPtr, &expected,
sizeof(
float)));
2334 bool valueMatch = (*destPtr == expected);
2359 int numSlotsAffected;
2363 static const MixOp kMixOps[] = {
2365 p->append(SkRasterPipelineOp::mix_float, slots);
2368 p->append(SkRasterPipelineOp::mix_2_floats, slots);
2371 p->append(SkRasterPipelineOp::mix_3_floats, slots);
2374 p->append(SkRasterPipelineOp::mix_4_floats, slots);
2384 for (
const MixOp& op : kMixOps) {
2386 std::iota(&slots[0], &slots[15 *
N], 1.0f);
2388 float weightValue = slots[0];
2389 float fromValue = slots[1 * op.numSlotsAffected *
N];
2390 float toValue = slots[2 * op.numSlotsAffected *
N];
2393 for (
int idx = 0; idx < 1 * op.numSlotsAffected *
N; ++idx) {
2400 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
2401 op.append(&
p, &alloc);
2405 float* destPtr = &slots[0];
2406 for (
int checkSlot = 0; checkSlot < op.numSlotsAffected; ++checkSlot) {
2407 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2408 float checkValue = (toValue - fromValue) *
to_mix_weight(weightValue) + fromValue;
2414 weightValue += 1.0f;
2426 int numSlotsAffected;
2430 static const MixOp kMixOps[] = {
2432 p->append(SkRasterPipelineOp::mix_int, slots);
2435 p->append(SkRasterPipelineOp::mix_2_ints, slots);
2438 p->append(SkRasterPipelineOp::mix_3_ints, slots);
2441 p->append(SkRasterPipelineOp::mix_4_ints, slots);
2451 for (
const MixOp& op : kMixOps) {
2453 for (
int idx = 0; idx < 1 * op.numSlotsAffected *
N; ++idx) {
2454 slots[idx] = (idx & 1) ? ~0 : 0;
2460 int weightValue = slots[0];
2461 int fromValue = slots[1 * op.numSlotsAffected *
N];
2462 int toValue = slots[2 * op.numSlotsAffected *
N];
2467 p.append(SkRasterPipelineOp::set_base_pointer, &slots[0]);
2468 op.append(&
p, &alloc);
2472 int* destPtr = &slots[0];
2473 for (
int checkSlot = 0; checkSlot < op.numSlotsAffected; ++checkSlot) {
2474 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2475 int checkValue = weightValue ? toValue : fromValue;
2481 weightValue = ~weightValue;
2492 alignas(64)
static constexpr float kColorDarkRed[4] = {0.5f, 0.0f, 0.0f, 0.75f};
2493 alignas(64)
static constexpr float kColorGreen[4] = {0.0f, 1.0f, 0.0f, 1.0f};
2499 p.appendConstantColor(&alloc, kColorGreen);
2500 p.append(SkRasterPipelineOp::jump, &
offset);
2501 p.appendConstantColor(&alloc, kColorDarkRed);
2502 p.append(SkRasterPipelineOp::store_src, slots);
2506 float* destPtr = &slots[0];
2507 for (
int checkSlot = 0; checkSlot < 4; ++checkSlot) {
2508 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2527 p.append(SkRasterPipelineOp::load_src, registerValue);
2528 p.append(SkRasterPipelineOp::exchange_src, exchangeValue);
2529 p.append(SkRasterPipelineOp::store_src, registerValue);
2532 int* registerPtr = ®isterValue[0];
2533 int* exchangePtr = &exchangeValue[0];
2535 for (
int checkSlot = 0; checkSlot < 4; ++checkSlot) {
2536 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2539 expectedRegister += 1;
2540 expectedExchange += 1;
2555 std::fill(&first [0], &first [
N], 0x12345678);
2556 std::fill(&second[0], &second[
N], 0x12345678);
2561 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
2562 p.append(SkRasterPipelineOp::branch_if_all_lanes_active, &ctx);
2563 p.append(SkRasterPipelineOp::store_src_a, first);
2564 p.append(SkRasterPipelineOp::store_src_a, second);
2567 int32_t* firstPtr = first;
2568 int32_t* secondPtr = second;
2569 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2578 std::fill(&first [0], &first [
N], 0x12345678);
2579 std::fill(&second[0], &second[
N], 0x12345678);
2585 p.append(SkRasterPipelineOp::load_src, kNoLanesActive);
2586 p.append(SkRasterPipelineOp::branch_if_all_lanes_active, &ctx);
2587 p.append(SkRasterPipelineOp::store_src_a, first);
2588 p.append(SkRasterPipelineOp::store_src_a, second);
2591 int32_t* firstPtr = first;
2592 int32_t* secondPtr = second;
2593 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2602 std::fill(&first [0], &first [
N], 0x12345678);
2603 std::fill(&second[0], &second[
N], 0x12345678);
2607 std::fill(oneLaneInactive, &oneLaneInactive[4*
N], ~0);
2608 oneLaneInactive[4*
N - 1] = 0;
2612 p.append(SkRasterPipelineOp::load_src, oneLaneInactive);
2613 p.append(SkRasterPipelineOp::branch_if_all_lanes_active, &ctx);
2614 p.append(SkRasterPipelineOp::store_src_a, first);
2615 p.append(SkRasterPipelineOp::store_src_a, second);
2618 int32_t* firstPtr = first;
2619 int32_t* secondPtr = second;
2620 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2637 std::fill(&first [0], &first [
N], 0x12345678);
2638 std::fill(&second[0], &second[
N], 0x12345678);
2643 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
2644 p.append(SkRasterPipelineOp::branch_if_any_lanes_active, &ctx);
2645 p.append(SkRasterPipelineOp::store_src_a, first);
2646 p.append(SkRasterPipelineOp::store_src_a, second);
2649 int32_t* firstPtr = first;
2650 int32_t* secondPtr = second;
2651 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2660 std::fill(&first [0], &first [
N], 0x12345678);
2661 std::fill(&second[0], &second[
N], 0x12345678);
2667 p.append(SkRasterPipelineOp::load_src, kNoLanesActive);
2668 p.append(SkRasterPipelineOp::branch_if_any_lanes_active, &ctx);
2669 p.append(SkRasterPipelineOp::store_src_a, first);
2670 p.append(SkRasterPipelineOp::store_src_a, second);
2673 int32_t* firstPtr = first;
2674 int32_t* secondPtr = second;
2675 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2684 std::fill(&first [0], &first [
N], 0x12345678);
2685 std::fill(&second[0], &second[
N], 0x12345678);
2689 oneLaneActive[4*
N - 1] = ~0;
2693 p.append(SkRasterPipelineOp::load_src, oneLaneActive);
2694 p.append(SkRasterPipelineOp::branch_if_any_lanes_active, &ctx);
2695 p.append(SkRasterPipelineOp::store_src_a, first);
2696 p.append(SkRasterPipelineOp::store_src_a, second);
2699 int32_t* firstPtr = first;
2700 int32_t* secondPtr = second;
2701 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2718 std::fill(&first [0], &first [
N], 0x12345678);
2719 std::fill(&second[0], &second[
N], 0x12345678);
2724 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
2725 p.append(SkRasterPipelineOp::branch_if_no_lanes_active, &ctx);
2726 p.append(SkRasterPipelineOp::store_src_a, first);
2727 p.append(SkRasterPipelineOp::store_src_a, second);
2730 int32_t* firstPtr = first;
2731 int32_t* secondPtr = second;
2732 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2741 std::fill(&first [0], &first [
N], 0x12345678);
2742 std::fill(&second[0], &second[
N], 0x12345678);
2748 p.append(SkRasterPipelineOp::load_src, kNoLanesActive);
2749 p.append(SkRasterPipelineOp::branch_if_no_lanes_active, &ctx);
2750 p.append(SkRasterPipelineOp::store_src_a, first);
2751 p.append(SkRasterPipelineOp::store_src_a, second);
2754 int32_t* firstPtr = first;
2755 int32_t* secondPtr = second;
2756 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2765 std::fill(&first [0], &first [
N], 0x12345678);
2766 std::fill(&second[0], &second[
N], 0x12345678);
2770 oneLaneActive[4*
N - 1] = ~0;
2774 p.append(SkRasterPipelineOp::load_src, oneLaneActive);
2775 p.append(SkRasterPipelineOp::branch_if_no_lanes_active, &ctx);
2776 p.append(SkRasterPipelineOp::store_src_a, first);
2777 p.append(SkRasterPipelineOp::store_src_a, second);
2780 int32_t* firstPtr = first;
2781 int32_t* secondPtr = second;
2782 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2789DEF_TEST(SkRasterPipeline_BranchIfActiveLanesEqual, r) {
2795 std::fill(
std::begin(allSixes), std::end(allSixes), 6);
2799 std::fill(
std::begin(mostlySixesWithOneFive), std::end(mostlySixesWithOneFive), 6);
2800 mostlySixesWithOneFive[
N - 1] = 5;
2805 matching.
ptr = allSixes;
2809 nonmatching.
value = 5;
2810 nonmatching.
ptr = mostlySixesWithOneFive;
2816 std::fill(&first [0], &first [
N], 0x12345678);
2817 std::fill(&second[0], &second[
N], 0x12345678);
2822 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
2823 p.append(SkRasterPipelineOp::branch_if_no_active_lanes_eq, &matching);
2824 p.append(SkRasterPipelineOp::store_src_a, first);
2825 p.append(SkRasterPipelineOp::store_src_a, second);
2828 int32_t* firstPtr = first;
2829 int32_t* secondPtr = second;
2830 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2839 std::fill(&first [0], &first [
N], 0x12345678);
2840 std::fill(&second[0], &second[
N], 0x12345678);
2845 p.append(SkRasterPipelineOp::init_lane_masks, &initLaneMasksCtx);
2846 p.append(SkRasterPipelineOp::branch_if_no_active_lanes_eq, &nonmatching);
2847 p.append(SkRasterPipelineOp::store_src_a, first);
2848 p.append(SkRasterPipelineOp::store_src_a, second);
2851 int32_t* firstPtr = first;
2852 int32_t* secondPtr = second;
2853 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2862 std::fill(&first [0], &first [
N], 0x12345678);
2863 std::fill(&second[0], &second[
N], 0x12345678);
2867 std::fill(
std::begin(mask), std::end(mask), ~0);
2872 p.append(SkRasterPipelineOp::load_src, mask);
2873 p.append(SkRasterPipelineOp::branch_if_no_active_lanes_eq, &nonmatching);
2874 p.append(SkRasterPipelineOp::store_src_a, first);
2875 p.append(SkRasterPipelineOp::store_src_a, second);
2878 int32_t* firstPtr = first;
2879 int32_t* secondPtr = second;
2880 for (
int checkLane = 0; checkLane <
N; ++checkLane) {
2897 p.append(SkRasterPipelineOp::srcover);
2904 uint32_t buf[72] = {
2905 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2906 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
2907 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
2908 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2909 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2910 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2914 dst = { buf + 36, 0 };
2918 p.append(SkRasterPipelineOp::load_8888, &
src);
2919 p.append(SkRasterPipelineOp::store_8888, &
dst);
2922 for (
int i = 0;
i < 36;
i++) {
2923 if (
i < 15 ||
i == 35) {
2931static uint16_t
h(
float f) {
2934 memcpy(&sem, &
f,
sizeof(sem));
2935 uint32_t
s = sem & 0x80000000,
2939 auto denorm = (int32_t)em < 0x38800000;
2941 return denorm ? SkTo<uint16_t>(0)
2942 : SkTo<uint16_t>((
s>>16) + (em>>13) - ((127-15)<<10));
2959 for (
unsigned i = 1;
i <= 4;
i++) {
2962 p.append(SkRasterPipelineOp::load_f32, &
src);
2963 p.append(SkRasterPipelineOp::store_f32, &
dst);
2965 for (
unsigned j = 0; j <
i; j++) {
2966 for (
unsigned k = 0; k < 4; k++) {
2972 for (
int j =
i; j < 4; j++) {
2981 alignas(8) uint16_t
data[][4] = {
2982 {
h(00),
h(01),
h(02),
h(03)},
2983 {
h(10),
h(11),
h(12),
h(13)},
2984 {
h(20),
h(21),
h(22),
h(23)},
2985 {
h(30),
h(31),
h(32),
h(33)},
2987 alignas(8) uint16_t
buffer[4][4];
2991 for (
unsigned i = 1;
i <= 4;
i++) {
2994 p.append(SkRasterPipelineOp::load_f16, &
src);
2995 p.append(SkRasterPipelineOp::store_f16, &
dst);
2997 for (
unsigned j = 0; j <
i; j++) {
2998 for (
int k = 0; k < 4; k++) {
3002 for (
int j =
i; j < 4; j++) {
3011 alignas(8) uint16_t
data[]= {
3017 alignas(8) uint16_t
buffer[4][4];
3021 for (
unsigned i = 1;
i <= 4;
i++) {
3024 p.append(SkRasterPipelineOp::load_af16, &
src);
3025 p.append(SkRasterPipelineOp::store_f16, &
dst);
3027 for (
unsigned j = 0; j <
i; j++) {
3028 uint16_t expected[] = {0, 0, 0,
data[j]};
3031 for (
int j =
i; j < 4; j++) {
3040 alignas(8) uint16_t
data[][4] = {
3041 {
h(00),
h(01),
h(02),
h(03)},
3042 {
h(10),
h(11),
h(12),
h(13)},
3043 {
h(20),
h(21),
h(22),
h(23)},
3044 {
h(30),
h(31),
h(32),
h(33)},
3046 alignas(8) uint16_t
buffer[4];
3050 for (
unsigned i = 1;
i <= 4;
i++) {
3053 p.append(SkRasterPipelineOp::load_f16, &
src);
3054 p.append(SkRasterPipelineOp::store_af16, &
dst);
3056 for (
unsigned j = 0; j <
i; j++) {
3059 for (
int j =
i; j < 4; j++) {
3066 alignas(8) uint16_t
data[][4] = {
3067 {
h(00),
h(01),
h(02),
h(03)},
3068 {
h(10),
h(11),
h(12),
h(13)},
3069 {
h(20),
h(21),
h(22),
h(23)},
3070 {
h(30),
h(31),
h(32),
h(33)},
3072 alignas(8) uint16_t
buffer[4][2];
3076 for (
unsigned i = 1;
i <= 4;
i++) {
3079 p.append(SkRasterPipelineOp::load_f16, &
src);
3080 p.append(SkRasterPipelineOp::store_rgf16, &
dst);
3082 for (
unsigned j = 0; j <
i; j++) {
3085 for (
int j =
i; j < 4; j++) {
3094 alignas(8) uint16_t
data[][2] = {
3100 alignas(8) uint16_t
buffer[4][4];
3104 for (
unsigned i = 1;
i <= 4;
i++) {
3107 p.append(SkRasterPipelineOp::load_rgf16, &
src);
3108 p.append(SkRasterPipelineOp::store_f16, &
dst);
3110 for (
unsigned j = 0; j <
i; j++) {
3111 uint16_t expected[] = {
data[j][0],
data[j][1],
h(0),
h(1)};
3114 for (
int j =
i; j < 4; j++) {
3125 alignas(8) uint16_t
data[][2] = {
3135 for (
unsigned i = 1;
i <= 4;
i++) {
3138 p.append(SkRasterPipelineOp::load_rg1616, &
src);
3139 p.append(SkRasterPipelineOp::store_8888, &
dst);
3141 for (
unsigned j = 0; j <
i; j++) {
3142 uint8_t expected[] = {
3150 for (
int j =
i; j < 4; j++) {
3159 alignas(8) uint16_t
data[] = {
3169 for (
unsigned i = 1;
i <= 4;
i++) {
3172 p.append(SkRasterPipelineOp::load_a16, &
src);
3173 p.append(SkRasterPipelineOp::store_8888, &
dst);
3175 for (
unsigned j = 0; j <
i; j++) {
3176 uint8_t expected[] = {0x00, 0x00, 0x00,
SkToU8(
data[j] >> 8)};
3179 for (
int j =
i; j < 4; j++) {
3188 uint8_t
data[][4] = {
3189 {0x00, 0x01, 0x02, 0x03},
3190 {0x10, 0x11, 0x12, 0x13},
3191 {0x20, 0x21, 0x22, 0x23},
3192 {0x30, 0x31, 0x32, 0x33},
3194 alignas(8) uint16_t
buffer[4];
3198 for (
unsigned i = 1;
i <= 4;
i++) {
3201 p.append(SkRasterPipelineOp::load_8888, &
src);
3202 p.append(SkRasterPipelineOp::store_a16, &
dst);
3204 for (
unsigned j = 0; j <
i; j++) {
3205 uint16_t expected = (
data[j][3] << 8) |
data[j][3];
3208 for (
int j =
i; j < 4; j++) {
3215 alignas(8) uint16_t
data[][4] = {
3216 {0x0000, 0x1000, 0x2000, 0x3000},
3217 {0x0001, 0x1001, 0x2001, 0x3001},
3218 {0x0002, 0x1002, 0x2002, 0x3002},
3219 {0x0003, 0x1003, 0x2003, 0x3003},
3221 alignas(8) uint16_t
buffer[4][4];
3225 for (
unsigned i = 1;
i <= 4;
i++) {
3228 p.append(SkRasterPipelineOp::load_16161616, &
src);
3229 p.append(SkRasterPipelineOp::swap_rb);
3230 p.append(SkRasterPipelineOp::store_16161616, &
dst);
3232 for (
unsigned j = 0; j <
i; j++) {
3236 for (
int j =
i; j < 4; j++) {
3237 for (uint16_t u16 :
buffer[j])
3246 for (
int i = 0;
i < 64;
i++) {
3256 p.append(SkRasterPipelineOp::load_8888, &ptr);
3257 p.append(SkRasterPipelineOp::swap_rb);
3258 p.append(SkRasterPipelineOp::store_8888, &ptr);
3261 for (
int i = 0;
i < 64;
i++) {
3262 uint32_t want = (4*
i+0) << 16
3266 if (
rgba[
i] != want) {
3267 ERRORF(r,
"got %08x, want %08x\n",
rgba[
i], want);
3276 for (
int i = 0;
i < 64;
i++) {
3277 rg[
i] = (4*
i+0) << 0
3285 p.append(SkRasterPipelineOp::load_rg88, &ptr);
3287 p.append(SkRasterPipelineOp::store_rg88, &ptr);
3290 for (
int i = 0;
i < 64;
i++) {
3291 uint32_t want = 0xff << 8
3293 if (rg[
i] != want) {
3294 ERRORF(r,
"got %08x, want %08x\n", rg[
i], want);
3301 for (
int i = 0;
i < 64;
i++) {
3303 rg[
i][1] = 2 *
i + 1;
3314 p.append(SkRasterPipelineOp::load_f32, &
src);
3316 p.append(SkRasterPipelineOp::store_f16, &
dst);
3319 for (
int i = 0;
i < 64;
i++) {
3335 uint32_t
rgba = 0xff00ff00;
3340 p.append(SkRasterPipelineOp::load_8888, &ptr);
3341 p.append(SkRasterPipelineOp::swap_rb);
3342 p.append(SkRasterPipelineOp::clamp_01);
3343 p.append(SkRasterPipelineOp::store_8888, &ptr);
3353 ctx->fStackAddrs.push_back(&active_pixels);
3389#if !defined(SK_SANITIZE_ADDRESS)
3390 void* baseline = fStackAddrs[0];
3391 for (
size_t i = 1;
i < fStackAddrs.size();
i++) {
3404 std::vector<void*> fStackAddrs;
3405 std::vector<Behavior> fExpectedBehavior;
3414 uint32_t
rgba = 0xff0000ff;
3419 p.append(SkRasterPipelineOp::load_8888, &ptr);
3421 p.append(SkRasterPipelineOp::swap_rb);
3423 p.append(SkRasterPipelineOp::store_8888, &ptr);
3433 uint32_t
rgba = 0xff0000ff;
3438 p.append(SkRasterPipelineOp::load_8888, &ptr);
3440 p.appendStackRewind();
3442 p.append(SkRasterPipelineOp::swap_rb);
3444 p.appendStackRewind();
3446 p.append(SkRasterPipelineOp::store_8888, &ptr);
static const uint32_t rgba[kNumPixels]
static constexpr bool SkIsNaN(T x)
static constexpr int SkRasterPipeline_kMaxStride_highp
static constexpr int kLastSignalingNaN
static bool compare_lt_uint(int a, int b)
static constexpr int kLastSignalingNegNaN
static int to_float(int a)
static int divide_unsigned(int a, int b)
static float to_uint(float a)
static uint16_t h(float f)
static int max_unsigned(int a, int b)
static float to_mix_weight(float value)
static bool compare_lteq_uint(int a, int b)
static int min_unsigned(int a, int b)
DEF_TEST(SkRasterPipeline, r)
static float to_int(float a)
constexpr uint8_t SkToU8(S x)
#define REPORTER_ASSERT(r, cond,...)
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
virtual void var(int slot, int32_t val)=0
virtual void scope(int delta)=0
virtual void enter(int fnIdx)=0
virtual void exit(int fnIdx)=0
virtual void line(int lineNum)=0
StackCheckerCtx * expectBaseline()
static Behavior GrowthBehavior()
StackCheckerCtx * expectGrowth()
void validate(skiatest::Reporter *r)
void apply(SkRasterPipeline *) const
static const char * begin(const StringSlice &s)
static void append(char **dst, size_t *count, const char *src, size_t n)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Dart_NativeFunction function
size_t raster_pipeline_highp_stride
static void * Pack(const T &ctx, SkArenaAlloc *alloc)
static UnpackedType< T > Unpack(const T *ctx)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
SINT T dot(const Vec< N, T > &a, const Vec< N, T > &b)
SI Vec< sizeof...(Ix), T > shuffle(const Vec< N, T > &)
SIN Vec< N, float > floor(const Vec< N, float > &x)
void(* fn)(SkRasterPipeline_CallbackCtx *self, int active_pixels)
std::shared_ptr< const fml::Mapping > data