Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
SkSL::RP::Program::Dumper Class Reference

Public Member Functions

 Dumper (const Program &p)
 
void dump (SkWStream *out, bool writeInstructionCount)
 
void buildLabelToStageMap ()
 
void buildUniqueSlotNameList ()
 
std::string branchOffset (const SkRasterPipeline_BranchCtx *ctx, int index) const
 
std::string imm (float immFloat, bool showAsFloat=true) const
 
std::string immCtx (const void *ctx, bool showAsFloat=true) const
 
std::string asRange (int first, int count) const
 
std::string slotOrUniformName (SkSpan< const SlotDebugInfo > debugInfo, SkSpan< const std::string > names, SlotRange range) const
 
std::string slotName (SlotRange range) const
 
std::string uniformName (SlotRange range) const
 
std::string uniformPtrCtx (const float *ptr, int numSlots) const
 
std::string valuePtrCtx (const float *ptr, int numSlots) const
 
std::string immutablePtrCtx (const float *ptr, int numSlots) const
 
std::string multiImmCtx (const float *ptr, int count) const
 
std::string ptrCtx (const void *ctx, int numSlots) const
 
std::byte * offsetToPtr (SkRPOffset offset) const
 
std::string offsetCtx (SkRPOffset offset, int numSlots) const
 
std::tuple< std::string, std::string > constantCtx (const void *v, int slots, bool showAsFloat=true) const
 
std::tuple< std::string, std::string > binaryOpCtx (const void *v, int numSlots) const
 
std::tuple< std::string, std::string > copyUniformCtx (const void *v, int numSlots) const
 
std::tuple< std::string, std::string > adjacentPtrCtx (const void *ctx, int numSlots) const
 
std::tuple< std::string, std::string > adjacentOffsetCtx (SkRPOffset offset, int numSlots) const
 
std::tuple< std::string, std::string > adjacentBinaryOpCtx (const void *v) const
 
std::tuple< std::string, std::string, std::string > adjacent3PtrCtx (const void *ctx, int numSlots) const
 
std::tuple< std::string, std::string, std::string > adjacent3OffsetCtx (SkRPOffset offset, int numSlots) const
 
std::tuple< std::string, std::string, std::string > adjacentTernaryOpCtx (const void *v) const
 
template<typename T >
std::string swizzleOffsetSpan (SkSpan< T > offsets) const
 
template<typename T >
size_t swizzleWidth (SkSpan< T > offsets) const
 
template<typename T >
std::string swizzlePtr (const void *ptr, SkSpan< T > offsets) const
 
std::tuple< std::string, std::string > swizzleCtx (ProgramOp op, const void *v) const
 
std::tuple< std::string, std::string > swizzleCopyCtx (ProgramOp op, const void *v) const
 
std::tuple< std::string, std::string > shuffleCtx (const void *v) const
 
std::tuple< std::string, std::string, std::string > matrixMultiply (const void *v) const
 

Detailed Description

Definition at line 2423 of file SkSLRasterPipelineBuilder.cpp.

Constructor & Destructor Documentation

◆ Dumper()

SkSL::RP::Program::Dumper::Dumper ( const Program p)
inline

Definition at line 2425 of file SkSLRasterPipelineBuilder.cpp.

2425: fProgram(p) {}

Member Function Documentation

◆ adjacent3OffsetCtx()

std::tuple< std::string, std::string, std::string > SkSL::RP::Program::Dumper::adjacent3OffsetCtx ( SkRPOffset  offset,
int  numSlots 
) const
inline

Definition at line 2722 of file SkSLRasterPipelineBuilder.cpp.

2723 {
2724 return this->adjacent3PtrCtx((std::byte*)fSlots.values.data() + offset, numSlots);
2725 }
std::tuple< std::string, std::string, std::string > adjacent3PtrCtx(const void *ctx, int numSlots) const
SeparatedVector2 offset

◆ adjacent3PtrCtx()

std::tuple< std::string, std::string, std::string > SkSL::RP::Program::Dumper::adjacent3PtrCtx ( const void *  ctx,
int  numSlots 
) const
inline

Definition at line 2713 of file SkSLRasterPipelineBuilder.cpp.

2714 {
2715 const float *ctxAsSlot = static_cast<const float*>(ctx);
2716 return {this->ptrCtx(ctxAsSlot, numSlots),
2717 this->ptrCtx(ctxAsSlot + (N * numSlots), numSlots),
2718 this->ptrCtx(ctxAsSlot + (2 * N * numSlots), numSlots)};
2719 }
std::string ptrCtx(const void *ctx, int numSlots) const

◆ adjacentBinaryOpCtx()

std::tuple< std::string, std::string > SkSL::RP::Program::Dumper::adjacentBinaryOpCtx ( const void *  v) const
inline

Definition at line 2706 of file SkSLRasterPipelineBuilder.cpp.

2706 {
2708 int numSlots = (ctx.src - ctx.dst) / (N * sizeof(float));
2709 return this->adjacentOffsetCtx(ctx.dst, numSlots);
2710 }
std::tuple< std::string, std::string > adjacentOffsetCtx(SkRPOffset offset, int numSlots) const
static UnpackedType< T > Unpack(const T *ctx)

◆ adjacentOffsetCtx()

std::tuple< std::string, std::string > SkSL::RP::Program::Dumper::adjacentOffsetCtx ( SkRPOffset  offset,
int  numSlots 
) const
inline

Definition at line 2700 of file SkSLRasterPipelineBuilder.cpp.

2700 {
2701 return this->adjacentPtrCtx((std::byte*)fSlots.values.data() + offset, numSlots);
2702 }
std::tuple< std::string, std::string > adjacentPtrCtx(const void *ctx, int numSlots) const

◆ adjacentPtrCtx()

std::tuple< std::string, std::string > SkSL::RP::Program::Dumper::adjacentPtrCtx ( const void *  ctx,
int  numSlots 
) const
inline

Definition at line 2693 of file SkSLRasterPipelineBuilder.cpp.

2693 {
2694 const float *ctxAsSlot = static_cast<const float*>(ctx);
2695 return std::make_tuple(this->ptrCtx(ctxAsSlot, numSlots),
2696 this->ptrCtx(ctxAsSlot + (N * numSlots), numSlots));
2697 }

◆ adjacentTernaryOpCtx()

std::tuple< std::string, std::string, std::string > SkSL::RP::Program::Dumper::adjacentTernaryOpCtx ( const void *  v) const
inline

Definition at line 2728 of file SkSLRasterPipelineBuilder.cpp.

2728 {
2730 int numSlots = ctx.delta / (sizeof(float) * N);
2731 return this->adjacent3OffsetCtx(ctx.dst, numSlots);
2732 }
std::tuple< std::string, std::string, std::string > adjacent3OffsetCtx(SkRPOffset offset, int numSlots) const

◆ asRange()

std::string SkSL::RP::Program::Dumper::asRange ( int  first,
int  count 
) const
inline

Definition at line 2515 of file SkSLRasterPipelineBuilder.cpp.

2515 {
2516 std::string text = std::to_string(first);
2517 if (count > 1) {
2518 text += ".." + std::to_string(first + count - 1);
2519 }
2520 return text;
2521 }
int count
Definition: FontMgrTest.cpp:50
std::u16string text
static SkString to_string(int n)
Definition: nanobench.cpp:119

◆ binaryOpCtx()

std::tuple< std::string, std::string > SkSL::RP::Program::Dumper::binaryOpCtx ( const void *  v,
int  numSlots 
) const
inline

Definition at line 2678 of file SkSLRasterPipelineBuilder.cpp.

2678 {
2680 return {this->offsetCtx(ctx.dst, numSlots),
2681 this->offsetCtx(ctx.src, numSlots)};
2682 }
std::string offsetCtx(SkRPOffset offset, int numSlots) const

◆ branchOffset()

std::string SkSL::RP::Program::Dumper::branchOffset ( const SkRasterPipeline_BranchCtx ctx,
int  index 
) const
inline

Definition at line 2478 of file SkSLRasterPipelineBuilder.cpp.

2478 {
2479 // The context's offset field contains a label ID
2480 int labelID = ctx->offset;
2481 const int* targetIndex = fLabelToStageMap.find(labelID);
2482 SkASSERT(targetIndex);
2483 return SkSL::String::printf("%+d (label %d at #%d)", *targetIndex - index, labelID,
2484 *targetIndex + 1);
2485 }
#define SkASSERT(cond)
Definition: SkAssert.h:116
V * find(const K &key) const
Definition: SkTHash.h:494
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: SkSLString.cpp:83

◆ buildLabelToStageMap()

void SkSL::RP::Program::Dumper::buildLabelToStageMap ( )
inline

Definition at line 2430 of file SkSLRasterPipelineBuilder.cpp.

2430 {
2431 for (int index = 0; index < fStages.size(); ++index) {
2432 if (fStages[index].op == ProgramOp::label) {
2433 int labelID = sk_bit_cast<intptr_t>(fStages[index].ctx);
2434 SkASSERT(!fLabelToStageMap.find(labelID));
2435 fLabelToStageMap[labelID] = index;
2436 }
2437 }
2438 }
int size() const
Definition: SkTArray.h:421

