blob: f8476aec38faa6ac585ce7aea8126de962cd048f [file] [log] [blame]
<!DOCTYPE html>
<html>
<meta charset=utf-8>
<title>Test the WHLSL test harness.</title>
<script src="js/whlsl-test-harness.js"></script>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
const epsilon = 0.0001;
const numericScalarTypes = ["int", "uchar", "uint", "float"];
const numericScalarFuncs = {
"int": callIntFunction,
"uchar": callUcharFunction,
"uint": callUintFunction,
"float": callFloatFunction
};
const scalarArgMakers = {
"int": makeInt,
"uchar": makeUchar,
"uint": makeUint,
"float": makeFloat
};
let mslTests = {};
mslTests.literals = () => {
checkBools("Return a literal of type bool.", "return true;");
checkFloat4s("return float4(0, 1, 2, 3);");
checkNumericScalars("return 42;", [], 42);
};
mslTests.singleArgument = () => {
checkBools("Upload and return a bool value.", "return in0;", [true]);
checkFloat4s("return in0.wzyx;", [[3, 2, 1, 0]]);
checkNumericScalars("return in0;", [42], 42);
};
mslTests.manyArguments = () => {
checkBools("Upload many bool values and return a calculated result.",
"return in0 & in1 & in2 & in3 & in4 & in5 & in6 & in7;",
[true, true, true, true, true, true, true, true]);
const body = `return in0 + in1 + in2 + in3 + in4 + in5 + in6 + in7;`;
let args = [];
for (let i = 0; i < 8; ++i)
args.push([0, 1, 2, 3]);
checkFloat4s(body, args, [0, 8, 16, 24]);
checkNumericScalars(body, [0, 1, 2, 3, 4, 5, 6, 7], 28);
};
mslTests.buffersWithOneValue = () => {
const body = `return in0[0];`
checkBools("Access and return a single bool through a bool*.", body, [[true]]);
checkFloat4s(body, [[[0, 1, 2, 3]]]);
checkNumericScalars(body, [[42]], 42);
};
mslTests.multipleBufferArguments = () => {
checkBools("Access multiple bools through various buffers and return a bool.",
"return in0[0] & in0[1] & in0[2] & in1 & in2[0];",
[[true, true, true], true, [true]]);
const body = `return in0[0] + in0[1] + in0[2] + in1 + in2[0];`;
const vector = [0, 1, 2, 3];
checkFloat4s(body, [[vector, vector, vector], vector, [vector]], [0, 5, 10, 15]);
checkNumericScalars(body, [[0, 1, 2], 3, [4]], 10);
};
mslTests.multipleArgumentTypes = () => {
const src = `float test(int i, uchar c, device uint* u, bool b, device bool* bs, float4 f4, device float* fs)
{
if (b && bs[0] && bs[1])
return i + c + u[0] + f4.x + f4.y + f4.z + f4.w + fs[0] + fs[1];
return 0;
}`;
const i = makeInt(1);
const c = makeUchar(2);
const u = makeUint([3]);
const b = makeBool(true);
const bs = makeBool([true, true]);
const f4 = makeFloat4([4, 5, 6, 7]);
const fs = makeFloat([8, 9]);
webGPUPromiseTest(() => {
return callFloatFunction(src, "test", [i, c, u, b, bs, f4, fs]).then(result => {
assert_approx_equals(result, 45, epsilon, "Test returned expected value.");
});
}, "Upload and calculate a result from varied argument types.");
};
mslTests.bufferStores = () => {
let src = `void test(device float4* out) {
*out = float4(0, 1, 2, 3);
}`;
const float4Out = makeFloat4([[0, 0, 0, 0]]);
callVoidFunction(src, "test", float4Out);
webGPUPromiseTest(() => {
return float4Out.getArrayBuffer().then(arrayBuffer => {
const result = new Float32Array(arrayBuffer);
for (let i; i < 4; ++i) {
assert_approx_equals(result[i], i, "Test stored expected values.");
}
});
}, "Store into a float4*.");
src = `void test(device uchar* in, device uchar* out) {
for (uint i = 0; i < 5; ++i)
out[i] = in[i];
}`;
const array = [0, 1, 2, 3, 4];
const input = makeUchar(array);
const output = makeUchar([0, 0, 0, 0, 0]);
callVoidFunction(src, "test", [input, output]);
webGPUPromiseTest(() => {
return output.getArrayBuffer().then(arrayBuffer => {
const result = new Uint8Array(arrayBuffer);
assert_array_equals(array, result, "Test stored expected values.");
});
}, "Upload a uchar* and store into a uchar*.");
};
window.addEventListener("load", () => {
harness.isWHLSL = false;
for (const name in mslTests) {
mslTests[name]();
}
});
/* Helper functions */
const checkNumericScalars = (body, argValues, expected) => {
let functions = [];
let src = "";
for (let type of numericScalarTypes) {
const name = `${type}Test`;
let inputArgs = [];
let values = [];
for (let i = 0; i < argValues.length; ++i) {
const isPointer = Array.isArray(argValues[i]);
inputArgs.push(`${isPointer ? "device " : ""}${type}${isPointer ? "*" : ""} in${i}`);
values.push(scalarArgMakers[type](argValues[i]));
}
src += `${type} ${name}(${inputArgs.join(", ")}) { ${body} }
`;
functions.push({ type: type, name: name, args: values, expected: expected });
}
for (const f of functions) {
const callFunc = numericScalarFuncs[f.type];
webGPUPromiseTest(async () => {
return callFunc(src, f.name, f.args).then(result => {
assert_approx_equals(result, f.expected, epsilon, "Test returned expected value.");
});
}, `Return an expected ${f.type} value.`);
}
};
const checkBools = (msg = "Return an expected bool value.", body, argValues = [], expected = true) => {
let src = "";
let inputArgs = [];
let values = [];
for (let i = 0; i < argValues.length; ++i) {
const isPointer = Array.isArray(argValues[i]);
inputArgs.push(`${isPointer ? "device " : ""}bool${isPointer ? "*" : ""} in${i}`);
values.push(makeBool(argValues[i]));
}
src += `bool boolTest(${inputArgs.join(", ")}) { ${body} }
`;
webGPUPromiseTest(async () => {
return callBoolFunction(src, "boolTest", values).then(result => {
assert_equals(result, expected, "Test returned expected value.");
});
}, msg);
};
const checkFloat4s = (body, argValues = [], expected = [0, 1, 2, 3]) => {
let src = "";
let inputArgs = [];
let values = [];
for (let i = 0; i < argValues.length; ++i) {
// Support arrays of float4, including one with a single float4.
const totalLength = argValues[i].flat().length;
const isPointer = argValues[i].length === 1 || totalLength > 4;
inputArgs.push(`${isPointer ? "device " : ""}float4${isPointer ? "*" : ""} in${i}`);
values.push(makeFloat4(argValues[i]));
}
src += `float4 float4Test(${inputArgs.join(", ")}) { ${body} }
`;
webGPUPromiseTest(async () => {
return callFloat4Function(src, "float4Test", values).then(result => {
for (let i = 0; i < 4; ++i)
assert_approx_equals(result[i], expected[i], epsilon, "Test returned expected value.");
});
}, "Return an expected float4 value.");
}
</script>
</html>