function validateTonemapper(tonemapper, inputFragColor, expectedColor) {
        if (!scene.highDynamicRangeSupported) {
          return;
        }

        scene.postProcessStages.tonemapper = tonemapper;

        const inputColorRgb = inputFragColor.map((n) =>
          Math.floor(Math.min(Math.max(n * 255, 0), 255)),
        );
        const fs =
          "void main() { \n" +
          `    out_FragColor = vec4(${inputFragColor.join(", ")}); \n` +
          "} \n";
        scene.primitives.add(new ViewportPrimitive(fs));

        // validate we start by rendering the expected color
        expect(scene)
          .withContext(`without HDR`)
          .toRenderAndCall((rgba) => {
            expect(rgba[0])
              .withContext("r")
              .toEqualEpsilon(inputColorRgb[0], 1);
            expect(rgba[1])
              .withContext("g")
              .toEqualEpsilon(inputColorRgb[1], 1);
            expect(rgba[2])
              .withContext("b")
              .toEqualEpsilon(inputColorRgb[2], 1);
            expect(rgba[3]).withContext("a").toEqual(inputColorRgb[3]);
          });
        // toggle HDR on
        scene.highDynamicRange = true;
        // validate we render a DIFFERENT color, not black, and that it matches the expected color
        expect(scene).toRenderAndCall(function (rgba) {
          expect(rgba).not.toEqual(black);
          expect(rgba).withContext(`with HDR`).not.toEqual(inputColorRgb);
          expect(rgba[0]).withContext("r").toEqual(expectedColor[0]);
          expect(rgba[1]).withContext("g").toEqual(expectedColor[1]);
          expect(rgba[2]).withContext("b").toEqual(expectedColor[2]);
          expect(rgba[3]).withContext("a").toEqual(expectedColor[3]);
        });
      }
@param {Tonemapper} tonemapper
@param {number[]} inputFragColor rgba in float values to use in fragment shader
@param {number[]} expectedColor rgba in rgb 0-255 to use for expected rendered colors