◆ buildUniqueSlotNameList()

void SkSL::RP::Program::Dumper::buildUniqueSlotNameList ( )
inline

Definition at line 2442 of file SkSLRasterPipelineBuilder.cpp.

2442 {
2443 if (fProgram.fDebugTrace) {
2444 fSlotNameList.reserve_exact(fProgram.fDebugTrace->fSlotInfo.size());
2445
2446 // The map consists of <variable name, <source position, unique name>>.
2448
2449 for (const SlotDebugInfo& slotInfo : fProgram.fDebugTrace->fSlotInfo) {
2450 // Look up this variable by its name and source position.
2451 int pos = slotInfo.pos.valid() ? slotInfo.pos.startOffset() : 0;
2452 THashMap<int, std::string>& positionMap = uniqueNameMap[slotInfo.name];
2453 std::string& uniqueName = positionMap[pos];
2454
2455 // Have we seen this variable name/position combination before?
2456 if (uniqueName.empty()) {
2457 // This is a unique name/position pair.
2458 uniqueName = slotInfo.name;
2459
2460 // But if it's not a unique _name_, it deserves a subscript to disambiguate it.
2461 int subscript = positionMap.count() - 1;
2462 if (subscript > 0) {
2463 for (char digit : std::to_string(subscript)) {
2464 // U+2080 through U+2089 (₀₁₂₃₄₅₆₇₈₉) in UTF8:
2465 uniqueName.push_back((char)0xE2);
2466 uniqueName.push_back((char)0x82);
2467 uniqueName.push_back((char)(0x80 + digit - '0'));
2468 }
2469 }
2470 }
2471
2472 fSlotNameList.push_back(uniqueName);
2473 }
2474 }
2475 }
SkPoint pos
std::vector< SlotDebugInfo > fSlotInfo
void reserve_exact(int n)
Definition: SkTArray.h:181
int count() const
Definition: SkTHash.h:471

◆ constantCtx()

std::tuple< std::string, std::string > SkSL::RP::Program::Dumper::constantCtx ( const void *  v,
int  slots,
bool  showAsFloat = true 
) const
inline

Definition at line 2668 of file SkSLRasterPipelineBuilder.cpp.

2670 {
2672 return {this->offsetCtx(ctx.dst, slots),
2673 this->imm(sk_bit_cast<float>(ctx.value), showAsFloat)};
2674 }
std::string imm(float immFloat, bool showAsFloat=true) const

◆ copyUniformCtx()

std::tuple< std::string, std::string > SkSL::RP::Program::Dumper::copyUniformCtx ( const void *  v,
int  numSlots 
) const
inline

Definition at line 2686 of file SkSLRasterPipelineBuilder.cpp.

2686 {
2687 const auto *ctx = static_cast<const SkRasterPipeline_UniformCtx*>(v);
2688 return {this->ptrCtx(ctx->dst, numSlots),
2689 this->multiImmCtx(reinterpret_cast<const float*>(ctx->src), numSlots)};
2690 }
std::string multiImmCtx(const float *ptr, int count) const

◆ dump()

void SkSL::RP::Program::Dumper::dump ( SkWStream out,
bool  writeInstructionCount 
)

Definition at line 2840 of file SkSLRasterPipelineBuilder.cpp.

