function basicExpressionShaderBody()

in src/webgpu/shader/execution/expression/expression.ts [664:779]


function basicExpressionShaderBody(
  expressionBuilder: ExpressionBuilder,
  params: ShaderBuilderParams
): string {
  const { parameterTypes, resultType, cases, inputSource } = params;

  assert(
    scalarTypeOf(resultType).kind !== 'abstract-int',
    `abstractIntShaderBuilder should be used when result type is 'abstract-int'`
  );
  assert(
    scalarTypeOf(resultType).kind !== 'abstract-float',
    `abstractFloatShaderBuilder should be used when result type is 'abstract-float'`
  );
  let nextUniqueIDSuffix = 0;
  const convHelpers: TypeConversionHelpers = {
    wgsl: '',
    uniqueID: () => `cts_symbol_${nextUniqueIDSuffix++}`,
  };
  if (inputSource === 'const') {
    let constEvaluationMode = params.constEvaluationMode;
    if (constEvaluationMode === undefined) {
      if (parameterTypes.some(ty => isAbstractType(scalarTypeOf(ty)))) {
        // Directly assign the expression to the output, to avoid an
        // intermediate store, which will concretize the value early
        constEvaluationMode = 'direct';
      } else {
        constEvaluationMode = globalTestConfig.unrollConstEvalLoops ? 'unrolled' : 'loop';
      }
    }
    //////////////////////////////////////////////////////////////////////////
    // Constant eval
    //////////////////////////////////////////////////////////////////////////
    let body = '';
    let valuesArray = '';
    switch (constEvaluationMode) {
      case 'direct': {
        body = cases
          .map(
            (c, i) =>
              `  outputs[${i}].value = ${toStorage(
                resultType,
                expressionBuilder(map(c.input, v => v.wgsl())),
                convHelpers
              )};`
          )
          .join('\n  ');
        break;
      }
      case 'unrolled': {
        body = cases
          .map((_, i) => {
            const value = `values[${i}]`;
            return `  outputs[${i}].value = ${toStorage(resultType, value, convHelpers)};`;
          })
          .join('\n  ');
        valuesArray = wgslValuesArray(cases, expressionBuilder);
        break;
      }
      case 'loop': {
        body = `
  for (var i = 0u; i < ${cases.length}; i++) {
    outputs[i].value = ${toStorage(resultType, `values[i]`, convHelpers)};
  }`;
        valuesArray = wgslValuesArray(cases, expressionBuilder);
        break;
      }
    }

    return `
${wgslOutputs(resultType, cases.length)}

${valuesArray}

${convHelpers.wgsl}

@compute @workgroup_size(1)
fn main() {
${body}
}
`;
  } else {
    //////////////////////////////////////////////////////////////////////////
    // Runtime eval
    //////////////////////////////////////////////////////////////////////////

    // returns the WGSL expression to load the ith parameter of the given type from the input buffer
    const paramExpr = (ty: Type, i: number) => fromStorage(ty, `inputs[i].param${i}`, convHelpers);

    // resolves to the expression that calls the builtin
    const expr = toStorage(
      resultType,
      expressionBuilder(parameterTypes.map(paramExpr)),
      convHelpers
    );

    return `
struct Input {
${wgslMembers(parameterTypes.map(storageType), inputSource, i => `param${i}`)}
}

${wgslOutputs(resultType, cases.length)}

${wgslInputVar(inputSource, cases.length)}

${convHelpers.wgsl}

@compute @workgroup_size(1)
fn main() {
  for (var i = 0; i < ${cases.length}; i++) {
    outputs[i].value = ${expr};
  }
}
`;
  }
}