Changeset 246824 in webkit
- Timestamp:
- Jun 25, 2019 6:40:52 PM (5 years ago)
- Location:
- trunk/LayoutTests
- Files:
-
- 4 edited
- 2 copied
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r246817 r246824 1 2019-06-25 Justin Fan <justin_fan@apple.com> 2 3 [WHLSL] Make whlsl-test-harness actually generate WHLSL shaders by default 4 https://bugs.webkit.org/show_bug.cgi?id=199028 5 6 Reviewed by Saam Barati. 7 8 whlsl-test-harness.js now generates WHLSL shaders and invokes WebKit's WHLSL compiler. 9 MSL mode remains to facilitate further harness tesing. 10 In addition, if WebGPU is not supported, synchronous Harness methods do nothing. 11 Asynchronous methods will throw a WebGPUUnsupportedError that "rejects" the returned Promise. 12 13 * TestExpectations: 14 * platform/mac/TestExpectations: 15 * webgpu/js/whlsl-test-harness.js: 16 (WebGPUUnsupportedError): Layout tests should catch these to fail gracefully if WebGPU is not supported. 17 (Data): 18 (Data.prototype.async.getArrayBuffer): 19 (Data.prototype.get isBuffer): Renamed from isPointer. 20 (Harness): 21 (Harness.prototype.async.requestDevice): Can be used to re-acquire a GPUDevice. 22 (Harness.prototype.set isWHLSL): Determines whether harness will generate WHLSL or MSL shaders. 23 (Harness.prototype.async.callTypedFunction): 24 (Harness.prototype.callVoidFunction): 25 (Harness.prototype.get device): 26 (Harness.prototype._clearResults): 27 (Harness.prototype._setUpArguments): 28 (Harness.prototype._callFunction): 29 (Data.prototype.get isPointer): Deleted. 30 (Harness.prototype._initialize): Deleted. 31 (Harness.prototype.async.callVoidFunction): Deleted. 32 (harness._initialize.async): Deleted. 33 * webgpu/msl-harness-test-expected.txt: Renamed from LayoutTests/webgpu/whlsl-harness-test-expected.txt. 34 * webgpu/msl-harness-test.html: Copied from LayoutTests/webgpu/whlsl-harness-test.html. 35 * webgpu/whlsl-test-harness-test-expected.html: Added. 36 * webgpu/whlsl-test-harness-test.html: Renamed from LayoutTests/webgpu/whlsl-harness-test.html. 37 1 38 2019-06-25 Daniel Bates <dabates@apple.com> 2 39 -
trunk/LayoutTests/TestExpectations
r246788 r246824 3441 3441 3442 3442 webkit.org/b/199039 editing/deleting/smart-delete-paragraph-003.html [ Skip ] 3443 3444 webkit.org/b/199028 webgpu/whlsl-test-harness-test.html [ Slow ] -
trunk/LayoutTests/platform/mac/TestExpectations
r246806 r246824 1787 1787 webkit.org/b/192956 [ Sierra ] inspector/canvas/resolveCanvasContext-webgpu.html [ Skip ] 1788 1788 1789 webkit.org/b/199076 [ HighSierra ] webgpu/whlsl-harness-test.html [ Skip ] 1789 webkit.org/b/199076 [ HighSierra ] webgpu/whlsl-test-harness-test.html [ Skip ] 1790 webkit.org/b/199028 [ HighSierra ] webgpu/msl-harness-test.html [ Skip ] 1790 1791 1791 1792 webkit.org/b/189680 platform/mac/media/audio-session-category-video-paused.html [ Pass Timeout ] -
trunk/LayoutTests/webgpu/js/whlsl-test-harness.js
r246628 r246824 64 64 /* Harness Classes */ 65 65 66 class WebGPUUnsupportedError extends Error { 67 constructor() 68 { 69 super("No GPUDevice detected!"); 70 } 71 }; 72 66 73 class Data { 67 74 /** … … 70 77 * @param {Number or Array[Number]} values - The raw data to be uploaded. 71 78 */ 72 constructor(harness, type, values, isPointer = false) 73 { 74 // One or more scalars in an array can be accessed through a pointer to buffer. 79 constructor(harness, type, values, isBuffer = false) 80 { 81 if (harness.device === undefined) 82 return; 83 // One or more scalars in an array can be accessed through an array reference. 75 84 // However, vector types are also created via an array of scalars. 76 85 // This ensures that buffers of just one vector are usable in a test function. 77 86 if (Array.isArray(values)) 78 this._is Pointer = isVectorType(type) ? isPointer : true;87 this._isBuffer = isVectorType(type) ? isBuffer : true; 79 88 else { 80 this._is Pointer = false;89 this._isBuffer = false; 81 90 values = [values]; 82 91 } … … 85 94 this._byteLength = (convertTypeToArrayType(type)).BYTES_PER_ELEMENT * values.length; 86 95 87 const [buffer, arrayBuffer] = harness. _device.createBufferMapped({96 const [buffer, arrayBuffer] = harness.device.createBufferMapped({ 88 97 size: this._byteLength, 89 98 usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ … … 102 111 async getArrayBuffer() 103 112 { 113 if (harness.device === undefined) 114 throw new WebGPUUnsupportedError(); 115 104 116 let result; 105 117 try { … … 113 125 114 126 get type() { return this._type; } 115 get is Pointer() { return this._isPointer; }127 get isBuffer() { return this._isBuffer; } 116 128 get buffer() { return this._buffer; } 117 129 get byteLength() { return this._byteLength; } … … 119 131 120 132 class Harness { 121 constructor() 122 { 123 this._shaderHeader = `#include <metal_stdlib> 124 using namespace metal; 133 constructor () 134 { 135 this.isWHLSL = true; 136 } 137 138 async requestDevice() 139 { 140 try { 141 const adapter = await navigator.gpu.requestAdapter(); 142 this._device = await adapter.requestDevice(); 143 } catch { 144 // WebGPU is not supported. 145 // FIXME: Add support for GPUAdapterRequestOptions and GPUDeviceDescriptor, 146 // and differentiate between descriptor validation errors and no WebGPU support. 147 } 148 } 149 150 // Sets whether Harness generates WHLSL or MSL shaders. 151 set isWHLSL(value) 152 { 153 this._isWHLSL = value; 154 this._shaderHeader = value ? "" : ` 155 #include <metal_stdlib> 156 using namespace metal; 125 157 `; 126 }127 128 _initialize(callback)129 {130 callback.bind(this)();131 158 } 132 159 … … 141 168 async callTypedFunction(type, functions, name, args) 142 169 { 143 const [argsLayouts, argsResourceBindings, argsStructCode, functionCallArgs] = this._setUpArguments(args); 144 145 if (!this._resultBuffer) { 146 this._resultBuffer = this._device.createBuffer({ 170 if (this._device === undefined) 171 throw new WebGPUUnsupportedError(); 172 173 const [argsLayouts, argsResourceBindings, argsDeclarations, functionCallArgs] = this._setUpArguments(args); 174 175 if (this._resultBuffer) { 176 this._clearResults() 177 } else { 178 this._resultBuffer = this.device.createBuffer({ 147 179 size: Types.MAX_SIZE, 148 usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ 180 usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ | GPUBufferUsage.TRANSFER_DST 149 181 }); 150 182 } … … 163 195 }); 164 196 165 const code = this._shaderHeader + functions + ` 166 struct _compute_args { 167 device ${convertTypeToWHLSLType(type)}* result [[id(0)]]; 168 ${argsStructCode}}; 169 170 kernel void _compute_main(device _compute_args& args [[buffer(0)]]) 171 { 172 *args.result = ${name}(${functionCallArgs.join(", ")}); 173 } 174 `; 175 197 let entryPointCode; 198 if (this._isWHLSL) { 199 argsDeclarations.unshift(`device ${convertTypeToWHLSLType(type)}[] result : register(u0)`); 200 entryPointCode = ` 201 [numthreads(1, 1, 1)] 202 compute void _compute_main(${argsDeclarations.join(", ")}) 203 { 204 result[0] = ${name}(${functionCallArgs.join(", ")}); 205 } 206 `; 207 } else { 208 argsDeclarations.unshift(`device ${convertTypeToWHLSLType(type)}* result [[id(0)]];`); 209 entryPointCode = ` 210 struct _compute_args { 211 ${argsDeclarations.join("\n")} 212 }; 213 214 kernel void _compute_main(device _compute_args& args [[buffer(0)]]) 215 { 216 *args.result = ${name}(${functionCallArgs.join(", ")}); 217 } 218 `; 219 } 220 const code = this._shaderHeader + functions + entryPointCode; 176 221 this._callFunction(code, argsLayouts, argsResourceBindings); 177 222 … … 193 238 * @param {Data or Array[Data]} args - Data arguments to be passed to the call of 'name'. 194 239 */ 195 async callVoidFunction(functions, name, args) 196 { 197 const [argsLayouts, argsResourceBindings, argsStructCode, functionCallArgs] = this._setUpArguments(args); 198 199 const code = this._shaderHeader + functions + ` 200 struct _compute_args { 201 ${argsStructCode}}; 202 203 kernel void _compute_main(device _compute_args& args [[buffer(0)]]) 204 { 205 ${name}(${functionCallArgs.join(", ")}); 206 } 207 `; 208 240 callVoidFunction(functions, name, args) 241 { 242 if (this._device === undefined) 243 return; 244 245 const [argsLayouts, argsResourceBindings, argsDeclarations, functionCallArgs] = this._setUpArguments(args); 246 247 let entryPointCode; 248 if (this._isWHLSL) { 249 entryPointCode = ` 250 [numthreads(1, 1, 1)] 251 compute void _compute_main(${argsDeclarations.join(", ")}) 252 { 253 ${name}(${functionCallArgs.join(", ")}); 254 }`; 255 } else { 256 entryPointCode = ` 257 struct _compute_args { 258 ${argsDeclarations.join("\n")} 259 }; 260 261 kernel void _compute_main(device _compute_args& args [[buffer(0)]]) 262 { 263 ${name}(${functionCallArgs.join(", ")}); 264 } 265 `; 266 } 267 const code = this._shaderHeader + functions + entryPointCode; 209 268 this._callFunction(code, argsLayouts, argsResourceBindings); 269 } 270 271 get device() { return this._device; } 272 273 _clearResults() 274 { 275 if (!this._clearBuffer) { 276 this._clearBuffer = this._device.createBuffer({ 277 size: Types.MAX_SIZE, 278 usage: GPUBufferUsage.TRANSFER_SRC 279 }); 280 } 281 const commandEncoder = this._device.createCommandEncoder(); 282 commandEncoder.copyBufferToBuffer(this._clearBuffer, 0, this._resultBuffer, 0, Types.MAX_SIZE); 283 this._device.getQueue().submit([commandEncoder.finish()]); 210 284 } 211 285 … … 219 293 } 220 294 221 // FIXME: Replace with WHLSL.222 295 // Expand bind group structure to represent any arguments. 223 let args StructCode = "";296 let argsDeclarations = []; 224 297 let functionCallArgs = []; 225 298 let argsLayouts = []; … … 228 301 for (let i = 1; i <= args.length; ++i) { 229 302 const arg = args[i - 1]; 230 argsStructCode += `device ${convertTypeToWHLSLType(arg.type)}* arg${i} [[id(${i})]]; 231 `; 232 const optionalDeref = (!arg.isPointer) ? "*" : ""; 233 functionCallArgs.push(optionalDeref + `args.arg${i}`); 303 if (this._isWHLSL) { 304 argsDeclarations.push(`device ${convertTypeToWHLSLType(arg.type)}[] arg${i} : register(u${i})`); 305 functionCallArgs.push(`arg${i}` + (arg.isBuffer ? "" : "[0]")); 306 } else { 307 argsDeclarations.push(`device ${convertTypeToWHLSLType(arg.type)}* arg${i} [[id(${i})]];`); 308 functionCallArgs.push((arg.isBuffer ? "" : "*") + `args.arg${i}`); 309 } 234 310 argsLayouts.push({ 235 311 binding: i, … … 246 322 } 247 323 248 return [argsLayouts, argsResourceBindings, args StructCode, functionCallArgs];324 return [argsLayouts, argsResourceBindings, argsDeclarations, functionCallArgs]; 249 325 } 250 326 251 327 _callFunction(code, argsLayouts, argsResourceBindings) 252 328 { 253 const shaders = this._device.createShaderModule({ code: code }); 329 const shaders = this._device.createShaderModule({ code: code, isWHLSL: this._isWHLSL }); 330 331 const bindGroupLayout = this._device.createBindGroupLayout({ 332 bindings: argsLayouts 333 }); 334 335 const pipelineLayout = this._device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }); 336 337 const bindGroup = this._device.createBindGroup({ 338 layout: bindGroupLayout, 339 bindings: argsResourceBindings 340 }); 341 254 342 // FIXME: Compile errors should be caught and reported here. 255 343 const pipeline = this._device.createComputePipeline({ 344 layout: pipelineLayout, 256 345 computeStage: { 257 346 module: shaders, … … 260 349 }); 261 350 262 const layout = this._device.createBindGroupLayout({263 bindings: argsLayouts264 });265 266 const bindGroup = this._device.createBindGroup({267 layout: layout,268 bindings: argsResourceBindings269 });270 271 351 const commandEncoder = this._device.createCommandEncoder(); 272 352 const passEncoder = commandEncoder.beginComputePass(); … … 283 363 284 364 const harness = new Harness(); 285 harness._initialize(async () => { 286 try { 287 const adapter = await navigator.gpu.requestAdapter(); 288 harness._device = await adapter.requestDevice(); 289 } catch (e) { 290 throw new Error("Harness error: Unable to acquire GPUDevice!"); 291 } 292 }); 365 harness.requestDevice(); 293 366 294 367 /* Global Helper Functions */ -
trunk/LayoutTests/webgpu/msl-harness-test.html
r246823 r246824 25 25 }; 26 26 27 let tests = {};28 29 tests.literals = () => {27 let mslTests = {}; 28 29 mslTests.literals = () => { 30 30 checkBools("Return a literal of type bool.", "return true;"); 31 31 checkFloat4s("return float4(0, 1, 2, 3);"); … … 33 33 }; 34 34 35 tests.singleArgument = () => {35 mslTests.singleArgument = () => { 36 36 checkBools("Upload and return a bool value.", "return in0;", [true]); 37 37 checkFloat4s("return in0.wzyx;", [[3, 2, 1, 0]]); … … 39 39 }; 40 40 41 tests.manyArguments = () => {41 mslTests.manyArguments = () => { 42 42 checkBools("Upload many bool values and return a calculated result.", 43 43 "return in0 & in1 & in2 & in3 & in4 & in5 & in6 & in7;", … … 52 52 }; 53 53 54 tests.buffersWithOneValue = () => {54 mslTests.buffersWithOneValue = () => { 55 55 const body = `return in0[0];` 56 56 checkBools("Access and return a single bool through a bool*.", body, [[true]]); … … 59 59 }; 60 60 61 tests.multipleBufferArguments = () => {61 mslTests.multipleBufferArguments = () => { 62 62 checkBools("Access multiple bools through various buffers and return a bool.", 63 63 "return in0[0] & in0[1] & in0[2] & in1 & in2[0];", … … 70 70 }; 71 71 72 tests.multipleArgumentTypes = () => {72 mslTests.multipleArgumentTypes = () => { 73 73 const src = `float test(int i, uchar c, device uint* u, bool b, device bool* bs, float4 f4, device float* fs) 74 74 { … … 85 85 const f4 = makeFloat4([4, 5, 6, 7]); 86 86 const fs = makeFloat([8, 9]); 87 promise_test(() => {87 webGPUPromiseTest(() => { 88 88 return callFloatFunction(src, "test", [i, c, u, b, bs, f4, fs]).then(result => { 89 89 assert_approx_equals(result, 45, epsilon, "Test returned expected value."); … … 92 92 }; 93 93 94 tests.bufferStores = () => {94 mslTests.bufferStores = () => { 95 95 let src = `void test(device float4* out) { 96 96 *out = float4(0, 1, 2, 3); … … 99 99 callVoidFunction(src, "test", float4Out); 100 100 101 promise_test(() => {101 webGPUPromiseTest(() => { 102 102 return float4Out.getArrayBuffer().then(arrayBuffer => { 103 103 const result = new Float32Array(arrayBuffer); … … 117 117 callVoidFunction(src, "test", [input, output]); 118 118 119 promise_test(() => {119 webGPUPromiseTest(() => { 120 120 return output.getArrayBuffer().then(arrayBuffer => { 121 121 const result = new Uint8Array(arrayBuffer); … … 126 126 127 127 window.addEventListener("load", () => { 128 for (const name in tests) { 129 tests[name](); 128 harness.isWHLSL = false; 129 for (const name in mslTests) { 130 mslTests[name](); 130 131 } 131 132 }); … … 154 155 for (const f of functions) { 155 156 const callFunc = numericScalarFuncs[f.type]; 156 promise_test(async () => {157 webGPUPromiseTest(async () => { 157 158 return callFunc(src, f.name, f.args).then(result => { 158 159 assert_approx_equals(result, f.expected, epsilon, "Test returned expected value."); … … 175 176 `; 176 177 177 promise_test(async () => {178 webGPUPromiseTest(async () => { 178 179 return callBoolFunction(src, "boolTest", values).then(result => { 179 180 assert_equals(result, expected, "Test returned expected value."); … … 198 199 `; 199 200 200 promise_test(async () => {201 webGPUPromiseTest(async () => { 201 202 return callFloat4Function(src, "float4Test", values).then(result => { 202 203 for (let i = 0; i < 4; ++i) … … 205 206 }, "Return an expected float4 value."); 206 207 } 208 209 const webGPUPromiseTest = (testFunc, msg) => { 210 promise_test(async () => { 211 return testFunc().catch(e => { 212 if (!(e instanceof WebGPUUnsupportedError)) 213 throw e; 214 }); 215 }, msg); 216 } 207 217 </script> 208 218 </html> -
trunk/LayoutTests/webgpu/whlsl-test-harness-test-expected.txt
r246823 r246824 1 1 2 PASS Return a literal of type bool.3 2 PASS Return an expected float4 value. 4 3 PASS Return an expected int value. 5 PASS Return an expected uchar value.6 4 PASS Return an expected uint value. 7 5 PASS Return an expected float value. 8 PASS Upload and return a bool value.9 6 PASS Return an expected float4 value. 10 7 PASS Return an expected int value. 11 PASS Return an expected uchar value.12 8 PASS Return an expected uint value. 13 9 PASS Return an expected float value. 14 PASS Upload many bool values and return a calculated result.15 10 PASS Return an expected float4 value. 16 11 PASS Return an expected int value. 17 PASS Return an expected uchar value.18 12 PASS Return an expected uint value. 19 13 PASS Return an expected float value. 20 PASS Access and return a single bool through a bool*.21 14 PASS Return an expected float4 value. 22 15 PASS Return an expected int value. 23 PASS Return an expected uchar value.24 16 PASS Return an expected uint value. 25 17 PASS Return an expected float value. 26 PASS Access multiple bools through various buffers and return a bool.27 18 PASS Return an expected float4 value. 28 19 PASS Return an expected int value. 29 PASS Return an expected uchar value.30 20 PASS Return an expected uint value. 31 21 PASS Return an expected float value. 32 22 PASS Upload and calculate a result from varied argument types. 33 PASS Store into a float4 *.34 PASS Upload a uchar* and store into a uchar*.23 PASS Store into a float4[]. 24 PASS Upload a int[] and store into a int[]. 35 25 -
trunk/LayoutTests/webgpu/whlsl-test-harness-test.html
r246823 r246824 2 2 <html> 3 3 <meta charset=utf-8> 4 <meta name="timeout" content="long"> 4 5 <title>Test the WHLSL test harness.</title> 5 6 <script src="js/whlsl-test-harness.js"></script> … … 9 10 const epsilon = 0.0001; 10 11 11 const numericScalarTypes = ["int", "uchar", "uint", "float"]; 12 // FIXME: Add "uchar" back in when operator+(uchar, uchar) is available. 13 const numericScalarTypes = ["int", "uint", "float"]; 12 14 13 15 const numericScalarFuncs = { … … 19 21 20 22 const scalarArgMakers = { 23 "bool": makeBool, 21 24 "int": makeInt, 22 25 "uchar": makeUchar, … … 25 28 }; 26 29 27 let tests = {};28 29 tests.literals = () => {30 let whlslTests = {}; 31 32 whlslTests.literals = () => { 30 33 checkBools("Return a literal of type bool.", "return true;"); 31 34 checkFloat4s("return float4(0, 1, 2, 3);"); … … 33 36 }; 34 37 35 tests.singleArgument = () => {38 whlslTests.singleArgument = () => { 36 39 checkBools("Upload and return a bool value.", "return in0;", [true]); 37 checkFloat4s("return in0 .wzyx;", [[3, 2, 1, 0]]);40 checkFloat4s("return in0;", [[0, 1, 2, 3]]); 38 41 checkNumericScalars("return in0;", [42], 42); 39 42 }; 40 43 41 tests.manyArguments = () => {44 whlslTests.manyArguments = () => { 42 45 checkBools("Upload many bool values and return a calculated result.", 43 "return in0 & in1 & in2 & in3 & in4 & in5 & in6 & in7;", 46 "return in0 & in1 & in2 & in3 & in4 & in5 & in6 & in7;", 44 47 [true, true, true, true, true, true, true, true]); 45 48 46 const body = `return in0 + in1 + in2 + in3 + in4 + in5 + in6 + in7;`;49 let body = "return float4(in0.x, in1.y, in2.z, in3.w);" 47 50 let args = []; 48 for (let i = 0; i < 8; ++i)51 for (let i = 0; i < 4; ++i) 49 52 args.push([0, 1, 2, 3]); 50 checkFloat4s(body, args, [0, 8, 16, 24]); 53 checkFloat4s(body, args, [0, 1, 2, 3]); 54 55 body = `return in0 + in1 + in2 + in3 + in4 + in5 + in6 + in7;`; 51 56 checkNumericScalars(body, [0, 1, 2, 3, 4, 5, 6, 7], 28); 52 57 }; 53 58 54 tests.buffersWithOneValue = () => {59 whlslTests.buffersWithOneValue = () => { 55 60 const body = `return in0[0];` 56 checkBools("Access and return a single bool through a bool *.", body, [[true]]);61 checkBools("Access and return a single bool through a bool[].", body, [[true]]); 57 62 checkFloat4s(body, [[[0, 1, 2, 3]]]); 58 63 checkNumericScalars(body, [[42]], 42); 59 64 }; 60 65 61 tests.multipleBufferArguments = () => {66 whlslTests.multipleBufferArguments = () => { 62 67 checkBools("Access multiple bools through various buffers and return a bool.", 63 68 "return in0[0] & in0[1] & in0[2] & in1 & in2[0];", 64 69 [[true, true, true], true, [true]]); 65 66 const body = `return in0[0] + in0[1] + in0[2] + in1 + in2[0];`; 70 71 let body = ` 72 float x = in0[0].x + in0[1].x + in0[2].x + in1.x + in2[0].x; 73 float y = in0[0].y + in0[1].y + in0[2].y + in1.y + in2[0].y; 74 float z = in0[0].z + in0[1].z + in0[2].z + in1.z + in2[0].z; 75 float w = in0[0].w + in0[1].w + in0[2].w + in1.w + in2[0].w; 76 77 return float4(x, y, z, w);`; 67 78 const vector = [0, 1, 2, 3]; 68 79 checkFloat4s(body, [[vector, vector, vector], vector, [vector]], [0, 5, 10, 15]); 80 81 body = `return in0[0] + in0[1] + in0[2] + in1 + in2[0];`; 69 82 checkNumericScalars(body, [[0, 1, 2], 3, [4]], 10); 70 83 }; 71 84 72 tests.multipleArgumentTypes = () => {73 const src = `float test(int i, uchar c, device uint* u, bool b, device bool* bs, float4 f4, device float*fs)85 whlslTests.multipleArgumentTypes = () => { 86 const src = `float test(int i, uchar c, float4 f4, device uint[] u, device float[] fs) 74 87 { 75 if (b && bs[0] && bs[1]) 76 return i + c + u[0] + f4.x + f4.y + f4.z + f4.w + fs[0] + fs[1]; 77 78 return 0; 88 return float(i) + float(c) + f4.x + f4.y + f4.z + f4.w + float(u[0]) + fs[0] + fs[1]; 79 89 }`; 80 90 const i = makeInt(1); 81 91 const c = makeUchar(2); 92 const f4 = makeFloat4([4, 5, 6, 7]); 82 93 const u = makeUint([3]); 83 const b = makeBool(true);84 const bs = makeBool([true, true]);85 const f4 = makeFloat4([4, 5, 6, 7]);86 94 const fs = makeFloat([8, 9]); 87 promise_test(() => {88 return callFloatFunction(src, "test", [i, c, u, b, bs, f4, fs]).then(result => {95 webGPUPromiseTest(() => { 96 return callFloatFunction(src, "test", [i, c, f4, u, fs]).then(result => { 89 97 assert_approx_equals(result, 45, epsilon, "Test returned expected value."); 90 98 }); … … 92 100 }; 93 101 94 tests.bufferStores = () => {95 let src = `void test(device float4 *out) {96 *out= float4(0, 1, 2, 3);102 whlslTests.bufferStores = () => { 103 let src = `void test(device float4[] out) { 104 out[0] = float4(0, 1, 2, 3); 97 105 }`; 98 106 const float4Out = makeFloat4([[0, 0, 0, 0]]); 99 107 callVoidFunction(src, "test", float4Out); 100 108 101 promise_test(() => {109 webGPUPromiseTest(() => { 102 110 return float4Out.getArrayBuffer().then(arrayBuffer => { 103 111 const result = new Float32Array(arrayBuffer); … … 106 114 } 107 115 }); 108 }, "Store into a float4 *.");109 110 src = `void test(device uchar* in, device uchar*out) {111 for (uint i = 0; i < 5; ++i)116 }, "Store into a float4[]."); 117 118 src = `void test(device int[] in, device int[] out) { 119 for (uint i = 0; i < 5; i = i + 1) 112 120 out[i] = in[i]; 113 121 }`; 114 122 const array = [0, 1, 2, 3, 4]; 115 const input = make Uchar(array);116 const output = make Uchar([0, 0, 0, 0, 0]);123 const input = makeInt(array); 124 const output = makeInt([0, 0, 0, 0, 0]); 117 125 callVoidFunction(src, "test", [input, output]); 118 126 119 promise_test(() => {127 webGPUPromiseTest(() => { 120 128 return output.getArrayBuffer().then(arrayBuffer => { 121 const result = new Uint 8Array(arrayBuffer);129 const result = new Uint32Array(arrayBuffer); 122 130 assert_array_equals(array, result, "Test stored expected values."); 123 131 }); 124 }, "Upload a uchar* and store into a uchar*.");132 }, "Upload a int[] and store into a int[]."); 125 133 }; 126 134 127 135 window.addEventListener("load", () => { 128 for (const name in tests) { 129 tests[name](); 136 try { 137 for (const name in whlslTests) { 138 if (!name.startsWith("_")) 139 whlslTests[name](); 140 } 141 } catch (e) { 142 if (window.testRunner) 143 testRunner.notifyDone(); 144 145 throw e; 130 146 } 131 147 }); … … 137 153 let src = ""; 138 154 for (let type of numericScalarTypes) { 139 const name = `${type}Test`; 140 141 let inputArgs = []; 142 let values = []; 143 for (let i = 0; i < argValues.length; ++i) { 144 const isPointer = Array.isArray(argValues[i]); 145 inputArgs.push(`${isPointer ? "device " : ""}${type}${isPointer ? "*" : ""} in${i}`); 146 values.push(scalarArgMakers[type](argValues[i])); 147 } 148 149 src += `${type} ${name}(${inputArgs.join(", ")}) { ${body} } 150 `; 155 let name, values; 156 [src, name, values] = appendScalarFunctionToSource(src, type, body, argValues); 151 157 functions.push({ type: type, name: name, args: values, expected: expected }); 152 158 } … … 154 160 for (const f of functions) { 155 161 const callFunc = numericScalarFuncs[f.type]; 156 promise_test(async () => {162 webGPUPromiseTest(async () => { 157 163 return callFunc(src, f.name, f.args).then(result => { 158 164 assert_approx_equals(result, f.expected, epsilon, "Test returned expected value."); … … 163 169 164 170 const checkBools = (msg = "Return an expected bool value.", body, argValues = [], expected = true) => { 165 let src = ""; 171 // FIXME (https://webkit.org/b/199093): Bool[] functions don't compile, so no-op for now. 172 return; 173 174 const [src, name, values] = appendScalarFunctionToSource("", "bool", body, argValues); 175 176 webGPUPromiseTest(async () => { 177 return callBoolFunction(src, name, values).then(result => { 178 assert_equals(result, expected, "Test returned expected value."); 179 }, e => { 180 if (!(e instanceof WebGPUUnsupportedError)) 181 throw e; 182 }); 183 }, msg); 184 }; 185 186 const checkFloat4s = (body, argValues = [], expected = [0, 1, 2, 3]) => { 166 187 let inputArgs = []; 167 188 let values = []; 168 189 for (let i = 0; i < argValues.length; ++i) { 169 const isPointer = Array.isArray(argValues[i]);170 inputArgs.push(`${isPointer ? "device " : ""}bool${isPointer ? "*" : ""} in${i}`);171 values.push(makeBool(argValues[i]));172 }173 174 src += `bool boolTest(${inputArgs.join(", ")}) { ${body} }175 `;176 177 promise_test(async () => {178 return callBoolFunction(src, "boolTest", values).then(result => {179 assert_equals(result, expected, "Test returned expected value.");180 });181 }, msg);182 };183 184 const checkFloat4s = (body, argValues = [], expected = [0, 1, 2, 3]) => {185 let src = "";186 let inputArgs = [];187 let values = [];188 189 for (let i = 0; i < argValues.length; ++i) {190 190 // Support arrays of float4, including one with a single float4. 191 191 const totalLength = argValues[i].flat().length; 192 const is Pointer = argValues[i].length === 1 || totalLength > 4;193 inputArgs.push(`${is Pointer ? "device " : ""}float4${isPointer ? "*" : ""} in${i}`);192 const isBuffer = argValues[i].length === 1 || totalLength > 4; 193 inputArgs.push(`${isBuffer ? "device " : ""}float4${isBuffer ? "[]" : ""} in${i}`); 194 194 values.push(makeFloat4(argValues[i])); 195 195 } 196 196 197 src += `float4 float4Test(${inputArgs.join(", ")}) { ${body} }197 const src = `float4 float4Test(${inputArgs.join(", ")}) { ${body} } 198 198 `; 199 199 200 promise_test(async () => {200 webGPUPromiseTest(async () => { 201 201 return callFloat4Function(src, "float4Test", values).then(result => { 202 202 for (let i = 0; i < 4; ++i) … … 205 205 }, "Return an expected float4 value."); 206 206 } 207 208 const appendScalarFunctionToSource = (src, type, body, argValues) => { 209 const name = `${type}Test`; 210 211 let inputArgs = []; 212 let values = []; 213 for (let i = 0; i < argValues.length; ++i) { 214 const isBuffer = Array.isArray(argValues[i]); 215 inputArgs.push(`${isBuffer ? "device " : ""}${type}${isBuffer ? "[]" : ""} in${i}`); 216 values.push(scalarArgMakers[type](argValues[i])); 217 } 218 219 src += `${type} ${name}(${inputArgs.join(", ")}) { ${body} } 220 `; 221 222 return [src, name, values]; 223 }; 224 225 const webGPUPromiseTest = (testFunc, msg) => { 226 promise_test(async () => { 227 return testFunc().catch(e => { 228 if (!(e instanceof WebGPUUnsupportedError)) 229 throw e; 230 }); 231 }, msg); 232 } 207 233 </script> 208 234 </html>
Note: See TracChangeset
for help on using the changeset viewer.