2840 {
2841 using POp = ProgramOp;
2842
2843 // Allocate memory for the slot and uniform data, even though the program won't ever be
2844 // executed. The program requires pointer ranges for managing its data, and ASAN will report
2845 // errors if those pointers are pointing at unallocated memory.
2846 SkArenaAlloc alloc(/*firstHeapAllocation=*/1000);
2847 fSlots = fProgram.allocateSlotData(&alloc);
2848 float* uniformPtr = alloc.makeArray<float>(fProgram.fNumUniformSlots);
2849 fUniforms = SkSpan(uniformPtr, fProgram.fNumUniformSlots);
2850
2851 // Turn this program into an array of Raster Pipeline stages.
2852 fProgram.makeStages(&fStages, &alloc, fUniforms, fSlots);
2853
2854 // Assemble lookup tables for program labels and slot names.
2855 this->buildLabelToStageMap();
2857
2858 // Emit the program's instruction count.
2859 if (writeInstructionCount) {
2860 int invocationCount = 0, instructionCount = 0;
2861 for (const Stage& stage : fStages) {
2862 switch (stage.op) {
2863 case POp::label:
2864 // consumes zero instructions
2865 break;
2866
2867 case POp::invoke_shader:
2868 case POp::invoke_color_filter:
2869 case POp::invoke_blender:
2870 case POp::invoke_to_linear_srgb:
2871 case POp::invoke_from_linear_srgb:
2872 ++invocationCount;
2873 break;
2874
2875 default:
2876 ++instructionCount;
2877 break;
2878 }
2879 }
2880
2881 out->writeText(std::to_string(instructionCount).c_str());
2882 out->writeText(" instructions");
2883 if (invocationCount > 0) {
2884 out->writeText(", ");
2885 out->writeText(std::to_string(invocationCount).c_str());
2886 out->writeText(" invocations");
2887 }
2888 out->writeText("\n\n");
2889 }
2890
2891 // Emit all of the program's immutable data.
2892 const char* header = "[immutable slots]\n";
2893 const char* footer = "";
2894 for (const Instruction& inst : fProgram.fInstructions) {
2896 out->writeText(header);
2897 out->writeText("i");
2898 out->writeText(std::to_string(inst.fSlotA).c_str());
2899 out->writeText(" = ");
2900 out->writeText(this->imm(sk_bit_cast<float>(inst.fImmA)).c_str());
2901 out->writeText("\n");
2902
2903 header = "";
2904 footer = "\n";
2905 }
2906 }
2907 out->writeText(footer);
2908
2909 // Emit the program's instruction list.
2910 for (int index = 0; index < fStages.size(); ++index) {
2911 const Stage& stage = fStages[index];
2912
2913 std::string opArg1, opArg2, opArg3, opSwizzle;
2914 switch (stage.op) {
2915 case POp::label:
2916 case POp::invoke_shader:
2917 case POp::invoke_color_filter:
2918 case POp::invoke_blender:
2919 opArg1 = this->immCtx(stage.ctx, /*showAsFloat=*/false);
2920 break;
2921
2922 case POp::case_op: {
2923 auto ctx = SkRPCtxUtils::Unpack((const SkRasterPipeline_CaseOpCtx*)stage.ctx);
2924 opArg1 = this->offsetCtx(ctx.offset, 1);
2925 opArg2 = this->offsetCtx(ctx.offset + sizeof(int32_t) * N, 1);
2926 opArg3 = this->imm(sk_bit_cast<float>(ctx.expectedValue), /*showAsFloat=*/false);
2927 break;
2928 }
2929 case POp::swizzle_1:
2930 case POp::swizzle_2:
2931 case POp::swizzle_3:
2932 case POp::swizzle_4:
2933 std::tie(opArg1, opArg2) = this->swizzleCtx(stage.op, stage.ctx);
2934 break;
2935
2936 case POp::swizzle_copy_slot_masked:
2937 case POp::swizzle_copy_2_slots_masked:
2938 case POp::swizzle_copy_3_slots_masked:
2939 case POp::swizzle_copy_4_slots_masked:
2940 std::tie(opArg1, opArg2) = this->swizzleCopyCtx(stage.op, stage.ctx);
2941 break;
2942
2943 case POp::refract_4_floats:
2944 std::tie(opArg1, opArg2) = this->adjacentPtrCtx(stage.ctx, 4);
2945 opArg3 = this->ptrCtx((const float*)(stage.ctx) + (8 * N), 1);
2946 break;
2947
2948 case POp::dot_2_floats:
2949 opArg1 = this->ptrCtx(stage.ctx, 1);
2950 std::tie(opArg2, opArg3) = this->adjacentPtrCtx(stage.ctx, 2);
2951 break;
2952
2953 case POp::dot_3_floats:
2954 opArg1 = this->ptrCtx(stage.ctx, 1);
2955 std::tie(opArg2, opArg3) = this->adjacentPtrCtx(stage.ctx, 3);
2956 break;
2957
2958 case POp::dot_4_floats:
2959 opArg1 = this->ptrCtx(stage.ctx, 1);
2960 std::tie(opArg2, opArg3) = this->adjacentPtrCtx(stage.ctx, 4);
2961 break;
2962
2963 case POp::shuffle:
2964 std::tie(opArg1, opArg2) = this->shuffleCtx(stage.ctx);
2965 break;
2966
2967 case POp::matrix_multiply_2:
2968 case POp::matrix_multiply_3:
2969 case POp::matrix_multiply_4:
2970 std::tie(opArg1, opArg2, opArg3) = this->matrixMultiply(stage.ctx);
2971 break;
2972
2973 case POp::load_condition_mask:
2974 case POp::store_condition_mask:
2975 case POp::load_loop_mask:
2976 case POp::store_loop_mask:
2977 case POp::merge_loop_mask:
2978 case POp::reenable_loop_mask:
2979 case POp::load_return_mask:
2980 case POp::store_return_mask:
2981 case POp::continue_op:
2982 case POp::cast_to_float_from_int: case POp::cast_to_float_from_uint:
2983 case POp::cast_to_int_from_float: case POp::cast_to_uint_from_float:
2984 case POp::abs_int:
2985 case POp::acos_float:
2986 case POp::asin_float:
2987 case POp::atan_float:
2988 case POp::ceil_float:
2989 case POp::cos_float:
2990 case POp::exp_float:
2991 case POp::exp2_float:
2992 case POp::log_float:
2993 case POp::log2_float:
2994 case POp::floor_float:
2995 case POp::invsqrt_float:
2996 case POp::sin_float:
2997 case POp::sqrt_float:
2998 case POp::tan_float:
2999 opArg1 = this->ptrCtx(stage.ctx, 1);
3000 break;
3001
3002 case POp::store_src_rg:
3003 case POp::cast_to_float_from_2_ints: case POp::cast_to_float_from_2_uints:
3004 case POp::cast_to_int_from_2_floats: case POp::cast_to_uint_from_2_floats:
3005 case POp::abs_2_ints:
3006 case POp::ceil_2_floats:
3007 case POp::floor_2_floats:
3008 case POp::invsqrt_2_floats:
3009 opArg1 = this->ptrCtx(stage.ctx, 2);
3010 break;
3011
3012 case POp::cast_to_float_from_3_ints: case POp::cast_to_float_from_3_uints:
3013 case POp::cast_to_int_from_3_floats: case POp::cast_to_uint_from_3_floats:
3014 case POp::abs_3_ints:
3015 case POp::ceil_3_floats:
3016 case POp::floor_3_floats:
3017 case POp::invsqrt_3_floats:
3018 opArg1 = this->ptrCtx(stage.ctx, 3);
3019 break;
3020
3021 case POp::load_src:
3022 case POp::load_dst:
3023 case POp::exchange_src:
3024 case POp::store_src:
3025 case POp::store_dst:
3026 case POp::store_device_xy01:
3027 case POp::invoke_to_linear_srgb:
3028 case POp::invoke_from_linear_srgb:
3029 case POp::cast_to_float_from_4_ints: case POp::cast_to_float_from_4_uints:
3030 case POp::cast_to_int_from_4_floats: case POp::cast_to_uint_from_4_floats:
3031 case POp::abs_4_ints:
3032 case POp::ceil_4_floats:
3033 case POp::floor_4_floats:
3034 case POp::invsqrt_4_floats:
3035 case POp::inverse_mat2:
3036 opArg1 = this->ptrCtx(stage.ctx, 4);
3037 break;
3038
3039 case POp::inverse_mat3:
3040 opArg1 = this->ptrCtx(stage.ctx, 9);
3041 break;
3042
3043 case POp::inverse_mat4:
3044 opArg1 = this->ptrCtx(stage.ctx, 16);
3045 break;
3046
3047 case POp::copy_constant:
3048 case POp::add_imm_float:
3049 case POp::mul_imm_float:
3050 case POp::cmple_imm_float:
3051 case POp::cmplt_imm_float:
3052 case POp::cmpeq_imm_float:
3053 case POp::cmpne_imm_float:
3054 case POp::min_imm_float:
3055 case POp::max_imm_float:
3056 std::tie(opArg1, opArg2) = this->constantCtx(stage.ctx, 1);
3057 break;
3058
3059 case POp::add_imm_int:
3060 case POp::mul_imm_int:
3061 case POp::bitwise_and_imm_int:
3062 case POp::bitwise_xor_imm_int:
3063 case POp::cmple_imm_int:
3064 case POp::cmple_imm_uint:
3065 case POp::cmplt_imm_int:
3066 case POp::cmplt_imm_uint:
3067 case POp::cmpeq_imm_int:
3068 case POp::cmpne_imm_int:
3069 std::tie(opArg1, opArg2) = this->constantCtx(stage.ctx, 1, /*showAsFloat=*/false);
3070 break;
3071
3072 case POp::splat_2_constants:
3073 case POp::bitwise_and_imm_2_ints:
3074 std::tie(opArg1, opArg2) = this->constantCtx(stage.ctx, 2);
3075 break;
3076
3077 case POp::splat_3_constants:
3078 case POp::bitwise_and_imm_3_ints:
3079 std::tie(opArg1, opArg2) = this->constantCtx(stage.ctx, 3);
3080 break;
3081
3082 case POp::splat_4_constants:
3083 case POp::bitwise_and_imm_4_ints:
3084 std::tie(opArg1, opArg2) = this->constantCtx(stage.ctx, 4);
3085 break;
3086
3087 case POp::copy_uniform:
3088 std::tie(opArg1, opArg2) = this->copyUniformCtx(stage.ctx, 1);
3089 break;
3090
3091 case POp::copy_2_uniforms:
3092 std::tie(opArg1, opArg2) = this->copyUniformCtx(stage.ctx, 2);
3093 break;
3094
3095 case POp::copy_3_uniforms:
3096 std::tie(opArg1, opArg2) = this->copyUniformCtx(stage.ctx, 3);
3097 break;
3098
3099 case POp::copy_4_uniforms:
3100 std::tie(opArg1, opArg2) = this->copyUniformCtx(stage.ctx, 4);
3101 break;
3102
3103 case POp::copy_slot_masked:
3104 case POp::copy_slot_unmasked:
3105 case POp::copy_immutable_unmasked:
3106 std::tie(opArg1, opArg2) = this->binaryOpCtx(stage.ctx, 1);
3107 break;
3108
3109 case POp::copy_2_slots_masked:
3110 case POp::copy_2_slots_unmasked:
3111 case POp::copy_2_immutables_unmasked:
3112 std::tie(opArg1, opArg2) = this->binaryOpCtx(stage.ctx, 2);
3113 break;
3114
3115 case POp::copy_3_slots_masked:
3116 case POp::copy_3_slots_unmasked:
3117 case POp::copy_3_immutables_unmasked:
3118 std::tie(opArg1, opArg2) = this->binaryOpCtx(stage.ctx, 3);
3119 break;
3120
3121 case POp::copy_4_slots_masked:
3122 case POp::copy_4_slots_unmasked:
3123 case POp::copy_4_immutables_unmasked:
3124 std::tie(opArg1, opArg2) = this->binaryOpCtx(stage.ctx, 4);
3125 break;
3126
3127 case POp::copy_from_indirect_uniform_unmasked:
3128 case POp::copy_from_indirect_unmasked:
3129 case POp::copy_to_indirect_masked: {
3130 const auto* ctx = static_cast<SkRasterPipeline_CopyIndirectCtx*>(stage.ctx);
3131 // We don't incorporate the indirect-limit in the output
3132 opArg1 = this->ptrCtx(ctx->dst, ctx->slots);
3133 opArg2 = this->ptrCtx(ctx->src, ctx->slots);
3134 opArg3 = this->ptrCtx(ctx->indirectOffset, 1);
3135 break;
3136 }
3137 case POp::swizzle_copy_to_indirect_masked: {
3138 const auto* ctx = static_cast<SkRasterPipeline_SwizzleCopyIndirectCtx*>(stage.ctx);
3139 opArg1 = this->ptrCtx(ctx->dst, this->swizzleWidth(SkSpan(ctx->offsets,
3140 ctx->slots)));
3141 opArg2 = this->ptrCtx(ctx->src, ctx->slots);
3142 opArg3 = this->ptrCtx(ctx->indirectOffset, 1);
3143 opSwizzle = this->swizzleOffsetSpan(SkSpan(ctx->offsets, ctx->slots));
3144 break;
3145 }
3146 case POp::merge_condition_mask:
3147 case POp::merge_inv_condition_mask:
3148 case POp::add_float: case POp::add_int:
3149 case POp::sub_float: case POp::sub_int:
3150 case POp::mul_float: case POp::mul_int:
3151 case POp::div_float: case POp::div_int: case POp::div_uint:
3152 case POp::bitwise_and_int:
3153 case POp::bitwise_or_int:
3154 case POp::bitwise_xor_int:
3155 case POp::mod_float:
3156 case POp::min_float: case POp::min_int: case POp::min_uint:
3157 case POp::max_float: case POp::max_int: case POp::max_uint:
3158 case POp::cmplt_float: case POp::cmplt_int: case POp::cmplt_uint:
3159 case POp::cmple_float: case POp::cmple_int: case POp::cmple_uint:
3160 case POp::cmpeq_float: case POp::cmpeq_int:
3161 case POp::cmpne_float: case POp::cmpne_int:
3162 std::tie(opArg1, opArg2) = this->adjacentPtrCtx(stage.ctx, 1);
3163 break;
3164
3165 case POp::mix_float: case POp::mix_int:
3166 std::tie(opArg1, opArg2, opArg3) = this->adjacent3PtrCtx(stage.ctx, 1);
3167 break;
3168
3169 case POp::add_2_floats: case POp::add_2_ints:
3170 case POp::sub_2_floats: case POp::sub_2_ints:
3171 case POp::mul_2_floats: case POp::mul_2_ints:
3172 case POp::div_2_floats: case POp::div_2_ints: case POp::div_2_uints:
3173 case POp::bitwise_and_2_ints:
3174 case POp::bitwise_or_2_ints:
3175 case POp::bitwise_xor_2_ints:
3176 case POp::mod_2_floats:
3177 case POp::min_2_floats: case POp::min_2_ints: case POp::min_2_uints:
3178 case POp::max_2_floats: case POp::max_2_ints: case POp::max_2_uints:
3179 case POp::cmplt_2_floats: case POp::cmplt_2_ints: case POp::cmplt_2_uints:
3180 case POp::cmple_2_floats: case POp::cmple_2_ints: case POp::cmple_2_uints:
3181 case POp::cmpeq_2_floats: case POp::cmpeq_2_ints:
3182 case POp::cmpne_2_floats: case POp::cmpne_2_ints:
3183 std::tie(opArg1, opArg2) = this->adjacentPtrCtx(stage.ctx, 2);
3184 break;
3185
3186 case POp::mix_2_floats: case POp::mix_2_ints:
3187 std::tie(opArg1, opArg2, opArg3) = this->adjacent3PtrCtx(stage.ctx, 2);
3188 break;
3189
3190 case POp::add_3_floats: case POp::add_3_ints:
3191 case POp::sub_3_floats: case POp::sub_3_ints:
3192 case POp::mul_3_floats: case POp::mul_3_ints:
3193 case POp::div_3_floats: case POp::div_3_ints: case POp::div_3_uints:
3194 case POp::bitwise_and_3_ints:
3195 case POp::bitwise_or_3_ints:
3196 case POp::bitwise_xor_3_ints:
3197 case POp::mod_3_floats:
3198 case POp::min_3_floats: case POp::min_3_ints: case POp::min_3_uints:
3199 case POp::max_3_floats: case POp::max_3_ints: case POp::max_3_uints:
3200 case POp::cmplt_3_floats: case POp::cmplt_3_ints: case POp::cmplt_3_uints:
3201 case POp::cmple_3_floats: case POp::cmple_3_ints: case POp::cmple_3_uints:
3202 case POp::cmpeq_3_floats: case POp::cmpeq_3_ints:
3203 case POp::cmpne_3_floats: case POp::cmpne_3_ints:
3204 std::tie(opArg1, opArg2) = this->adjacentPtrCtx(stage.ctx, 3);
3205 break;
3206
3207 case POp::mix_3_floats: case POp::mix_3_ints:
3208 std::tie(opArg1, opArg2, opArg3) = this->adjacent3PtrCtx(stage.ctx, 3);
3209 break;
3210
3211 case POp::add_4_floats: case POp::add_4_ints:
3212 case POp::sub_4_floats: case POp::sub_4_ints:
3213 case POp::mul_4_floats: case POp::mul_4_ints:
3214 case POp::div_4_floats: case POp::div_4_ints: case POp::div_4_uints:
3215 case POp::bitwise_and_4_ints:
3216 case POp::bitwise_or_4_ints:
3217 case POp::bitwise_xor_4_ints:
3218 case POp::mod_4_floats:
3219 case POp::min_4_floats: case POp::min_4_ints: case POp::min_4_uints:
3220 case POp::max_4_floats: case POp::max_4_ints: case POp::max_4_uints:
3221 case POp::cmplt_4_floats: case POp::cmplt_4_ints: case POp::cmplt_4_uints:
3222 case POp::cmple_4_floats: case POp::cmple_4_ints: case POp::cmple_4_uints:
3223 case POp::cmpeq_4_floats: case POp::cmpeq_4_ints:
3224 case POp::cmpne_4_floats: case POp::cmpne_4_ints:
3225 std::tie(opArg1, opArg2) = this->adjacentPtrCtx(stage.ctx, 4);
3226 break;
3227
3228 case POp::mix_4_floats: case POp::mix_4_ints:
3229 std::tie(opArg1, opArg2, opArg3) = this->adjacent3PtrCtx(stage.ctx, 4);
3230 break;
3231
3232 case POp::add_n_floats: case POp::add_n_ints:
3233 case POp::sub_n_floats: case POp::sub_n_ints:
3234 case POp::mul_n_floats: case POp::mul_n_ints:
3235 case POp::div_n_floats: case POp::div_n_ints: case POp::div_n_uints:
3236 case POp::bitwise_and_n_ints:
3237 case POp::bitwise_or_n_ints:
3238 case POp::bitwise_xor_n_ints:
3239 case POp::mod_n_floats:
3240 case POp::min_n_floats: case POp::min_n_ints: case POp::min_n_uints:
3241 case POp::max_n_floats: case POp::max_n_ints: case POp::max_n_uints:
3242 case POp::cmplt_n_floats: case POp::cmplt_n_ints: case POp::cmplt_n_uints:
3243 case POp::cmple_n_floats: case POp::cmple_n_ints: case POp::cmple_n_uints:
3244 case POp::cmpeq_n_floats: case POp::cmpeq_n_ints:
3245 case POp::cmpne_n_floats: case POp::cmpne_n_ints:
3246 case POp::atan2_n_floats:
3247 case POp::pow_n_floats:
3248 std::tie(opArg1, opArg2) = this->adjacentBinaryOpCtx(stage.ctx);
3249 break;
3250
3251 case POp::mix_n_floats: case POp::mix_n_ints:
3252 case POp::smoothstep_n_floats:
3253 std::tie(opArg1, opArg2, opArg3) = this->adjacentTernaryOpCtx(stage.ctx);
3254 break;
3255
3256 case POp::jump:
3257 case POp::branch_if_all_lanes_active:
3258 case POp::branch_if_any_lanes_active:
3259 case POp::branch_if_no_lanes_active:
3260 opArg1 = this->branchOffset(static_cast<SkRasterPipeline_BranchCtx*>(stage.ctx),
3261 index);
3262 break;
3263
3264 case POp::branch_if_no_active_lanes_eq: {
3265 const auto* ctx = static_cast<SkRasterPipeline_BranchIfEqualCtx*>(stage.ctx);
3266 opArg1 = this->branchOffset(ctx, index);
3267 opArg2 = this->ptrCtx(ctx->ptr, 1);
3268 opArg3 = this->imm(sk_bit_cast<float>(ctx->value));
3269 break;
3270 }
3271 case POp::trace_var: {
3272 const auto* ctx = static_cast<SkRasterPipeline_TraceVarCtx*>(stage.ctx);
3273 opArg1 = this->ptrCtx(ctx->traceMask, 1);
3274 opArg2 = this->ptrCtx(ctx->data, ctx->numSlots);
3275 if (ctx->indirectOffset != nullptr) {
3276 opArg3 = " + " + this->ptrCtx(ctx->indirectOffset, 1);
3277 }
3278 break;
3279 }
3280 case POp::trace_line: {
3281 const auto* ctx = static_cast<SkRasterPipeline_TraceLineCtx*>(stage.ctx);
3282 opArg1 = this->ptrCtx(ctx->traceMask, 1);
3283 opArg2 = std::to_string(ctx->lineNumber);
3284 break;
3285 }
3286 case POp::trace_enter:
3287 case POp::trace_exit: {
3288 const auto* ctx = static_cast<SkRasterPipeline_TraceFuncCtx*>(stage.ctx);
3289 opArg1 = this->ptrCtx(ctx->traceMask, 1);
3290 opArg2 = (fProgram.fDebugTrace &&
3291 ctx->funcIdx >= 0 &&
3292 ctx->funcIdx < (int)fProgram.fDebugTrace->fFuncInfo.size())
3293 ? fProgram.fDebugTrace->fFuncInfo[ctx->funcIdx].name
3294 : "???";
3295 break;
3296 }
3297 case POp::trace_scope: {
3298 const auto* ctx = static_cast<SkRasterPipeline_TraceScopeCtx*>(stage.ctx);
3299 opArg1 = this->ptrCtx(ctx->traceMask, 1);
3300 opArg2 = SkSL::String::printf("%+d", ctx->delta);
3301 break;
3302 }
3303 default:
3304 break;
3305 }
3306
3307 std::string_view opName;
3308 switch (stage.op) {
3309 #define M(x) case POp::x: opName = #x; break;
3312 #undef M
3313 }
3314
3315 std::string opText;
3316 switch (stage.op) {
3317 case POp::trace_var:
3318 opText = "TraceVar(" + opArg2 + opArg3 + ") when " + opArg1 + " is true";
3319 break;
3320
3321 case POp::trace_line:
3322 opText = "TraceLine(" + opArg2 + ") when " + opArg1 + " is true";
3323 break;
3324
3325 case POp::trace_enter:
3326 opText = "TraceEnter(" + opArg2 + ") when " + opArg1 + " is true";
3327 break;
3328
3329 case POp::trace_exit:
3330 opText = "TraceExit(" + opArg2 + ") when " + opArg1 + " is true";
3331 break;
3332
3333 case POp::trace_scope:
3334 opText = "TraceScope(" + opArg2 + ") when " + opArg1 + " is true";
3335 break;
3336
3337 case POp::init_lane_masks:
3338 opText = "CondMask = LoopMask = RetMask = true";
3339 break;
3340
3341 case POp::load_condition_mask:
3342 opText = "CondMask = " + opArg1;
3343 break;
3344
3345 case POp::store_condition_mask:
3346 opText = opArg1 + " = CondMask";
3347 break;
3348
3349 case POp::merge_condition_mask:
3350 opText = "CondMask = " + opArg1 + " & " + opArg2;
3351 break;
3352
3353 case POp::merge_inv_condition_mask:
3354 opText = "CondMask = " + opArg1 + " & ~" + opArg2;
3355 break;
3356
3357 case POp::load_loop_mask:
3358 opText = "LoopMask = " + opArg1;
3359 break;
3360
3361 case POp::store_loop_mask:
3362 opText = opArg1 + " = LoopMask";
3363 break;
3364
3365 case POp::mask_off_loop_mask:
3366 opText = "LoopMask &= ~(CondMask & LoopMask & RetMask)";
3367 break;
3368
3369 case POp::reenable_loop_mask:
3370 opText = "LoopMask |= " + opArg1;
3371 break;
3372
3373 case POp::merge_loop_mask:
3374 opText = "LoopMask &= " + opArg1;
3375 break;
3376
3377 case POp::load_return_mask:
3378 opText = "RetMask = " + opArg1;
3379 break;
3380
3381 case POp::store_return_mask:
3382 opText = opArg1 + " = RetMask";
3383 break;
3384
3385 case POp::mask_off_return_mask:
3386 opText = "RetMask &= ~(CondMask & LoopMask & RetMask)";
3387 break;
3388
3389 case POp::store_src_rg:
3390 opText = opArg1 + " = src.rg";
3391 break;
3392
3393 case POp::exchange_src:
3394 opText = "swap(src.rgba, " + opArg1 + ")";
3395 break;
3396
3397 case POp::store_src:
3398 opText = opArg1 + " = src.rgba";
3399 break;
3400
3401 case POp::store_dst:
3402 opText = opArg1 + " = dst.rgba";
3403 break;
3404
3405 case POp::store_device_xy01:
3406 opText = opArg1 + " = DeviceCoords.xy01";
3407 break;
3408
3409 case POp::load_src:
3410 opText = "src.rgba = " + opArg1;
3411 break;
3412
3413 case POp::load_dst:
3414 opText = "dst.rgba = " + opArg1;
3415 break;
3416
3417 case POp::bitwise_and_int:
3418 case POp::bitwise_and_2_ints:
3419 case POp::bitwise_and_3_ints:
3420 case POp::bitwise_and_4_ints:
3421 case POp::bitwise_and_n_ints:
3422 case POp::bitwise_and_imm_int:
3423 case POp::bitwise_and_imm_2_ints:
3424 case POp::bitwise_and_imm_3_ints:
3425 case POp::bitwise_and_imm_4_ints:
3426 opText = opArg1 + " &= " + opArg2;
3427 break;
3428
3429 case POp::bitwise_or_int:
3430 case POp::bitwise_or_2_ints:
3431 case POp::bitwise_or_3_ints:
3432 case POp::bitwise_or_4_ints:
3433 case POp::bitwise_or_n_ints:
3434 opText = opArg1 + " |= " + opArg2;
3435 break;
3436
3437 case POp::bitwise_xor_int:
3438 case POp::bitwise_xor_2_ints:
3439 case POp::bitwise_xor_3_ints:
3440 case POp::bitwise_xor_4_ints:
3441 case POp::bitwise_xor_n_ints:
3442 case POp::bitwise_xor_imm_int:
3443 opText = opArg1 + " ^= " + opArg2;
3444 break;
3445
3446 case POp::cast_to_float_from_int:
3447 case POp::cast_to_float_from_2_ints:
3448 case POp::cast_to_float_from_3_ints:
3449 case POp::cast_to_float_from_4_ints:
3450 opText = opArg1 + " = IntToFloat(" + opArg1 + ")";
3451 break;
3452
3453 case POp::cast_to_float_from_uint:
3454 case POp::cast_to_float_from_2_uints:
3455 case POp::cast_to_float_from_3_uints:
3456 case POp::cast_to_float_from_4_uints:
3457 opText = opArg1 + " = UintToFloat(" + opArg1 + ")";
3458 break;
3459
3460 case POp::cast_to_int_from_float:
3461 case POp::cast_to_int_from_2_floats:
3462 case POp::cast_to_int_from_3_floats:
3463 case POp::cast_to_int_from_4_floats:
3464 opText = opArg1 + " = FloatToInt(" + opArg1 + ")";
3465 break;
3466
3467 case POp::cast_to_uint_from_float:
3468 case POp::cast_to_uint_from_2_floats:
3469 case POp::cast_to_uint_from_3_floats:
3470 case POp::cast_to_uint_from_4_floats:
3471 opText = opArg1 + " = FloatToUint(" + opArg1 + ")";
3472 break;
3473
3474 case POp::copy_slot_masked: case POp::copy_2_slots_masked:
3475 case POp::copy_3_slots_masked: case POp::copy_4_slots_masked:
3476 case POp::swizzle_copy_slot_masked: case POp::swizzle_copy_2_slots_masked:
3477 case POp::swizzle_copy_3_slots_masked: case POp::swizzle_copy_4_slots_masked:
3478 opText = opArg1 + " = Mask(" + opArg2 + ")";
3479 break;
3480
3481 case POp::copy_uniform: case POp::copy_2_uniforms:
3482 case POp::copy_3_uniforms: case POp::copy_4_uniforms:
3483 case POp::copy_slot_unmasked: case POp::copy_2_slots_unmasked:
3484 case POp::copy_3_slots_unmasked: case POp::copy_4_slots_unmasked:
3485 case POp::copy_immutable_unmasked: case POp::copy_2_immutables_unmasked:
3486 case POp::copy_3_immutables_unmasked: case POp::copy_4_immutables_unmasked:
3487 case POp::copy_constant: case POp::splat_2_constants:
3488 case POp::splat_3_constants: case POp::splat_4_constants:
3489 case POp::swizzle_1: case POp::swizzle_2:
3490 case POp::swizzle_3: case POp::swizzle_4:
3491 case POp::shuffle:
3492 opText = opArg1 + " = " + opArg2;
3493 break;
3494
3495 case POp::copy_from_indirect_unmasked:
3496 case POp::copy_from_indirect_uniform_unmasked:
3497 opText = opArg1 + " = Indirect(" + opArg2 + " + " + opArg3 + ")";
3498 break;
3499
3500 case POp::copy_to_indirect_masked:
3501 opText = "Indirect(" + opArg1 + " + " + opArg3 + ") = Mask(" + opArg2 + ")";
3502 break;
3503
3504 case POp::swizzle_copy_to_indirect_masked:
3505 opText = "Indirect(" + opArg1 + " + " + opArg3 + ")." + opSwizzle + " = Mask(" +
3506 opArg2 + ")";
3507 break;
3508
3509 case POp::abs_int:
3510 case POp::abs_2_ints:
3511 case POp::abs_3_ints:
3512 case POp::abs_4_ints:
3513 opText = opArg1 + " = abs(" + opArg1 + ")";
3514 break;
3515
3516 case POp::acos_float:
3517 opText = opArg1 + " = acos(" + opArg1 + ")";
3518 break;
3519
3520 case POp::asin_float:
3521 opText = opArg1 + " = asin(" + opArg1 + ")";
3522 break;
3523
3524 case POp::atan_float:
3525 opText = opArg1 + " = atan(" + opArg1 + ")";
3526 break;
3527
3528 case POp::atan2_n_floats:
3529 opText = opArg1 + " = atan2(" + opArg1 + ", " + opArg2 + ")";
3530 break;
3531
3532 case POp::ceil_float:
3533 case POp::ceil_2_floats:
3534 case POp::ceil_3_floats:
3535 case POp::ceil_4_floats:
3536 opText = opArg1 + " = ceil(" + opArg1 + ")";
3537 break;
3538
3539 case POp::cos_float:
3540 opText = opArg1 + " = cos(" + opArg1 + ")";
3541 break;
3542
3543 case POp::refract_4_floats:
3544 opText = opArg1 + " = refract(" + opArg1 + ", " + opArg2 + ", " + opArg3 + ")";
3545 break;
3546
3547 case POp::dot_2_floats:
3548 case POp::dot_3_floats:
3549 case POp::dot_4_floats:
3550 opText = opArg1 + " = dot(" + opArg2 + ", " + opArg3 + ")";
3551 break;
3552
3553 case POp::exp_float:
3554 opText = opArg1 + " = exp(" + opArg1 + ")";
3555 break;
3556
3557 case POp::exp2_float:
3558 opText = opArg1 + " = exp2(" + opArg1 + ")";
3559 break;
3560
3561 case POp::log_float:
3562 opText = opArg1 + " = log(" + opArg1 + ")";
3563 break;
3564
3565 case POp::log2_float:
3566 opText = opArg1 + " = log2(" + opArg1 + ")";
3567 break;
3568
3569 case POp::pow_n_floats:
3570 opText = opArg1 + " = pow(" + opArg1 + ", " + opArg2 + ")";
3571 break;
3572
3573 case POp::sin_float:
3574 opText = opArg1 + " = sin(" + opArg1 + ")";
3575 break;
3576
3577 case POp::sqrt_float:
3578 opText = opArg1 + " = sqrt(" + opArg1 + ")";
3579 break;
3580
3581 case POp::tan_float:
3582 opText = opArg1 + " = tan(" + opArg1 + ")";
3583 break;
3584
3585 case POp::floor_float:
3586 case POp::floor_2_floats:
3587 case POp::floor_3_floats:
3588 case POp::floor_4_floats:
3589 opText = opArg1 + " = floor(" + opArg1 + ")";
3590 break;
3591
3592 case POp::invsqrt_float:
3593 case POp::invsqrt_2_floats:
3594 case POp::invsqrt_3_floats:
3595 case POp::invsqrt_4_floats:
3596 opText = opArg1 + " = inversesqrt(" + opArg1 + ")";
3597 break;
3598
3599 case POp::inverse_mat2:
3600 case POp::inverse_mat3:
3601 case POp::inverse_mat4:
3602 opText = opArg1 + " = inverse(" + opArg1 + ")";
3603 break;
3604
3605 case POp::add_float: case POp::add_int:
3606 case POp::add_2_floats: case POp::add_2_ints:
3607 case POp::add_3_floats: case POp::add_3_ints:
3608 case POp::add_4_floats: case POp::add_4_ints:
3609 case POp::add_n_floats: case POp::add_n_ints:
3610 case POp::add_imm_float: case POp::add_imm_int:
3611 opText = opArg1 + " += " + opArg2;
3612 break;
3613
3614 case POp::sub_float: case POp::sub_int:
3615 case POp::sub_2_floats: case POp::sub_2_ints:
3616 case POp::sub_3_floats: case POp::sub_3_ints:
3617 case POp::sub_4_floats: case POp::sub_4_ints:
3618 case POp::sub_n_floats: case POp::sub_n_ints:
3619 opText = opArg1 + " -= " + opArg2;
3620 break;
3621
3622 case POp::mul_float: case POp::mul_int:
3623 case POp::mul_2_floats: case POp::mul_2_ints:
3624 case POp::mul_3_floats: case POp::mul_3_ints:
3625 case POp::mul_4_floats: case POp::mul_4_ints:
3626 case POp::mul_n_floats: case POp::mul_n_ints:
3627 case POp::mul_imm_float: case POp::mul_imm_int:
3628 opText = opArg1 + " *= " + opArg2;
3629 break;
3630
3631 case POp::div_float: case POp::div_int: case POp::div_uint:
3632 case POp::div_2_floats: case POp::div_2_ints: case POp::div_2_uints:
3633 case POp::div_3_floats: case POp::div_3_ints: case POp::div_3_uints:
3634 case POp::div_4_floats: case POp::div_4_ints: case POp::div_4_uints:
3635 case POp::div_n_floats: case POp::div_n_ints: case POp::div_n_uints:
3636 opText = opArg1 + " /= " + opArg2;
3637 break;
3638
3639 case POp::matrix_multiply_2:
3640 case POp::matrix_multiply_3:
3641 case POp::matrix_multiply_4:
3642 opText = opArg1 + " = " + opArg2 + " * " + opArg3;
3643 break;
3644
3645 case POp::mod_float:
3646 case POp::mod_2_floats:
3647 case POp::mod_3_floats:
3648 case POp::mod_4_floats:
3649 case POp::mod_n_floats:
3650 opText = opArg1 + " = mod(" + opArg1 + ", " + opArg2 + ")";
3651 break;
3652
3653 case POp::min_float: case POp::min_int: case POp::min_uint:
3654 case POp::min_2_floats: case POp::min_2_ints: case POp::min_2_uints:
3655 case POp::min_3_floats: case POp::min_3_ints: case POp::min_3_uints:
3656 case POp::min_4_floats: case POp::min_4_ints: case POp::min_4_uints:
3657 case POp::min_n_floats: case POp::min_n_ints: case POp::min_n_uints:
3658 case POp::min_imm_float:
3659 opText = opArg1 + " = min(" + opArg1 + ", " + opArg2 + ")";
3660 break;
3661
3662 case POp::max_float: case POp::max_int: case POp::max_uint:
3663 case POp::max_2_floats: case POp::max_2_ints: case POp::max_2_uints:
3664 case POp::max_3_floats: case POp::max_3_ints: case POp::max_3_uints:
3665 case POp::max_4_floats: case POp::max_4_ints: case POp::max_4_uints:
3666 case POp::max_n_floats: case POp::max_n_ints: case POp::max_n_uints:
3667 case POp::max_imm_float:
3668 opText = opArg1 + " = max(" + opArg1 + ", " + opArg2 + ")";
3669 break;
3670
3671 case POp::cmplt_float: case POp::cmplt_int: case POp::cmplt_uint:
3672 case POp::cmplt_2_floats: case POp::cmplt_2_ints: case POp::cmplt_2_uints:
3673 case POp::cmplt_3_floats: case POp::cmplt_3_ints: case POp::cmplt_3_uints:
3674 case POp::cmplt_4_floats: case POp::cmplt_4_ints: case POp::cmplt_4_uints:
3675 case POp::cmplt_n_floats: case POp::cmplt_n_ints: case POp::cmplt_n_uints:
3676 case POp::cmplt_imm_float: case POp::cmplt_imm_int: case POp::cmplt_imm_uint:
3677 opText = opArg1 + " = lessThan(" + opArg1 + ", " + opArg2 + ")";
3678 break;
3679
3680 case POp::cmple_float: case POp::cmple_int: case POp::cmple_uint:
3681 case POp::cmple_2_floats: case POp::cmple_2_ints: case POp::cmple_2_uints:
3682 case POp::cmple_3_floats: case POp::cmple_3_ints: case POp::cmple_3_uints:
3683 case POp::cmple_4_floats: case POp::cmple_4_ints: case POp::cmple_4_uints:
3684 case POp::cmple_n_floats: case POp::cmple_n_ints: case POp::cmple_n_uints:
3685 case POp::cmple_imm_float: case POp::cmple_imm_int: case POp::cmple_imm_uint:
3686 opText = opArg1 + " = lessThanEqual(" + opArg1 + ", " + opArg2 + ")";
3687 break;
3688
3689 case POp::cmpeq_float: case POp::cmpeq_int:
3690 case POp::cmpeq_2_floats: case POp::cmpeq_2_ints:
3691 case POp::cmpeq_3_floats: case POp::cmpeq_3_ints:
3692 case POp::cmpeq_4_floats: case POp::cmpeq_4_ints:
3693 case POp::cmpeq_n_floats: case POp::cmpeq_n_ints:
3694 case POp::cmpeq_imm_float: case POp::cmpeq_imm_int:
3695 opText = opArg1 + " = equal(" + opArg1 + ", " + opArg2 + ")";
3696 break;
3697
3698 case POp::cmpne_float: case POp::cmpne_int:
3699 case POp::cmpne_2_floats: case POp::cmpne_2_ints:
3700 case POp::cmpne_3_floats: case POp::cmpne_3_ints:
3701 case POp::cmpne_4_floats: case POp::cmpne_4_ints:
3702 case POp::cmpne_n_floats: case POp::cmpne_n_ints:
3703 case POp::cmpne_imm_float: case POp::cmpne_imm_int:
3704 opText = opArg1 + " = notEqual(" + opArg1 + ", " + opArg2 + ")";
3705 break;
3706
3707 case POp::mix_float: case POp::mix_int:
3708 case POp::mix_2_floats: case POp::mix_2_ints:
3709 case POp::mix_3_floats: case POp::mix_3_ints:
3710 case POp::mix_4_floats: case POp::mix_4_ints:
3711 case POp::mix_n_floats: case POp::mix_n_ints:
3712 opText = opArg1 + " = mix(" + opArg2 + ", " + opArg3 + ", " + opArg1 + ")";
3713 break;
3714
3715 case POp::smoothstep_n_floats:
3716 opText = opArg1 + " = smoothstep(" + opArg1 + ", " + opArg2 + ", " + opArg3 + ")";
3717 break;
3718
3719 case POp::jump:
3720 case POp::branch_if_all_lanes_active:
3721 case POp::branch_if_any_lanes_active:
3722 case POp::branch_if_no_lanes_active:
3723 case POp::invoke_shader:
3724 case POp::invoke_color_filter:
3725 case POp::invoke_blender:
3726 opText = std::string(opName) + " " + opArg1;
3727 break;
3728
3729 case POp::invoke_to_linear_srgb:
3730 opText = opArg1 + " = toLinearSrgb(" + opArg1 + ")";
3731 break;
3732
3733 case POp::invoke_from_linear_srgb:
3734 opText = opArg1 + " = fromLinearSrgb(" + opArg1 + ")";
3735 break;
3736
3737 case POp::branch_if_no_active_lanes_eq:
3738 opText = "branch " + opArg1 + " if no lanes of " + opArg2 + " == " + opArg3;
3739 break;
3740
3741 case POp::label:
3742 opText = "label " + opArg1;
3743 break;
3744
3745 case POp::case_op:
3746 opText = "if (" + opArg1 + " == " + opArg3 +
3747 ") { LoopMask = true; " + opArg2 + " = false; }";
3748 break;
3749
3750 case POp::continue_op:
3751 opText = opArg1 +
3752 " |= Mask(0xFFFFFFFF); LoopMask &= ~(CondMask & LoopMask & RetMask)";
3753 break;
3754
3755 default:
3756 break;
3757 }
3758
3759 opName = opName.substr(0, 30);
3760 if (!opText.empty()) {
3761 out->writeText(SkSL::String::printf("%-30.*s %s\n",
3762 (int)opName.size(), opName.data(),
3763 opText.c_str()).c_str());
3764 } else {
3765 out->writeText(SkSL::String::printf("%.*s\n",
3766 (int)opName.size(), opName.data()).c_str());
3767 }
3768 }
3769}
#define SK_RASTER_PIPELINE_OPS_ALL(M)
#define SKRP_EXTENDED_OPS(M)
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
std::vector< FunctionDebugInfo > fFuncInfo
std::string immCtx(const void *ctx, bool showAsFloat=true) const
std::tuple< std::string, std::string > swizzleCopyCtx(ProgramOp op, const void *v) const
std::tuple< std::string, std::string > copyUniformCtx(const void *v, int numSlots) const
std::tuple< std::string, std::string > constantCtx(const void *v, int slots, bool showAsFloat=true) const
std::string swizzleOffsetSpan(SkSpan< T > offsets) const
std::tuple< std::string, std::string > adjacentBinaryOpCtx(const void *v) const
std::tuple< std::string, std::string, std::string > adjacentTernaryOpCtx(const void *v) const
std::tuple< std::string, std::string, std::string > matrixMultiply(const void *v) const
std::string branchOffset(const SkRasterPipeline_BranchCtx *ctx, int index) const
std::tuple< std::string, std::string > shuffleCtx(const void *v) const
std::tuple< std::string, std::string > swizzleCtx(ProgramOp op, const void *v) const
std::tuple< std::string, std::string > binaryOpCtx(const void *v, int numSlots) const
const char * c_str() const
Definition: SkString.h:133
inst
Definition: malisc.py:37
SI Vec< sizeof...(Ix), T > shuffle(const Vec< N, T > &)
Definition: SkVx.h:667
static const char header[]
Definition: skpbench.cpp:88

◆ imm()

std::string SkSL::RP::Program::Dumper::imm ( float  immFloat,
bool  showAsFloat = true 
) const
inline

Definition at line 2488 of file SkSLRasterPipelineBuilder.cpp.

2488 {
2489 // Special case exact zero as "0" for readability (vs `0x00000000 (0.0)`).
2490 if (sk_bit_cast<int32_t>(immFloat) == 0) {
2491 return "0";
2492 }
2493 // Start with `0x3F800000` as a baseline.
2494 uint32_t immUnsigned;
2495 memcpy(&immUnsigned, &immFloat, sizeof(uint32_t));
2496 auto text = SkSL::String::printf("0x%08X", immUnsigned);
2497
2498 // Extend it to `0x3F800000 (1.0)` for finite floating point values.
2499 if (showAsFloat && std::isfinite(immFloat)) {
2500 text += " (";
2501 text += skstd::to_string(immFloat);
2502 text += ')';
2503 }
2504 return text;
2505 }
std::string to_string(float value)
Definition: SkSLString.cpp:50
SINT bool isfinite(const Vec< N, T > &v)
Definition: SkVx.h:1003

◆ immCtx()

std::string SkSL::RP::Program::Dumper::immCtx ( const void *  ctx,
bool  showAsFloat = true 
) const
inline

Definition at line 2508 of file SkSLRasterPipelineBuilder.cpp.

2508 {
2509 float f;
2510 memcpy(&f, &ctx, sizeof(float));
2511 return this->imm(f, showAsFloat);
2512 }

◆ immutablePtrCtx()

std::string SkSL::RP::Program::Dumper::immutablePtrCtx ( const float *  ptr,
int  numSlots 
) const
inline

Definition at line 2604 of file SkSLRasterPipelineBuilder.cpp.

2604 {
2605 const float* end = ptr + numSlots;
2606 if (ptr >= fSlots.immutable.begin() && end <= fSlots.immutable.end()) {
2607 int index = ptr - fSlots.immutable.begin();
2608 return 'i' + this->asRange(index, numSlots) + ' ' +
2609 this->multiImmCtx(ptr, numSlots);
2610 }
2611 return {};
2612 }
std::string asRange(int first, int count) const
glong glong end

◆ matrixMultiply()

std::tuple< std::string, std::string, std::string > SkSL::RP::Program::Dumper::matrixMultiply ( const void *  v) const
inline

Definition at line 2809 of file SkSLRasterPipelineBuilder.cpp.

2809 {
2811 int leftMatrix = ctx.leftColumns * ctx.leftRows;
2812 int rightMatrix = ctx.rightColumns * ctx.rightRows;
2813 int resultMatrix = ctx.rightColumns * ctx.leftRows;
2814 SkRPOffset leftOffset = ctx.dst + (ctx.rightColumns * ctx.leftRows * sizeof(float) * N);
2815 SkRPOffset rightOffset = leftOffset + (ctx.leftColumns * ctx.leftRows * sizeof(float) * N);
2816 return {SkSL::String::printf("mat%dx%d(%s)",
2817 ctx.rightColumns,
2818 ctx.leftRows,
2819 this->offsetCtx(ctx.dst, resultMatrix).c_str()),
2820 SkSL::String::printf("mat%dx%d(%s)",
2821 ctx.leftColumns,
2822 ctx.leftRows,
2823 this->offsetCtx(leftOffset, leftMatrix).c_str()),
2824 SkSL::String::printf("mat%dx%d(%s)",
2825 ctx.rightColumns,
2826 ctx.rightRows,
2827 this->offsetCtx(rightOffset, rightMatrix).c_str())};
2828 }
uint32_t SkRPOffset

◆ multiImmCtx()

std::string SkSL::RP::Program::Dumper::multiImmCtx ( const float *  ptr,
int  count 
) const
inline

Definition at line 2615 of file SkSLRasterPipelineBuilder.cpp.

2615 {
2616 // If this is a uniform, print it by name.
2617 if (std::string text = this->uniformPtrCtx(ptr, count); !text.empty()) {
2618 return text;
2619 }
2620 // Emit a single bracketed immediate.
2621 if (count == 1) {
2622 return '[' + this->imm(*ptr) + ']';
2623 }
2624 // Emit a list like `[0x00000000 (0.0), 0x3F80000 (1.0)]`.
2625 std::string text = "[";
2626 auto separator = SkSL::String::Separator();
2627 while (count--) {
2628 text += separator();
2629 text += this->imm(*ptr++);
2630 }
2631 return text + ']';
2632 }
std::string uniformPtrCtx(const float *ptr, int numSlots) const
std::string void void auto Separator()
Definition: SkSLString.h:30

◆ offsetCtx()

std::string SkSL::RP::Program::Dumper::offsetCtx ( SkRPOffset  offset,
int  numSlots 
) const
inline

Definition at line 2663 of file SkSLRasterPipelineBuilder.cpp.

2663 {
2664 return this->ptrCtx(this->offsetToPtr(offset), numSlots);
2665 }
std::byte * offsetToPtr(SkRPOffset offset) const

◆ offsetToPtr()

std::byte * SkSL::RP::Program::Dumper::offsetToPtr ( SkRPOffset  offset) const
inline

Definition at line 2658 of file SkSLRasterPipelineBuilder.cpp.

2658 {
2659 return (std::byte*)fSlots.values.data() + offset;
2660 }

◆ ptrCtx()

std::string SkSL::RP::Program::Dumper::ptrCtx ( const void *  ctx,
int  numSlots 
) const
inline

Definition at line 2635 of file SkSLRasterPipelineBuilder.cpp.

2635 {
2636 const float *ctxAsSlot = static_cast<const float*>(ctx);
2637 // Check for uniform, value, and immutable pointers.
2638 if (std::string uniform = this->uniformPtrCtx(ctxAsSlot, numSlots); !uniform.empty()) {
2639 return uniform;
2640 }
2641 if (std::string value = this->valuePtrCtx(ctxAsSlot, numSlots); !value.empty()) {
2642 return value;
2643 }
2644 if (std::string value = this->immutablePtrCtx(ctxAsSlot, numSlots); !value.empty()) {
2645 return value;
2646 }
2647 // Handle pointers to temporary stack slots.
2648 if (ctxAsSlot >= fSlots.stack.begin() && ctxAsSlot < fSlots.stack.end()) {
2649 int stackIdx = ctxAsSlot - fSlots.stack.begin();
2650 SkASSERT((stackIdx % N) == 0);
2651 return '$' + this->asRange(stackIdx / N, numSlots);
2652 }
2653 // This pointer is out of our expected bounds; this generally isn't expected to happen.
2654 return "ExternalPtr(" + this->asRange(0, numSlots) + ")";
2655 }
std::string valuePtrCtx(const float *ptr, int numSlots) const
std::string immutablePtrCtx(const float *ptr, int numSlots) const
uint8_t value

◆ shuffleCtx()

std::tuple< std::string, std::string > SkSL::RP::Program::Dumper::shuffleCtx ( const void *  v) const
inline

Definition at line 2791 of file SkSLRasterPipelineBuilder.cpp.

2791 {
2792 const auto* ctx = static_cast<const SkRasterPipeline_ShuffleCtx*>(v);
2793
2794 std::string dst = this->ptrCtx(ctx->ptr, ctx->count);
2795 std::string src = "(" + dst + ")[";
2796 for (int index = 0; index < ctx->count; ++index) {
2797 if (ctx->offsets[index] % (N * sizeof(float))) {
2798 src.push_back('?');
2799 } else {
2800 src += std::to_string(ctx->offsets[index] / (N * sizeof(float)));
2801 }
2802 src.push_back(' ');
2803 }
2804 src.back() = ']';
2805 return std::make_tuple(dst, src);
2806 }
dst
Definition: cp.py:12

◆ slotName()

std::string SkSL::RP::Program::Dumper::slotName ( SlotRange  range) const
inline

Definition at line 2556 of file SkSLRasterPipelineBuilder.cpp.

2556 {
2557 return this->slotOrUniformName(fProgram.fDebugTrace->fSlotInfo, fSlotNameList, range);
2558 }
std::string slotOrUniformName(SkSpan< const SlotDebugInfo > debugInfo, SkSpan< const std::string > names, SlotRange range) const

◆ slotOrUniformName()

std::string SkSL::RP::Program::Dumper::slotOrUniformName ( SkSpan< const SlotDebugInfo debugInfo,
SkSpan< const std::string >  names,
SlotRange  range 
) const
inline

Definition at line 2528 of file SkSLRasterPipelineBuilder.cpp.

2530 {
2531 SkASSERT(range.index >= 0 && (range.index + range.count) <= (int)debugInfo.size());
2532
2533 std::string text;
2534 auto separator = SkSL::String::Separator();
2535 while (range.count > 0) {
2536 const SlotDebugInfo& slotInfo = debugInfo[range.index];
2537 text += separator();
2538 text += names.empty() ? slotInfo.name : names[range.index];
2539
2540 // Figure out how many slots we can chomp in this iteration.
2541 int entireVariable = slotInfo.columns * slotInfo.rows;
2542 int slotsToChomp = std::min(range.count, entireVariable - slotInfo.componentIndex);
2543 // If we aren't consuming an entire variable, from first slot to last...
2544 if (slotsToChomp != entireVariable) {
2545 // ... decorate it with a range suffix.
2546 text += '(' + this->asRange(slotInfo.componentIndex, slotsToChomp) + ')';
2547 }
2548 range.index += slotsToChomp;
2549 range.count -= slotsToChomp;
2550 }
2551
2552 return text;
2553 }
constexpr size_t size() const
Definition: SkSpan_impl.h:95
static float min(float r, float g, float b)
Definition: hsl.cpp:48
static const char *const names[]
Definition: symbols.cc:24

◆ swizzleCopyCtx()

std::tuple< std::string, std::string > SkSL::RP::Program::Dumper::swizzleCopyCtx ( ProgramOp  op,
const void *  v 
) const
inline

Definition at line 2782 of file SkSLRasterPipelineBuilder.cpp.

2782 {
2783 const auto* ctx = static_cast<const SkRasterPipeline_SwizzleCopyCtx*>(v);
2784 int destSlots = (int)op - (int)BuilderOp::swizzle_copy_slot_masked + 1;
2785
2786 return {this->swizzlePtr(ctx->dst, SkSpan(ctx->offsets, destSlots)),
2787 this->ptrCtx(ctx->src, destSlots)};
2788 }
std::string swizzlePtr(const void *ptr, SkSpan< T > offsets) const

◆ swizzleCtx()

std::tuple< std::string, std::string > SkSL::RP::Program::Dumper::swizzleCtx ( ProgramOp  op,
const void *  v 
) const
inline

Definition at line 2774 of file SkSLRasterPipelineBuilder.cpp.

2774 {
2776 int destSlots = (int)op - (int)BuilderOp::swizzle_1 + 1;
2777 return {this->offsetCtx(ctx.dst, destSlots),
2778 this->swizzlePtr(this->offsetToPtr(ctx.dst), SkSpan(ctx.offsets, destSlots))};
2779 }

◆ swizzleOffsetSpan()

template<typename T >
std::string SkSL::RP::Program::Dumper::swizzleOffsetSpan ( SkSpan< T offsets) const
inline

Definition at line 2736 of file SkSLRasterPipelineBuilder.cpp.

2736 {
2737 std::string src;
2738 for (uint16_t offset : offsets) {
2739 if (offset == (0 * N * sizeof(float))) {
2740 src.push_back('x');
2741 } else if (offset == (1 * N * sizeof(float))) {
2742 src.push_back('y');
2743 } else if (offset == (2 * N * sizeof(float))) {
2744 src.push_back('z');
2745 } else if (offset == (3 * N * sizeof(float))) {
2746 src.push_back('w');
2747 } else {
2748 src.push_back('?');
2749 }
2750 }
2751 return src;
2752 }
list offsets
Definition: mskp_parser.py:37

◆ swizzlePtr()

template<typename T >
std::string SkSL::RP::Program::Dumper::swizzlePtr ( const void *  ptr,
SkSpan< T offsets 
) const
inline

Definition at line 2768 of file SkSLRasterPipelineBuilder.cpp.

2768 {
2769 return "(" + this->ptrCtx(ptr, this->swizzleWidth(SkSpan(offsets))) + ")." +
2770 this->swizzleOffsetSpan(SkSpan(offsets));
2771 }
size_t swizzleWidth(SkSpan< T > offsets) const

◆ swizzleWidth()

template<typename T >
size_t SkSL::RP::Program::Dumper::swizzleWidth ( SkSpan< T offsets) const
inline

Definition at line 2759 of file SkSLRasterPipelineBuilder.cpp.

2759 {
2760 size_t highestComponent = *std::max_element(offsets.begin(), offsets.end()) /
2761 (N * sizeof(float));
2762 size_t swizzleWidth = offsets.size();
2763 return std::max(swizzleWidth, highestComponent + 1);
2764 }
static float max(float r, float g, float b)
Definition: hsl.cpp:49

◆ uniformName()

std::string SkSL::RP::Program::Dumper::uniformName ( SlotRange  range) const
inline

Definition at line 2561 of file SkSLRasterPipelineBuilder.cpp.

2561 {
2562 return this->slotOrUniformName(fProgram.fDebugTrace->fUniformInfo, /*names=*/{}, range);
2563 }
std::vector< SlotDebugInfo > fUniformInfo

◆ uniformPtrCtx()

std::string SkSL::RP::Program::Dumper::uniformPtrCtx ( const float *  ptr,
int  numSlots 
) const
inline

Definition at line 2566 of file SkSLRasterPipelineBuilder.cpp.

2566 {
2567 const float* end = ptr + numSlots;
2568 if (ptr >= fUniforms.begin() && end <= fUniforms.end()) {
2569 int uniformIdx = ptr - fUniforms.begin();
2570 if (fProgram.fDebugTrace) {
2571 // Handle pointers to named uniform slots.
2572 std::string name = this->uniformName({uniformIdx, numSlots});
2573 if (!name.empty()) {
2574 return name;
2575 }
2576 }
2577 // Handle pointers to uniforms (when no debug info exists).
2578 return 'u' + this->asRange(uniformIdx, numSlots);
2579 }
2580 return {};
2581 }
std::string uniformName(SlotRange range) const
constexpr T * begin() const
Definition: SkSpan_impl.h:90
constexpr T * end() const
Definition: SkSpan_impl.h:91
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32

◆ valuePtrCtx()

std::string SkSL::RP::Program::Dumper::valuePtrCtx ( const float *  ptr,
int  numSlots 
) const
inline

Definition at line 2584 of file SkSLRasterPipelineBuilder.cpp.

2584 {
2585 const float* end = ptr + (N * numSlots);
2586 if (ptr >= fSlots.values.begin() && end <= fSlots.values.end()) {
2587 int valueIdx = ptr - fSlots.values.begin();
2588 SkASSERT((valueIdx % N) == 0);
2589 valueIdx /= N;
2590 if (fProgram.fDebugTrace) {
2591 // Handle pointers to named value slots.
2592 std::string name = this->slotName({valueIdx, numSlots});
2593 if (!name.empty()) {
2594 return name;
2595 }
2596 }
2597 // Handle pointers to value slots (when no debug info exists).
2598 return 'v' + this->asRange(valueIdx, numSlots);
2599 }
2600 return {};
2601 }
std::string slotName(SlotRange range) const

The documentation for this class was generated from the following file: